• Writing in the front
  • The body of the
    • Left shift register
    • Right shift register
    • Serial input parallel output shift register
    • Parallel input serial output shift register
  • The resources
  • Hand over a friend


Writing in the front

  • Personal wechat official account: FPGA LAB
  • Personal Blog Homepage
  • Note: Learn to use!

The body of the

In digital electronics, the shift register is a cascade of flip-flops in which the output pin Q of one flip-flop is connected to the data input pin (D) of the next. Because all flip-flops work on the same clock, the bit array stored in the shift register shifts by one position. For example, if a 5-bit right-shift register has an initial value of 10110 and the input to the shift register is bound to O, the next mode will be 01011 and the next mode will be 00101.

Schematic diagram of the 5-bit shift register

There are many types of shift registers, which need to be designed according to the requirements, but all changes are the same, each clock, register array shift once, the following inventory of various shift registers:

  1. Left shift register
  2. Right shift register
  3. Serial input parallel output shift register
  4. Parallel input serial output shift register

The following are known respectively.

Left shift register

The so-called left shift is defined as a net high shift, because we usually define variables as:

reg [MSB:LSB] VAR;
Copy the code

The high position is to the left and the base is to the right, so a shift to the left is a shift to the high position. You can actually subdivide it further, is it cyclic left or is it acyclic?

Loop left shift register

The so-called circular left shift is to shift the highest position to the lowest position, the second highest position as the highest position, in turn.

Circuit design:

Take the four-digit cycle shift as an example, the circuit design Verilog code is given:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Reborn Lee
// Module Name: cycle_left_register
// Additional Comments:
// https://blog.csdn.net/reborn_lee //////////////////////////////////////////////////////////////////////////////////   module cycle_left_register #(parameter MSB = 4) ( input [MSB - 1 : 0] din,  input i_rst,  input i_load,  input i_clk,  output [MSB - 1 : 0] dout  );   reg [MSB - 1 : 0] dout_mid;  always@ (posedge i_clk) begin  if(i_rst) begin  dout_mid <= 'd0;  end  else if(i_load) begin  dout_mid <= din;  end  else begin  dout_mid <= {dout_mid[MSB - 2 : 0], dout_mid[MSB - 1]};  end  end  assign dout = dout_mid;   endmodule    Copy the code

Note: there is a signal called load signal i_load. When this signal is valid, the input din is assigned to the intermediate register dout_mid, so that the input is moved left once for each rising edge of the clock.

The test code

The test code is given briefly:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Reborn Lee
// Module Name: cycle_left_register_tb
// https://blog.csdn.net/reborn_lee
//////////////////////////////////////////////////////////////////////////////////   module cycle_left_register_tb(   );  parameter MSB = 4;   reg [MSB - 1 : 0] din;  reg i_rst;  reg i_clk;  reg i_load;  wire [MSB - 1 : 0] dout;   //generate clock  initial begin  i_clk = 0;  forever begin  #5 i_clk = ~i_clk;  end  end   //generate rst and input data   initial begin  i_rst = 1;  din = 0;  i_load = 0;   # 22   i_rst = 0; @ (negedge i_clk) begin  din = 'b1011;  i_load = 1;  end  @ (negedge i_clk) begin  i_load = 0;  end   repeat(5) @ (posedge i_clk);  @ (negedge i_clk) begin  din = 'd0101;  i_load = 1;  end  @ (negedge i_clk) i_load = 0;   repeat(4) @ (posedge i_clk);   #10 $finish;   end   initial  $monitor (" i_rst = %0b, i_load = %0b, din = %b, dout = %b", i_rst, i_load, din, dout);   cycle_left_register #(.MSB(MSB))inst_cycle_left_register(  .i_clk(i_clk),  .i_rst(i_rst),  .i_load(i_load),  .din(din),  .dout(dout)  );    endmodule   Copy the code

Simulation results are given:

Simulation results of left shift register

Monitoring records:

 i_rst = 1, i_load = 0, din = 0000, dout = xxxx
 i_rst = 1, i_load = 0, din = 0000, dout = 0000
 i_rst = 0, i_load = 0, din = 0000, dout = 0000
 i_rst = 0, i_load = 1, din = 1011, dout = 0000
 i_rst = 0, i_load = 1, din = 1011, dout = 1011
 i_rst = 0, i_load = 0, din = 1011, dout = 1011
 i_rst = 0, i_load = 0, din = 1011, dout = 0111
 i_rst = 0, i_load = 0, din = 1011, dout = 1110
 i_rst = 0, i_load = 0, din = 1011, dout = 1101
 i_rst = 0, i_load = 0, din = 1011, dout = 1011
 i_rst = 0, i_load = 0, din = 1011, dout = 0111
 i_rst = 0, i_load = 1, din = 0101, dout = 0111
 i_rst = 0, i_load = 1, din = 0101, dout = 0101
 i_rst = 0, i_load = 0, din = 0101, dout = 0101
 i_rst = 0, i_load = 0, din = 0101, dout = 1010
 i_rst = 0, i_load = 0, din = 0101, dout = 0101
 i_rst = 0, i_load = 0, din = 0101, dout = 1010
 i_rst = 0, i_load = 0, din = 0101, dout = 0101
Copy the code

Acyclic left shift register

Acyclic left shift for cyclic left shift, the highest digit is not moved to the lowest digit, but discarded, and the lowest digit is added to zero. Modify the shift statement:

dout_mid <= {dout_mid[MSB - 2 : 0], dout_mid[MSB - 1]};
Copy the code

To:

dout_mid <= {dout_mid[MSB - 2 : 0],1'b0};
Copy the code

Behavior simulation waveform

Acyclic left shift register simulation diagram
 i_rst = 1, i_load = 0, din = 0000, dout = xxxx
 i_rst = 1, i_load = 0, din = 0000, dout = 0000
 i_rst = 0, i_load = 0, din = 0000, dout = 0000
 i_rst = 0, i_load = 1, din = 1011, dout = 0000
 i_rst = 0, i_load = 1, din = 1011, dout = 1011
 i_rst = 0, i_load = 0, din = 1011, dout = 1011
 i_rst = 0, i_load = 0, din = 1011, dout = 0110
 i_rst = 0, i_load = 0, din = 1011, dout = 1100
 i_rst = 0, i_load = 0, din = 1011, dout = 1000
 i_rst = 0, i_load = 0, din = 1011, dout = 0000
 i_rst = 0, i_load = 1, din = 0101, dout = 0000
 i_rst = 0, i_load = 1, din = 0101, dout = 0101
 i_rst = 0, i_load = 0, din = 0101, dout = 0101
 i_rst = 0, i_load = 0, din = 0101, dout = 1010
 i_rst = 0, i_load = 0, din = 0101, dout = 0100
 i_rst = 0, i_load = 0, din = 0101, dout = 1000
 i_rst = 0, i_load = 0, din = 0101, dout = 0000
Copy the code

Matters needing attention:

Circular shift statement:

dout_mid <= {dout_mid[MSB - 2 : 0],1'b0};
Copy the code

The lowest order must be written as 1’b0. If 0 is written, that is:

dout_mid <= {dout_mid[MSB - 2 : 0],0};
Copy the code

Then the simulation result becomes:

4 – bit shift register simulation diagram anomaly of acyclic left shift

So that means I’m just assigning 0 to dout_mid.

Right shift register

The right shift register and the left shift register are symmetric, that is, each rising edge of the clock is moved to the lower one, here also need to rewrite, we only need to change one of the shift statement.

This is divided into cycles and non-cycles.

Cyclic right shift

That is:

dout_mid <= {dout_mid[MSB - 2 : 0], dout_mid[MSB - 1]};
Copy the code

To:

dout_mid <= {dout_mid[0], dout_mid[MSB - 1 : 1]};
Copy the code

For the benefit of beginners, here is the full design code:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Reborn Lee
// Module Name: cycle_left_register
// Additional Comments:
// https://blog.csdn.net/reborn_lee //////////////////////////////////////////////////////////////////////////////////   module shift_register #(parameter MSB = 4) ( input [MSB - 1 : 0] din,  input i_rst,  input i_load,  input i_clk,  output [MSB - 1 : 0] dout  );   reg [MSB - 1 : 0] dout_mid;  always@ (posedge i_clk) begin  if(i_rst) begin  dout_mid <= 'd0;  end  else if(i_load) begin  dout_mid <= din;  end  else begin  // dout_mid <= {dout_mid[MSB - 2 : 0], 1'b0}; // normal left shift  // dout_mid <= {dout_mid[MSB - 2 : 0], dout_mid[MSB - 1]}; //cycle left shift  dout_mid <= {dout_mid[0],dout_mid[MSB - 1 : 1]};  end  end  assign dout = dout_mid;   endmodule  Copy the code

Simulation waveform:

Since the simulation file is consistent with the above circular left shift, just change the example, there is no need to give here, directly give the simulation waveform:

Loop right shift register to simulate waveform

Monitoring records

 i_rst = 1, i_load = 0, din = 0000, dout = xxxx
 i_rst = 1, i_load = 0, din = 0000, dout = 0000
 i_rst = 0, i_load = 0, din = 0000, dout = 0000
 i_rst = 0, i_load = 1, din = 1011, dout = 0000
 i_rst = 0, i_load = 1, din = 1011, dout = 1011
 i_rst = 0, i_load = 0, din = 1011, dout = 1011
 i_rst = 0, i_load = 0, din = 1011, dout = 1101
 i_rst = 0, i_load = 0, din = 1011, dout = 1110
 i_rst = 0, i_load = 0, din = 1011, dout = 0111
 i_rst = 0, i_load = 0, din = 1011, dout = 1011
 i_rst = 0, i_load = 0, din = 1011, dout = 1101
 i_rst = 0, i_load = 1, din = 0101, dout = 1101
 i_rst = 0, i_load = 1, din = 0101, dout = 0101
 i_rst = 0, i_load = 0, din = 0101, dout = 0101
 i_rst = 0, i_load = 0, din = 0101, dout = 1010
 i_rst = 0, i_load = 0, din = 0101, dout = 0101
 i_rst = 0, i_load = 0, din = 0101, dout = 1010
 i_rst = 0, i_load = 0, din = 0101, dout = 0101
Copy the code

Acyclic right shift register

As opposed to cyclic right shift register, only need to change to: highest bit fill zero. That is, shift the statement:


dout_mid <= {dout_mid[0],dout_mid[MSB - 1 : 1]};
Copy the code

To:

dout_mid <= {1'b0,dout_mid[MSB - 1 : 1]};
Copy the code

Simulation waveform is:

Acyclic right shift register

Monitoring records

 i_rst = 1, i_load = 0, din = 0000, dout = xxxx
 i_rst = 1, i_load = 0, din = 0000, dout = 0000
 i_rst = 0, i_load = 0, din = 0000, dout = 0000
 i_rst = 0, i_load = 1, din = 1011, dout = 0000
 i_rst = 0, i_load = 1, din = 1011, dout = 1011
 i_rst = 0, i_load = 0, din = 1011, dout = 1011
 i_rst = 0, i_load = 0, din = 1011, dout = 0101
 i_rst = 0, i_load = 0, din = 1011, dout = 0010
 i_rst = 0, i_load = 0, din = 1011, dout = 0001
 i_rst = 0, i_load = 0, din = 1011, dout = 0000
 i_rst = 0, i_load = 1, din = 0101, dout = 0000
 i_rst = 0, i_load = 1, din = 0101, dout = 0101
 i_rst = 0, i_load = 0, din = 0101, dout = 0101
 i_rst = 0, i_load = 0, din = 0101, dout = 0010
 i_rst = 0, i_load = 0, din = 0101, dout = 0001
 i_rst = 0, i_load = 0, din = 0101, dout = 0000
Copy the code

Serial input parallel output shift register

3 bit serial output parallel output shift register schematic

The shift register design has five inputs and an N-bit output, and the design is parameterized with the parameter MSB to indicate the width of the shift register. If MSB is 4, it becomes a 4-bit shift register. If MSB is 8, it becomes an 8-bit shift register. The shift register has some key functions.

  • This can be enabled or disabled by driving the designed EN signal
  • Dir can be moved left and right when driving
  • If you pull the RSTN to low, the shift register is reset and the output is 0
  • The input data value of the shift register can be controlled by the D pin

Therefore, there is no need to write left shift and right shift separately here, in one design, controlled by a signal dir, dir is 0, move left, otherwise, move right!

Design code


`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Reborn Lee
// Module Name: shift_register
// https://blog.csdn.net/reborn_lee //////////////////////////////////////////////////////////////////////////////////   module shift_register#(parameter MSB = 8) ( input i_clk,  input i_rst,  input i_dir,  input i_en,  input din,  output reg [MSB - 1 : 0] dout   );   always@ (posedge i_clk) begin  if (i_rst) begin  // reset  dout <= 'd0;  end  else if (i_en) begin  case(i_dir)  0: begin //left shift  dout <= {dout[MSB - 2: 0], din};  end  1: begin  dout <= {din, dout[MSB - 1 : 1]};  end  endcase   end  else begin  dout <= dout;  end  end  endmodule  Copy the code

The simulation code

`timescale 1ns/1ps
module shift_register_tb;
 parameter MSB = 8;

    reg i_clk;
 reg i_rst;  reg i_dir;  reg i_en;  reg din;  wire [MSB - 1 : 0] dout;   initial begin  i_clk = 0;  forever begin  # 5 i_clk = ~i_clk;  end  end   initial begin  i_rst = 1;  i_en = 0;  i_dir = 0;  din = 0;   # 18 @ (negedge i_clk) begin  i_rst = 0;  i_en = 1;  end   repeat(8) begin @ (negedge i_clk) begin  din = $random;  end  end  @ (negedge i_clk) begin  i_rst = 1;   end   #18  i_rst = 0;  i_dir = 1;   repeat(8) begin @ (negedge i_clk) begin  din = $random;  end  end  # 20 $finish;    end     shift_register #(.MSB(MSB))inst_shift_register (  .i_clk(i_clk),  .i_rst(i_rst),  .i_dir(i_dir),  .i_en(i_en),  .din(din),  .dout(dout)   );      endmodule Copy the code

The simulation waveform

Shift to the left
Moves to the right

Parallel input serial output shift register

The schematic diagram of parallel input serial output is as follows:

Schematic diagram of 3 – bit parallel input serial output shift register

The circuit consists of three D triggers in series. This means that the output of one D-trigger is connected to the input of the next d-trigger. All of these triggers synchronize with each other because the same clock signal is applied to each trigger.

In this shift register, we can apply parallel input to each D trigger by setting Preset Enable to 1. For each forward edge trigger of the clock signal, data is transferred from one level to the next. Therefore, we will get serial output from the right-most D trigger.

At the same time, we still set a control direction of the enable signal i_DIR, if i_DIR is 0, the parallel output moved to the left, take the highest bit as the serial output; Otherwise, move right and take the lowest order as serial output.

Circuit design


//paralell input and serial output shift register
module shift_register#(parameter MSB = 4) ( input i_clk,
 input i_load,
 input i_dir,  input [MSB - 1 : 0] din,  output dout  );   reg [MSB - 1 : 0] q_mid = 0;  always@ (posedge i_clk) begin  if(i_load) begin  q_mid <= din;  end  else begin  case(i_dir)  1'b0: begin  q_mid <= {q_mid[MSB - 2 : 0].1'b0}; //no cycle  end  1'b1: begin  q_mid <= {1'b0, q_mid[MSB - 1 : 1]}; //no cycle  end   endcase   end  end   assign dout = i_dir ? (q_mid[0]) : (q_mid[MSB - 1]);   endmodule  Copy the code

The simulation file

`timescale 1ns/1ps
module shift_register_tb;
 parameter MSB = 4;

    reg i_clk;
 reg i_dir;  reg i_load;  reg [MSB - 1 : 0] din;  wire dout;   initial begin  i_clk = 0;  forever begin  # 5 i_clk = ~i_clk;  end  end   initial begin  i_load = 0;  i_dir = 0;  din = $random;   # 18 @ (negedge i_clk) begin  i_load = 1;  end  @ (negedge i_clk) i_load = 0;    repeat(3) @ (negedge i_clk); //finish shift output     din = $random;  i_load = 1;  @ (negedge i_clk) i_load = 0;  i_dir = 1;   repeat(3) begin @ (negedge i_clk);  end  # 20 $finish;    end  // Monitor values of these variables and print them into the logfile for debug  initial  $monitor ("i_load=%0b, i_dir=%0b, din=%b, dout = %0b", i_load, i_dir, din, dout);   shift_register #(.MSB(MSB))inst_shift_register(  .i_clk(i_clk),  .i_dir(i_dir),  .i_load(i_load),  .din(din),  .dout(dout)   );      endmodule Copy the code
4bit parallel input serial output shift register

Monitoring data

i_load=0, i_dir=0, din=0100,   dout = 0
i_load=1, i_dir=0, din=0100,   dout = 0
i_load=0, i_dir=0, din=0100,   dout = 0
i_load=0, i_dir=0, din=0100,   dout = 1
i_load=0, i_dir=0, din=0100,   dout = 0
i_load=1, i_dir=0, din=0001,   dout = 0
i_load=0, i_dir=1, din=0001,   dout = 1
i_load=0, i_dir=1, din=0001,   dout = 0
Copy the code

The resources

  • Reference 1
  • Resources 2
  • Resources 3

Hand over a friend

  • Personal wechat public account: FPGA LAB, QR code at the lower left corner;

  • Zhihu: Li Ruiboen, qr code in the lower right corner.

  • FPGA/IC technology communication 2020