data/full_repos/permissive/20726090/hw/vlog/system/uart.v
None: at end of input
1: b'%Error: data/full_repos/permissive/20726090/hw/vlog/system/uart.v:54: Cannot find include file: system_config_defines.v\n`include "system_config_defines.v" \n         ^~~~~~~~~~~~~~~~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/20726090/hw/vlog/system,data/full_repos/permissive/20726090/system_config_defines.v\n             data/full_repos/permissive/20726090/hw/vlog/system,data/full_repos/permissive/20726090/system_config_defines.v.v\n             data/full_repos/permissive/20726090/hw/vlog/system,data/full_repos/permissive/20726090/system_config_defines.v.sv\n             system_config_defines.v\n             system_config_defines.v.v\n             system_config_defines.v.sv\n             obj_dir/system_config_defines.v\n             obj_dir/system_config_defines.v.v\n             obj_dir/system_config_defines.v.sv\n%Error: data/full_repos/permissive/20726090/hw/vlog/system/uart.v:55: Cannot find include file: global_defines.v\n`include "global_defines.v" \n         ^~~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/20726090/hw/vlog/system/uart.v:88: Cannot find include file: register_addresses.v\n`include "register_addresses.v" \n         ^~~~~~~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/20726090/hw/vlog/system/uart.v:133: Define or directive not defined: \'`AMBER_CLK_DIVIDER\'\nlocalparam real CLK_FREQ          = 800.0 / `AMBER_CLK_DIVIDER ;  \n                                            ^~~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/20726090/hw/vlog/system/uart.v:133: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nlocalparam real CLK_FREQ          = 800.0 / `AMBER_CLK_DIVIDER ;  \n                                                               ^\n%Error: data/full_repos/permissive/20726090/hw/vlog/system/uart.v:812: Define or directive not defined: \'`TB_ERROR_MESSAGE\'\n        `TB_ERROR_MESSAGE\n        ^~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/20726090/hw/vlog/system/uart.v:931: Define or directive not defined: \'`TB_WARNING_MESSAGE\'\n        `TB_WARNING_MESSAGE\n        ^~~~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/20726090/hw/vlog/system/uart.v:936: Define or directive not defined: \'`TB_WARNING_MESSAGE\'\n        `TB_WARNING_MESSAGE\n        ^~~~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/20726090/hw/vlog/system/uart.v:942: Define or directive not defined: \'`TB_WARNING_MESSAGE\'\n        `TB_WARNING_MESSAGE\n        ^~~~~~~~~~~~~~~~~~~\n%Error: Exiting due to 9 error(s)\n'
module uart  #(
parameter WB_DWIDTH  = 32,
parameter WB_SWIDTH  = 4
)(
input                       i_clk,

input       [31:0]          i_wb_adr,
input       [WB_SWIDTH-1:0] i_wb_sel,
input                       i_wb_we,
output      [WB_DWIDTH-1:0] o_wb_dat,
input       [WB_DWIDTH-1:0] i_wb_dat,
input                       i_wb_cyc,
input                       i_wb_stb,
output                      o_wb_ack,
output                      o_wb_err,

output                      o_uart_int,

input                       i_uart_cts_n,
output                      o_uart_txd,
output                      o_uart_rts_n,
input                       i_uart_rxd

);


`include "register_addresses.v"


localparam [3:0] TXD_IDLE  = 4'd0,
                 TXD_START = 4'd1,
                 TXD_DATA0 = 4'd2,
                 TXD_DATA1 = 4'd3,
                 TXD_DATA2 = 4'd4,
                 TXD_DATA3 = 4'd5,
                 TXD_DATA4 = 4'd6,
                 TXD_DATA5 = 4'd7,
                 TXD_DATA6 = 4'd8,
                 TXD_DATA7 = 4'd9,
                 TXD_STOP1 = 4'd10,
                 TXD_STOP2 = 4'd11,
                 TXD_STOP3 = 4'd12;
                 
localparam [3:0] RXD_IDLE       = 4'd0,
                 RXD_START      = 4'd1,
                 RXD_START_MID  = 4'd2,
                 RXD_START_MID1 = 4'd3,
                 RXD_DATA0      = 4'd4,
                 RXD_DATA1      = 4'd5,
                 RXD_DATA2      = 4'd6,
                 RXD_DATA3      = 4'd7,
                 RXD_DATA4      = 4'd8,
                 RXD_DATA5      = 4'd9,
                 RXD_DATA6      = 4'd10,
                 RXD_DATA7      = 4'd11,
                 RXD_STOP       = 4'd12;


localparam RX_INTERRUPT_COUNT = 24'h3fffff; 






`ifndef Veritak
localparam real UART_BAUD         = `AMBER_UART_BAUD;

`ifdef XILINX_VIRTEX6_FPGA
localparam real CLK_FREQ          = 1200.0 / `AMBER_CLK_DIVIDER ;
`else
localparam real CLK_FREQ          = 800.0 / `AMBER_CLK_DIVIDER ;
`endif

localparam real UART_BIT_PERIOD   = 1000000000 / UART_BAUD;
localparam real UART_WORD_PERIOD  = ( UART_BIT_PERIOD * 12 );
localparam real CLK_PERIOD        = 1000 / CLK_FREQ;
localparam real CLKS_PER_WORD     = UART_WORD_PERIOD / CLK_PERIOD;
localparam real CLKS_PER_BIT      = CLKS_PER_WORD / 12;




localparam [9:0] TX_BITPULSE_COUNT         = CLKS_PER_BIT;
localparam [9:0] TX_CLKS_PER_WORD          = CLKS_PER_WORD;
`else
localparam [9:0] TX_BITPULSE_COUNT         = 30;
localparam [9:0] TX_CLKS_PER_WORD          = 360;
`endif

localparam [9:0] TX_BITADJUST_COUNT        = TX_CLKS_PER_WORD - 11*TX_BITPULSE_COUNT;

localparam [9:0] RX_BITPULSE_COUNT         = TX_BITPULSE_COUNT-2;
localparam [9:0] RX_HALFPULSE_COUNT        = TX_BITPULSE_COUNT/2 - 4;




reg             tx_interrupt = 'd0;
reg             rx_interrupt = 'd0;
reg   [23:0]    rx_int_timer = 'd0;

wire            fifo_enable;

reg   [7:0]     tx_fifo    [0:15];
wire            tx_fifo_full;
wire            tx_fifo_empty;
wire            tx_fifo_half_or_less_full;
wire            tx_fifo_push;
wire            tx_fifo_push_not_full;
wire            tx_fifo_pop_not_empty;
reg   [4:0]     tx_fifo_wp = 'd0;
reg   [4:0]     tx_fifo_rp = 'd0;
reg   [4:0]     tx_fifo_count = 'd0;
reg             tx_fifo_full_flag = 'd0;

reg   [7:0]     rx_fifo    [0:15];
reg             rx_fifo_empty = 1'd1;
reg             rx_fifo_full = 1'd0;
wire            rx_fifo_half_or_more;
reg   [4:0]     rx_fifo_count = 'd0;
wire            rx_fifo_push;
wire            rx_fifo_push_not_full;
wire            rx_fifo_pop;
wire            rx_fifo_pop_not_empty;
reg   [4:0]     rx_fifo_wp = 'd0;
reg   [4:0]     rx_fifo_rp = 'd0;

wire  [7:0]     tx_byte;
reg   [3:0]     txd_state = TXD_IDLE;
reg             txd = 1'd1;
reg             tx_bit_pulse = 'd0;
reg   [9:0]     tx_bit_pulse_count = 'd0;

reg   [7:0]     rx_byte = 'd0;
reg   [3:0]     rxd_state = RXD_IDLE;
wire            rx_start;
reg             rxen = 'd0;
reg   [9:0]     rx_bit_pulse_count = 'd0;
reg             restart_rx_bit_count = 'd0;
reg   [4:0]     rxd_d = 5'h1f;
reg   [3:0]     uart0_cts_n_d = 4'hf;


reg  [7:0]      uart_rsr_reg = 'd0;
reg  [7:0]      uart_lcrh_reg = 'd0;
reg  [7:0]      uart_lcrm_reg = 'd0;
reg  [7:0]      uart_lcrl_reg = 'd0;
reg  [7:0]      uart_cr_reg = 'd0;


reg  [31:0]     wb_rdata32 = 'd0;
wire            wb_start_write;
wire            wb_start_read;
reg             wb_start_read_d1 = 'd0;
wire [31:0]     wb_wdata32;

integer         i;







assign wb_start_write = i_wb_stb &&  i_wb_we && !wb_start_read_d1;
assign wb_start_read  = i_wb_stb && !i_wb_we && !o_wb_ack;

always @( posedge i_clk )
    wb_start_read_d1 <= wb_start_read;

assign o_wb_err = 1'd0;
assign o_wb_ack = i_wb_stb && ( wb_start_write || wb_start_read_d1 );

generate
if (WB_DWIDTH == 128) 
    begin : wb128
    assign wb_wdata32   = i_wb_adr[3:2] == 2'd3 ? i_wb_dat[127:96] :
                          i_wb_adr[3:2] == 2'd2 ? i_wb_dat[ 95:64] :
                          i_wb_adr[3:2] == 2'd1 ? i_wb_dat[ 63:32] :
                                                  i_wb_dat[ 31: 0] ;
                                                                                                                                            
    assign o_wb_dat    = {4{wb_rdata32}};
    end
else
    begin : wb32
    assign wb_wdata32  = i_wb_dat;
    assign o_wb_dat    = wb_rdata32;
    end
endgenerate

        



                       
assign rx_fifo_pop           = wb_start_read && i_wb_adr[15:0] == AMBER_UART_DR;
assign rx_fifo_push_not_full = rx_fifo_push && !rx_fifo_full;
assign rx_fifo_pop_not_empty = rx_fifo_pop && !rx_fifo_empty;
assign rx_fifo_half_or_more  = rx_fifo_count >= 5'd8;


always @ ( posedge i_clk ) 
    begin
    if ( fifo_enable )
        begin

        if ( rx_fifo_push_not_full )
            begin
            rx_fifo[rx_fifo_wp[3:0]]    <= rx_byte;                
            rx_fifo_wp                  <= rx_fifo_wp + 1'd1;
            end

        if ( rx_fifo_pop_not_empty )
            begin
            rx_fifo_rp                  <= rx_fifo_rp + 1'd1;
            end
            
        if ( rx_fifo_push_not_full && !rx_fifo_pop_not_empty )
            rx_fifo_count <= rx_fifo_count + 1'd1;
        else if ( rx_fifo_pop_not_empty  && !rx_fifo_push_not_full )
            rx_fifo_count <= rx_fifo_count - 1'd1;
        
        rx_fifo_full  <= rx_fifo_wp == {~rx_fifo_rp[4], rx_fifo_rp[3:0]};
        rx_fifo_empty <= rx_fifo_wp == rx_fifo_rp;
        
        if ( rx_fifo_empty || rx_fifo_pop )
            rx_int_timer     <= 'd0;
        else if ( rx_int_timer != RX_INTERRUPT_COUNT )
            rx_int_timer     <= rx_int_timer + 1'd1;
        
            
        end
    else
        begin
        rx_int_timer     <= 'd0;
        
        if ( rx_fifo_push )
            begin
            rx_fifo[0]         <= rx_byte;
            rx_fifo_empty      <= 1'd0;
            rx_fifo_full       <= 1'd1;
            end
        else if ( rx_fifo_pop )
            begin
            rx_fifo_empty      <= 1'd1;
            rx_fifo_full       <= 1'd0;
            end
        end
    end








always @ ( posedge i_clk )
    begin 

    if ( wb_start_write && i_wb_adr[15:0] == AMBER_UART_ICR )
        tx_interrupt <= 1'd0;


    else if  ( fifo_enable ) 


        tx_interrupt <= tx_fifo_half_or_less_full && uart_cr_reg[5];
    else 


        tx_interrupt <= tx_fifo_empty && uart_cr_reg[5];
    end






always @ ( posedge i_clk )
    if (fifo_enable)
        rx_interrupt <=  rx_fifo_half_or_more || rx_int_timer == RX_INTERRUPT_COUNT;
    else    
        rx_interrupt <=  rx_fifo_full;


assign o_uart_int   = ( tx_interrupt & uart_cr_reg[5] )  |
                      ( rx_interrupt & uart_cr_reg[4] )  ;

assign fifo_enable = uart_lcrh_reg[4];


       




assign   o_uart_txd                 = txd;

assign   tx_fifo_full               = fifo_enable ? tx_fifo_count >= 5'd16 :  tx_fifo_full_flag;
assign   tx_fifo_empty              = fifo_enable ? tx_fifo_count == 5'd00 : !tx_fifo_full_flag;
assign   tx_fifo_half_or_less_full  =               tx_fifo_count <= 5'd8;
assign   tx_byte                    = fifo_enable ? tx_fifo[tx_fifo_rp[3:0]] : tx_fifo[0] ;

assign   tx_fifo_push               = wb_start_write && i_wb_adr[15:0] == AMBER_UART_DR;
assign   tx_fifo_push_not_full      = tx_fifo_push && !tx_fifo_full;
assign   tx_fifo_pop_not_empty      = txd_state == TXD_STOP3 && tx_bit_pulse == 1'd1 && !tx_fifo_empty;

        

always @( posedge i_clk )
    begin      

    if ( fifo_enable )
        begin

        if ( tx_fifo_push_not_full )
            begin
            tx_fifo[tx_fifo_wp[3:0]] <= wb_wdata32[7:0];
            tx_fifo_wp <= tx_fifo_wp + 1'd1;
            end
        
            

        if ( tx_fifo_pop_not_empty )
            tx_fifo_rp <= tx_fifo_rp + 1'd1;
            

        if (tx_fifo_push_not_full && !tx_fifo_pop_not_empty)
            tx_fifo_count <= tx_fifo_count + 1'd1;
            

        else if (tx_fifo_pop_not_empty  && !tx_fifo_push_not_full)
            tx_fifo_count <= tx_fifo_count - 1'd1;
        end
        

    else  
        begin

        tx_fifo_wp    <= 'd0;
        tx_fifo_rp    <= 'd0;
        tx_fifo_count <= 'd0;
        

        if ( tx_fifo_push_not_full )
            begin
            tx_fifo[0]          <= wb_wdata32[7:0];
            tx_fifo_full_flag   <= 1'd1;
            end

        else if ( tx_fifo_pop_not_empty )
            tx_fifo_full_flag   <= 1'd0;

        end        
    end





always @( posedge i_clk )
    uart0_cts_n_d <= {uart0_cts_n_d[2:0], i_uart_cts_n};
                                            




always @( posedge i_clk )
    if (( tx_bit_pulse_count == (TX_BITADJUST_COUNT-1) && txd_state == TXD_STOP2 ) ||
        ( tx_bit_pulse_count == (TX_BITPULSE_COUNT-1)  && txd_state != TXD_STOP2 )  )
        begin
        tx_bit_pulse_count <= 'd0;
        tx_bit_pulse       <= 1'd1;
        end
    else
        begin
        tx_bit_pulse_count <= tx_bit_pulse_count + 1'd1;
        tx_bit_pulse       <= 1'd0;
        end









    
     

always @( posedge i_clk )
    if ( tx_bit_pulse )
    
        case ( txd_state )
        
            TXD_IDLE :
                begin
                txd       <= 1'd1;
                
                if ( uart0_cts_n_d[3:1] == 3'b000 && !tx_fifo_empty )
                    txd_state <= TXD_START;
                end
                
            TXD_START :
                begin
                txd       <= 1'd0;
                txd_state <= TXD_DATA0;
                end
                
            TXD_DATA0 :
                begin
                txd       <= tx_byte[0];
                txd_state <= TXD_DATA1;
                end
                
            TXD_DATA1 :
                begin
                txd       <= tx_byte[1];
                txd_state <= TXD_DATA2;
                end
                
            TXD_DATA2 :
                begin
                txd       <= tx_byte[2];
                txd_state <= TXD_DATA3;
                end
                
            TXD_DATA3 :
                begin
                txd       <= tx_byte[3];
                txd_state <= TXD_DATA4;
                end
                
            TXD_DATA4 :
                begin
                txd       <= tx_byte[4];
                txd_state <= TXD_DATA5;
                end
                
            TXD_DATA5 :
                begin
                txd       <= tx_byte[5];
                txd_state <= TXD_DATA6;
                end
                
            TXD_DATA6 :
                begin
                txd       <= tx_byte[6];
                txd_state <= TXD_DATA7;
                end
                
            TXD_DATA7 :
                begin
                txd       <= tx_byte[7];
                txd_state <= TXD_STOP1;
                end
                
            TXD_STOP1 :
                begin
                txd       <= 1'd1;
                txd_state <= TXD_STOP2;
                end

            TXD_STOP2 :
                begin
                txd       <= 1'd1;
                txd_state <= TXD_STOP3;
                end
                
            TXD_STOP3 :
                begin
                txd       <= 1'd1;
                txd_state <= TXD_IDLE;
                end
                
            default :
                begin
                txd       <= 1'd1;
                end
                
        endcase








assign o_uart_rts_n  = ~rxen;

assign rx_fifo_push  = rxd_state == RXD_STOP && rx_bit_pulse_count == 10'd0;





always @( posedge i_clk )
    if ( restart_rx_bit_count )
        rx_bit_pulse_count <= 'd0;
    else
        rx_bit_pulse_count <= rx_bit_pulse_count + 1'd1;





always @( posedge i_clk )
    rxd_d[4:0] <= {rxd_d[3:0], i_uart_rxd};

assign rx_start = rxd_d[4:3] == 2'b11 && rxd_d[1:0] == 2'b00;






always @( posedge i_clk )
    case ( rxd_state )
    
        RXD_IDLE :
            if ( rx_fifo_full )
                rxen                    <= 1'd0;
            else
                begin
                rxd_state               <= RXD_START;
                rxen                    <= 1'd1;
                restart_rx_bit_count    <= 1'd1;
                rx_byte                 <= 'd0;
                end
            
        RXD_START : 

            if ( rx_start ) 
                begin
                rxd_state               <= RXD_START_MID1;
                restart_rx_bit_count    <= 1'd1;
                end
            else    
                restart_rx_bit_count    <= 1'd0;




        RXD_START_MID1 :
            rxd_state               <= RXD_START_MID;
            
        RXD_START_MID :
            if ( rx_bit_pulse_count == RX_HALFPULSE_COUNT )
                begin
                rxd_state               <= RXD_DATA0;
                restart_rx_bit_count    <= 1'd1;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        RXD_DATA0 :
            if ( rx_bit_pulse_count == RX_BITPULSE_COUNT )
                begin
                rxd_state               <= RXD_DATA1;
                restart_rx_bit_count    <= 1'd1;
                rx_byte[0]              <= i_uart_rxd;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        RXD_DATA1 :
            if ( rx_bit_pulse_count == RX_BITPULSE_COUNT )
                begin
                rxd_state               <= RXD_DATA2;
                restart_rx_bit_count    <= 1'd1;
                rx_byte[1]              <= i_uart_rxd;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        RXD_DATA2 :
            if ( rx_bit_pulse_count == RX_BITPULSE_COUNT )
                begin
                rxd_state               <= RXD_DATA3;
                restart_rx_bit_count    <= 1'd1;
                rx_byte[2]              <= i_uart_rxd;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        RXD_DATA3 :
            if ( rx_bit_pulse_count == RX_BITPULSE_COUNT )
                begin
                rxd_state               <= RXD_DATA4;
                restart_rx_bit_count    <= 1'd1;
                rx_byte[3]              <= i_uart_rxd;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        RXD_DATA4 :
            if ( rx_bit_pulse_count ==  RX_BITPULSE_COUNT )
                begin
                rxd_state               <= RXD_DATA5;
                restart_rx_bit_count    <= 1'd1;
                rx_byte[4]              <= i_uart_rxd;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        RXD_DATA5 :
            if ( rx_bit_pulse_count ==  RX_BITPULSE_COUNT )
                begin
                rxd_state               <= RXD_DATA6;
                restart_rx_bit_count    <= 1'd1;
                rx_byte[5]              <= i_uart_rxd;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        RXD_DATA6 :
            if ( rx_bit_pulse_count ==  RX_BITPULSE_COUNT )
                begin
                rxd_state               <= RXD_DATA7;
                restart_rx_bit_count    <= 1'd1;
                rx_byte[6]              <= i_uart_rxd;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        RXD_DATA7 :
            if ( rx_bit_pulse_count ==  RX_BITPULSE_COUNT )
                begin
                rxd_state               <= RXD_STOP;
                restart_rx_bit_count    <= 1'd1;
                rx_byte[7]              <= i_uart_rxd;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        RXD_STOP :
            if ( rx_bit_pulse_count ==  RX_BITPULSE_COUNT )
                begin
                rxd_state               <= RXD_IDLE;
                restart_rx_bit_count    <= 1'd1;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        default :
            begin
            rxd_state       <= RXD_IDLE;
            end
            
    endcase

        



always @( posedge i_clk )
    if ( wb_start_write )
        case ( i_wb_adr[15:0] )

            AMBER_UART_RSR:  uart_rsr_reg      <= wb_wdata32[7:0];

            AMBER_UART_LCRH: uart_lcrh_reg     <= wb_wdata32[7:0];

            AMBER_UART_LCRM: uart_lcrm_reg     <= wb_wdata32[7:0];

            AMBER_UART_LCRL: uart_lcrl_reg     <= wb_wdata32[7:0];

            AMBER_UART_CR:   uart_cr_reg       <= wb_wdata32[7:0];
        endcase





always @( posedge i_clk )
    if ( wb_start_read )
        case ( i_wb_adr[15:0] )
        
            AMBER_UART_CID0:    wb_rdata32 <= 32'h0d;
            AMBER_UART_CID1:    wb_rdata32 <= 32'hf0;
            AMBER_UART_CID2:    wb_rdata32 <= 32'h05;
            AMBER_UART_CID3:    wb_rdata32 <= 32'hb1;
            AMBER_UART_PID0:    wb_rdata32 <= 32'h10;
            AMBER_UART_PID1:    wb_rdata32 <= 32'h10;
            AMBER_UART_PID2:    wb_rdata32 <= 32'h04;
            AMBER_UART_PID3:    wb_rdata32 <= 32'h00;
            
            AMBER_UART_DR:
                    if ( fifo_enable )
                        wb_rdata32 <= {24'd0, rx_fifo[rx_fifo_rp[3:0]]};
                    else    
                        wb_rdata32 <= {24'd0, rx_fifo[0]};
                                      
            AMBER_UART_RSR:     wb_rdata32 <= uart_rsr_reg;
            AMBER_UART_LCRH:    wb_rdata32 <= uart_lcrh_reg;
            AMBER_UART_LCRM:    wb_rdata32 <= uart_lcrm_reg;
            AMBER_UART_LCRL:    wb_rdata32 <= uart_lcrl_reg;
            AMBER_UART_CR:      wb_rdata32 <= uart_cr_reg;
            

            AMBER_UART_FR:      wb_rdata32 <= {tx_fifo_empty,
                                             rx_fifo_full,
                                             tx_fifo_full,
                                             rx_fifo_empty,
                                             !tx_fifo_empty,
                                             1'd1,
                                             1'd1,
                                             !uart0_cts_n_d[3]
                                             };
            

            AMBER_UART_IIR:     wb_rdata32 <= {5'd0, 
                                             1'd0,
                                             tx_interrupt,
                                             rx_interrupt,
                                             1'd0
                                            };
                                            
            default:            wb_rdata32 <= 32'h00c0ffee;
            
        endcase

        















`ifndef Veritak


initial
    begin
    if ((( TX_BITPULSE_COUNT * CLK_PERIOD ) > (UART_BIT_PERIOD * 1.03) ) ||
        (( TX_BITPULSE_COUNT * CLK_PERIOD ) < (UART_BIT_PERIOD * 0.97) ) )
        begin
        `TB_ERROR_MESSAGE
        $display("UART TX bit period, %.1f, is too big. UART will not work!", TX_BITPULSE_COUNT * CLK_PERIOD);
        $display("Baud rate is %f, and baud bit period is %.1f", UART_BAUD, UART_BIT_PERIOD);
        $display("Either reduce the baud rate, or increase the system clock frequency");
        $display("------");
        end
    end
`endif
    

`ifdef AMBER_UART_DEBUG
wire            wb_read_ack;
reg             uart0_rx_int_d1 = 'd0;

assign wb_read_ack = i_wb_stb && !i_wb_we &&  o_wb_ack;

`ifndef Veritak
initial
    begin
    $display("%m UART period = %f nS, want %f nS, %d, %d", 
             (TX_BITPULSE_COUNT*11 + TX_BITADJUST_COUNT) * CLK_PERIOD,
             UART_WORD_PERIOD,
             TX_BITPULSE_COUNT, TX_BITADJUST_COUNT);
    end
`endif



always @ ( posedge i_clk )
    if ( wb_start_write && i_wb_adr[15:0] == AMBER_UART_ICR )
            ;
    else if ( fifo_enable ) 
        begin
        if (tx_interrupt == 1'd0 && tx_fifo_half_or_less_full && uart_cr_reg[5])
            $display("%m: tx_interrupt Interrupt Set with FIFO enabled");
        if (tx_interrupt == 1'd1 && !(tx_fifo_half_or_less_full && uart_cr_reg[5]))
            $display("%m: tx_interrupt Interrupt Cleared with FIFO enabled");
        end
    else
        begin
        if (tx_interrupt == 1'd0 && tx_fifo_empty && uart_cr_reg[5])
            $display("%m: tx_interrupt Interrupt Set with FIFO disabled");
        if (tx_interrupt == 1'd1 && !(tx_fifo_empty && uart_cr_reg[5]))
            $display("%m: tx_interrupt Interrupt Cleared with FIFO disabled");
        end



always @ ( posedge i_clk )
    begin
    uart0_rx_int_d1 <= rx_interrupt;

    if ( rx_interrupt && !uart0_rx_int_d1 )
        begin
        `TB_DEBUG_MESSAGE
        $display("rx_interrupt Interrupt fifo_enable %d, rx_fifo_full %d", 
                 fifo_enable, rx_fifo_full);
        $display("rx_fifo_half_or_more %d, rx_int_timer 0x%08h, rx_fifo_count %d", 
                 rx_fifo_half_or_more, rx_int_timer, rx_fifo_count);
        end
        
    if ( !rx_interrupt && uart0_rx_int_d1 )
        begin
        `TB_DEBUG_MESSAGE
        $display("rx_interrupt Interrupt Cleared fifo_enable %d, rx_fifo_full %d", 
                 fifo_enable, rx_fifo_full);
        $display("    rx_fifo_half_or_more %d, rx_int_timer 0x%08h, rx_fifo_count %d", 
                 rx_fifo_half_or_more, rx_int_timer, rx_fifo_count);
        end
    end


always @( posedge i_clk )
    if ( wb_read_ack || wb_start_write )
        begin
        `TB_DEBUG_MESSAGE
        
        if ( wb_start_write )
            $write("Write 0x%08x to   ", wb_wdata32);
        else
            $write("Read  0x%08x from ", o_wb_dat);
            
        case ( i_wb_adr[15:0] )
            AMBER_UART_PID0:    $write("UART PID0 register"); 
            AMBER_UART_PID1:    $write("UART PID1 register"); 
            AMBER_UART_PID2:    $write("UART PID2 register"); 
            AMBER_UART_PID3:    $write("UART PID3 register"); 
            AMBER_UART_CID0:    $write("UART CID0 register"); 
            AMBER_UART_CID1:    $write("UART CID1 register"); 
            AMBER_UART_CID2:    $write("UART CID2 register"); 
            AMBER_UART_CID3:    $write("UART CID3 register"); 
            AMBER_UART_DR:      $write("UART Tx/Rx char %c", wb_start_write ? wb_wdata32[7:0] : o_wb_dat[7:0] );
            AMBER_UART_RSR:     $write("UART (Read) Receive status, (Write) Error Clear");
            AMBER_UART_LCRH:    $write("UART Line Control High Byte");
            AMBER_UART_LCRM:    $write("UART Line Control Middle Byte");
            AMBER_UART_LCRL:    $write("UART Line Control Low Byte");
            AMBER_UART_CR:      $write("UART Control Register");
            AMBER_UART_FR:      $write("UART Flag Register");
            AMBER_UART_IIR:     $write("UART (Read) Interrupt Identification Register");

            default:
                begin
                `TB_ERROR_MESSAGE
                $write("Unknown UART Register region");
                end
        endcase
        
        $write(", Address 0x%08h\n", i_wb_adr); 
        end
`endif





always @ ( posedge i_clk )
    begin
    if ( rx_fifo_pop  && !rx_fifo_push && rx_fifo_empty )
        begin
        `TB_WARNING_MESSAGE
        $write("UART rx FIFO underflow\n");
        end
    if ( !rx_fifo_pop  && rx_fifo_push && rx_fifo_full )
        begin
        `TB_WARNING_MESSAGE
        $write("UART rx FIFO overflow\n");
        end

    if ( tx_fifo_push && tx_fifo_full )
        begin
        `TB_WARNING_MESSAGE
        $display("UART tx FIFO overflow - char = %c", wb_wdata32[7:0]);
        end
    end






wire    [(10*8)-1:0]    xTXD_STATE;
wire    [(14*8)-1:0]    xRXD_STATE;

 
assign xTXD_STATE      = txd_state == TXD_IDLE       ? "TXD_IDLE"   :
                         txd_state == TXD_START      ? "TXD_START"  :
                         txd_state == TXD_DATA0      ? "TXD_DATA0"  :
                         txd_state == TXD_DATA1      ? "TXD_DATA1"  :
                         txd_state == TXD_DATA2      ? "TXD_DATA2"  :
                         txd_state == TXD_DATA3      ? "TXD_DATA3"  :
                         txd_state == TXD_DATA4      ? "TXD_DATA4"  :
                         txd_state == TXD_DATA5      ? "TXD_DATA5"  :
                         txd_state == TXD_DATA6      ? "TXD_DATA6"  :
                         txd_state == TXD_DATA7      ? "TXD_DATA7"  :
                         txd_state == TXD_STOP1      ? "TXD_STOP1"  :
                         txd_state == TXD_STOP2      ? "TXD_STOP2"  :
                         txd_state == TXD_STOP3      ? "TXD_STOP3"  :
                                                       "UNKNOWN"    ;

assign xRXD_STATE      = rxd_state == RXD_IDLE       ? "RXD_IDLE"      :
                         rxd_state == RXD_START      ? "RXD_START"     :
                         rxd_state == RXD_START_MID1 ? "RXD_START_MID1":
                         rxd_state == RXD_START_MID  ? "RXD_START_MID" :
                         rxd_state == RXD_DATA0      ? "RXD_DATA0"     :
                         rxd_state == RXD_DATA1      ? "RXD_DATA1"     :
                         rxd_state == RXD_DATA2      ? "RXD_DATA2"     :
                         rxd_state == RXD_DATA3      ? "RXD_DATA3"     :
                         rxd_state == RXD_DATA4      ? "RXD_DATA4"     :
                         rxd_state == RXD_DATA5      ? "RXD_DATA5"     :
                         rxd_state == RXD_DATA6      ? "RXD_DATA6"     :
                         rxd_state == RXD_DATA7      ? "RXD_DATA7"     :
                         rxd_state == RXD_STOP       ? "RXD_STOP"      :
                                                       "UNKNOWN"       ;




endmodule
module uart  #(
parameter WB_DWIDTH  = 32,
parameter WB_SWIDTH  = 4
)(
input                       i_clk,

input       [31:0]          i_wb_adr,
input       [WB_SWIDTH-1:0] i_wb_sel,
input                       i_wb_we,
output      [WB_DWIDTH-1:0] o_wb_dat,
input       [WB_DWIDTH-1:0] i_wb_dat,
input                       i_wb_cyc,
input                       i_wb_stb,
output                      o_wb_ack,
output                      o_wb_err,

output                      o_uart_int,

input                       i_uart_cts_n,
output                      o_uart_txd,
output                      o_uart_rts_n,
input                       i_uart_rxd

);



`include "register_addresses.v"


localparam [3:0] TXD_IDLE  = 4'd0,
                 TXD_START = 4'd1,
                 TXD_DATA0 = 4'd2,
                 TXD_DATA1 = 4'd3,
                 TXD_DATA2 = 4'd4,
                 TXD_DATA3 = 4'd5,
                 TXD_DATA4 = 4'd6,
                 TXD_DATA5 = 4'd7,
                 TXD_DATA6 = 4'd8,
                 TXD_DATA7 = 4'd9,
                 TXD_STOP1 = 4'd10,
                 TXD_STOP2 = 4'd11,
                 TXD_STOP3 = 4'd12;
                 
localparam [3:0] RXD_IDLE       = 4'd0,
                 RXD_START      = 4'd1,
                 RXD_START_MID  = 4'd2,
                 RXD_START_MID1 = 4'd3,
                 RXD_DATA0      = 4'd4,
                 RXD_DATA1      = 4'd5,
                 RXD_DATA2      = 4'd6,
                 RXD_DATA3      = 4'd7,
                 RXD_DATA4      = 4'd8,
                 RXD_DATA5      = 4'd9,
                 RXD_DATA6      = 4'd10,
                 RXD_DATA7      = 4'd11,
                 RXD_STOP       = 4'd12;


localparam RX_INTERRUPT_COUNT = 24'h3fffff; 






`ifndef Veritak
localparam real UART_BAUD         = `AMBER_UART_BAUD;

`ifdef XILINX_VIRTEX6_FPGA
localparam real CLK_FREQ          = 1200.0 / `AMBER_CLK_DIVIDER ;
`else
localparam real CLK_FREQ          = 800.0 / `AMBER_CLK_DIVIDER ;
`endif

localparam real UART_BIT_PERIOD   = 1000000000 / UART_BAUD;
localparam real UART_WORD_PERIOD  = ( UART_BIT_PERIOD * 12 );
localparam real CLK_PERIOD        = 1000 / CLK_FREQ;
localparam real CLKS_PER_WORD     = UART_WORD_PERIOD / CLK_PERIOD;
localparam real CLKS_PER_BIT      = CLKS_PER_WORD / 12;




localparam [9:0] TX_BITPULSE_COUNT         = CLKS_PER_BIT;
localparam [9:0] TX_CLKS_PER_WORD          = CLKS_PER_WORD;
`else
localparam [9:0] TX_BITPULSE_COUNT         = 30;
localparam [9:0] TX_CLKS_PER_WORD          = 360;
`endif

localparam [9:0] TX_BITADJUST_COUNT        = TX_CLKS_PER_WORD - 11*TX_BITPULSE_COUNT;

localparam [9:0] RX_BITPULSE_COUNT         = TX_BITPULSE_COUNT-2;
localparam [9:0] RX_HALFPULSE_COUNT        = TX_BITPULSE_COUNT/2 - 4;




reg             tx_interrupt = 'd0;
reg             rx_interrupt = 'd0;
reg   [23:0]    rx_int_timer = 'd0;

wire            fifo_enable;

reg   [7:0]     tx_fifo    [0:15];
wire            tx_fifo_full;
wire            tx_fifo_empty;
wire            tx_fifo_half_or_less_full;
wire            tx_fifo_push;
wire            tx_fifo_push_not_full;
wire            tx_fifo_pop_not_empty;
reg   [4:0]     tx_fifo_wp = 'd0;
reg   [4:0]     tx_fifo_rp = 'd0;
reg   [4:0]     tx_fifo_count = 'd0;
reg             tx_fifo_full_flag = 'd0;

reg   [7:0]     rx_fifo    [0:15];
reg             rx_fifo_empty = 1'd1;
reg             rx_fifo_full = 1'd0;
wire            rx_fifo_half_or_more;
reg   [4:0]     rx_fifo_count = 'd0;
wire            rx_fifo_push;
wire            rx_fifo_push_not_full;
wire            rx_fifo_pop;
wire            rx_fifo_pop_not_empty;
reg   [4:0]     rx_fifo_wp = 'd0;
reg   [4:0]     rx_fifo_rp = 'd0;

wire  [7:0]     tx_byte;
reg   [3:0]     txd_state = TXD_IDLE;
reg             txd = 1'd1;
reg             tx_bit_pulse = 'd0;
reg   [9:0]     tx_bit_pulse_count = 'd0;

reg   [7:0]     rx_byte = 'd0;
reg   [3:0]     rxd_state = RXD_IDLE;
wire            rx_start;
reg             rxen = 'd0;
reg   [9:0]     rx_bit_pulse_count = 'd0;
reg             restart_rx_bit_count = 'd0;
reg   [4:0]     rxd_d = 5'h1f;
reg   [3:0]     uart0_cts_n_d = 4'hf;


reg  [7:0]      uart_rsr_reg = 'd0;
reg  [7:0]      uart_lcrh_reg = 'd0;
reg  [7:0]      uart_lcrm_reg = 'd0;
reg  [7:0]      uart_lcrl_reg = 'd0;
reg  [7:0]      uart_cr_reg = 'd0;


reg  [31:0]     wb_rdata32 = 'd0;
wire            wb_start_write;
wire            wb_start_read;
reg             wb_start_read_d1 = 'd0;
wire [31:0]     wb_wdata32;

integer         i;







assign wb_start_write = i_wb_stb &&  i_wb_we && !wb_start_read_d1;
assign wb_start_read  = i_wb_stb && !i_wb_we && !o_wb_ack;

always @( posedge i_clk )
    wb_start_read_d1 <= wb_start_read;

assign o_wb_err = 1'd0;
assign o_wb_ack = i_wb_stb && ( wb_start_write || wb_start_read_d1 );

generate
if (WB_DWIDTH == 128) 
    begin : wb128
    assign wb_wdata32   = i_wb_adr[3:2] == 2'd3 ? i_wb_dat[127:96] :
                          i_wb_adr[3:2] == 2'd2 ? i_wb_dat[ 95:64] :
                          i_wb_adr[3:2] == 2'd1 ? i_wb_dat[ 63:32] :
                                                  i_wb_dat[ 31: 0] ;
                                                                                                                                            
    assign o_wb_dat    = {4{wb_rdata32}};
    end
else
    begin : wb32
    assign wb_wdata32  = i_wb_dat;
    assign o_wb_dat    = wb_rdata32;
    end
endgenerate

        



                       
assign rx_fifo_pop           = wb_start_read && i_wb_adr[15:0] == AMBER_UART_DR;
assign rx_fifo_push_not_full = rx_fifo_push && !rx_fifo_full;
assign rx_fifo_pop_not_empty = rx_fifo_pop && !rx_fifo_empty;
assign rx_fifo_half_or_more  = rx_fifo_count >= 5'd8;


always @ ( posedge i_clk ) 
    begin
    if ( fifo_enable )
        begin

        if ( rx_fifo_push_not_full )
            begin
            rx_fifo[rx_fifo_wp[3:0]]    <= rx_byte;                
            rx_fifo_wp                  <= rx_fifo_wp + 1'd1;
            end

        if ( rx_fifo_pop_not_empty )
            begin
            rx_fifo_rp                  <= rx_fifo_rp + 1'd1;
            end
            
        if ( rx_fifo_push_not_full && !rx_fifo_pop_not_empty )
            rx_fifo_count <= rx_fifo_count + 1'd1;
        else if ( rx_fifo_pop_not_empty  && !rx_fifo_push_not_full )
            rx_fifo_count <= rx_fifo_count - 1'd1;
        
        rx_fifo_full  <= rx_fifo_wp == {~rx_fifo_rp[4], rx_fifo_rp[3:0]};
        rx_fifo_empty <= rx_fifo_wp == rx_fifo_rp;
        
        if ( rx_fifo_empty || rx_fifo_pop )
            rx_int_timer     <= 'd0;
        else if ( rx_int_timer != RX_INTERRUPT_COUNT )
            rx_int_timer     <= rx_int_timer + 1'd1;
        
            
        end
    else
        begin
        rx_int_timer     <= 'd0;
        
        if ( rx_fifo_push )
            begin
            rx_fifo[0]         <= rx_byte;
            rx_fifo_empty      <= 1'd0;
            rx_fifo_full       <= 1'd1;
            end
        else if ( rx_fifo_pop )
            begin
            rx_fifo_empty      <= 1'd1;
            rx_fifo_full       <= 1'd0;
            end
        end
    end








always @ ( posedge i_clk )
    begin 

    if ( wb_start_write && i_wb_adr[15:0] == AMBER_UART_ICR )
        tx_interrupt <= 1'd0;


    else if  ( fifo_enable ) 


        tx_interrupt <= tx_fifo_half_or_less_full && uart_cr_reg[5];
    else 


        tx_interrupt <= tx_fifo_empty && uart_cr_reg[5];
    end






always @ ( posedge i_clk )
    if (fifo_enable)
        rx_interrupt <=  rx_fifo_half_or_more || rx_int_timer == RX_INTERRUPT_COUNT;
    else    
        rx_interrupt <=  rx_fifo_full;


assign o_uart_int   = ( tx_interrupt & uart_cr_reg[5] )  |
                      ( rx_interrupt & uart_cr_reg[4] )  ;

assign fifo_enable = uart_lcrh_reg[4];


       




assign   o_uart_txd                 = txd;

assign   tx_fifo_full               = fifo_enable ? tx_fifo_count >= 5'd16 :  tx_fifo_full_flag;
assign   tx_fifo_empty              = fifo_enable ? tx_fifo_count == 5'd00 : !tx_fifo_full_flag;
assign   tx_fifo_half_or_less_full  =               tx_fifo_count <= 5'd8;
assign   tx_byte                    = fifo_enable ? tx_fifo[tx_fifo_rp[3:0]] : tx_fifo[0] ;

assign   tx_fifo_push               = wb_start_write && i_wb_adr[15:0] == AMBER_UART_DR;
assign   tx_fifo_push_not_full      = tx_fifo_push && !tx_fifo_full;
assign   tx_fifo_pop_not_empty      = txd_state == TXD_STOP3 && tx_bit_pulse == 1'd1 && !tx_fifo_empty;

        

always @( posedge i_clk )
    begin      

    if ( fifo_enable )
        begin

        if ( tx_fifo_push_not_full )
            begin
            tx_fifo[tx_fifo_wp[3:0]] <= wb_wdata32[7:0];
            tx_fifo_wp <= tx_fifo_wp + 1'd1;
            end
        
            

        if ( tx_fifo_pop_not_empty )
            tx_fifo_rp <= tx_fifo_rp + 1'd1;
            

        if (tx_fifo_push_not_full && !tx_fifo_pop_not_empty)
            tx_fifo_count <= tx_fifo_count + 1'd1;
            

        else if (tx_fifo_pop_not_empty  && !tx_fifo_push_not_full)
            tx_fifo_count <= tx_fifo_count - 1'd1;
        end
        

    else  
        begin

        tx_fifo_wp    <= 'd0;
        tx_fifo_rp    <= 'd0;
        tx_fifo_count <= 'd0;
        

        if ( tx_fifo_push_not_full )
            begin
            tx_fifo[0]          <= wb_wdata32[7:0];
            tx_fifo_full_flag   <= 1'd1;
            end

        else if ( tx_fifo_pop_not_empty )
            tx_fifo_full_flag   <= 1'd0;

        end        
    end





always @( posedge i_clk )
    uart0_cts_n_d <= {uart0_cts_n_d[2:0], i_uart_cts_n};
                                            




always @( posedge i_clk )
    if (( tx_bit_pulse_count == (TX_BITADJUST_COUNT-1) && txd_state == TXD_STOP2 ) ||
        ( tx_bit_pulse_count == (TX_BITPULSE_COUNT-1)  && txd_state != TXD_STOP2 )  )
        begin
        tx_bit_pulse_count <= 'd0;
        tx_bit_pulse       <= 1'd1;
        end
    else
        begin
        tx_bit_pulse_count <= tx_bit_pulse_count + 1'd1;
        tx_bit_pulse       <= 1'd0;
        end









    
     

always @( posedge i_clk )
    if ( tx_bit_pulse )
    
        case ( txd_state )
        
            TXD_IDLE :
                begin
                txd       <= 1'd1;
                
                if ( uart0_cts_n_d[3:1] == 3'b000 && !tx_fifo_empty )
                    txd_state <= TXD_START;
                end
                
            TXD_START :
                begin
                txd       <= 1'd0;
                txd_state <= TXD_DATA0;
                end
                
            TXD_DATA0 :
                begin
                txd       <= tx_byte[0];
                txd_state <= TXD_DATA1;
                end
                
            TXD_DATA1 :
                begin
                txd       <= tx_byte[1];
                txd_state <= TXD_DATA2;
                end
                
            TXD_DATA2 :
                begin
                txd       <= tx_byte[2];
                txd_state <= TXD_DATA3;
                end
                
            TXD_DATA3 :
                begin
                txd       <= tx_byte[3];
                txd_state <= TXD_DATA4;
                end
                
            TXD_DATA4 :
                begin
                txd       <= tx_byte[4];
                txd_state <= TXD_DATA5;
                end
                
            TXD_DATA5 :
                begin
                txd       <= tx_byte[5];
                txd_state <= TXD_DATA6;
                end
                
            TXD_DATA6 :
                begin
                txd       <= tx_byte[6];
                txd_state <= TXD_DATA7;
                end
                
            TXD_DATA7 :
                begin
                txd       <= tx_byte[7];
                txd_state <= TXD_STOP1;
                end
                
            TXD_STOP1 :
                begin
                txd       <= 1'd1;
                txd_state <= TXD_STOP2;
                end

            TXD_STOP2 :
                begin
                txd       <= 1'd1;
                txd_state <= TXD_STOP3;
                end
                
            TXD_STOP3 :
                begin
                txd       <= 1'd1;
                txd_state <= TXD_IDLE;
                end
                
            default :
                begin
                txd       <= 1'd1;
                end
                
        endcase








assign o_uart_rts_n  = ~rxen;

assign rx_fifo_push  = rxd_state == RXD_STOP && rx_bit_pulse_count == 10'd0;





always @( posedge i_clk )
    if ( restart_rx_bit_count )
        rx_bit_pulse_count <= 'd0;
    else
        rx_bit_pulse_count <= rx_bit_pulse_count + 1'd1;





always @( posedge i_clk )
    rxd_d[4:0] <= {rxd_d[3:0], i_uart_rxd};

assign rx_start = rxd_d[4:3] == 2'b11 && rxd_d[1:0] == 2'b00;






always @( posedge i_clk )
    case ( rxd_state )
    
        RXD_IDLE :
            if ( rx_fifo_full )
                rxen                    <= 1'd0;
            else
                begin
                rxd_state               <= RXD_START;
                rxen                    <= 1'd1;
                restart_rx_bit_count    <= 1'd1;
                rx_byte                 <= 'd0;
                end
            
        RXD_START : 

            if ( rx_start ) 
                begin
                rxd_state               <= RXD_START_MID1;
                restart_rx_bit_count    <= 1'd1;
                end
            else    
                restart_rx_bit_count    <= 1'd0;




        RXD_START_MID1 :
            rxd_state               <= RXD_START_MID;
            
        RXD_START_MID :
            if ( rx_bit_pulse_count == RX_HALFPULSE_COUNT )
                begin
                rxd_state               <= RXD_DATA0;
                restart_rx_bit_count    <= 1'd1;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        RXD_DATA0 :
            if ( rx_bit_pulse_count == RX_BITPULSE_COUNT )
                begin
                rxd_state               <= RXD_DATA1;
                restart_rx_bit_count    <= 1'd1;
                rx_byte[0]              <= i_uart_rxd;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        RXD_DATA1 :
            if ( rx_bit_pulse_count == RX_BITPULSE_COUNT )
                begin
                rxd_state               <= RXD_DATA2;
                restart_rx_bit_count    <= 1'd1;
                rx_byte[1]              <= i_uart_rxd;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        RXD_DATA2 :
            if ( rx_bit_pulse_count == RX_BITPULSE_COUNT )
                begin
                rxd_state               <= RXD_DATA3;
                restart_rx_bit_count    <= 1'd1;
                rx_byte[2]              <= i_uart_rxd;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        RXD_DATA3 :
            if ( rx_bit_pulse_count == RX_BITPULSE_COUNT )
                begin
                rxd_state               <= RXD_DATA4;
                restart_rx_bit_count    <= 1'd1;
                rx_byte[3]              <= i_uart_rxd;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        RXD_DATA4 :
            if ( rx_bit_pulse_count ==  RX_BITPULSE_COUNT )
                begin
                rxd_state               <= RXD_DATA5;
                restart_rx_bit_count    <= 1'd1;
                rx_byte[4]              <= i_uart_rxd;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        RXD_DATA5 :
            if ( rx_bit_pulse_count ==  RX_BITPULSE_COUNT )
                begin
                rxd_state               <= RXD_DATA6;
                restart_rx_bit_count    <= 1'd1;
                rx_byte[5]              <= i_uart_rxd;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        RXD_DATA6 :
            if ( rx_bit_pulse_count ==  RX_BITPULSE_COUNT )
                begin
                rxd_state               <= RXD_DATA7;
                restart_rx_bit_count    <= 1'd1;
                rx_byte[6]              <= i_uart_rxd;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        RXD_DATA7 :
            if ( rx_bit_pulse_count ==  RX_BITPULSE_COUNT )
                begin
                rxd_state               <= RXD_STOP;
                restart_rx_bit_count    <= 1'd1;
                rx_byte[7]              <= i_uart_rxd;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        RXD_STOP :
            if ( rx_bit_pulse_count ==  RX_BITPULSE_COUNT )
                begin
                rxd_state               <= RXD_IDLE;
                restart_rx_bit_count    <= 1'd1;
                end
            else    
                restart_rx_bit_count    <= 1'd0;
            
        default :
            begin
            rxd_state       <= RXD_IDLE;
            end
            
    endcase

        



always @( posedge i_clk )
    if ( wb_start_write )
        case ( i_wb_adr[15:0] )

            AMBER_UART_RSR:  uart_rsr_reg      <= wb_wdata32[7:0];

            AMBER_UART_LCRH: uart_lcrh_reg     <= wb_wdata32[7:0];

            AMBER_UART_LCRM: uart_lcrm_reg     <= wb_wdata32[7:0];

            AMBER_UART_LCRL: uart_lcrl_reg     <= wb_wdata32[7:0];

            AMBER_UART_CR:   uart_cr_reg       <= wb_wdata32[7:0];
        endcase





always @( posedge i_clk )
    if ( wb_start_read )
        case ( i_wb_adr[15:0] )
        
            AMBER_UART_CID0:    wb_rdata32 <= 32'h0d;
            AMBER_UART_CID1:    wb_rdata32 <= 32'hf0;
            AMBER_UART_CID2:    wb_rdata32 <= 32'h05;
            AMBER_UART_CID3:    wb_rdata32 <= 32'hb1;
            AMBER_UART_PID0:    wb_rdata32 <= 32'h10;
            AMBER_UART_PID1:    wb_rdata32 <= 32'h10;
            AMBER_UART_PID2:    wb_rdata32 <= 32'h04;
            AMBER_UART_PID3:    wb_rdata32 <= 32'h00;
            
            AMBER_UART_DR:
                    if ( fifo_enable )
                        wb_rdata32 <= {24'd0, rx_fifo[rx_fifo_rp[3:0]]};
                    else    
                        wb_rdata32 <= {24'd0, rx_fifo[0]};
                                      
            AMBER_UART_RSR:     wb_rdata32 <= uart_rsr_reg;
            AMBER_UART_LCRH:    wb_rdata32 <= uart_lcrh_reg;
            AMBER_UART_LCRM:    wb_rdata32 <= uart_lcrm_reg;
            AMBER_UART_LCRL:    wb_rdata32 <= uart_lcrl_reg;
            AMBER_UART_CR:      wb_rdata32 <= uart_cr_reg;
            

            AMBER_UART_FR:      wb_rdata32 <= {tx_fifo_empty,
                                             rx_fifo_full,
                                             tx_fifo_full,
                                             rx_fifo_empty,
                                             !tx_fifo_empty,
                                             1'd1,
                                             1'd1,
                                             !uart0_cts_n_d[3]
                                             };
            

            AMBER_UART_IIR:     wb_rdata32 <= {5'd0, 
                                             1'd0,
                                             tx_interrupt,
                                             rx_interrupt,
                                             1'd0
                                            };
                                            
            default:            wb_rdata32 <= 32'h00c0ffee;
            
        endcase

        















`ifndef Veritak


initial
    begin
    if ((( TX_BITPULSE_COUNT * CLK_PERIOD ) > (UART_BIT_PERIOD * 1.03) ) ||
        (( TX_BITPULSE_COUNT * CLK_PERIOD ) < (UART_BIT_PERIOD * 0.97) ) )
        begin
        `TB_ERROR_MESSAGE
        $display("UART TX bit period, %.1f, is too big. UART will not work!", TX_BITPULSE_COUNT * CLK_PERIOD);
        $display("Baud rate is %f, and baud bit period is %.1f", UART_BAUD, UART_BIT_PERIOD);
        $display("Either reduce the baud rate, or increase the system clock frequency");
        $display("------");
        end
    end
`endif
    

`ifdef AMBER_UART_DEBUG
wire            wb_read_ack;
reg             uart0_rx_int_d1 = 'd0;

assign wb_read_ack = i_wb_stb && !i_wb_we &&  o_wb_ack;

`ifndef Veritak
initial
    begin
    $display("%m UART period = %f nS, want %f nS, %d, %d", 
             (TX_BITPULSE_COUNT*11 + TX_BITADJUST_COUNT) * CLK_PERIOD,
             UART_WORD_PERIOD,
             TX_BITPULSE_COUNT, TX_BITADJUST_COUNT);
    end
`endif



always @ ( posedge i_clk )
    if ( wb_start_write && i_wb_adr[15:0] == AMBER_UART_ICR )
            ;
    else if ( fifo_enable ) 
        begin
        if (tx_interrupt == 1'd0 && tx_fifo_half_or_less_full && uart_cr_reg[5])
            $display("%m: tx_interrupt Interrupt Set with FIFO enabled");
        if (tx_interrupt == 1'd1 && !(tx_fifo_half_or_less_full && uart_cr_reg[5]))
            $display("%m: tx_interrupt Interrupt Cleared with FIFO enabled");
        end
    else
        begin
        if (tx_interrupt == 1'd0 && tx_fifo_empty && uart_cr_reg[5])
            $display("%m: tx_interrupt Interrupt Set with FIFO disabled");
        if (tx_interrupt == 1'd1 && !(tx_fifo_empty && uart_cr_reg[5]))
            $display("%m: tx_interrupt Interrupt Cleared with FIFO disabled");
        end



always @ ( posedge i_clk )
    begin
    uart0_rx_int_d1 <= rx_interrupt;

    if ( rx_interrupt && !uart0_rx_int_d1 )
        begin
        `TB_DEBUG_MESSAGE
        $display("rx_interrupt Interrupt fifo_enable %d, rx_fifo_full %d", 
                 fifo_enable, rx_fifo_full);
        $display("rx_fifo_half_or_more %d, rx_int_timer 0x%08h, rx_fifo_count %d", 
                 rx_fifo_half_or_more, rx_int_timer, rx_fifo_count);
        end
        
    if ( !rx_interrupt && uart0_rx_int_d1 )
        begin
        `TB_DEBUG_MESSAGE
        $display("rx_interrupt Interrupt Cleared fifo_enable %d, rx_fifo_full %d", 
                 fifo_enable, rx_fifo_full);
        $display("    rx_fifo_half_or_more %d, rx_int_timer 0x%08h, rx_fifo_count %d", 
                 rx_fifo_half_or_more, rx_int_timer, rx_fifo_count);
        end
    end


always @( posedge i_clk )
    if ( wb_read_ack || wb_start_write )
        begin
        `TB_DEBUG_MESSAGE
        
        if ( wb_start_write )
            $write("Write 0x%08x to   ", wb_wdata32);
        else
            $write("Read  0x%08x from ", o_wb_dat);
            
        case ( i_wb_adr[15:0] )
            AMBER_UART_PID0:    $write("UART PID0 register"); 
            AMBER_UART_PID1:    $write("UART PID1 register"); 
            AMBER_UART_PID2:    $write("UART PID2 register"); 
            AMBER_UART_PID3:    $write("UART PID3 register"); 
            AMBER_UART_CID0:    $write("UART CID0 register"); 
            AMBER_UART_CID1:    $write("UART CID1 register"); 
            AMBER_UART_CID2:    $write("UART CID2 register"); 
            AMBER_UART_CID3:    $write("UART CID3 register"); 
            AMBER_UART_DR:      $write("UART Tx/Rx char %c", wb_start_write ? wb_wdata32[7:0] : o_wb_dat[7:0] );
            AMBER_UART_RSR:     $write("UART (Read) Receive status, (Write) Error Clear");
            AMBER_UART_LCRH:    $write("UART Line Control High Byte");
            AMBER_UART_LCRM:    $write("UART Line Control Middle Byte");
            AMBER_UART_LCRL:    $write("UART Line Control Low Byte");
            AMBER_UART_CR:      $write("UART Control Register");
            AMBER_UART_FR:      $write("UART Flag Register");
            AMBER_UART_IIR:     $write("UART (Read) Interrupt Identification Register");

            default:
                begin
                `TB_ERROR_MESSAGE
                $write("Unknown UART Register region");
                end
        endcase
        
        $write(", Address 0x%08h\n", i_wb_adr); 
        end
`endif





always @ ( posedge i_clk )
    begin
    if ( rx_fifo_pop  && !rx_fifo_push && rx_fifo_empty )
        begin
        `TB_WARNING_MESSAGE
        $write("UART rx FIFO underflow\n");
        end
    if ( !rx_fifo_pop  && rx_fifo_push && rx_fifo_full )
        begin
        `TB_WARNING_MESSAGE
        $write("UART rx FIFO overflow\n");
        end

    if ( tx_fifo_push && tx_fifo_full )
        begin
        `TB_WARNING_MESSAGE
        $display("UART tx FIFO overflow - char = %c", wb_wdata32[7:0]);
        end
    end






wire    [(10*8)-1:0]    xTXD_STATE;
wire    [(14*8)-1:0]    xRXD_STATE;

 
assign xTXD_STATE      = txd_state == TXD_IDLE       ? "TXD_IDLE"   :
                         txd_state == TXD_START      ? "TXD_START"  :
                         txd_state == TXD_DATA0      ? "TXD_DATA0"  :
                         txd_state == TXD_DATA1      ? "TXD_DATA1"  :
                         txd_state == TXD_DATA2      ? "TXD_DATA2"  :
                         txd_state == TXD_DATA3      ? "TXD_DATA3"  :
                         txd_state == TXD_DATA4      ? "TXD_DATA4"  :
                         txd_state == TXD_DATA5      ? "TXD_DATA5"  :
                         txd_state == TXD_DATA6      ? "TXD_DATA6"  :
                         txd_state == TXD_DATA7      ? "TXD_DATA7"  :
                         txd_state == TXD_STOP1      ? "TXD_STOP1"  :
                         txd_state == TXD_STOP2      ? "TXD_STOP2"  :
                         txd_state == TXD_STOP3      ? "TXD_STOP3"  :
                                                       "UNKNOWN"    ;

assign xRXD_STATE      = rxd_state == RXD_IDLE       ? "RXD_IDLE"      :
                         rxd_state == RXD_START      ? "RXD_START"     :
                         rxd_state == RXD_START_MID1 ? "RXD_START_MID1":
                         rxd_state == RXD_START_MID  ? "RXD_START_MID" :
                         rxd_state == RXD_DATA0      ? "RXD_DATA0"     :
                         rxd_state == RXD_DATA1      ? "RXD_DATA1"     :
                         rxd_state == RXD_DATA2      ? "RXD_DATA2"     :
                         rxd_state == RXD_DATA3      ? "RXD_DATA3"     :
                         rxd_state == RXD_DATA4      ? "RXD_DATA4"     :
                         rxd_state == RXD_DATA5      ? "RXD_DATA5"     :
                         rxd_state == RXD_DATA6      ? "RXD_DATA6"     :
                         rxd_state == RXD_DATA7      ? "RXD_DATA7"     :
                         rxd_state == RXD_STOP       ? "RXD_STOP"      :
                                                       "UNKNOWN"       ;




endmodule