eris2206

Documentation: http://frombelow.net/projects/eris2206/
Clone: git clone https://git.frombelow.net/eris2206.git
Log | Files | Refs | Submodules | README | LICENSE

uart.v (5145B)


      1 /*
      2  * Copyright 2022 Gerd Beuster (gerd@frombelow.net). This is free
      3  * soft-/hardware under the GNU GPL v3 license or any later
      4  * version. See COPYING in the root directory for details.
      5  */
      6 
      7 `ifndef uart_v
      8  `define uart_v
      9 
     10 // In order to send a byte, din is set to the byte to be send and
     11 // write is set to 1. While transmitting, bit 0 of the status register
     12 // is 1.
     13 //
     14 // In order to receive a byte, the receive buffer must be cleared by
     15 // writing to the status register. Once the byte is received, bit 1 of
     16 // the status register is set to 1.
     17 
     18 module uart(input clk, // 12 Mhz system clock
     19             // Data to be send via the serial line is read from din.
     20             input [7:0]  din,
     21 	    // When reg_select is set to 0 (see below), dout carries
     22 	    // the last byte received via the serial line.
     23 	    // When reg_select is set to 1, dout carries the current bits:
     24 	    // Bit 0: The UART is in the process of sending the byte at din
     25 	    // Bit 1: The UART received a byte.
     26             output [7:0] dout,
     27 	    // When reg_select is set to 0 (see below), setting write to 1
     28 	    // starts serial transmission of din.
     29 	    // When reg_select is set to 1, setting write to 1 clears
     30 	    // the receive buffer.
     31             input 	 write,
     32 	    //  0: Data Register
     33 	    //  1: Status register
     34             input 	 reg_select,
     35             // Connections to hardware lines
     36             output reg 	 tx,
     37             input 	 rx);
     38 
     39    reg [9:0]             tx_buffer; // Internal transmit buffer (start bit, data, stop bit)
     40    reg [7:0]             rx_buffer; // Internal receive buffer
     41    reg [7:0]             received_byte; // Last complete byte received
     42    reg [7:0]             bit_time_tx; // Clock ticks until bit transmitted
     43    reg [3:0]             curr_bit_tx; // Index of bit currently transmitted
     44    reg                   rx_busy;
     45    reg                   tx_busy;
     46    wire                  recv_buffer_full;
     47 
     48    parameter ticks_per_bit = 104; // Clock ticks per bit for 115200 bps @ 12 Mhz
     49 
     50    assign dout = reg_select ? {6'b000000, recv_buffer_full, tx_busy} : received_byte;
     51 
     52    initial
     53      begin
     54         tx_busy <= 0;
     55         tx <= 1;
     56         curr_bit_tx <= 0;
     57         rx_busy <= 0;
     58      end
     59 
     60    /*
     61     * Transmitter
     62     *
     63     */
     64 
     65    always @(posedge(clk))
     66      begin
     67         // Begin of transmission
     68         if (write && !reg_select && !tx_busy)
     69           // Transmissions starts on write operation to data register:
     70           // Fill the internal transmit buffer, and get busy.
     71           begin
     72              tx_buffer <= {1'b1, din, 1'b0};
     73              curr_bit_tx <= 0;
     74              bit_time_tx <= ticks_per_bit;
     75              tx_busy <= 1;
     76           end
     77         // End of transmission
     78         if (curr_bit_tx == 10)
     79           begin
     80              // Keep tx high will not transmitting.
     81              tx <= 1;
     82              // If the CPU clock is significangtly slower than the
     83              // system clock, write may still be high. In order to
     84              // avoid sending the same byte again, we only set tx_busy
     85              // to low when write is low as well.
     86              if(!write)
     87                begin
     88                   tx_busy <= 0;
     89                   curr_bit_tx <= 0;
     90                end
     91           end // if (curr_bit_tx == 10)
     92         else
     93           // In transmission
     94           begin
     95              if (tx_busy)
     96                // Output current bit
     97                begin
     98                   tx <= tx_buffer[curr_bit_tx];
     99                   bit_time_tx <= bit_time_tx - 1;
    100                end
    101              if (bit_time_tx == 0)
    102                // Switch to next bit
    103                begin
    104                   curr_bit_tx <= curr_bit_tx + 1;
    105                   bit_time_tx <= ticks_per_bit;
    106                end
    107           end
    108      end // always @ (posedge(clk))
    109 
    110    /*
    111     * Receiver
    112     *
    113     */
    114 
    115    reg [7:0] bit_time_rx; // Clock ticks until bit received
    116    reg [3:0] curr_bit_rx; // Index of bit currently received
    117 
    118    assign recv_buffer_full = (curr_bit_rx == 9);
    119    always @(posedge(clk))
    120      begin
    121         if (write && reg_select)
    122           curr_bit_rx <= 0;
    123         else
    124           begin
    125              if (!rx_busy && !rx)
    126                begin
    127                   // Start receving once we get the start bit
    128                   rx_busy <= 1;
    129                   curr_bit_rx <= 0;
    130                   // bit_time_rx hits 0 in the middle
    131                   // of the first data bit
    132                   bit_time_rx <= ticks_per_bit * 1.5;
    133                end
    134              else if ((curr_bit_rx == 9) && rx)
    135                begin
    136                   // If this is the stop bit, we are done
    137                   rx_busy <= 0;
    138                   received_byte <= rx_buffer;
    139                end
    140              else if ((rx_busy) && (bit_time_rx == 0))
    141                // We are in the middle of the next bit.
    142                begin
    143                   // Read it
    144                   rx_buffer[curr_bit_rx] <= rx;
    145                   curr_bit_rx <= curr_bit_rx + 1;
    146                   bit_time_rx <= ticks_per_bit;
    147                end
    148              else
    149                bit_time_rx <= bit_time_rx - 1;
    150           end
    151      end // always @ (posedge(clk))
    152 
    153 endmodule
    154 
    155 `endif