7/15 레지스터

정유석·2024년 7월 15일

교육 - 베릴로그

목록 보기
8/28

복습
조합회로+플립플롭=카운터
조합회로와 플립플롭의 조합은 일반적으로 순차 회로의 기본 구조를 형성하며, 카운터는 이러한 순차 회로의 대표적인 예이다

module up_downcounter_p(
    input clk, reset_p,
    input up_down,
    output reg [3:0] count);
    
    always @(posedge clk or posedge reset_p)begin
        if(reset_p)count = 0;
        else begin
            if(up_down)begin
                count = count + 1;
            end
            else begin
                count = count -1;
            end
        end
    end
endmodule

(alway문 안에있는것이 복합적이지만 약간의 조합회로 역할, reg로 선언된 count가 플립플롭 역할)



덧셈기, pdt의 영향으로(캐리가 반영되기전) 결과전에 잠시 잘못된 값이 나옴

pdt시간보다 크게 클럭을 설정하면 클럭안에 동작이 완료되고 다음 클럭때 반영
RTL:register transfer level




상승엣지 사용 : cur, old (1,0)
하강엣지 사용 : cur, old (0,1)

상승 엣지 감지: (cur, old) = (1, 0)
cur = 1: 현재 클럭 상태가 높음
old = 0: 이전 클럭 상태가 낮았음
이 조합은 클럭이 낮은 상태에서 높은 상태로 변화했음을 나타낸다. 즉, 상승 엣지이다.
하강 엣지 감지: (cur, old) = (0, 1)
cur = 0: 현재 클럭 상태가 낮음
old = 1: 이전 클럭 상태가 높았음
이 조합은 클럭이 높은 상태에서 낮은 상태로 변화했음을 나타낸다. 즉, 하강 엣지이다.

edge_detector

edge_detector_p

module edge_detector_p(
    input clk, reset_p,
    input cp,
    output p_edge, n_edge);
    
    reg ff_cur, ff_old;
    always @(posedge clk or posedge reset_p)begin
        if(reset_p)begin
            ff_cur<=0;
            ff_old<=0;
        end
        else begin
            
            ff_cur <= cp;
            ff_old <= ff_cur;
        end
    end
    
    assign p_edge = ({ff_cur, ff_old} == 2'b10) ? 1 : 0;
    assign n_edge = ({ff_cur, ff_old} == 2'b01) ? 1 : 0;
endmodule

edge_detector_n

module edge_detector_n(
    input clk, reset_p,
    input cp,
    output p_edge, n_edge);
    
    reg ff_cur, ff_old;
    always @(negedge clk or posedge reset_p)begin
        if(reset_p)begin
            ff_cur<=0;
            ff_old<=0;
        end
        else begin
            
            ff_cur <= cp;
            ff_old <= ff_cur;
        end
    end
    
    assign p_edge = ({ff_cur, ff_old} == 2'b10) ? 1 : 0;
    assign n_edge = ({ff_cur, ff_old} == 2'b01) ? 1 : 0;
endmodule

edge_detector_n 결과

레지스터

D플립플롭으로 레지스터 메모리 만들기
병렬입력 병렬출력

module register_8bit_n(
    input [7:0] d,
    input clk, reset_p, enable,
    output reg [7:0] q);
    
    always @(negedge clk or posedge reset_p)begin
        if(reset_p) q = 0;
        else if(enable) q = d;
    end
endmodule


D플립플롭 겹쳐놓음

레지스터 분류

직입직출 : 입출력선이 1개씩, 비트를 쉬프트해서 1비트씩 보낼 수 있다

직입직출

블럭킹, 넌블럭킹 주의
always문 안에는 블럭킹, 넌블럭킹 통일하는것이 좋다

module shift_register_SISO_n(
    input clk, reset_p,
    input d,
    output q);
    
    reg [3:0] siso_reg;
    always @(negedge clk or posedge reset_p)begin
        if(reset_p)siso_reg<=0;
        else begin
            siso_reg[3]<=d;
            siso_reg[2]<=siso_reg[3];
            siso_reg[1]<=siso_reg[2];
            siso_reg[0]<=siso_reg[1];
        end
    end
    assign q=siso_reg[0];
endmodule

쉬프트하는걸 결합연산자 사용으로 구현

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

파라미터를 이용한 N비트 쉬프트 레지스터
우쉬프트 레지스터 (최하위비트부터 출력)

module shift_register_SISO_Nbit_n #(parameter N=8)(
    input clk, 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 begin
            siso_reg<={d, siso_reg[N-1:1]};
//            siso_reg[3]<=d;
//            siso_reg[2]<=siso_reg[3];
//            siso_reg[1]<=siso_reg[2];
//            siso_reg[0]<=siso_reg[1];
        end
    end
    assign q=siso_reg[0];
endmodule

시뮬레이션에서 d값에 1010을 준다면 1주고 10ns 실행 0주고 10ns실행 1주고 10ns실행 0주고 10ns
테스트벤치 사용해서 코드로 실행

테스트 벤치 시작

이니셜값 시뮬레이션 최초값 설정
(대략적인 순서:테스트 벤치-인스턴스-입출력-이니셜 초기값-클락설정-이니셜 설정)
테스트벤치의 모듈 선언후 괄호안에 변수를 선언 하지 않는것은 외부와의 연결이 필요없는, 내부에서만 사용되는 변수들이기 때문이다(괄호안에 선언되는 변수들은 외부와의 통신을 위한 포트)
우쉬프트 테스트 벤치

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/07/15 11:24:03
// Design Name: 
// Module Name: tb_shift_register_SISO_Nbit_n
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module tb_shift_register_SISO_Nbit_n();

    reg clk, reset_p;	//input값 reg로 선언
    reg d;
    wire q;
    
    parameter data = 4'b1010;	//입력해줄 값
    
    shift_register_SISO_Nbit_n #(.N(4)) DUT(    //DUT=design under test
        .clk(clk), .reset_p(reset_p),
        .d(d),
        .q(q));
    
    initial begin 	//초기 설정
        clk=0;
        reset_p=1;
        d=data[0];
    end
    
    always #5 clk = ~clk; //#=time delay, 5ns, edit 1th code, 5ns=0 -> 5ns=1 =>10ns clk
    	//#은 시간지연, #뒤에 지연할 시간, 코드첫번째줄 설정된 시간 단위, 5ns마다 클락 변경 전체 10ns 주기
    integer i;	//for문에 쓸 i선언
    initial begin
        #10;
        reset_p = 0;
        for(i=0;i<4;i=i+1)begin
            d=data[i]; #10;
        end
//        d = data[0]; #10;
//        d = data[1]; #10;
//        d = data[2]; #10;
//        d = data[3]; #10;
//        #40;
        $finish;	//시뮬레이션 종료
    end 
    
endmodule

직입직출 N비트 우쉬프트 테스트벤치

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/07/15 11:24:03
// Design Name: 
// Module Name: tb_shift_register_SISO_Nbit_n
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module tb_shift_register_SISO_Nbit_n();

    reg clk, reset_p;
    reg d;
    wire q;
    
    parameter data = 8'b11010011;
    
    shift_register_SISO_Nbit_n #(.N(8)) DUT(    //DUT=design under test
        .clk(clk), .reset_p(reset_p),
        .d(d),
        .q(q));
    
    initial begin 
        clk=0;
        reset_p=1;
        d=data[0];
    end
    
    always #5 clk = ~clk; //#=time delay, 5ns, edit 1th code, 5ns=0 -> 5ns=1 =>10ns clk
    integer i;
    initial begin
        #10;
        reset_p = 0;
        for(i=0;i<8;i=i+1)begin
            d=data[i]; #10;
        end
//        d = data[0]; #10;
//        d = data[1]; #10;
//        d = data[2]; #10;
//        d = data[3]; #10;
        #70;
        $finish;
    end 
    
endmodule

직입직출 N비트 우쉬프트 레지스터 결과

좌쉬프트 (최상위 비트부터 출력)

module shift_register_SISO_Nbit_msb_n #(parameter N=8)(
    input clk, 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 begin
            siso_reg<={siso_reg[N-2:0], d};	//좌쉬프트 오버플로우로 최상위비트 버림
//            siso_reg[3]<=d;
//            siso_reg[2]<=siso_reg[3];
//            siso_reg[1]<=siso_reg[2];
//            siso_reg[0]<=siso_reg[1];
        end
    end
    assign q=siso_reg[N-1];
endmodule

좌쉬프트 테스트벤치

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/07/15 14:08:46
// Design Name: 
// Module Name: tb_shift_register_siso_nbit_msb_n
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
module tb_shift_register_SISO_Nbit_msb_n();

    reg clk, reset_p;
    reg d;
    wire q;
    
    parameter data = 8'b11010011;
    
    shift_register_SISO_Nbit_msb_n #(.N(8)) DUT(    //DUT=design under test
        .clk(clk), .reset_p(reset_p),
        .d(d),
        .q(q));
    
    initial begin 
        clk=0;
        reset_p=1;
        d=data[7];
    end
    
    always #5 clk = ~clk; //#=time delay, 5ns, edit 1th code, 5ns=0 -> 5ns=1 =>10ns clk
    integer i;
    initial begin
        #10;
        reset_p = 0;
        for(i=7;i>0;i=i-1)begin
            d=data[i]; #10;
        end
//        d = data[0]; #10;
//        d = data[1]; #10;
//        d = data[2]; #10;
//        d = data[3]; #10;
        #80;
        $finish;
    end 
    
endmodule

직렬입력 병렬 출력




demux 이용, demux의 선택값이 주소값
8비트 레지스터 여러개를 8비트 데이터 버스에 연결(선이 너무 많아져서 데이터 버스에 연결), 3상 버퍼(3상 버퍼의 제어비트)를 이용하여 데이터 버스에 연결 또는 차단

module shift_register_SIPO_n(
    input clk, reset_p,
    input d,
    input rd_en, //read enable
    output [3:0] q);
    
    reg [3:0] sipo_reg;
    always @(negedge clk or posedge reset_p)begin
        if(reset_p)sipo_reg<=0;
        else begin
            sipo_reg<={d, sipo_reg[3:1]};
        end
    end
    
    assign q=rd_en ? 4'bz : sipo_reg;	//re_en이 1이면 차단(임피던스)
    //bufif0 {q[0], sipi_reg[0], rd_en);//3phase buffer
endmodule

N비트짜리 직입병출

module shift_register_SIPO_Nbit_n #(parameter N=8)(
    input clk, reset_p,
    input d,
    input rd_en, //read enable
    output [N-1:0] q);
    
    reg [N-1:0] sipo_reg;
    always @(negedge clk or posedge reset_p)begin
        if(reset_p)sipo_reg<=0;
        else begin
            sipo_reg<={d, sipo_reg[N-1:1]};
        end
    end
    
    assign q=rd_en ? 'bz : sipo_reg;	//임피던스는 몇비트든지간에 모두 임피던스로 채워짐 때문에 따로 써줄필요없음 (문법적으로도 N으로 두지 못함)
    //bufif0 {q[0], sipi_reg[0], rd_en);//3phase buffer
endmodule

N비트 직입병출 테스트벤치

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/07/15 15:26:39
// Design Name: 
// Module Name: tb_shift_register_SIPO_Nbit_n
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module tb_shift_register_SIPO_Nbit_n();
    
    reg clk, reset_p;
    reg d;
    reg rd_en;
    wire [7:0] q;

    parameter data = 8'b10100011;

    shift_register_SIPO_Nbit_n #(.N(8)) DUT(clk, reset_p, d, rd_en, q);

    initial begin
        clk = 0;
        reset_p = 1;
        d = 0;
        rd_en = 0;
    end
    
    always #5 clk = ~clk;
    
    integer i;
    initial begin
        #10;
        reset_p = 0; #10;
        for(i=0; i<8; i=i+1)begin
            d = data[i]; #10;
        end
        //#30;
        $finish;
    end
endmodule

결과

정해진 출력이 끝나고 30ns를 더 줬을때 마지막 입력인 1이 계속 쉬프트

rd_en 꺼놨다가 입력이 모두 들어오면 rd_en을 켜서 마지막에 출력

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/07/15 15:26:39
// Design Name: 
// Module Name: tb_shift_register_SIPO_Nbit_n
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module tb_shift_register_SIPO_Nbit_n();
    
    reg clk, reset_p;
    reg d;
    reg rd_en;
    wire [7:0] q;

    parameter data = 8'b10100011;

    shift_register_SIPO_Nbit_n #(.N(8)) DUT(clk, reset_p, d, rd_en, q);

    initial begin
        clk = 0;
        reset_p = 1;
        d = data[0];
        rd_en = 1;
    end
    
    always #5 clk = ~clk;
    
    integer i;
    initial begin
        #10;
        reset_p = 0; #10;
        for(i=1; i<8; i=i+1)begin
            #10; d = data[i];
        end
        rd_en=0; #1;
        $finish;
    end
endmodule

z:임피던스(연결이 끊어진 상태), x:unkown(출력이 2개연결되서 어떤게 출력될지 모르는 상태);레이싱상태

병입직출


mux를 통해 병렬입력을 받을지 쉬프트할지 결정
shift_load`(1,0)이면 쉬프트, shift_load`(0,1)이면 병렬입력

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

N비트 병입직출

module shift_register_PISO_Nbit_n #(parameter N=8)(
    input clk, reset_p,
    input [N-1:0] d,
    input shift_load,
    output q);
    
    reg [N-1:0] piso_reg;
    always @(negedge clk or posedge reset_p)begin
        if(reset_p)piso_reg<=0;
        else begin
            if(shift_load)begin
                piso_reg<={1'b0, piso_reg[N-1:1]};
            end
            else begin
                piso_reg = d;
            end
        end
    end
    assign q=piso_reg[0];
endmodule

8비트 병입직출 테스트벤치

module tb_shift_register_PISO_Nbit_n();
    reg clk, reset_p;
    reg [7:0] d;
    reg shift_load;
    wire q;
    
    parameter data = 8'b10100011;
    
    shift_register_PISO_Nbit_n #(.N(8)) DUT(clk, reset_p, d, shift_load, q); 

   initial begin
        clk = 0;
        reset_p = 1;
        d = 0;
        shift_load = 0;
    end

    always #5 clk = ~clk;
    
    initial begin
        #10;
        reset_p = 0;
        d=data;
        #10;
        shift_load = 1;
        #70;
        $finish;        
    end 
endmodule

profile
개인 기록공간

0개의 댓글