Q191FreeSystemVerilog
Pipeline a parameterized barrel rotator
Question
Design a fully parameterized left/right barrel rotator split across two registered stages. Pipeline valid with the data and write a BFM that predicts rotations and checks the fixed latency. Keep SW and LOW_BITS at their derived defaults. A word sampled into stage one at C0 reaches the output register just after C1; a downstream register or input-#1step clocking sample observes it at C2. The supplied testbench resets the DUT and initializes valid_in=0 before serialized BFM calls; reset remains inactive during each call. Sample known reset and valid controls, and known shift/direction controls for each accepted word. Preserve each data bit as 0, 1, X, or Z when rotating it.
Implementation scaffold
module barrel_rotator_2stage #(
parameter int unsigned W = 32,
parameter int unsigned SW = (W <= 1) ? 1 : $clog2(W),
parameter int unsigned LOW_BITS = (SW + 1) / 2
) (
input logic clk,
input logic rst_n,
input logic valid_in,
input logic [W-1:0] din,
input logic [SW-1:0] shamt,
input logic right,
output logic valid_out,
output logic [W-1:0] dout
);
logic [W-1:0] low_result, high_result;
logic [W-1:0] p1_data;
logic [SW-1:0] p1_shamt;
logic p1_right, p1_valid;
function automatic logic [W-1:0] rotate_by(
input logic [W-1:0] x,
input logic right_dir,
input int unsigned amount
);
int unsigned s;
logic [W-1:0] result;
s = amount % W;
if (s == 0) return x;
for (int unsigned i = 0; i < W; i++) begin
if (right_dir) begin
if (i < W - s) result[i] = x[i + s];
else result[i] = x[i - (W - s)];
end else begin
if (i < s) result[i] = x[(W - s) + i];
else result[i] = x[i - s];
end
end
return result;
endfunction
always_comb begin : rotate_low_stage
// TODO: Implement rotate_low_stage using the supplied state and interface.
end
always_ff @(posedge clk or negedge rst_n) begin : capture_low_stage
// TODO: Implement capture_low_stage using the supplied state and interface.
end
always_comb begin : rotate_high_stage
// TODO: Implement rotate_high_stage using the supplied state and interface.
end
always_ff @(posedge clk or negedge rst_n) begin : capture_high_stage
// TODO: Implement capture_high_stage using the supplied state and interface.
end
assert property (@(posedge clk) disable iff (!rst_n)
valid_in |-> ##2 valid_out);
endmodule
interface rotator_if #(
parameter int unsigned W = 32,
parameter int unsigned SW = (W <= 1) ? 1 : $clog2(W)
) (input logic clk);
logic valid_in, right, valid_out;
logic [W-1:0] din, dout;
logic [SW-1:0] shamt;
clocking cb @(posedge clk);
default input #1step output #0;
output valid_in, din, shamt, right;
input valid_out, dout;
endclocking
modport TB (clocking cb);
endinterface
class rotator_bfm #(
int unsigned W = 32,
int unsigned SW = (W <= 1) ? 1 : $clog2(W)
);
virtual rotator_if #(W, SW).TB vif;
function new(virtual rotator_if #(W, SW).TB vif); this.vif = vif; endfunction
function automatic logic [W-1:0] predict(
logic [W-1:0] x, logic [SW-1:0] amount, logic right_dir
);
// TODO: implement this body.
endfunction
task rotate_and_check(
input logic [W-1:0] x,
input logic [SW-1:0] amount,
input logic right_dir
);
// TODO: implement this body.
endtask
endclassTrace one case
W=8; stable input din=8'b1001_0001, right=0, shamt=3 is sampled into stage one at C0.The output register holds dout=8'b1000_1100 and valid_out=1 just after C1. A pre-edge or input-#1step observer sees that result at C2.The lower and upper rotations compose to rotate-left-three. Both data and valid cross the same two registers; observation region explains the C1 versus C2 labels.
Requirements
- Support any W greater than zero, including W = 1, and reduce shift amounts modulo W.
- Apply lower shift-control bits before the first register and upper bits before the output register.
- Pipeline direction, remaining shift bits, and valid alongside data.
- The predictor must return the unchanged word for a zero effective shift and support W=1. Equivalent SystemVerilog expressions using a full-width logical shift are legal; a zero guard makes this boundary explicit.
