Q085FreeSystemVerilog
Schedule bank commands with accepted-slot cooldown
Interview prompt
Question
Buffer a frame of commands for four banks, then reorder across banks so repeated commands to one bank have at least C intervening accepted slots. Emit accepted idle tokens only when no pending bank is eligible. Use 1 <= MAX_CMDS <= 16. Load 1 through MAX_CMDS commands and assert cmd_last only on the final accepted command. cooldown_c is captured with the first accepted command and applies to the entire frame. An output slot advances time only when slot_valid and slot_ready are both high.
Candidate starting point
Implementation scaffold
module cooldown_bank_scheduler #(
parameter int unsigned MAX_CMDS = 16
) (
input logic clk,
input logic rst_n,
input logic cmd_valid,
output logic cmd_ready,
input logic cmd_last,
input logic [1:0] cmd_bank,
input logic [7:0] cmd_id,
input logic [1:0] cooldown_c,
output logic slot_valid,
input logic slot_ready,
output logic slot_idle,
output logic slot_last,
output logic [1:0] slot_bank,
output logic [7:0] slot_cmd_id
);
typedef enum logic {LOAD, RUN} state_t;
state_t state_q;
logic [7:0] fifo_q [0:3][0:MAX_CMDS-1];
int unsigned head_q [0:3];
int unsigned tail_q [0:3];
int unsigned pending_q [0:3];
int unsigned total_q;
logic [1:0] cooldown_q [0:3];
logic [1:0] c_q;
logic choice_valid;
logic [1:0] choice_bank;
int unsigned best_count;
assign cmd_ready = (state_q == LOAD) && (total_q < MAX_CMDS);
assign slot_valid = (state_q == RUN);
assign slot_idle = slot_valid && !choice_valid;
assign slot_bank = choice_valid ? choice_bank : 2'b00;
assign slot_cmd_id = choice_valid ? fifo_q[choice_bank][head_q[choice_bank]] : 8'h00;
assign slot_last = slot_valid && choice_valid && (total_q == 1);
always_comb begin : choose_eligible_bank
// TODO: Implement choose_eligible_bank using the supplied state and interface.
end
always_ff @(posedge clk) begin : load_and_commit_slot
// TODO: Implement load_and_commit_slot using the supplied state and interface.
end
endmoduleReviewed example
Trace one case
Input
C=1; framed commands in arrival order: bank0=A, bank0=B, bank1=CExpected output
accepted slots: bank0 A, bank1 C, bank0 BBank 0 initially has the largest queue; after A, one accepted command from bank 1 supplies the required intervening cooldown slot before B.
What to cover
Requirements
- Buffer 1 through 16 commands and capture C in the range 0 through 3 with the first command.
- Preserve arrival order within each bank while allowing reordering across banks.
- Choose the eligible bank with the largest pending count and break ties by lower bank ID.
- Advance cooldown, FIFO heads, and pending counts only when slot_valid and slot_ready are both high.
- Count accepted idle tokens as intervening slots and hold the selected token stable during backpressure.
