본문 바로가기

RTL Design/Verilog RTL 설계

Verilog RTL 설계(7월 15일 - 3, SISO Register, SIPO Register)

1. 4bit SISO Register에서 4번째 F/F부터 데이터 값, d를 Store 하는 SISO Shift Register

  • 4bit SISO Regster에서 마지막 Flip Flop부터 Store하게 된다.
  • 4bit SISO Register의 첫 번째 Flip Flop에서 Shift되어 데이터 출력되어 나온다.

출력 예시

 

 

< Source >

module Reversed_SISO_Shift_Register_by_using_parameter_n #(parameter N = 8)(
    input clk, enable, reset_p,
    input d,
    output q );
    
    reg [N-1 : 0] siso_reg;
    
    always @(negedge clk or posedge reset_p) begin
        if(reset_p)  siso_reg = 0;
        else if(enable) siso_reg = {siso_reg[N-2 : 0], d};
    end
    
    assign q = siso_reg[N-1];
    
endmodule

 

  • SISO Register의 데이터 siso_reg 내에서 siso_reg [N-1]을 shift 시켜 내보내고, siso_reg [0]자리에 새로운 데이터를 저장한다.
  • siso_reg [N-2 : 0] 와 새로운 데이터, d와 결합 연산자를 통해 결합한 뒤, 레지스터에 저장한다.
  • siso_reg [N-1] : MSB, siso_reg [0] : LSB  

 

< Test Bench >

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/07/16 07:59:52
// Design Name: 
// Module Name: tb_Reversed_SISO_Shift_Register_by_using_parameter_n
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module tb_Reversed_SISO_Shift_Register_by_using_parameter_n();
    // Set type of input/Ouput variables.
    reg clk, enable, reset_p;
    reg d;
    wire q;
    
    // Data
    parameter data = 4'b1101;
    
    // Create instance.
    Reversed_SISO_Shift_Register_by_using_parameter_n #(.N(4)) DUT(
    clk, enable, reset_p, d, q );
    
    // Initialization of simulation.
    initial begin 
        clk = 0; enable = 1; reset_p = 1; d = 0;
    end
    
    // Set Clock Pulse.
    always #5 clk = ~clk;
    
    // Variable.
    integer  i;
    
    // Processing of simulation.
    initial begin 
        #10;
        
        // Disable reset_p
        reset_p = 0;
        
        // Save data in register
        for(i = 3; i>=0; i = i-1) begin
            d = data[i]; #10;
       end
        
        // End of Simulation
       $finish;
    end

endmodule

 

< Simulation >

 

 

 

 

 

 

 

2. SIPO Shift Register (Series Input Parallel Output)

  • 직렬 형태로 데이터를 입력 받은 뒤, 레지스터에 저장된 데이터들을 병렬 형태로 내보내는 레지스터
  • SPIO Shift Register는 다음과 같은 블록도를 갖는다.

4bit SIPO Shift Register

 

  • ★★★★★★
    Q) SPIO Register의 하단에 3항 buffer의 역활은 무엇인가?
    A)
    아래 그림은 8bit register 4개를 병렬로 연결한 회로를 표현한 것이다.

8bit register 4개를 병렬 연결

 

  • 8bit register 4개는 공통의 data bus를 이용하고 있는 상태이다.
  • Q) 8bit register는 4개인데, 공통의 data bus는 1개이고, 어떻게 공유하고, 어떻게 제어할 수 있는가?
    A) 각각 8bit register들은 1개의 삼항 연산자를 가진다. 삼항 연산자를 사용하지 않을 경우, 공통의 data bus에서 데이터들이 겹치는 상황이 발생할 수 있기 때문에 이를 방지하고자 삼항 연산자를 통해 특정 8bit register만 data bus를 이용하고, 나머지 register들은 연결을 끊어줌으로서 제어하게 된다.

    하지만, 한 번에 공통의 data bus는 단 하나의 8bit register만 연결하여 데이터를 전송 및 받을 수 있다.

 

 

 

2.1. 4bit SIPO Shift Register (Negative edge),  삼항 버퍼를 고려 X

 

< Source >

module SIPO_Shift_Register_4bit_n(
    input clk, enable, reset_p,
    input d,
    output [3:0] q );
    
    reg [3:0] sipo_reg; 
    
    always @(negedge clk or posedge reset_p) begin
        if(reset_p) sipo_reg <= 0;
        else if(enable) sipo_reg <= {d, sipo_reg[3:1]};
    end
    
    assign q = sipo_reg;
    
endmodule

 

  • Parall Output는 Common data bus를 사용하기 때문에 여러 개의 register들이 하나의 data bus를 사용하는 과정에서 교차하는 문제점을 해결하고자 삼항 버퍼를 사용해야한다.
  • 위 소스 코드는 삼항 버퍼를 제외한 1개의 8bit SIPO shift register를 사용한다는 가정에서 만든 것이다.
  • 하나의 8bit SIPO shift register를 사용하기 때문에 삼항 버퍼가 필요 없다.

 

< Test bench >

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/07/16 08:41:41
// Design Name: 
// Module Name: tb_4bit_SIPO_Shift_Register_n
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module tb_4bit_SIPO_Shift_Register_n( );
    // set type of input / output.
    reg clk, enable, reset_p, d;
    wire q;
    
    // data 
    parameter data = 4'b0101;
    
    // create instance.
    SIPO_Shift_Register_4bit_n DUT( clk, enable, reset_p, d,  q);
    
    // initialization of simulation.
    initial begin
        clk = 0; enable = 1; reset_p = 1; d = 0;
    end
    
    // set clock pulse
    always #5 clk = ~clk;
    
    // Variable
    integer i;
    
    // Processing of simulation.
    initial begin
        #10;
        
        // disable reset_p
        reset_p = 0;
        
        // save data.
        for(i = 0; i<4; i = i+1) begin
            d = data[i]; #10;
       end

        // delay time : 40ns
        #40;
        
        // end of finish
        $finish;
        
    end
    
endmodule

 

 

< Simulation >

 

 

 

 

 

 

 

2.2. 4bit SIPO Shift Register (Negative edge),  삼항 버퍼를 고려 O

 

< Source >

module SIPO_Shift_Register_4bit_n_Buffer (
    input clk, enable, reset_p,
    input d, 
    input read_enable_p,
    output [3:0] q );
    
    reg [3:0] spio_reg;
    
    always @(negedge clk or posedge reset_p) begin
        if(reset_p) spio_reg <= 0;
        else if(enable) spio_reg <= {d, spio_reg[3:1]};
    end
    
    assign q = (read_enable_p)? spio_reg : 4'bz;
    
endmodule
  • 8bit SIPO Shift Register들이 여러 개 존재하다는 가정을 두고, 하나의 공통의 data bus를 사용하기 때문에 데이터가 겹치는 문제점을 해결하고자 삼항 버퍼를 이용한다.
  • read_enable_p 값이 1일 때, 레지스터에 저장된 데이터, spio_reg 값을 읽을 수 있고, 
    read_enable_p 값이 0이면 임피던스 상태 값을 출력으로 내보낸다.

 

< Test bench >

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/07/16 08:41:41
// Design Name: 
// Module Name: tb_4bit_SIPO_Shift_Register_n
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module tb_4bit_SIPO_Shift_Register_n_Buffer( );
    // set type of input / output.
    reg clk, enable, reset_p, d, read_enable_p;
    wire [3:0] q;
    
    // data 
    parameter data = 4'b0101;
    
    // create instance.
    SIPO_Shift_Register_4bit_n_Buffer DUT(clk, enable, reset_p, d, read_enable_p, q);
    
    // initialization of simulation.
    initial begin
        clk = 0; enable = 1; reset_p = 1; d = 0; read_enable_p = 0;
    end
    
    // set clock pulse
    always #5 clk = ~clk;
    
    // Variable
    integer i;
    
    // Processing of simulation.
    initial begin
        #10;
        
        // disable reset_p
        reset_p = 0;
        
        // save data.
        for(i = 0; i<4; i = i+1) begin
            #10; d = data[i];
       end

        // Read data.
        read_enable_p = 1;
        #5;
        
        // end of finish
        $finish;
        
    end
    
endmodule
  • 입력값을 받는 동안에는 read_enable_p = 0이기 때문에 출력값은 임피던스 상태로 출력된다.
  • 입력값을 다 받고 난 뒤에는 read_enable_p = 1로 변환하여 5ns 동안 저장된 레지스터 값을 출력으로 내보낸다.

 

< Simulation >

 

 

 

 

 

 

2.3. N bit SIPO Shift Register (Negative edge),  삼항 버퍼를 고려 O

 

< Source >

module SIPO_Shift_Register_N_bit_n_buffer_parameter #(parameter N = 8)(
    input clk, enable, reset_p,
    input input_data,
    input read_enable_p,
    output [N-1 : 0] output_data  );
    
    reg [N-1 : 0] sipo_reg;
    
    always @(negedge clk or posedge reset_p) begin
        if(reset_p) sipo_reg = 0;
        else if(enable)  sipo_reg = {input_data, sipo_reg[N-1:1]};
    end
    
    // Read enable 값이 1일 때, 레지스터에 저장된 데이터를 읽을 수 있다. 
    // Read enable 값이 0일 때, 임피던스 상태값을 내보낸다.
    assign output_data = (read_enable_p)? sipo_reg : 1'bz;
    
endmodule

 

 

< Test bench >

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/07/16 10:45:40
// Design Name: 
// Module Name: tb_SIPO_Shift_Register_Nbit_n
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

module tb_SIPO_Shift_Register_Nbit_n_parameter_buffer(  );
    // Set type of input / output 
    reg clk, enable, reset_p;
    reg input_data;
    reg read_enable_p;
    wire [6:0] output_data;
    
    // data
    parameter data = 7'b1110101;
    
    // Create instance
    SIPO_Shift_Register_N_bit_n_buffer_parameter #(.N(7)) DUT(
    clk, enable, reset_p, input_data,  read_enable_p, output_data  );
    
    // Initialization of simualtion.
    initial begin 
        clk = 0; enable = 1; reset_p = 1;
        input_data = 0; read_enable_p = 0;
   end
   
   // set clock pulse
   always #5 clk = ~clk;
   
   // varaible
   integer i;
   
   // processing of simulation.
   initial begin
        #10;
    
     // disable reset_p
     reset_p = 0;
   
    // write data
     for(i = 0; i<7; i = i+1) begin
           #10; input_data = data[i];
     end
    
        // enable read_enable_p
        read_enable_p = 1; #10;
    
        // disable read_enable_p
        read_enable_p = 0; #10;
        
        // End of simulation.
        $finish;
    end
    
endmodule

 

 

< Simulation >

  • SIPO Shift Register에 입력 데이터 1110101을 다 넣기 전까지는 read_enable_p = 0 값을 가져 disable 상태이다.
  • 입력 데이터 1110101을 다 넣은 뒤에 read_enable_p = 1로 변화시켜 레지스터에 저장된 데이터 값을 10ns 동안 출력시켜 확인한다.