Shift register (SIPO, PISO, SISO) in Verilog - Mini Project: Build & Apply
Write a Verilog module called SIPO with inputs clk, reset, and serial_in. Create a 4-bit output parallel_out. Inside, use a 4-bit register called shift_reg. On the rising edge of clk, if reset is high, clear shift_reg to 0. Otherwise, shift shift_reg left by 1 and put serial_in into the least significant bit. Assign parallel_out to shift_reg.
Think of shift_reg as a row of 4 boxes. Each clock tick, move all bits one box to the left and put the new bit in the rightmost box.
Add a new Verilog module called PISO with inputs clk, reset, load, and 4-bit parallel_in. Create a 1-bit output serial_out. Use a 4-bit register shift_reg. On the rising edge of clk, if reset is high, clear shift_reg. Else if load is high, load parallel_in into shift_reg. Otherwise, shift shift_reg right by 1. Assign serial_out to the least significant bit of shift_reg.
Imagine loading 4 beads at once, then pushing them out one by one from the right side.
Add a Verilog module called SISO with inputs clk, reset, and serial_in. Create a 1-bit output serial_out. Use a 4-bit register shift_reg. On the rising edge of clk, if reset is high, clear shift_reg. Otherwise, shift shift_reg left by 1 and put serial_in into the least significant bit. Assign serial_out to the most significant bit of shift_reg.
This is like SIPO but you only watch the leftmost bit as output, moving bits one by one.
Write a testbench module called test_shift_registers. Declare reg clk, reset, serial_in, load, and [3:0] parallel_in. Declare wires [3:0] parallel_out and serial_out_piso, serial_out_siso. Instantiate SIPO, PISO, and SISO modules with these signals. Initialize clk to 0 and toggle it every 5 time units. Apply a reset pulse at start. Load parallel_in with 4'b1010 and set load high for one clock cycle. Feed serial_in with bits 1,0,1,1 on consecutive clock cycles. Use $display to print parallel_out, serial_out_piso, and serial_out_siso at each clock rising edge.
Use a clock that toggles every 5 time units. Reset first, then load parallel data into PISO. Feed serial bits to SIPO and SISO. Print outputs at each clock rising edge.
Practice
Solution
Step 1: Understand shift register types
SIPO means data enters serially and exits in parallel form.Step 2: Match the description
The question asks for serial input to parallel output, which matches SIPO.Final Answer:
SIPO (Serial-In Parallel-Out) -> Option DQuick Check:
Serial input to parallel output = SIPO [OK]
- Confusing PISO with SIPO
- Thinking SISO converts to parallel output
- Mixing up input and output directions
Solution
Step 1: Identify PISO input type
PISO shift register takes parallel input, so input must be a bus (multiple bits).Step 2: Check port declaration syntax
input [3:0] parallel_in correctly declares a 4-bit input bus.Final Answer:
input [3:0] parallel_in -> Option AQuick Check:
Parallel input uses input [3:0] [OK]
- Using output instead of input for inputs
- Declaring parallel input as single bit
- Confusing serial and parallel port directions
q after 3 clock cycles if d inputs are 1, 0, 1 respectively?reg [3:0] q;
always @(posedge clk) begin
q <= {q[2:0], d};
endSolution
Step 1: Understand shifting operation
Each clock, bits shift left and new bit d enters at LSB (rightmost).Step 2: Trace each clock cycle
Initial q=0000 (assumed).
Cycle 1: q=0000 -> shift left + d=1 -> 0001
Cycle 2: q=0001 -> shift left + d=0 -> 0010
Cycle 3: q=0010 -> shift left + d=1 -> 0101Final Answer:
4'b0101 -> Option AQuick Check:
Shift left + input d = 0101 after 3 cycles [OK]
- Assuming shift right instead of left
- Not updating q each cycle
- Mixing bit order in concatenation
module piso_shift(
input clk,
input [3:0] parallel_in,
input load,
output reg serial_out
);
reg [3:0] shift_reg;
always @(posedge clk) begin
if (load)
shift_reg <= parallel_in;
else
shift_reg <= shift_reg >> 1;
serial_out <= shift_reg[0];
end
endmoduleSolution
Step 1: Understand PISO operation
PISO outputs bits serially starting from the most significant bit (MSB), which is shift_reg[3] here.Step 2: Check serial_out assignment
Code assigns serial_out = shift_reg[0], which is the least significant bit (LSB), incorrect for PISO.Final Answer:
serial_out should output shift_reg[3], not shift_reg[0] -> Option BQuick Check:
PISO outputs MSB first = shift_reg[3] [OK]
- Assigning serial_out to LSB instead of MSB
- Confusing shift direction for PISO
- Thinking load must be asynchronous
Solution
Step 1: Identify required functionality
The design needs to convert parallel input to serial output, which matches PISO behavior.Step 2: Describe implementation
Load 8-bit parallel data into a register on load signal, then shift right each clock cycle outputting MSB (or LSB depending on design) as serial output.Final Answer:
Use a PISO shift register; load 8-bit data and shift out MSB serially each clock -> Option CQuick Check:
Parallel to serial = PISO shift register [OK]
- Choosing SIPO instead of PISO
- Confusing serial input with parallel input
- Using SISO which only shifts serial data
Ready to prove it?
Pass the test and this pattern moves unknown
