`resetall `timescale 1ns/10ps module UART_verilog( clock, reset_N, address, writeData, write, readData, read, serialIn, serialOut ); // Internal Declarations input clock; input reset_N; input address; input [7:0] writeData; input write; output [7:0] readData; input read; input serialIn; output serialOut; wire clock; wire reset_N; wire address; wire [7:0] writeData; wire write; wire [7:0] readData; wire read; wire serialIn; wire serialOut; // hds interface_end parameter ONCE = 1, TWICE = 2; parameter IDLE = 0, START = 1, SEND = 2, STOP = 3; parameter // IDLE = 0, // START = 1, RECEIVE = 2, // STOP = 3, FULL = 4, ERROR = 5; parameter c_TX = 0, c_RX = 0, c_STATUS = 1; parameter RxReady = 0, RxError = 1, TxReady = 2; reg s_serialOut; reg [7:0] s_readData; reg [2:0] RxState; reg [1:0] TxState; reg [2:1] serialInRetimed; reg [7:0] Tx, Rx; reg [3:0] RxSampleCount, RxBitCount, TxSampleCount, TxBitCount; reg v_serialOut; reg [7:0] v_readData; //+++++++++++++++++++++++++++ // + // Main clocked logic. + // + //+++++++++++++++++++++++++++ always @(posedge clock or negedge reset_N) if( !reset_N ) begin RxState = IDLE; TxState = IDLE; Tx = 8'b0; Rx = 8'b0; serialInRetimed = {1'b1,1'b1}; s_serialOut <= 1'b1; RxSampleCount = 0; RxBitCount = 0; TxSampleCount = 0; TxBitCount = 0; end else begin //++++++++++++++++++++++++++++++++++++++++++++++++ // + // Assign all temporary registers in order to + // avoid generating unwanted flip-flops. + // + //++++++++++++++++++++++++++++++++++++++++++++++++ v_serialOut = s_serialOut; v_readData = 8'b0; //+++++++++++++++++++++++++++++ // + // Read/Write Registers. + // + //+++++++++++++++++++++++++++++ if( write == 1'b1 ) case( address ) c_TX: begin Tx = writeData; TxState = START; end default:; endcase if( read == 1'b1 ) case( address ) c_RX: begin v_readData = Rx; RxState = IDLE; end c_STATUS: begin if( RxState==FULL ) v_readData[RxReady] = 1'b1; if( RxState==ERROR ) begin v_readData[RxError] = 1'b1; RxState = IDLE; end if( TxState==IDLE ) v_readData[TxReady] = 1'b1; end default:; endcase //+++++++++++++++++++++++++++++++ // + // Transmit State Machine. + // + //+++++++++++++++++++++++++++++++ case( TxState ) IDLE: ; START: begin v_serialOut = 1'b0; // Start Bit. TxSampleCount = 0; TxBitCount = 0; TxState = SEND; end SEND: begin TxSampleCount = TxSampleCount+1; // Eight Data Bits. if( TxSampleCount == 8 ) begin TxSampleCount = 0; v_serialOut = Tx[TxBitCount]; TxBitCount = TxBitCount+1; if( TxBitCount==8 ) TxState = STOP; end end STOP: begin TxSampleCount = TxSampleCount+1; if( TxSampleCount == 8 ) begin v_serialOut = 1'b1; // Stop Bit. TxState = IDLE; end end endcase //++++++++++++++++++++++++++++++ // + // Receive State Machine. + // + //++++++++++++++++++++++++++++++ case( RxState ) IDLE: if( serialInRetimed[TWICE] == 1'b0 ) // Falling Edge of Start Bit. begin RxSampleCount = 0; RxBitCount = 0; RxState = RECEIVE; end START: begin RxSampleCount = RxSampleCount+1; if( RxSampleCount == 4 ) // Centre of Start Bit RxState = RECEIVE; end RECEIVE: begin RxSampleCount = RxSampleCount+1; // Eight Data Bits. if( RxSampleCount == 8 ) begin RxSampleCount = 0; Rx[RxBitCount] = serialInRetimed[TWICE]; RxBitCount = RxBitCount+1; if( RxBitCount==8 ) RxState = STOP; end end STOP: begin RxSampleCount = RxSampleCount+1; if( RxSampleCount == 8 ) if( serialInRetimed[TWICE] == 1'b1 ) // Check Stop Bit RxState = FULL; else RxState = ERROR; end FULL: ; ERROR: ; endcase //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + // Re-time any asynchronous signals before use in order + // to avoid race hazards or problems of metastability + // + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ serialInRetimed[TWICE] = serialInRetimed[ONCE]; serialInRetimed[ONCE] = serialIn; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + // Assign the temporary registers to their `real' counterparts. + // + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ s_serialOut <= v_serialOut; s_readData <= v_readData; end //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // + // Assign the outputs from their associated internal signals. + // + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ assign serialOut = s_serialOut; assign readData = s_readData; endmodule