Tutorials
Learn More
Universal Shift Register
A universal shift register is a sequential logic that can store data within and on every clock pulse it transfers data to the output port.
The universal shift register can be used as
- Parallel In Parallel Out shift register
- Parallel In Serial Out shift register
- Serial In Parallel Out shift register
- Serial In Serial Out shift register
Operation
Mode control |
Operation |
|
0 |
0 |
No change |
0 |
1 |
Shift right |
1 |
0 |
Shift left |
1 |
1 |
Parallel load |
Block Diagram
Universal Shift Register Verilog Code
module universal_shift_reg(
input clk, rst_n,
input [1:0] select, // select operation
input [3:0] p_din, // parallel data in
input s_left_din, // serial left data in
input s_right_din, // serial right data in
output reg [3:0] p_dout, //parallel data out
output s_left_dout, // serial left data out
output s_right_dout // serial right data out
);
always@(posedge clk) begin
if(!rst_n) p_dout <= 0;
else begin
case(select)
2'h1: p_dout <= {s_right_din,p_dout[3:1]}; // Right Shift
2'h2: p_dout <= {p_dout[2:0],s_left_din}; // Left Shift
2'h3: p_dout <= p_din; // Parallel in - Parallel out
default: p_dout <= p_dout; // Do nothing
endcase
end
end
assign s_left_dout = p_dout[0];
assign s_right_dout = p_dout[3];
endmodule
Testbench Code
module TB;
reg clk, rst_n;
reg [1:0] select;
reg [3:0] p_din;
reg s_left_din, s_right_din;
wire [3:0] p_dout; //parallel data out
wire s_left_dout, s_right_dout;
universal_shift_reg usr(clk, rst_n, select, p_din, s_left_din, s_right_din, p_dout, s_left_dout, s_right_dout);
always #2 clk = ~clk;
initial begin
$monitor("select=%b, p_din=%b, s_left_din=%b, s_right_din=%b --> p_dout = %b, s_left_dout = %b, s_right_dout = %b",select, p_din, s_left_din, s_right_din, p_dout, s_left_dout, s_right_dout);
clk = 0; rst_n = 0;
#3 rst_n = 1;
p_din = 4'b1101;
s_left_din = 1'b1;
s_right_din = 1'b0;
select = 2'h3; #10;
select = 2'h1; #20;
p_din = 4'b1101;
select = 2'h3; #10;
select = 2'h2; #20;
select = 2'h0; #20;
$finish;
end
// To enable waveform
initial begin
$dumpfile("dump.vcd"); $dumpvars;
end
endmodule
Output:
select=xx, p_din=xxxx, s_left_din=x, s_right_din=x --> p_dout = xxxx, s_left_dout = x, s_right_dout = x
select=xx, p_din=xxxx, s_left_din=x, s_right_din=x --> p_dout = 0000, s_left_dout = 0, s_right_dout = 0
select=11, p_din=1101, s_left_din=1, s_right_din=0 --> p_dout = 0000, s_left_dout = 0, s_right_dout = 0
select=11, p_din=1101, s_left_din=1, s_right_din=0 --> p_dout = 1101, s_left_dout = 1, s_right_dout = 1
select=01, p_din=1101, s_left_din=1, s_right_din=0 --> p_dout = 1101, s_left_dout = 1, s_right_dout = 1
select=01, p_din=1101, s_left_din=1, s_right_din=0 --> p_dout = 0110, s_left_dout = 0, s_right_dout = 0
select=01, p_din=1101, s_left_din=1, s_right_din=0 --> p_dout = 0011, s_left_dout = 1, s_right_dout = 0
select=01, p_din=1101, s_left_din=1, s_right_din=0 --> p_dout = 0001, s_left_dout = 1, s_right_dout = 0
select=01, p_din=1101, s_left_din=1, s_right_din=0 --> p_dout = 0000, s_left_dout = 0, s_right_dout = 0
select=11, p_din=1101, s_left_din=1, s_right_din=0 --> p_dout = 0000, s_left_dout = 0, s_right_dout = 0
select=11, p_din=1101, s_left_din=1, s_right_din=0 --> p_dout = 1101, s_left_dout = 1, s_right_dout = 1
select=10, p_din=1101, s_left_din=1, s_right_din=0 --> p_dout = 1101, s_left_dout = 1, s_right_dout = 1
select=10, p_din=1101, s_left_din=1, s_right_din=0 --> p_dout = 1011, s_left_dout = 1, s_right_dout = 1
select=10, p_din=1101, s_left_din=1, s_right_din=0 --> p_dout = 0111, s_left_dout = 1, s_right_dout = 0
select=10, p_din=1101, s_left_din=1, s_right_din=0 --> p_dout = 1111, s_left_dout = 1, s_right_dout = 1
select=00, p_din=1101, s_left_din=1, s_right_din=0 --> p_dout = 1111, s_left_dout = 1, s_right_dout = 1
Verilog Codes