Altifigence Academy

32 / 37 · Lab

Integrated lab: periodic pulses and an enabled accumulator

Specify inter-module transfers using previous values and compare enable stalls, consecutive pulses and simultaneous reset against a reference model.

Define the connection before composing the modules

Build a sampler that accepts a four-bit unsigned sample at every rising edge with enable=1. Every Nth accepted sample produces a registered pulse. An accumulator consumes that pulse and its corresponding saved sample at the following rising edge, even if enable is then 0. The eight-bit total wraps modulo 256. Synchronous reset clears both stages and discards any pending sample.

The one-edge delay is part of the contract. The accumulator reads the old pulse and old saved sample; it cannot see the other stage’s new nonblocking values at the same edge.

Save the parameter lesson’s modulo_tick module as modulo_tick.sv and this module as periodic_accumulator.sv. N must be positive.

SystemVerilog
module periodic_accumulator #(parameter integer N = 3) (
  input  logic       clk, rst, enable,
  input  logic [3:0] sample,
  output logic       pulse,
  output logic [7:0] total
);
  localparam integer CW = (N <= 1) ? 1 : $clog2(N);
  wire [CW-1:0] count;
  logic [3:0] saved_sample;
  modulo_tick #(.N(N)) tick_u (
    .clk(clk), .rst(rst), .enable(enable),
    .count(count), .pulse(pulse)
  );
  always_ff @(posedge clk) begin
    if (rst) saved_sample <= 4'b0;
    else if (enable) saved_sample <= sample;
  end
  always_ff @(posedge clk) begin
    if (rst) total <= 8'b0;
    else if (pulse) total <= total + {4'b0, saved_sample};
  end
endmodule

Track the sample and event together

For N=3, use this table. Inputs are pre-edge and outputs are post-update.

Edgerstenablesamplepulse aftertotal after
E011900
E101200
E201400
E301710
E400907
E501107
E601307
E701517
E8111500

At E4, the accumulator adds 7, not the new external sample 9. enable only controls new acceptance; it does not cancel a pending event. At E8, reset discards pending 5 and clears the total. Copying the accumulator condition as enable && pulse would lose the E4 event.

Write a reference at the system boundary

Keep an accepted-sample count, an optional pending value and an integer total. At each non-reset edge, first consume the previous pending value modulo 256, then examine current enable/sample to decide whether a new Nth sample becomes pending. Reset clears all three. This model does not depend on tick_u.count or saved_sample.

Reuse the testbench lesson’s falling-edge stimulus and post-update comparison. Compare pulse and total at every edge. Also check that total holds when no event is pending and that a consumed event is removed.

Cover integration failures

  • Run N=1 to generate consecutive pulses. Each accepted sample must be consumed once at the next edge.
  • Run N=3 with disabled gaps before and after a terminal sample. Count accepted edges, not all clock edges.
  • Change the external sample during a disabled consumption edge; the saved sample must be used.
  • Reset with a pending event. The total and pending event are both discarded.
  • Accumulate enough samples to cross 255 and verify modulo-256 wrap.

Deliberately replace saved_sample with sample in the accumulator. The E4 case must fail. Then gate consumption with enable and confirm another failure. Restore the correct implementation before recording the passing run.

This exercise verifies a single-clock, finite-width functional contract. It does not demonstrate a multi-clock crossing, physical timing closure or a free-account DDS product run. Those require their own execution and acceptance evidence.

Your choice applies to this browser. Change it any time using the footer.