[하만]세미콘 아카데미/verilog

0516 upCounter_FSM

내머리속은이런걸로 2024. 6. 22. 11:31

ASM (Algorithmic State Machine)

 

schematic

  • DataPath : UpCounter & FndController
  • Control Unit : Control Unit

 

upCounter.v

`timescale 1ns / 1ps

module upCounter (
    input         clk,
    input         reset,
    input         tick,
    input         run_stop,  // B1
    input         clear,     // B2
    output [13:0] count
);

    reg [13:0] counter_reg, counter_next;
    assign count = counter_reg;

    always @(posedge clk, posedge reset) begin
        if (reset) begin
            counter_reg <= 0;
        end else begin
            counter_reg <= counter_next;
        end
    end

    always @(*) begin
        counter_next = counter_reg;

        if (tick && run_stop) begin
            if (counter_reg == 9999) begin
                counter_next = 0;
            end else begin
                counter_next = counter_reg + 1;
            end
        end else if (clear) begin
            counter_next = 0;
        end
    end

endmodule

 

control_unit.v

`timescale 1ns / 1ps

module control_unit (
    input  clk,
    input  reset,
    input  btn_run_stop,  // B1
    input  btn_clear,    // B2
    output run_stop,
    output clear,

    output led_stop,
    output led_run,
    output led_clear
);

    parameter STOP = 2'd0, RUN = 2'd1, CLEAR = 2'd2;
    reg [1:0] state, state_next;
    reg run_stop_reg, run_stop_next, clear_reg, clear_next;

    assign run_stop = run_stop_reg;
    assign clear = clear_reg;

    // state register
    always @(posedge clk, posedge reset) begin
        if (reset) begin
            state        <= STOP;
            run_stop_reg <= 1'b0;
            clear_reg    <= 1'b0;
        end else begin
            state        <= state_next;
            run_stop_reg <= run_stop_next;
            clear_reg    <= clear_next;
        end
    end

    // next state combinational logic
    always @(*) begin
        state_next = state;
        case (state)
            STOP: begin
                if (btn_run_stop) state_next = RUN;
                else if (btn_clear) state_next = CLEAR;
                else state_next = STOP;
            end
            RUN: begin
                if (btn_run_stop) state_next = STOP;
                else state_next = RUN;
            end
            CLEAR: begin
                state_next = STOP;
            end
        endcase
    end

    // output combinational logic
    assign led_stop = (state == STOP) ? 1'b1 : 1'b0;
    assign led_run = (state == RUN) ? 1'b1 : 1'b0;
    assign led_clear = (state == CLEAR) ? 1'b1 : 1'b0;
    
    always @(*) begin
        run_stop_next = 1'b0;
        clear_next = 1'b0;

        case (state)
            STOP: begin
                run_stop_next = 1'b0;
            end
            RUN: begin
                run_stop_next = 1'b1;
            end
            CLEAR: begin
                clear_next = 1'b1;
            end
        endcase
    end

endmodule

 

top.v

`timescale 1ns / 1ps


module top (
    input        clk,
    input        reset,
    input        btn_run_stop,
    input        btn_clear,
    output [3:0] fndCom,
    output [7:0] fndFont,

    output led_stop,
    output led_run,
    output led_clear
);

    wire w_clk_10hz;
    wire w_run_stop, w_clear;
    wire [13:0] w_digit;

    clkDiv #(
        .MAX_COUNT(10_000_000)
    ) U_ClkDiv_10hz (
        .clk(clk),
        .reset(reset),
        .o_clk(w_clk_10hz)
    );

    upCounter U_upCounter (
        .clk(clk),
        .reset(reset),
        .tick(w_clk_10hz),
        .run_stop(w_run_stop),  // B1
        .clear(w_clear),     // B2
        .count(w_digit)
    );

    fndController U_fndController (
        .clk(clk),
        .reset(reset),
        .digit(w_digit),
        .fndFont(fndFont),
        .fndCom(fndCom)
    );

    wire w_btn_run_stop, w_btn_clear;

    button U_Btn_RunStop (
        .clk(clk),
        .in (btn_run_stop),
        .out(w_btn_run_stop)
    );

    button U_Btn_Clear (
        .clk(clk),
        .in (btn_clear),
        .out(w_btn_clear)
    );

    control_unit U_ControlUnit (
        .clk(clk),
        .reset(reset),
        .btn_run_stop(w_btn_run_stop),  // B1
        .btn_clear(w_btn_clear),     // B2
        .run_stop(w_run_stop),
        .clear(w_clear),
        .led_stop(led_stop),
        .led_run(led_run),
        .led_clear(led_clear)
    );
    /*
    ila_0 U_ILA (
	    .clk(clk), // input wire clk
	    .probe0(w_btn_run_stop), // input wire [0:0]  probe0  
	    .probe1(w_btn_clear), // input wire [0:0]  probe1 
	    .probe2(w_run_stop), // input wire [0:0]  probe2 
	    .probe3(w_clear), // input wire [0:0]  probe3 
	    .probe4(w_digit), // input wire [13:0]  probe4 
	    .probe5(fndCom) // input wire [3:0]  probe5
    );
*/
endmodule

 

button.v

`timescale 1ns / 1ps

module button (
    input  clk,
    input  in,
    output out
);

    localparam N = 8;  // shift 횟수

    reg [N-1 : 0] q_reg, q_next;

    always @(posedge clk) begin
        q_reg <= q_next;
    end

    // next state logic
    always @(q_reg, in) begin
        q_next = {in, q_reg[N-1:1]};
    end

    // output logic
    assign out = ~(&q_reg[N-1:1]) & q_reg[0]; // 하강 edge
    // assign out = (&q_reg[N-1:1] & ~q_reg[0]);

endmodule

 

fndController.v

`timescale 1ns / 1ps

module fndController (
    input         clk,
    input         reset,
    input  [13:0] digit,
    output [ 7:0] fndFont,
    output [ 3:0] fndCom
    );

    wire [3:0] w_digit_1, w_digit_10, w_digit_100, w_digit_1000;
    wire [3:0] w_digit;
    wire [1:0] w_count;
    wire w_clk_1khz;

    clkDiv #(.MAX_COUNT(100_000)) U_ClkDiv(
        .clk(clk),
        .reset(reset),
        .o_clk(w_clk_1khz)
    );

    counter #(.MAX_COUNT(4)) U_Counter_2bit(
        .clk(w_clk_1khz),
        .reset(reset),
        .count(w_count)
    );

    Decoder U_Decoder_2x4 (
        .x(w_count),
        .y(fndCom)
    );

    digitSplitter U_DigitSplitter (
        .i_digit(digit),
        .o_digit_1(w_digit_1),
        .o_digit_10(w_digit_10),
        .o_digit_100(w_digit_100),
        .o_digit_1000(w_digit_1000)
    );

    Mux U_Mux (
        .sel(w_count),
        .x0 (w_digit_1),
        .x1 (w_digit_10),
        .x2 (w_digit_100),
        .x3 (w_digit_1000),
        .y  (w_digit)
    );

    BCDtoSEG U_BcdToSeg0 (
        .bcd(w_digit),
        .seg(fndFont)
    );

endmodule


module Decoder (
    input      [1:0] x,
    output reg [3:0] y
);

    always @(x) begin
        case (x)
            2'h0: y = 4'b1110;
            2'h1: y = 4'b1101;
            2'h2: y = 4'b1011;
            2'h3: y = 4'b0111;
            default: y = 4'b1110;
        endcase
    end

endmodule

module digitSplitter (
    input  [13:0] i_digit,
    output [ 3:0] o_digit_1,
    output [ 3:0] o_digit_10,
    output [ 3:0] o_digit_100,
    output [ 3:0] o_digit_1000
);

    assign o_digit_1 = i_digit % 10;
    assign o_digit_10 = i_digit / 10 % 10;
    assign o_digit_100 = i_digit / 100 % 10;
    assign o_digit_1000 = i_digit / 1000 % 10;

endmodule

module Mux (
    input      [1:0] sel,
    input      [3:0] x0,
    input      [3:0] x1,
    input      [3:0] x2,
    input      [3:0] x3,
    output reg [3:0] y
);

    always @(sel, x0, x1, x2, x3) begin
        case (sel)
            2'b00:   y = x0;
            2'b01:   y = x1;
            2'b10:   y = x2;
            2'b11:   y = x3;
            default: y = x0;
        endcase
    end

endmodule

module BCDtoSEG (
    input      [3:0] bcd,
    output reg [7:0] seg
);

    always @(bcd) begin
        case (bcd)
            4'h0: seg = 8'hc0;
            4'h1: seg = 8'hf9;
            4'h2: seg = 8'ha4;
            4'h3: seg = 8'hb0;
            4'h4: seg = 8'h99;
            4'h5: seg = 8'h92;
            4'h6: seg = 8'h82;
            4'h7: seg = 8'hf8;
            4'h8: seg = 8'h80;
            4'h9: seg = 8'h90;
            4'ha: seg = 8'h88;
            4'hb: seg = 8'h83;
            4'hc: seg = 8'hc6;
            4'hd: seg = 8'ha1;
            4'he: seg = 8'h86;
            4'hf: seg = 8'h8e;
            default: seg = 8'hff;
        endcase
    end

endmodule

module counter #(parameter MAX_COUNT = 4)(
    input  clk,
    input reset,
    output [$clog2(MAX_COUNT)-1:0]  count
);

    reg [$clog2(MAX_COUNT)-1:0] counter = 0;
    assign count = counter;

    always @(posedge clk, posedge reset) begin  // 비동기 reset
        if (reset == 1'b1) begin
            counter <= 0;
        end
        else begin
            if (counter == MAX_COUNT - 1) begin
                counter <= 0;
            end
            else begin
                counter <= counter + 1;
            end
        end
    end

endmodule

module clkDiv #(parameter MAX_COUNT = 100)(
    input clk,
    input reset,
    output o_clk
);
    reg [$clog2(MAX_COUNT)-1:0] counter = 0;
    reg r_tick = 0 ;

    assign o_clk = r_tick;

    always @(posedge clk, posedge reset) begin
        if (reset) begin
            counter <= 0;
        end
        else begin
            if (counter == (MAX_COUNT - 1)) begin
                counter <= 0;
                r_tick <= 1'b1;
            end
            else begin
                counter <= counter + 1;
                r_tick <= 1'b0;
            end
        end
    end
    
endmodule

 

schematic

 

constraint

## LEDs

set_property -dict { PACKAGE_PIN U16  IOSTANDARD LVCMOS33 } [get_ports { led_stop  }]; #IO_L23N_T3_A02_D18_14        ,Sch=LED0
set_property -dict { PACKAGE_PIN E19  IOSTANDARD LVCMOS33 } [get_ports { led_run  }]; #IO_L3N_T0_DQS_EMCCLK_14      ,Sch=LED1
set_property -dict { PACKAGE_PIN U19  IOSTANDARD LVCMOS33 } [get_ports { led_clear  }]; #IO_L15P_T2_DQS_RDWR_B_14     ,Sch=LED2
##7 segment display

set_property -dict { PACKAGE_PIN W7  IOSTANDARD LVCMOS33 } [get_ports { fndFont[0] }]; #IO_L13P_T2_MRCC_34 ,Sch=CA
set_property -dict { PACKAGE_PIN W6  IOSTANDARD LVCMOS33 } [get_ports { fndFont[1] }]; #IO_L13N_T2_MRCC_34 ,Sch=CB
set_property -dict { PACKAGE_PIN U8  IOSTANDARD LVCMOS33 } [get_ports { fndFont[2] }]; #IO_L14P_T2_SRCC_34 ,Sch=CC
set_property -dict { PACKAGE_PIN U8  IOSTANDARD LVCMOS33 } [get_ports { fndFont[2] }]; #IO_L14P_T2_SRCC_34 ,Sch=CC
set_property -dict { PACKAGE_PIN V8  IOSTANDARD LVCMOS33 } [get_ports { fndFont[3] }]; #IO_L14N_T2_SRCC_34 ,Sch=CD
set_property -dict { PACKAGE_PIN U5  IOSTANDARD LVCMOS33 } [get_ports { fndFont[4] }]; #IO_L16P_T2_34      ,Sch=CE
set_property -dict { PACKAGE_PIN V5  IOSTANDARD LVCMOS33 } [get_ports { fndFont[5] }]; #IO_L16N_T2_34      ,Sch=CF
set_property -dict { PACKAGE_PIN U7  IOSTANDARD LVCMOS33 } [get_ports { fndFont[6] }]; #IO_L19P_T3_34      ,Sch=CG
set_property -dict { PACKAGE_PIN V7  IOSTANDARD LVCMOS33 } [get_ports { fndFont[7] }]; #IO_L19N_T3_VREF_34 ,Sch=DP
set_property -dict { PACKAGE_PIN U2  IOSTANDARD LVCMOS33 } [get_ports { fndCom[0]  }]; #IO_L9N_T1_DQS_34   ,Sch=DP
set_property -dict { PACKAGE_PIN U4  IOSTANDARD LVCMOS33 } [get_ports { fndCom[1]  }]; #IO_L11P_T1_SRCC_34 ,Sch=DP
set_property -dict { PACKAGE_PIN V4  IOSTANDARD LVCMOS33 } [get_ports { fndCom[2]  }]; #IO_L11N_T1_SRCC_34 ,Sch=DP
set_property -dict { PACKAGE_PIN W4  IOSTANDARD LVCMOS33 } [get_ports { fndCom[3]  }]; #IO_L12N_T1_MRCC_34 ,Sch=DP


##Buttons

set_property -dict { PACKAGE_PIN U18  IOSTANDARD LVCMOS33 } [get_ports { reset }]; #IO_L18N_T2_A11_D27_14 ,Sch=BTNC
set_property -dict { PACKAGE_PIN T18  IOSTANDARD LVCMOS33 } [get_ports { btn_run_stop }]; #IO_L17N_T2_A13_D29_14 ,Sch=BTNU
#set_property -dict { PACKAGE_PIN W19  IOSTANDARD LVCMOS33 } [get_ports { fndSel[1] }]; #IO_L16N_T2_A15_D31_14 ,Sch=BTNL
#set_property -dict { PACKAGE_PIN T17  IOSTANDARD LVCMOS33 } [get_ports { fndSel[0] }]; #IO_L17P_T2_A14_D30_14 ,Sch=BTNR
set_property -dict { PACKAGE_PIN U17  IOSTANDARD LVCMOS33 } [get_ports { btn_clear }]; #IO_L18P_T2_A12_D28_14 ,Sch=BTND

 

video

- 0514 upCounter_FSM과 동작 시퀀스가 같다.

 

'[하만]세미콘 아카데미 > verilog' 카테고리의 다른 글

0517 uart_tx  (0) 2024.06.22
0516 UART  (0) 2024.06.22
0514 upCounter_FND_FSM  (0) 2024.06.22
0514 upCounter_Fnd_moore_machine  (0) 2024.06.22
0514 assignment, FSM, button_moore_mealy  (0) 2024.06.22