본문 바로가기

[Harman] 반도체 설계/Vivado

[Vivado] 06. Calculator 8bit, FSM StopWatch 0.1s UpCount

 

[1] StopWatch 설계 후, FSM (sw[0], sw[1]) 으로 Stop, Run, Clear 상태 제어. stopwatch 내부에 clkDivider 와 0.1s Counter 가 필요하다. clkDivider 는 10hz, Counter 는 0 ~ 9999 까지 Count 하도록 설계한다(14bit).  fig.1 과 같이 FSM 의 stoprun 신호를 받을 수 있는 enable 과 clear 신호를 받는 reset(clear) port 를 선언해주어야 한다. 

fig.1

 

`timescale 1ns / 1ps

module stopwatch(
    input clk,
    input reset,
    input i_run_stop,
    input i_clear,
    output [13:0] o_upCounter
    );
    
    wire w_clk;
    
    clkDivider_10hz U_clkDivider_10hz(
        .clk(clk),
        .reset(reset),
        .i_clear(i_clear),
        .i_enable(i_run_stop),
        .o_clk(w_clk)
    );

    upcounter U_upcounter(
        .clk(w_clk),
        .reset(reset),
        .i_clear(i_clear),
        .o_upCounter(o_upCounter)
    );
    
endmodule  
    
    
    
module clkDivider_10hz (
    input clk,
    input reset,
    input i_clear,
    input i_enable,
    output reg o_clk
);
    reg [31:0] r_counter = 0;
    
    always@(posedge clk, posedge reset, posedge i_clear) begin
        if(reset || i_clear) begin 
            r_counter <= 0; 
            o_clk <= 1'b0;
        end else if(i_enable) begin 
            if(r_counter == 10_000_000 - 1) begin // 10hz
                r_counter <= 0;
                o_clk <= 1'b1;
            end else begin 
                r_counter <= r_counter + 1;
                o_clk <= 1'b0;
            end
        end
        else r_counter <= r_counter;
    end    
endmodule



module upcounter (
    input clk,
    input reset,
    input i_clear,
    output reg [13:0] o_upCounter = 0
);
    
    always@(posedge clk, posedge reset, posedge i_clear) begin
        if(reset || i_clear) begin
            o_upCounter <= 0;
        end
        else begin
            if(o_upCounter == 9999) begin 
                o_upCounter <= 0;
            end
            else begin 
                o_upCounter <= o_upCounter + 1;
            end
        end
    end
endmodule

 

FSM : Run, Stop, Clear

 

Moore Machine

 

Current nextState -
reset input state output state  
stoprun clear  
1 - - 0 0 STOP  
0 sw[0] = 1 STOP  1   0  RUN i_stoprunSW
0 sw[1] = 1 STOP  0   1  CLEAR i_clearSW
0 sw[0] = 0 STOP 0 0 STOP else
0 sw[1] = 0 STOP 0 0 STOP else
0 sw[0] = 0 RUN  0   0  STOP !i_stoprunSW
0 sw[0] = 1 RUN 1 0 RUN else
0 sw[1] = 0 CLEAR 0 0 STOP !i_clearSW
0 sw[1] = 1 CLEAR 0 1 CLEAR  
default 0 0 STOP  

 

`timescale 1ns / 1ps

module FSM_stopwatch(
    input clk,
    input reset,
    input i_stoprunSW, // i_a[0]
    input i_clearSW,   // i_a[1]
    output reg o_stoprun,
    output reg o_clear
    );

    parameter S_STOP = 2'd0, S_RUN = 2'd1, S_CLEAR = 2'd2;
    reg [1:0] state = S_STOP, nextState ;

    always @(posedge clk, posedge reset) begin
        if(reset) state <= S_STOP;
        else state <= nextState;
    end

    always @(*) begin
        case (state)
            S_STOP : begin    
                if(i_stoprunSW) nextState <= S_RUN;
                else if(i_clearSW) nextState <= S_CLEAR;
                else nextState <= S_STOP;
            end

            S_RUN : begin
                if(!i_stoprunSW) nextState <= S_STOP;
                else nextState <= S_RUN;
            end

            S_CLEAR : begin
                if(!i_clearSW) nextState <= S_STOP;
                else nextState <= S_CLEAR;
            end
            default : nextState <= S_STOP;
        endcase
    end

    always @(*) begin
        case (state)
            S_STOP : begin
                o_stoprun = 1'b0;
                o_clear = 1'b0;
            end 

            S_RUN : begin
                o_stoprun = 1'b1;
                o_clear = 1'b0;
            end

            S_CLEAR : begin
                o_stoprun = 1'b0;
                o_clear = 1'b1;            
            end

            default : begin
                o_stoprun = 1'b0;
                o_clear = 1'b0;            
            end 
        endcase
    end

endmodule

 

[2] mux 의 sw[15] 로 Calculator, StopWatch 동작 제어. mux 를 통해 FndController 에 {5'b0, w_sum} 와 [13:0] o_counter, 중 하나를 선택해서 내보낸다. 

 

`timescale 1ns / 1ps

module mux_2x1_14bit(
    input i_sel,        // i_b[7] = sw[15]
    input [13:0] i_x0,  // Calculator_Value
    input [13:0] i_x1,  // stopwatch_Value
    output reg [13:0] o_y
    );

    always @(*) begin
        case (i_sel)
            1'b0 : o_y = i_x0;
            1'b1 : o_y = i_x1; 
            default: o_y = 14'b0;
        endcase
    end
endmodule
`timescale 1ns / 1ps

module Calculator_8bit_FSM_stopwatch (
    input clk,
    input reset,
    input [7:0] i_a,
    input [7:0] i_b,
    output [3:0] o_digitSel,
    output [7:0] o_fndFont
    );

    wire [8:0] w_sum;
    wire w_stoprun, w_clear;
    wire [13:0] w_stopwatchValue, w_FndsourceValue;
    
    FSM_stopwatch U_FSM_stopwatch(
        .clk(clk),
        .reset(reset),
        .i_stoprunSW(i_a[0]),
        .i_clearSW(i_a[1]),
        .o_stoprun(w_stoprun),
        .o_clear(w_clear)
    );

    stopwatch U_stopwatch(
        .clk(clk),
        .reset(reset),
        .i_run_stop(w_stoprun),
        .i_clear(w_clear),
        .o_upCounter(w_stopwatchValue)
    );

    adder_8bit U_adder_8bit(
        .i_a(i_a),
        .i_b(i_b),
        .o_sum(w_sum[7:0]),
        .o_carry(w_sum[8])
    );
    
    mux_2x1_14bit U_mux_2x1_14bit(
        .i_sel(i_b[7]),
        .i_x0({5'b0, w_sum}),
        .i_x1(w_stopwatchValue),
        .o_y(w_FndsourceValue)
    );

    FndController U_FndController(
        .clk(clk),
        .reset(reset),
        .i_sw_bcd(w_FndsourceValue),
        .o_digitSel(o_digitSel),
        .o_fndFont(o_fndFont)
    );

endmodule

FSM, stopwatch

 

mux_2x1_14bit

 

Schematic