0
0
VerilogHow-ToBeginner · 3 min read

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
endmodule
Output
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 load to capture parallel data synchronously.
  • Shift bits out serially on each clock when load is low.
  • Assign serial_out before 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.