Advertisement
Guest User

Untitled

a guest
Dec 27th, 2011
196
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. `timescale 1ns / 1ps
  2. /**
  3.     @brief A single 8-bit, no parity, 1 stop bit serial port.
  4.    
  5.     This is the raw UART and does not have a FIFO etc. The parent module must read
  6.     data the cycle after it becomes available and process or store it.
  7.    
  8.     @param clk      20.48 MHz clock signal
  9.     @param clkdiv   Clock divisor for baud rate generator (115200 baud = 178)
  10.  
  11.     @param tx       Outbound serial data line
  12.     @param txin     8-bit wide bus containing data to be transmitted
  13.     @param txrdy    Bring high for 1 clk when data is ready to be transmitted
  14.     @param txactive Indicates if transmitter is busy
  15.    
  16.     @param rx       Inbound serial data line
  17.     @param rxout    8-bit wide bus containing data recieved
  18.     @param rxrdy    Goes high for one clk when valid data is present on rxout
  19.     @param rxactive Indicates if reciever is busy
  20.  */
  21. module UART(clk, clkdiv, tx, txin, txrdy, txactive, rx, rxout, rxrdy, rxactive);
  22.  
  23.     input wire clk;
  24.     input wire[15:0] clkdiv;
  25.     input wire rx;
  26.    
  27.     //1/4 of the clock divisor (for 90 degree phase offset)
  28.     wire[13:0] clkdiv_offset;
  29.     assign clkdiv_offset = clkdiv[15:2];
  30.    
  31.     ///////////////////////////////////////////////////////////////////////////////////////////////
  32.     //Receiver
  33.     reg[15:0] rxbrg;
  34.     output reg rxactive;
  35.     reg[4:0] rxbitcount;
  36.     reg[7:0] rxbuf;
  37.     output reg[7:0] rxout;
  38.     output reg rxrdy;
  39.     initial begin
  40.         rxbrg <= 0;
  41.         rxactive <= 0;
  42.         rxbitcount <= 0;
  43.         rxbuf <= 0;
  44.         rxout <= 0;
  45.         rxrdy <= 0;
  46.     end
  47.    
  48.     always @(posedge clk) begin
  49.        
  50.         //Clear data from output after one clock
  51.         if(rxrdy) begin
  52.             rxrdy <= 0;
  53.             rxout <= 0;
  54.         end
  55.        
  56.         //If not currently recieving, look for falling edge on RX (start bit)
  57.         if(!rxactive) begin
  58.             if(rx == 0) begin
  59.                
  60.                 //Falling edge, start receiving after 1.25 bit period
  61.                 //We want to sample 90 degrees out of phase with the original signal to get nice stable values
  62.                 rxactive <= 1;
  63.                 rxbrg <= clkdiv_offset + clkdiv;
  64.                 rxbitcount <= 0;
  65.             end
  66.         end
  67.        
  68.         //Currently recieving
  69.         else begin
  70.             rxbrg <= rxbrg - 1;
  71.            
  72.             //Time to sample a new bit
  73.             if(rxbrg == 0) begin
  74.            
  75.                 //If we are on bits 0 through 7 (not the stop bit) read the bit into the rxbuf and bump the bit count, then reset the baud generator
  76.                 if(rxbitcount < 8) begin
  77.                     rxbuf <= {rx, rxbuf[7:1]};
  78.                     rxbitcount <= rxbitcount + 1;
  79.                     rxbrg <= clkdiv;
  80.                 end
  81.                
  82.                 //Stop bit
  83.                 else begin
  84.                    
  85.                     //Should always be 1, print warning in sim if this isnt the case
  86.                     if(rx != 1)
  87.                         $display("[UART] Warning - stop bit isn't zero");
  88.                    
  89.                     //We're done reading
  90.                     rxbitcount <= 0;
  91.                     rxactive <= 0;
  92.                    
  93.                     //Data is ready
  94.                     rxout <= rxbuf;
  95.                     rxrdy <= 1;
  96.                     $display("[UART] Read byte 0x%02x - '%c'", rxbuf, rxbuf);
  97.                 end
  98.                
  99.             end
  100.    
  101.         end
  102.        
  103.     end
  104.    
  105.     ///////////////////////////////////////////////////////////////////////////////////////////////
  106.     //Transmitter
  107.     output reg tx;
  108.     input wire txrdy;
  109.     input wire [7:0] txin;
  110.    
  111.     reg[15:0] txbrg;
  112.     reg[7:0] txbuf;
  113.     output reg txactive;
  114.     reg [3:0] txbitcount;
  115.     initial begin
  116.         tx <= 1;
  117.         txbuf <= 0;
  118.         txactive <= 0;
  119.         txbrg <= 0;
  120.         txbitcount <= 0;
  121.     end
  122.    
  123.     always @(posedge clk) begin
  124.        
  125.         //Time to start sending a new byte?
  126.         if(txrdy) begin
  127.        
  128.             //Already transmitting? Drop the byte, nothing we can do here.
  129.             //TODO: add a FIFO
  130.             if(txactive) begin
  131.                 $display("[UART] Warning - transmit buffer overflow, byte dropped");
  132.             end
  133.            
  134.             //Nope, set up a transmission
  135.             else begin
  136.                 if(txin > 8'h20) begin
  137.                     $display("[UART] sending byte 0x%02x - '%c'", txin, txin);
  138.                 end
  139.                 else begin
  140.                     $display("[UART] sending byte 0x%02x", txin);
  141.                 end
  142.                 txbuf <= txin;
  143.                 txactive <= 1;
  144.                 txbitcount <= 0;
  145.                
  146.                 //Send the start bit immediately
  147.                 tx <= 0;
  148.                 txbrg <= clkdiv;
  149.             end
  150.            
  151.         end
  152.        
  153.         //Currently transmitting?
  154.         if(txactive) begin
  155.        
  156.             //Done with this bit?
  157.             if(txbrg == 0) begin
  158.                
  159.                 //Are we still sending normal data bits?
  160.                 //Send the next data bit (LSB first)
  161.                 if(txbitcount < 8) begin
  162.                     txbitcount <= txbitcount + 1;
  163.                     tx <= txbuf[0];
  164.                     txbuf <= {1'b0, txbuf[7:1]};
  165.                     txbrg <= clkdiv;
  166.                 end
  167.                
  168.                 //Time to send the stop bit?
  169.                 //Send it
  170.                 else if(txbitcount == 8) begin
  171.                     txbitcount <= 9;
  172.                     tx <= 1;
  173.                     txbrg <= clkdiv;
  174.                 end
  175.                
  176.                 //Done sending? Reset stuff
  177.                 else if(txbitcount == 9) begin
  178.                     txbitcount <= 0;
  179.                     txactive <= 0;
  180.                 end
  181.                
  182.             end
  183.            
  184.             //Nope, just keep count
  185.             else begin
  186.                 txbrg <= txbrg - 1;
  187.             end
  188.        
  189.         end
  190.        
  191.     end
  192.  
  193. endmodule
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement