UVM & RTL/Verilog HDL

[33] Verilog HDL 순차회로 설계과제 ( FSM )

Return 2022. 3. 7. 01:16

★ 다음 그림의 상태 전이도를 갖는 Moore FSM회로를 설계하고, 시뮬레이션을 통해 동작을 확인한다. active-low 리셋에 의해 상태 ST0로 초기화되며, 출력은 0이된다. 상태 ST1에서 bypass입력이 들어오면 ST3로 전이되고, 그 이외의 경우에는 ST0 > ST1 > ST2 > ST3의 순서로 전이된다. 상태 ST0, ST1, ST2, ST3에서 각각 0,1,2,3의 값을 출력한다. 레지스터는 active-low 비동기식 리셋을 갖는다. 

module fsm_moore(clk,reset,bypass,out); 
    input clk, reset, bypass;
    output reg [2:0] out;
    reg [1:0] state, next;
    parameter ST0 = 2'b00, ST1 = 2'b01, ST2 = 2'b10, ST3 = 2'b11;

    // state register
    always@(posedge clk or negedge reset)begin 
        if(!reset) state <= ST0;
        else state <= next;
    end

    // next logic 
    always@(*)begin 
        next = 2'bxx;
        case(state)
            ST0 : next = ST1;
            ST1 : begin 
                    if(bypass) next = ST3;
                    else next = ST2;
                    end
            ST2 : next = ST3;
            ST3 : next = ST0;
        endcase
    end

    // output register 
    always@(posedge clk or negedge reset)begin
        if(!reset) begin 
            out <= 2'b0;
        end
        else begin 
            out <= 2'b0;
            case(state)
                ST0 : out <= 2'b00;
                ST1 : out <= 2'b01;
                ST2 : out <= 2'b10;
                ST3 : out <= 2'b11;
            endcase
        end
    end
endmodule

▣ TESTBENCH

module tb_fsm_moore;
    reg clk, reset, bypass;
    wire [2:0] out;

    fsm_moore uo(clk,reset,bypass,out);

    always 
        #10 clk = ~clk;
    
    initial begin 
        clk = 1'b0; reset = 1'b0; bypass = 1'b0;
        #30 reset = 1'b1;
        #80 bypass = 1'b1;
    end
endmodule

★ 다음 그림의 상태 전이도를 갖는 Mealy FSM회로를 설계하고 시뮬레이션을 통해 동작을 확인한다. 옆의 그림은 검출기의 동작에 대한 예를 보인 것이다. 비트단위로 입력되는 din_bit에서 비트패턴 '0110'이 검출되면 출력 detect_out은 1이 되고, 그렇지 않은 경우에는 0을 출력한다. 레지스터는 active-high 비동기식 리셋을 갖는다. 

module fsm_mealy(clk,rst,din_bit,dout_bit);
    input clk,rst,din_bit;
    output dout_bit;
    reg [2:0] state_reg, next_state;

    parameter start=3'b000,st1=3'b001,st2=3'b010,st3=3'b011,st4=3'b100;

    always@(*)begin 
        case(state_reg)
            start : if(din_bit==0) next_state = st1;
                    else if(din_bit==1) next_state = start;
            st1 : if(din_bit==0) next_state  = st1;
                    else if(din_bit==1) next_state = st2;
            st2 : if(din_bit==0) next_state = st1;
                    else if(din_bit==1) next_state = st3;
            st3 : if(din_bit==0) next_state = st4;
                    else if(din_bit==1) next_state = start;
            st4 : if(din_bit==0) next_state = st1;
                  else if(din_bit==1) next_state = st2;
        endcase
    end

    always@(posedge clk or posedge rst)begin
        if(rst) state_reg <= start;
        else state_reg <= next_state;
    end

    assign dout_bit = ((state_reg==st4)&&(din_bit==0));
    
endmodule

▣ TESTBENCH

module tb_fsm_mealy;
    reg clk,rst,din_bit;
    wire dout_bit;

    fsm_mealy u0(clk,rst,din_bit,dout_bit);

    always
        #10 clk = ~clk;
    
    initial begin
        clk = 1'b0; rst = 1'b1; din_bit =1'b0;
        #20 rst = 1'b0; din_bit =1'b1;
        #20 din_bit =1'b0;
        #20 din_bit =1'b1;
        #20 din_bit =1'b1;
        #20 din_bit =1'b0;
        #20 din_bit =1'b1;
        #20 din_bit =1'b0;
        #20 din_bit =1'b0;
        #20 din_bit =1'b1;
        #20 din_bit =1'b1;
        #20 din_bit =1'b0;
        #20 din_bit =1'b1;
        #20 din_bit =1'b1;
        #20 din_bit =1'b0;
    end
    
endmodule

★ 기본적인 Pipeline 형태를 모델링하고 테스트벤치를 이용한 시뮬레이션을 통해 동작을 확인한다. 

module pipline_test(clk,rst_n,i_valid,i_value,o_valid,o_value);
    input clk,rst_m,i_valid;
    input [31:0] i_value;
    output o_valid;
    output [63:0] o_value;

    reg [2:0] r_valid;
    reg     [63:0]  r_power_of_2;
    reg     [63:0]  r_power_of_4;
    reg     [63:0]  r_power_of_8;
    wire    [63:0]  power_of_2;
    wire    [63:0]  power_of_4;
    wire    [63:0]  power_of_8;

    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) r_valid <= 3'b0;
        else r_valid <= {[1:0]r_valid,i_valid};
    end

    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) begin 
            r_power_of_2 <= 64'd0;
            r_power_of_4 <= 64'd0;
            r_power_of_8 <= 64'd0;
        end else begin
            r_power_of_2 <= power_of_2;
            r_power_of_4 <= power_of_4;
            r_power_of_8 <= power_of_8;
        end
    end

    assign power_of_2 = i_value * i_value;
    assign power_of_4 = power_of_2 * power_of_2;
    assign power_of_8 = power_of_4 * power_of_4;

    assign o_valid = r_valid[2];
    assign o_value = r_power_of_8;

endmodule

▣ TESTBENCH

module tb_pipline_test;
    reg clk,rst_n,i_valid;
    reg [31:0] i_value;
    wire [31:0] o_value;
    wire o_valid;
    integer i;

    pipline_test u0(clk,rst_n,i_valid,i_value,o_valid,o_value)

    always
        #10 clk = ~clk;
    
    initial begin 
        clk = 1'b0; rst_n =0; i_valid =0; i_value=0;
        #40 rst_n=1;
        for(i=0;i<100;i=i+1)begin
            @(negedge clk);
            i_valid = i;
            i_value = i;
        end
        i_value = 0;
        i_valid = 0;
    end

endmodule

★ 다음 그림과 같은 상태 전이도를 같는 FSM회로를 설계하고 시뮬레이션을 통해 동작을 확인한다.

module fsm_test(clk,rst_n,i_run,i_done,o_done);
    input clk,rst_n,i_run,i_done;
    output o_done;
    reg [1:0] state_reg, next_state;

    parameter IDLE=2'b00, RUN=2'b01, DONE=2'b10;

    always@(*)begin 
        case(state_reg)
            IDLE : if(i_run==1) next_state = RUN;
            RUN : if(i_done==1) next_state = DONE;
            DONE : next_state = IDLE;
        endcase
    end

    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) state_reg <= IDLE;
        else state_reg <= next_state;
    end

    assign o_done = (state_reg==DONE);
endmodule

▣ TESTBENCH

module tb_fsm_test;
    reg clk,rst_n,i_run,i_done;
    wire o_done;

    fsm_test u0(clk,rst_n,i_run,i_done,o_done);

    always
        #10 clk = ~clk;
    
    initial begin 
        clk=1'b0; rst_n=1'b0; i_run=1;i_done=1;
        #20 rst_n=1'b1;
    end
endmodule