HDL & Digital Design Flow
Level 5 — Mastery (cross-domain: coding + timing math + digital design) Time limit: 90 minutes Total marks: 60
Instructions: Answer all three questions. Verilog code must be synthesizable unless a testbench is explicitly requested. Show timing arithmetic in full. Use
$...$conventions for math where helpful.
Question 1 — RTL Design, Blocking vs Non-blocking, and Synthesis (22 marks)
You are to design a synchronous 4-bit accumulator with saturation and parity output. Specification:
- Inputs:
clk,rst_n(active-low async reset),en,din[3:0]. - Output:
acc[3:0],ovf(sticky saturation flag),par(even parity ofacc). - On each rising clock edge with
en=1, computeacc + din. If the true sum ≥ 16 (would overflow 4 bits), clampaccto4'b1111and setovf=1(sticky until reset). Otherwise store the sum. paris combinational: XOR-reduction ofacc.
(a) Write synthesizable Verilog for this module. Use correct reset style, correct assignment type (blocking vs non-blocking) in each block, and separate the combinational par logic. (10)
(b) A colleague writes the accumulator update as:
always @(posedge clk) begin
sum = acc + din; // 5-bit temp
acc = sum[3:0];
endinside a single always block that also drives another register from acc. Explain precisely what functional bug the use of blocking assignments introduces here versus non-blocking, and state the RTL rule for register inference. (6)
(c) After synthesis, the tool reports your saturating adder maps to a 5-bit carry-ripple adder plus a comparator. Sketch (in words + a gate/logic count estimate) the combinational cone that feeds acc, and identify which signal path is likely the critical path into the acc register. (6)
Question 2 — Static Timing Analysis (20 marks)
A register-to-register path in a synchronous design has these parameters:
| Parameter | Value |
|---|---|
| Clock period target | to be found |
| Launch clock-to-Q, | 0.30 ns |
| Combinational logic delay, | 3.10 ns |
| Setup time, | 0.25 ns |
| Hold time, | 0.15 ns |
| Clock skew (capture − launch), | +0.20 ns |
| Clock jitter (uncertainty), | 0.10 ns |
(a) Write the setup timing inequality including skew and jitter, then compute the minimum clock period and the corresponding maximum frequency. (8)
(b) Write the hold timing inequality. Given the shortest combinational path from launch to capture is ns, determine whether a hold violation exists (show the slack). If it violates, state one concrete fix. (7)
(c) The design is retargeted from an FPGA to an ASIC. Explain two reasons the same RTL typically achieves a higher on the ASIC, referencing the physical delay model behind . (5)
Question 3 — Testbench, Simulation & Critical Path Proof (18 marks)
(a) Write a self-checking Verilog testbench for the accumulator of Q1 that: generates a 10 ns clock, applies async reset, then drives at least three din values including one that forces saturation, and uses $error/$display to flag any mismatch against a reference model computed in the testbench. (10)
(b) Consider the ripple-carry critical path of an -bit adder where each full-adder carry stage has delay and the sum XOR has delay . Derive the worst-case propagation delay as a function of , and compute it for , ns, ns. State how a carry-lookahead structure changes the asymptotic delay order. (8)
Answer keyMark scheme & solutions
Question 1
(a) Synthesizable module (10 marks)
module sat_acc (
input clk, rst_n, en,
input [3:0] din,
output reg [3:0] acc,
output reg ovf,
output par
);
wire [4:0] sum = {1'b0, acc} + {1'b0, din}; // 5-bit true sum
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
acc <= 4'b0000;
ovf <= 1'b0;
end else if (en) begin
if (sum >= 5'd16) begin
acc <= 4'b1111; // saturate/clamp
ovf <= 1'b1; // sticky
end else begin
acc <= sum[3:0];
end
end
end
assign par = ^acc; // combinational even-parity XOR reduction
endmoduleMark scheme:
- Async active-low reset in sensitivity list +
if(!rst_n)first: 2 - Non-blocking (
<=) for all sequential outputs: 2 - Correct 5-bit sum / overflow detection (
sum>=16): 2 - Saturation clamp to
4'hFand stickyovf(not cleared except reset): 2 paras separate combinationalassign ^acc: 2 Why: sequential state must use non-blocking to model true register behaviour; parity is purely combinational so it belongs inassign, not the clocked block.
(b) Blocking-assignment bug (6 marks)
- With blocking
=, statements execute in order within the same delta cycle:sumandaccupdate immediately, so a second register that readsaccin the same block sees the new (already-updated) value instead of the old value — collapsing what should be two pipeline stages into one, or creating a race/wrong data. (3) - With non-blocking
<=, all RHS are evaluated first, then updates commit at end of the time step, so every register samples the pre-edge value — correctly modelling parallel flip-flops. (2) - RTL rule: use non-blocking
<=for sequential (clocked) logic, blocking=for combinational (always @*) logic. (1)
(c) Critical-path cone (6 marks)
- Cone feeding
acc: 5-bit ripple-carry adder (acc+din) → comparatorsum>=16(effectivelysum[4]OR-detect since any value ≥16 sets bit4, so really justsum[4]) → 4×2:1 mux selecting betweensum[3:0]and1111. (3) - Gate estimate: ~5 full adders (≈5×5=25 gates), overflow test ≈1 gate (
sum[4]), 4 muxes (≈4×3=12 gates) → ~40 gates. (1) - Critical path: carry chain of the 5-bit adder (LSB carry-in rippling to
sum[4]), which then drives the mux-select — i.e.acc[0]/din[0] → carry ripple → sum[4] → mux → acc[3]. (2)
Question 2
(a) Setup analysis (8 marks)
Setup inequality (skew and jitter degrading the budget):
Rearranged:
Marks: inequality with correct sign of skew/jitter 3, arithmetic 3, frequency 2. Why: positive skew (capture later than launch) relaxes setup, jitter always tightens it.
(b) Hold analysis (7 marks)
Hold inequality:
Compute both sides:
- LHS ns
- RHS ns
Hold slack ns → no hold violation (passes, marginally). (5) Fix if it had failed: insert buffer/delay cells on the data path to increase , or reduce clock skew via clock-tree balancing. (2) Why: hold is independent of ; positive skew hurts hold (opposite of setup), so skew is added to the required side.
(c) FPGA → ASIC (5 marks)
- Routing: FPGA logic goes through programmable interconnect (switch boxes, pass transistors) adding large RC delay; ASIC uses dedicated custom metal routing → smaller . (2.5)
- Logic mapping: FPGA implements logic in LUTs (fixed delay per lookup) whereas ASIC standard cells give optimally sized gates/transistors; is the sum of intrinsic gate delay + interconnect RC, both lower on ASIC. (2.5)
Question 3
(a) Self-checking testbench (10 marks)
module tb_sat_acc;
reg clk, rst_n, en;
reg [3:0] din;
wire [3:0] acc;
wire ovf, par;
reg [4:0] model_acc; // reference (5-bit to see overflow)
reg model_ovf;
sat_acc dut(.clk(clk), .rst_n(rst_n), .en(en),
.din(din), .acc(acc), .ovf(ovf), .par(par));
initial clk = 0;
always #5 clk = ~clk; // 10 ns period
// reference model
task ref_update;
input [3:0] d;
reg [4:0] s;
begin
s = model_acc[3:0] + d;
if (s >= 16) begin model_acc = 5'd15; model_ovf = 1; end
else model_acc = s;
end
endtask
task check;
begin
if (acc !== model_acc[3:0])
$error("acc mismatch: dut=%0d exp=%0d", acc, model_acc[3:0]);
if (ovf !== model_ovf)
$error("ovf mismatch: dut=%b exp=%b", ovf, model_ovf);
else $display("OK acc=%0d ovf=%b par=%b", acc, ovf, par);
end
endtask
initial begin
en=0; din=0; model_ovf=0; model_acc=0;
rst_n=0; @(negedge clk); rst_n=1; // async reset release
en=1;
din=4'd5; ref_update(5); @(negedge clk); check;
din=4'd7; ref_update(7); @(negedge clk); check;
din=4'd9; ref_update(9); @(negedge clk); check; // forces saturation
$finish;
end
endmoduleMarks: clock gen 2, async reset apply/release 2, ≥3 stimuli incl. saturation case 2, reference model 2, self-check with $error 2.
(b) Ripple-carry delay derivation (8 marks)
The worst case propagates a carry from bit 0 through all carry stages, then the final sum XOR:
For :
Carry-lookahead reduces the carry generation to a tree, giving delay order instead of . (2 for order statement) Mark scheme: derivation/formula 3, arithmetic 3, CLA order 2.
[
{"claim":"Setup Tmin = 0.30+3.10+0.25-0.20+0.10 = 3.55 ns",
"code":"Tmin = 0.30+3.10+0.25-0.20+0.10; result = abs(Tmin-3.55)<1e-9"},
{"claim":"fmax = 1/3.55 ns approx 281.69 MHz",
"code":"f = 1/(3.55e-9); result = abs(f-2.81690e8) < 1e5"},
{"claim":"Hold slack = (0.30+0.20)-(0.15+0.20+0.10) = +0.05 ns (pass)",
"code":"slack = (0.30+0.20)-(0.15+0.20+0.10); result = abs(slack-0.05)<1e-9 and slack>=0"},
{"claim":"Ripple adder N=4: 4*0.18+0.12 = 0.84 ns",
"code":"T = 4*0.18+0.12; result = abs(T-0.84)<1e-9"}
]