Verilog Code for PISO Shift Register: Syntax and Example
A
PISO shift register in Verilog loads parallel data on a clock edge and shifts it out serially on subsequent clocks. It typically uses a register array and control signals like load and shift to manage data flow.Syntax
The basic syntax for a PISO shift register includes inputs for parallel data, a load signal to capture data, a clock, and a serial output. Internally, a register stores the data and shifts it out bit by bit on each clock when load is low.
- clk: Clock signal to synchronize operations.
- load: When high, loads parallel data into the register.
- parallel_in: The parallel data input bus.
- serial_out: The serial output bit shifted out.
verilog
module piso_shift_register #(parameter WIDTH = 8) ( input wire clk, input wire load, input wire [WIDTH-1:0] parallel_in, output reg serial_out ); reg [WIDTH-1:0] shift_reg; always @(posedge clk) begin if (load) begin shift_reg <= parallel_in; // Load parallel data end else begin serial_out <= shift_reg[WIDTH-1]; // Output MSB shift_reg <= {shift_reg[WIDTH-2:0], 1'b0}; // Shift left end end endmodule
Example
This example shows a PISO shift register with 4-bit width. It loads the 4-bit input when load is high, then shifts out bits serially on each clock cycle when load is low.
verilog
module testbench();
reg clk = 0;
reg load;
reg [3:0] parallel_in;
wire serial_out;
piso_shift_register #(4) uut (
.clk(clk),
.load(load),
.parallel_in(parallel_in),
.serial_out(serial_out)
);
always #5 clk = ~clk; // 10 time units clock period
initial begin
// Load 4'b1011
load = 1;
parallel_in = 4'b1011;
#10;
load = 0;
// Shift out bits
repeat (4) begin
#10;
$display("Time %0t: serial_out = %b", $time, serial_out);
end
$finish;
end
endmoduleOutput
Time 20: serial_out = 1
Time 30: serial_out = 0
Time 40: serial_out = 1
Time 50: serial_out = 1
Common Pitfalls
Common mistakes include:
- Not using a load signal to capture parallel data, causing incorrect shifting.
- Shifting in the wrong direction (left vs right), which changes output order.
- Not updating the serial output before shifting, losing the current bit.
- Forgetting to initialize registers, leading to unknown outputs.
Always ensure the serial output is assigned before the shift operation in the clocked block.
verilog
/* Wrong way: shifting before output assignment loses MSB */ always @(posedge clk) begin if (load) begin shift_reg <= parallel_in; end else begin shift_reg <= {shift_reg[WIDTH-2:0], 1'b0}; // Shift first serial_out <= shift_reg[WIDTH-1]; // Output after shift (wrong) end end /* Correct way: output before shift */ always @(posedge clk) begin if (load) begin shift_reg <= parallel_in; end else begin serial_out <= shift_reg[WIDTH-1]; // Output first shift_reg <= {shift_reg[WIDTH-2:0], 1'b0}; // Then shift end end
Quick Reference
Remember these tips for PISO shift registers:
- Use
loadto capture parallel data synchronously. - Shift bits out serially on each clock when
loadis low. - Assign
serial_outbefore shifting to avoid losing data. - Initialize registers if simulation or hardware requires known start state.
Key Takeaways
Use a load signal to capture parallel data into the shift register synchronously.
Shift bits out serially on each clock cycle when not loading data.
Assign the serial output before shifting the register to preserve the output bit.
Initialize registers to avoid unknown states in simulation or hardware.
Verify shift direction matches the desired output bit order.