R4.3.1 An adder tree with its valid pipe

EasyImplementIcarus Verilog + Yosys · serverReview the topic

Pipeline a four-input adder in two stages and carry a valid bit and a tag through the same registers, so every result leaves with its own tag and nothing comes out of a gap.

Hardware context: A sensor-hub adder that sums four readings per sample in two pipeline stages, each sample tagged with its sensor group. Pipeline the four-input adder with a valid pipe and a tag that leave with their sum.

A sensor hub adds four 8-bit readings per sample, and the sum is too deep for its clock in one cycle (lesson R4.3). Each sample carries a 4-bit tag naming its sensor group. The consumer reads sum and out_tag only in cycles where out_valid is 1. Samples arrive with gaps, and a reset can come while samples are still inside the pipe.

Write add4_tag as a two-stage pipeline: stage 1 registers the two pair sums, stage 2 the final sum. The valid bit and the tag travel through the same two registers as the data.

Brief: ports clk, rst_n, in_valid, a, b, c, d [7:0] and in_tag [3:0] in; out_valid, sum [9:0] and out_tag [3:0] out. Rising-edge clock; rst_n asynchronous and active-low, clearing the valid bits, so samples in flight are dropped; the data registers need no reset. Latency 2: a sample taken at edge k (in_valid = 1) is on sum and out_tag with out_valid = 1 in the cycle after edge k + 1. One sample per cycle, gaps anywhere. sum is the full 10-bit total, 0 to 1020. No latch.

Signals in the timeline

SignalWidthRole
clk1stimulus, the same for every design
rst_n1stimulus, the same for every design
in_valid1stimulus, the same for every design
in_tag4stimulus, the same for every design
out_valid1stimulus, the same for every design
sum10stimulus, the same for every design
out_tag4stimulus, the same for every design
Full specification
The module (keep the name and the ports)
module add4_tag (
  input  logic       clk,
  input  logic       rst_n,      // asynchronous, active-low
  input  logic       in_valid,   // a, b, c, d and in_tag hold a sample this cycle
  input  logic [7:0] a, b, c, d,
  input  logic [3:0] in_tag,
  output logic       out_valid,  // sum and out_tag hold a result this cycle
  output logic [9:0] sum,
  output logic [3:0] out_tag
);
  // your design
endmodule
RuleDefinition
cycle cThe stretch just before edge c; cycle 0 follows the case's reset. A value "in cycle c" is the one edge c samples.
resultsum = a + b + c + d and out_tag = in_tag of one sample, with out_valid = 1, two cycles after the cycle that offered it
reset pulserst_n low for 1 ns in the middle of a cycle: the sample offered in that cycle is still taken at the edge that ends it; earlier samples not yet out are lost
outside a resultsum and out_tag may hold anything while out_valid is 0

The result is {sum_total, first_wrong, wrong, results, valid_cycles}: the cycles in which out_valid was 1, the number of results, how many of them differed from the right sum and tag (in order), the position of the first one that did (shown only when not 0), and the sum of every result's sum.

Synthesis check: the design must build on the site's synthesis flow with no latch.

Examples

Example 1

Five samples with gaps
Input
cycle 0: 1+2+3+4 tag 1; cycle 1: 10+20+30+40 tag 2; cycle 3: 100+100+100+100 tag 3; cycle 6: 255+255+255+255 tag 4; cycle 7: 5+5+5+5 tag 5
Output
valid_cycles = {2, 3, 5, 8, 9}, results = 5, wrong = 0, sum_total = 1550

The samples offered in cycles 0, 1, 3, 6 and 7 come out in cycles 2, 3, 5, 8 and 9, two cycles later, with sums 10, 100, 400, 1020 and 20: 1550 in all. The gaps travel through the pipe as cycles with out_valid = 0.

Example 2

Back to back
Input
cycle 0: 1+1+1+1 tag 9; cycle 1: 2+2+2+2 tag 8; cycle 2: 3+3+3+3 tag 7; cycle 3: 40+30+20+10 tag 6; cycle 4: 0+0+0+0 tag 5; cycle 5: 128+128+128+128 tag 4
Output
valid_cycles = {2, 3, 4, 5, 6, 7}, results = 6, wrong = 0, sum_total = 636

Six samples in six cycles give six results in cycles 2 to 7, one per cycle, each with its own tag.

Example 3

A reset in flight
Input
cycle 0: 7+0+0+0 tag 1; cycle 1: 0+7+0+0 tag 2; cycle 2: 0+0+7+0 tag 3; cycle 3: reset pulse; cycle 4: 0+0+0+7 tag 4; cycle 5: 9+9+9+9 tag 5
Output
valid_cycles = {2, 6, 7}, results = 3, wrong = 0, sum_total = 50

The reset pulse in cycle 3 clears the valid pipe. The sample of cycle 0 is already out (cycle 2); those of cycles 1 and 2 are lost. The samples of cycles 4 and 5 come out in cycles 6 and 7.

Constraints and contract

  • Each case resets the design, then runs 20 cycles; every sample in a case comes out before it ends.
  • Keep the module name and the ports.

Hints

Hint 1

For each output, count the registers it crosses on its way from the inputs. The brief asks for two on every one of them, not only on sum.

Hint 2

A valid bit that crosses one register is 1 a cycle early, beside the sum of the sample before. The tag has the same problem. Each needs a stage-1 register next to the pair sums.

Hint 3

Two always_ff blocks are enough: one with no reset for the data (the pair sums and the tag, then the final sum and the tag again), and one with the asynchronous reset for the stage-1 valid bit and out_valid.

What the grader checks: Eight directed and ten seeded scripts of 20 cycles drive the pipeline with gaps, back-to-back samples, the largest inputs and reset pulses between edges; the cycles of out_valid and every result's sum and tag, in order, are compared with an independent model of the brief. Values under out_valid = 0 are not checked.

The submitted design must synthesize with 0 latches and no combinational loop. Counts come from the pinned open-source synthesis flow. They are proxies for logic size and depth, not physical area or timing.

18 checks on Icarus Verilog + Yosys · server. Run the examples first, then check the full regression. The suite is local and inspectable. A passing result establishes the tested cases, not a proof for all possible inputs.

See all 1 steps and the final capstone
Your code SystemVerilogSaved locally
Ln 1, Col 1Tab indents · Ctrl/⌘ + Enter runs samples
Not run yet

Five samples with gaps

Input
cycle 0: 1+2+3+4 tag 1; cycle 1: 10+20+30+40 tag 2; cycle 3: 100+100+100+100 tag 3; cycle 6: 255+255+255+255 tag 4; cycle 7: 5+5+5+5 tag 5
Expected output
valid_cycles = {2, 3, 5, 8, 9}, results = 5, wrong = 0, sum_total = 1550

The samples offered in cycles 0, 1, 3, 6 and 7 come out in cycles 2, 3, 5, 8 and 9, two cycles later, with sums 10, 100, 400, 1020 and 20: 1550 in all. The gaps travel through the pipe as cycles with out_valid = 0.

Run samples executes all 3 example checks. Check all tests runs 18 checks.

Icarus Verilog + Yosys · server