R2.4.1 A digit counter with a carry

EasyImplementIcarus Verilog + Yosys · serverReview the topic

Design a modulo-N counter with an enable and a carry output, so that digits can be chained, for any N from 2 to 16.

Hardware context: One digit of a stopwatch: a modulo-N counter with an enable and a carry. Design the chainable modulo-N digit counter for any N from 2 to 16.

A stopwatch is a chain of digit counters: tenths, seconds (0 to 9), tens of seconds (0 to 5). Each digit counts when the digit before it carries. Write modn_en, one digit of the chain (lesson R2.4).

count runs 0, 1, ..., N-1 and then 0 again, and moves at a rising edge only when en is 1. carry tells the next digit that this one is about to wrap: it is 1 while en is 1 and count holds N-1, so the next digit's en can be this digit's carry.

Brief: parameter N from 2 to 16; ports clk, rst_n (asynchronous, active-low) and en in, count[$clog2(N)-1:0] and carry out; count is 0 after reset; one edge of latency; carry is combinational from en and count; corner cases: N a power of two, N = 2, en low at the last value. The tests run copies with N = 10, 6, 16 and 2. No latch. Synthesis check: the design must build on the site's synthesis flow with no latch. The cell and level counts come from an open-source flow and are a proxy for area and depth, not a foundry result.

Signals in the timeline

SignalWidthRole
ens16input of each check
which2input of each check
Full specification
The module you write (keep the name, the parameter and the ports)
module modn_en #(parameter int N = 10) (
  input  logic                 clk,
  input  logic                 rst_n,      // asynchronous, active-low
  input  logic                 en,
  output logic [$clog2(N)-1:0] count,
  output logic                 carry
);
  // your design
endmodule
Inputs before the edgecount after the edgecarry before the edge
en = 0count (held)0
en = 1, count < N-1count + 10
en = 1, count = N-101
rst_n = 0 (at any time)0per en and count

The tests reset the counter and run 16 steps: en is driven, carry is sampled just before the edge, and count is sampled just after it. The result is carry_before_edges (the edges, 0 to 15, before which carry was 1) and count_e0 to count_e15, the count after each edge.

Examples

Example 1

N = 10, enabled every step
Input
N = 10, en per step: 1111111111111111
Output
carry_before_edges = {9}, count_e0 = 1, count_e1 = 2, count_e2 = 3, count_e3 = 4, count_e4 = 5, count_e5 = 6, count_e6 = 7, count_e7 = 8, count_e8 = 9, count_e9 = 0, count_e10 = 1, count_e11 = 2, count_e12 = 3, count_e13 = 4, count_e14 = 5, count_e15 = 6

count is 1 to 9 after edges 0 to 8. carry is 1 before edge 9, where count holds 9 and en is 1, and that edge wraps count to 0.

Example 2

N = 6 with pauses
Input
N = 6, en per step: 1101110011110111
Output
carry_before_edges = {8, 15}, count_e0 = 1, count_e1 = 2, count_e2 = 2, count_e3 = 3, count_e4 = 4, count_e5 = 5, count_e6 = 5, count_e7 = 5, count_e8 = 0, count_e9 = 1, count_e10 = 2, count_e11 = 3, count_e12 = 3, count_e13 = 4, count_e14 = 5, count_e15 = 0

Steps with en 0 hold the count (edges 2, 6, 7 and 12). count is 5 before edges 6, 7 and 8, but carry is 1 only before edge 8, the one where en is 1; it is 1 again before edge 15.

Example 3

N = 16
Input
N = 16, en per step: 1111111111111111
Output
carry_before_edges = {15}, count_e0 = 1, count_e1 = 2, count_e2 = 3, count_e3 = 4, count_e4 = 5, count_e5 = 6, count_e6 = 7, count_e7 = 8, count_e8 = 9, count_e9 = 10, count_e10 = 11, count_e11 = 12, count_e12 = 13, count_e13 = 14, count_e14 = 15, count_e15 = 0

With N = 16 the last value is 15, the top of four bits: carry before edge 15, and the compare and the natural wrap agree.

Constraints and contract

  • N is between 2 and 16; inputs are known 0/1 values.
  • Keep the module name, the parameter N and the ports.

Hints

Hint 1

The register is $clog2(N) bits wide. The decision is what its next value is: hold, add one, or go back to 0.

Hint 2

Write carry first, as an assign from en and a compare with N-1. Then the next value is 0 when carry is 1, count + 1 when en is 1, and count otherwise.

Hint 3

Compare with N-1, not N: with N = 10 the last value is 9. A compare that waits for N gives eleven values, and with N = 16 the value 16 does not fit in four bits at all.

What the grader checks: Eight directed and eight seeded scripts of sixteen enable steps run on copies with N = 10, 6, 16 and 2; count after every edge and carry before every edge are compared with an independent model. Passing shows the counter on those four values of N; other N between 2 and 16 follow the same code but are not simulated. The synthesis check adds the latch count.

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.

16 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

N = 10, enabled every step

Input
N = 10, en per step: 1111111111111111
Expected output
carry_before_edges = {9}, count_e0 = 1, count_e1 = 2, count_e2 = 3, count_e3 = 4, count_e4 = 5, count_e5 = 6, count_e6 = 7, count_e7 = 8, count_e8 = 9, count_e9 = 0, count_e10 = 1, count_e11 = 2, count_e12 = 3, count_e13 = 4, count_e14 = 5, count_e15 = 6

count is 1 to 9 after edges 0 to 8. carry is 1 before edge 9, where count holds 9 and en is 1, and that edge wraps count to 0.

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

Icarus Verilog + Yosys · server