Tutorials

Learn More

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

  1. Parallel In Parallel Out shift register
  2. Parallel In Serial Out shift register
  3. Serial In Parallel Out shift register
  4. Serial In Serial Out shift register

Operation

Mode control
(select)

Operation

0

0

No change

0

1

Shift right

1

0

Shift left

1

1

Parallel load

Block Diagram

universal shift register

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