Skip to content

Instantly share code, notes, and snippets.

@catbraincell
Last active October 20, 2025 03:19
Show Gist options
  • Select an option

  • Save catbraincell/deec9d4c290c082c2ef63b5eba0ea415 to your computer and use it in GitHub Desktop.

Select an option

Save catbraincell/deec9d4c290c082c2ef63b5eba0ea415 to your computer and use it in GitHub Desktop.
Synthesizable variable-length bidirectional shift register
module bidir_shiftreg #(
parameter integer W = 32
) (
input wire clk,
input wire nrst,
input wire lsbfirst, // 1 = LSB-first shift (right), 0 = MSB-first (left)
input wire [$clog2(W)-1:0] N, // active bits val[N:0]
input wire [W-1:0] load, // parallel load
input wire load_en,
output reg [W-1:0] val, // parallel output
input wire shift_en,
input wire din, // serial in
output wire dout // serial val
);
// Serial output always from ACTIVE range only
assign dout = lsbfirst ? val[N] : val[0];
integer i;
always @(posedge clk) begin
if (!nrst) begin
// FULL RESET
val <= {W{1'b0}};
end else if (load_en) begin
// PARALLEL LOAD, THEN ZEROIZE UPPER BITS
for (i = 0; i < W; i = i + 1)
val[i] <= (i > N) ? 1'b0 : load[i];
end else if (shift_en) begin
// PURE BIT-PERFECT SYNTHESIZABLE SHIFTER
for (i = 0; i < W; i = i + 1) begin
if (i > N) begin
// always force inactive bits to zero
val[i] <= 0;
end else if (lsbfirst) begin
// LSB-first -> shift toward MSB
if (i == 0) val[i] <= din; // new LSB
else val[i] <= val[i-1]; // shift up
end else begin
// MSB-first -> shift toward LSB
if (i == N) val[i] <= din; // din enters at top of active region
else if (i == W-1) val[i] <= 0;
else val[i] <= val[i+1]; // shift down
end
end
end
end
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment