UART FSM

uart_top.v

`timescale 1ns / 1ps

module uart_top(
    input RST,
    input CLK,
    input RXD,
    output [6:0] AN,
    output CA,
    output PAR_ERR,
    output FRM_ERR
    );

wire    [7:0]   rx_data;

uart_rx uart_rx_0 (
    .RST        (RST),
    .CLK        (CLK),
    .RXD        (RXD),
    .RX_DATA    (rx_data),
    .RX_DATA_RDY    (),
    .FRM_ERR    (FRM_ERR),
    .PARITY_ERR (PAR_ERR)
    );    

display_inf disp_0 (
    .RST            (RST),
    .CLK            (CLK),      // 125 Mhz
    .NUM_1S         (rx_data[3:0]),
    .NUM_10S        (rx_data[7:4]),
    .CA             (CA),
    .AN             (AN)
    );    


endmodule

 

uart_rx.v

`timescale 1ns / 1ps


module uart_rx(
    input RST,
    input CLK,
    input RXD,
    output [7:0] RX_DATA,
    output      RX_DATA_RDY,
    output      FRM_ERR,
    output      PARITY_ERR

    );

wire    baud_x16_en;

uart_baud_gen uart_baud_gen  (
    .RST    (RST),
    .CLK    (CLK),
    .BAUD_X16_EN    (baud_x16_en)
    );
        
uart_rx_cntl uart_rx_cntl(
    .RST        (RST),
    .CLK        (CLK),
    .RXD        (RXD),
    .BAUD_X16_EN    (baud_x16_en),
    .RX_DATA        (RX_DATA),
    .RX_DATA_RDY   (RX_DATA_RDY),
    .FRM_ERR        (FRM_ERR),
    .PARITY_ERR     (PARITY_ERR)
    );
    
endmodule

 

uart_baud_gen.v

`timescale 1ns / 1ps

module uart_baud_gen(
    input RST,
    input CLK,
    output BAUD_X16_EN
    );
parameter CLK_FREQ = 125_000_000;
parameter BAUD_RATE = 9600;
localparam MAX_CNT = (CLK_FREQ)/(BAUD_RATE*16);

reg [12:0] cnt;
reg        enable;

assign BAUD_X16_EN = enable;

always @(posedge CLK)
begin
    if (RST) begin
        cnt <= 13'd0;
        enable <= 1'b0;
    end else begin
        if(cnt == (MAX_CNT-1))  begin
            cnt <= 13'd0;
            enable <= 1'b1;
        end else begin
            cnt <= cnt + 1;
            enable <= 1'b0;
        end
    end
end     //always                                    
                
    
endmodule

 

uart_rx_cntl

`timescale 1ns / 1ps

module uart_rx_cntl(
    input RST,
    input CLK,
(* mark_debug = "true" *)    
    input RXD,
(* mark_debug = "true" *)    
    input BAUD_X16_EN,  //over_sample_cnt_done,
    output [7:0]    RX_DATA,
(* mark_debug = "true" *)    
    output reg             RX_DATA_RDY,
(* mark_debug = "true" *)
    output  reg     FRM_ERR,
(* mark_debug = "true" *)
    output                  PARITY_ERR
//    output reg [1:0] fsm_state
    );

localparam [1:0]    idle = 2'b00,
                    start = 2'b01,
                    data  = 2'b10,
                    stop = 2'b11;
(* mark_debug = "true" *)
reg [1:0]   curr_state;//
reg [1:0]  next_state;
(* mark_debug = "true" *)
wire        over_sample_cnt_done;
(* mark_debug = "true" *)
reg [3:0]   over_sample_cnt;
(* mark_debug = "true" *)
reg [3:0]   bit_cnt;
(* mark_debug = "true" *)
wire        bit_cnt_done;
(* mark_debug = "true" *)
reg [8:0]   rx_frame;

reg rx_d;

always @(posedge CLK)
begin 
    if(RST)
        curr_state <= idle;
    else
        curr_state <= next_state;
end  //always

always @(curr_state, over_sample_cnt_done, bit_cnt_done, RXD)
begin
    case (curr_state)
        idle : begin
            if(RXD == 1'b0)
                next_state = start;
            else
                next_state = idle;
//            fsm_state = 2'b00;
        end
        start : begin
            if(over_sample_cnt_done) begin
                if(RXD)
                    next_state = idle;
                else
                    next_state = data;
            end
            else next_state = start;
//            fsm_state = 2'b01;
        end
        data : begin
            if(over_sample_cnt_done && bit_cnt_done)
                next_state = stop;
            else
                next_state = data;
//            fsm_state = 2'b10;
        end
        stop : begin
            if(over_sample_cnt_done)
                next_state = idle;
            else
                next_state = stop;
//            fsm_state = 2'b11;
        end
        default : next_state = idle;
    endcase
end //always                                                                                                                                                                                                            

// over sample count                                    
always @(posedge CLK)
begin
    if(RST || curr_state == idle)
        over_sample_cnt <= 4'd7;
    else if (BAUD_X16_EN) begin
        if(over_sample_cnt_done)
            over_sample_cnt <= 4'd15;
        else
            over_sample_cnt <= over_sample_cnt - 1;
    end
end         
assign over_sample_cnt_done = (over_sample_cnt == 4'd0) & BAUD_X16_EN;

// bit cnt generate
always @(posedge CLK)
begin
    if(RST || curr_state != data)
        bit_cnt <= 4'd0;
    else if(over_sample_cnt_done)
        bit_cnt <= bit_cnt + 1;
end //always
assign bit_cnt_done = (over_sample_cnt_done && (bit_cnt == 4'd8));


// output data generate
assign RX_DATA = rx_frame[7:0];
  
always @(posedge CLK)
begin
    if (RST)  
        rx_frame <= 9'd0;
     else if (curr_state == data && over_sample_cnt_done)
        rx_frame[bit_cnt] <= RXD;
end  //always  

//always @(posedge CLK)
//    rx_d <= RXD;
  
 always @(posedge CLK)
    RX_DATA_RDY <= bit_cnt_done;
                                  
assign PARITY_ERR = RX_DATA_RDY & ( rx_frame[8] != ^RX_DATA);                           

always @(posedge CLK)
begin
    if(RST)
        FRM_ERR <= 1'b0;
    else if((curr_state == stop) && over_sample_cnt_done)
        if (!RXD)
            FRM_ERR <= 1'b1;
        else
            FRM_ERR <= 1'b0;
end
                                                                                    
endmodule

 

disp_inf.v

`timescale 1ns / 1ps

module display_inf(
    input           RST,
    input           CLK,      // 125 Mhz
    input [3:0]     NUM_1S,
    input [3:0]     NUM_10S,
    output reg     CA,
    output reg [6:0] AN
    );
parameter CLK_FREQ = 125_000_000;
parameter CNT_MAX = CLK_FREQ / 1000_000; 

reg [26:0] clk_cnt;
wire    enable;

always @(posedge CLK)
begin
    if(RST)
        clk_cnt <= 27'd0;
    else begin
        if( clk_cnt == (CNT_MAX -1))
            clk_cnt <= 27'd0;
        else
            clk_cnt <= clk_cnt + 1;
    end                                
end

assign enable = (clk_cnt == (CNT_MAX -1));

always @(posedge CLK)
    if(RST)
        CA <= 1'b0;
    else if (enable)
        CA <= ~CA;

always @(CA, NUM_1S, NUM_10S)
begin
    if (CA) begin
        case (NUM_10S)
            4'd0 : AN = 7'h7e;
            4'd1 : AN = 7'h30;
            4'd2 : AN = 7'h6d;
            4'd3 : AN = 7'h79;
            4'd4 : AN = 7'h33;
            4'd5 : AN = 7'h5b;
            4'd6 : AN = 7'h5f;
            4'd7 : AN = 7'h70;
            4'd8 : AN = 7'h7f;
            4'd9 : AN = 7'h7b;            
            default : AN = 7'h00;
        endcase  
    end else begin
        case (NUM_1S)
            4'd0 : AN = 8'h7e;
            4'd1 : AN = 8'h30;
            4'd2 : AN = 8'h6d;
            4'd3 : AN = 8'h79;
            4'd4 : AN = 7'h33;
            4'd5 : AN = 7'h5b;
            4'd6 : AN = 7'h5f;
            4'd7 : AN = 7'h70;
            4'd8 : AN = 7'h7f;
            4'd9 : AN = 7'h7b;                                    
            default : AN = 8'h00;
        endcase  
    end        
end        

endmodule

RXD and BAUD X16 Enable in Testbench
Parity, Frame Error in Testbench

'Circuit Design > 🔥HDL' 카테고리의 다른 글

[Verilog] 10. FIFO(First In First Out)  (0) 2024.06.03
[Verilog] 9. RAM(Random Access Memory)  (0) 2024.05.27
[Verilog] 7. 교통신호기 FSM  (0) 2024.04.29
[Verilog] 6.FSM Security  (0) 2024.04.29
[Verilog] 5. FSM Demo.  (1) 2024.04.26