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
| Signal | Width | Role |
|---|---|---|
clk | 1 | stimulus, the same for every design |
rst_n | 1 | stimulus, the same for every design |
in_valid | 1 | stimulus, the same for every design |
in_tag | 4 | stimulus, the same for every design |
out_valid | 1 | stimulus, the same for every design |
sum | 10 | stimulus, the same for every design |
out_tag | 4 | stimulus, the same for every design |
Full specification
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
| Rule | Definition |
|---|---|
| cycle c | The stretch just before edge c; cycle 0 follows the case's reset. A value "in cycle c" is the one edge c samples. |
| result | sum = 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 pulse | rst_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 result | sum 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