Q079FreeSystemVerilog
Build a reloadable countdown timer
Interview prompt
Question
Design a parameterized countdown timer with load, load_value, busy, and a one-cycle expired pulse. Add a BFM task that starts a nonzero delay and waits for expiry. W is a positive integer. The environment resets the timer, initializes load=0, and serializes calls to the BFM task.
Candidate starting point
Implementation scaffold
module countdown_timer #(
parameter int unsigned W = 16
) (
input logic clk,
input logic rst_n,
input logic load,
input logic [W-1:0] load_value,
output logic busy,
output logic expired
);
logic [W-1:0] count_q;
always_ff @(posedge clk or negedge rst_n) begin : timer_state
// TODO: Implement timer_state using the supplied state and interface.
end
endmodule
interface timer_if #(parameter int unsigned W = 16) (input logic clk);
logic load, busy, expired;
logic [W-1:0] load_value;
clocking cb @(posedge clk);
default input #1step output #0;
output load, load_value;
input busy, expired;
endclocking
modport TB (clocking cb);
endinterface
class timer_bfm #(int unsigned W = 16);
virtual timer_if #(W).TB vif;
function new(virtual timer_if #(W).TB vif); this.vif = vif; endfunction
task start_and_wait(input logic [W-1:0] value);
// TODO: implement this body.
endtask
endclassReviewed example
Trace one case
Input
load value 3, observe three countdown edges; later load value 0Expected output
busy during the first two countdown edges and expired pulses on the third; zero load pulses expired immediately and remains idleA nonzero N expires after exactly N active edges, while load priority and the zero special case each produce one-cycle pulses.
What to cover
Requirements
- Loading has priority over counting.
- A value N expires after N active countdown edges.
- expired is a pulse, not a permanent idle indicator.
- A zero load expires immediately and leaves the timer idle.
