UVM & RTL/Verilog HDL

[25] Verilog HDL 순차회로 설계과제 (LATCH, FILP FLOP)

Return 2022. 3. 5. 19:00

★ Negative level-sensitive 방식으로 동작하는 8비트 D래치회로를 설계하고, 테스트벤치를 작성하여 기능을 검증한다.

module dlatch8(clk,d,q);
    input clk;
    input [7:0] d;
    output reg [7:0] q;

    always@(*)begin
        if(!clk) q=d;
    end

endmodule

▣ TESTBENCH

// 설계과제 11.1 testbench 
module tb_dlatch8;
    reg clk;
    reg [7:0] d;
    wire [7:0] q;

    dlatch8 uo(clk,d,q);

    initial begin
        clk = 1'b0;
        d = 1'b0;
    end

    always begin 
        #15 d= 1'b1; #20 d=1'b0;
        #10 d = 1'b1; #10 d= 1'b0;
    end

    always
        #10 clk = ~clk;
endmodule

★ active-low 셋과 리셋을 갖는 negative level-sensitive 8bit D래치를 설계하고, 테스트벤치를 작성하여 기능을 검증한다. 

// 설계과제 11.2 
module d1latch8_set(clk,rst,d,q);
    input clk, rst;
    input [7:0] d;
    output reg [7:0] q;

    always@(*)begin 
        if(!rst) q=8'b0;
        else if(!clk) q= d;
    end
endmodule

▣ TESTBENCH

// 설계과제 11.2 testbench 
module tb_dlatch8;
    reg clk,rst;
    reg [7:0] d;
    wire [7:0] q;

    d1latch8_set u0(clk,rst,d,q);

    initial begin
        clk = 1'b0;
        rst = 1'b1;
        d = 1'b0;
        #20 rst = 1'b0;
        #20 rst = 1'b1;
    end

    always begin 
        #15 d= 1'b1; #20 d=1'b0;
        #10 d = 1'b1; #10 d= 1'b0;
    end

    always
        #10 clk = ~clk;
endmodule

★ 다음 코드에서 blocking할당문의 순서를 바꾼경우이다. 바꾸기 전 회로와 동일한 회로인지, 만약 다른 회로라면 어떤 회로가 되는지 시뮬레이션과 합성을 통해 확인하고, 그 이유를 생각해본다.

▣ TESTBENCH

module tb_latch_blk2;
    reg en,a,b,c;
    wire y;
    
    latch_blk2 u0(en,a,b,c,y);
    
    always
        #10 clk = ~clk;
    
    initial begin
        clk = 1'b0;
        en = 1;
        a = 0;
        b = 0;
        c = 1;
    end
endmodule

위의 시뮬레이션 결과를 보면 80ns까지 X(unkonown) 값이 y로 출력되는데 이는 blocking의 특성을 잘 내타내는 시뮬레이션 입니다. DUT를 살펴보면 m값이 도출 되기전, y값에 m값이 필요합니다. (순서가 중요한 blocking) 즉, 출력 y를 나타내기 위해 m값이 필요한데 m값을 모르는 상태이니 출력 y값이 X(unkonwn)으로 출력되는 것 입니다. 

★ 다음 코드는 nonblocking할당문의 순서를 바꾼 경우이다. 바꾸기 전 회로와 동일한 회로인지, 만약 다른 회로라면 어떤 회로가 되는지 시뮬레이션과 합성을 통해 확인하고, 그 이유를 생각해본다. 

▣ TESTBENCH

module tb_latch_blk2;
    reg en,a,b,c;
    wire y;
    
    latch_blk2 u0(en,a,b,c,y);
    
    always
        #80 en = ~en;
    
    initial begin
        en = 1;
        a = 0;
        b = 0;
        c = 1;
        
        #160 a = 1; b = 1; c =0;
    end
endmodule

nonblocking 구문이 쓰인 두문장의 순서를 바꿔도 동일한 시뮬레이션 결과를 도출합니다. 위의 두 예제를 통해서 우리는 blocking할당문 nonblocking할당문의 차이를 알 수 있습니다. 

 

★ q와 q_bar출력을 갖는 D플립플롭은 다음과 같이 모델링하면, 단순 D플립플롭이 아닌 다른 회로가 된다. 시뮬레이션과 합성을 통해 코드의 모델링이 어떤 회로로 동작하는지 확인하고, 그 이유를 생각해 본다. 

정상적인 D FF
비정상적인 D FF

q_bar에 nonblocking 할당문 ~q를 사용했다. 여기서 발생하는 문제점은 첫번째 nonblocking할당문에서 q에 d가 들어가기전 q의 값이 두번째 nonblocking할당문으로 들어가야하는데 이값은 아직 정해지지 않은 값이다. 그래서 q_bar가 q에 비해 더 긴 X(unkowun)값을 지늬고 있다. 또한 계속해서 그 이전의 q값이 q_bar에 들어가기때문에 q_bar가 q에 늦게 들어가는 형태의 시뮬레이션을 보이고 있다. 

★ 일반적인 clock의 생성과 clock gating의 생성을 모델링하고, 시뮬레이션을 통해 동작을 확인한다. 

module clk_gating(clk_i,clk_en,clk_o);
    input clk_i, clk_en;
    output clk_o;

    assign clk_o = clk_i & clk_en;

endmodule

▣ TESTBENCH

module tb_clk_gating;
    reg clk_i, clk_en;
    wire clk_o;

    clk_gating u0(clk_i,clk_en,clk_o);
    
    always
        #10 clk_i = ~clk_i;
    
    initial begin 
        clk_i = 0;
        clk_en = 1; 
        #100 clk_en = 0;
        #100 clk_en = 1;
        $finish;
    end
endmodule

★ 다음의 D플립플롭을 Verilog HDL로 모델링하고, 시뮬레이션을 통해 동작을 확인한다. 

① 동기식 active-high 리셋을 갖는 D 플립플롭

module dff_test1(
    input clk,
    input rst,
    input d,
    output reg q
);

    always@(posedge clk)begin
        if(rst) q <= 1'b0;
        else q <= d;
    end
endmodule

동기식 active-high reset을 갖는 D FF

② 동기식 active-high 셋을 갖는 D 플립플롭 

module dff_test2(
    input clk,
    input st,
    input d,
    output reg q
);

    always@(posedge clk)begin
        if(st) q <= 1'b1;
        else q <= d;
    end
endmodule

동기식 active-high set을 갖는 D FF

③ 동기식 active-low 셋과 리셋을 갖는 D플립플롭

module dff_test3(
    input clk,
    input rst,
    input st,
    input d,
    output reg q
);

    always@(posedge clk)begin
        if(!rst) q <= 1'b0;
        else if(!st) q<= 1'b1;
        else q <= d;
    end
endmodule

동기식 active-low set/reset을 갖는 D FF&nbsp;

④ 비동기식 active-high 리셋을 갖는 D플립플롭

module dff_test4(
    input clk,
    input rst,
    input d,
    output reg q
);

    always@(posedge clk or posedge rst)begin
        if(rst) q <= 1'b0;
        else q <= d;
    end
endmodule

비동기식 active-high reset을 갖는 D FF

⑤ 비동기식 active-high 셋을 갖는 D플립플롭

module dff_test5(
    input clk,
    input st,
    input d,
    output reg q
);

    always@(posedge clk or posedge st)begin
        if(st) q <= 1'b1;
        else q <= d;
    end
endmodule

비동기식 active-high set을 갖는 D FF

⑥ 비동기식 active-low 셋과 리셋을 갖는 D플립플롭 

module dff_test6(
    input clk,
    input rst,
    input st,
    input d,
    output reg q
);

    always@(posedge clk or posedge rst or posedge st)begin
        if(!rst) q <= 1'b0;
        else if(!st) q<= 1'b1;
        else q <= d;
    end
endmodule

비동기식 active-low set/reset을 갖는 D FF

★ 다음의 D플립플롭을 모델링하고 시뮬레이션을 통해 동작을 확인한다. 

module d_ff_test(
    input clk,
    input sync_reset,
    input async_reset,
    input async_reset_n,
    input i_value,

    output reg o_value_sync_reset,
    output reg o_value_async_reset,
    output reg o_value_async_reset_n,
    output reg o_value_mixed_reset,
    output reg o_vlaue_no_rest 
);

    // 1. sync reset 
    always@(posedge clk)begin 
        if(sync_reset) begin 
            o_value_async_reset <= 1'b0;
        end
        else begin
            o_value_async_reset <= i_value;
        end
    end

    // 2. async_reset 
    always@(posedge clk or posedge async_reset)begin
        if(async_reset) o_value_async_reset <= 1'b0;
        else o_value_async_reset <= i_value;
    end

    // 3. async_reset_n
    always@(posedge clk or negedge async_reset_n)begin 
        if(!async_reset_n) o_value_async_reset_n <= 1'b0;
        else o_value_async_reset_n <= i_value;
    end

    // 4. mixed
    always@(posedge clk or posedge async_reset or posedge sync_reset)begin 
        if(async_reset) o_value_mixed_reset <= 1'b0;
        else if(sync_reset) o_value_mixed_reset <= 1'b0;
        else o_value_mixed_reset <= i_value;
    end

    // 5. no reset 
    always@(posedge clk)begin 
        o_vlaue_no_rest <= i_value;
    end

endmodule

▣ TESTBENCH

module tb_d_ff_test;
    reg clk;
    reg clk_enable;
    reg sync_reset;
    reg async_reset;
    reg async_reset_n;
    reg i_value;

    wire o_value_sync_reset;
    wire o_value_async_reset;
    wire o_value_async_reset_n;
    wire o_value_mixed_reset;
    wire o_vlaue_no_rest;

    always begin 
        #10 clk = ~clk;
    end

    initial begin
        clk = 0;
        clk_enable = 0;
        sync_reset = 0;
        async_reset = 0;
        async_reset_n = 1;
        i_value = 1;

        #50 
        sync_reset = 1;
        async_reset = 1;
        async_reset_n = 0;

        #20
        sync_reset = 1;
        async_reset = 1;
        async_reset_n = 0;

        #20 
        clk_enable = 1;

        #20
        sync_reset = 1;

        #20 
        sync_reset = 0;
    end

    wire clk_dut = clk && clk_enable;

    d_ff_test u0(clk_dut,sync_reset,async_reset,async_reset_n,i_value,o_value_sync_reset,o_value_async_reset,o_value_async_reset_n,o_value_mixed_reset,o_vlaue_no_rest);

endmodule