Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- `timescale 1ns / 1ps
- /**
- @brief A single 8-bit, no parity, 1 stop bit serial port.
- This is the raw UART and does not have a FIFO etc. The parent module must read
- data the cycle after it becomes available and process or store it.
- @param clk 20.48 MHz clock signal
- @param clkdiv Clock divisor for baud rate generator (115200 baud = 178)
- @param tx Outbound serial data line
- @param txin 8-bit wide bus containing data to be transmitted
- @param txrdy Bring high for 1 clk when data is ready to be transmitted
- @param txactive Indicates if transmitter is busy
- @param rx Inbound serial data line
- @param rxout 8-bit wide bus containing data recieved
- @param rxrdy Goes high for one clk when valid data is present on rxout
- @param rxactive Indicates if reciever is busy
- */
- module UART(clk, clkdiv, tx, txin, txrdy, txactive, rx, rxout, rxrdy, rxactive);
- input wire clk;
- input wire[15:0] clkdiv;
- input wire rx;
- //1/4 of the clock divisor (for 90 degree phase offset)
- wire[13:0] clkdiv_offset;
- assign clkdiv_offset = clkdiv[15:2];
- ///////////////////////////////////////////////////////////////////////////////////////////////
- //Receiver
- reg[15:0] rxbrg;
- output reg rxactive;
- reg[4:0] rxbitcount;
- reg[7:0] rxbuf;
- output reg[7:0] rxout;
- output reg rxrdy;
- initial begin
- rxbrg <= 0;
- rxactive <= 0;
- rxbitcount <= 0;
- rxbuf <= 0;
- rxout <= 0;
- rxrdy <= 0;
- end
- always @(posedge clk) begin
- //Clear data from output after one clock
- if(rxrdy) begin
- rxrdy <= 0;
- rxout <= 0;
- end
- //If not currently recieving, look for falling edge on RX (start bit)
- if(!rxactive) begin
- if(rx == 0) begin
- //Falling edge, start receiving after 1.25 bit period
- //We want to sample 90 degrees out of phase with the original signal to get nice stable values
- rxactive <= 1;
- rxbrg <= clkdiv_offset + clkdiv;
- rxbitcount <= 0;
- end
- end
- //Currently recieving
- else begin
- rxbrg <= rxbrg - 1;
- //Time to sample a new bit
- if(rxbrg == 0) begin
- //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
- if(rxbitcount < 8) begin
- rxbuf <= {rx, rxbuf[7:1]};
- rxbitcount <= rxbitcount + 1;
- rxbrg <= clkdiv;
- end
- //Stop bit
- else begin
- //Should always be 1, print warning in sim if this isnt the case
- if(rx != 1)
- $display("[UART] Warning - stop bit isn't zero");
- //We're done reading
- rxbitcount <= 0;
- rxactive <= 0;
- //Data is ready
- rxout <= rxbuf;
- rxrdy <= 1;
- $display("[UART] Read byte 0x%02x - '%c'", rxbuf, rxbuf);
- end
- end
- end
- end
- ///////////////////////////////////////////////////////////////////////////////////////////////
- //Transmitter
- output reg tx;
- input wire txrdy;
- input wire [7:0] txin;
- reg[15:0] txbrg;
- reg[7:0] txbuf;
- output reg txactive;
- reg [3:0] txbitcount;
- initial begin
- tx <= 1;
- txbuf <= 0;
- txactive <= 0;
- txbrg <= 0;
- txbitcount <= 0;
- end
- always @(posedge clk) begin
- //Time to start sending a new byte?
- if(txrdy) begin
- //Already transmitting? Drop the byte, nothing we can do here.
- //TODO: add a FIFO
- if(txactive) begin
- $display("[UART] Warning - transmit buffer overflow, byte dropped");
- end
- //Nope, set up a transmission
- else begin
- if(txin > 8'h20) begin
- $display("[UART] sending byte 0x%02x - '%c'", txin, txin);
- end
- else begin
- $display("[UART] sending byte 0x%02x", txin);
- end
- txbuf <= txin;
- txactive <= 1;
- txbitcount <= 0;
- //Send the start bit immediately
- tx <= 0;
- txbrg <= clkdiv;
- end
- end
- //Currently transmitting?
- if(txactive) begin
- //Done with this bit?
- if(txbrg == 0) begin
- //Are we still sending normal data bits?
- //Send the next data bit (LSB first)
- if(txbitcount < 8) begin
- txbitcount <= txbitcount + 1;
- tx <= txbuf[0];
- txbuf <= {1'b0, txbuf[7:1]};
- txbrg <= clkdiv;
- end
- //Time to send the stop bit?
- //Send it
- else if(txbitcount == 8) begin
- txbitcount <= 9;
- tx <= 1;
- txbrg <= clkdiv;
- end
- //Done sending? Reset stuff
- else if(txbitcount == 9) begin
- txbitcount <= 0;
- txactive <= 0;
- end
- end
- //Nope, just keep count
- else begin
- txbrg <= txbrg - 1;
- end
- end
- end
- endmodule
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement