0
0
VerilogHow-ToBeginner · 3 min read

Verilog Code for PIPO Shift Register: Syntax and Example

A PIPO shift register in Verilog loads data in parallel on a clock edge and outputs it in parallel. Use a register array to store bits and assign inputs and outputs directly. The code includes a clock and reset to control loading and clearing the register.
📐

Syntax

The PIPO shift register uses a reg array to hold bits. On the rising edge of the clock, if reset is active, the register clears; otherwise, it loads the input data in parallel. The output is assigned directly from the register.

  • clk: Clock signal to trigger loading.
  • reset: Clears the register when high.
  • data_in: Parallel input data bus.
  • data_out: Parallel output data bus.
verilog
module pipo_shift_register #(parameter WIDTH = 8) (
    input wire clk,
    input wire reset,
    input wire [WIDTH-1:0] data_in,
    output reg [WIDTH-1:0] data_out
);

always @(posedge clk or posedge reset) begin
    if (reset) begin
        data_out <= 0;
    end else begin
        data_out <= data_in;
    end
end

endmodule
💻

Example

This example shows an 8-bit PIPO shift register. It loads 8-bit data on the rising clock edge and outputs it immediately. Reset clears the output to zero.

verilog
module testbench();
    reg clk = 0;
    reg reset;
    reg [7:0] data_in;
    wire [7:0] data_out;

    // Instantiate the PIPO shift register
    pipo_shift_register #(8) uut (
        .clk(clk),
        .reset(reset),
        .data_in(data_in),
        .data_out(data_out)
    );

    // Clock generation
    always #5 clk = ~clk; // 10 time units period

    initial begin
        // Initialize
        reset = 1;
        data_in = 8'b00000000;
        #10;
        reset = 0;

        // Load data 10101010
        data_in = 8'b10101010;
        #10;

        // Load data 11110000
        data_in = 8'b11110000;
        #10;

        // Load data 00001111
        data_in = 8'b00001111;
        #10;

        $finish;
    end

    initial begin
        $monitor("At time %0t: data_in = %b, data_out = %b", $time, data_in, data_out);
    end
endmodule
Output
At time 0: data_in = 00000000, data_out = 00000000 At time 10: data_in = 10101010, data_out = 00000000 At time 20: data_in = 10101010, data_out = 10101010 At time 30: data_in = 11110000, data_out = 10101010 At time 40: data_in = 11110000, data_out = 11110000 At time 50: data_in = 00001111, data_out = 11110000 At time 60: data_in = 00001111, data_out = 00001111
⚠️

Common Pitfalls

Common mistakes include:

  • Not using posedge clk in the always block, causing incorrect timing.
  • Forgetting to handle reset, which can leave the register in an unknown state.
  • Assigning data_out inside a combinational block instead of sequential always block.

Always use non-blocking assignments (<=) inside sequential blocks to avoid race conditions.

verilog
/* Wrong: combinational assignment causes glitches */
always @(*) begin
    data_out = data_in; // Should be in posedge clk block
end

/* Right: sequential assignment on clock edge */
always @(posedge clk or posedge reset) begin
    if (reset) data_out <= 0;
    else data_out <= data_in;
end
📊

Quick Reference

Remember these key points for PIPO shift registers:

  • Use reg [WIDTH-1:0] for storage.
  • Load data on clock rising edge.
  • Use reset to clear the register.
  • Use non-blocking assignments inside always @(posedge clk).

Key Takeaways

A PIPO shift register loads and outputs data in parallel on the clock edge.
Use a register array and non-blocking assignments inside a clocked always block.
Always include a reset to initialize or clear the register.
Avoid combinational assignments for sequential logic to prevent glitches.
Test with a simple testbench to verify correct parallel loading and output.