//------------------------------------------------------------------------------ // Uart Reciever // Created March 21, 2004 by James Patchell // // Doing a Uart Reciever is a lot more complicated than doing a Uart Transmitter // Parameters: // dout.......this is the data that is recieved, valid only when ready is true // clk........16x baud rate clock // reset......resets all of the registers // rxd........recieve data input // frame......frame error output........Not Implemented Yet // overrun....overrun error output......Not Implemented Yet // ready......indicates that all 8 bits have been read // //------------------------------------------------------------------------------ // Revision History: // Rev 1.01 // April 17, 2005 // Changed the shift register to shift the LSB out first //------------------------------------------------------------------------------
module uartrx(dout,clk,bclk,reset,rxd,frame,overrun,ready,busy,CS); output 7:0 dout; //data output from input shift register input clk; //system clock input bclk; //16x baud rate clock input reset; //reinitializes the whole mess input rxd; //serial port input output frame; //framing error output overrun; //overrun error output ready; //data is ready output 3:0 CS; //For debug use output busy;
wire frame;
wire overrun;
reg [7:0] dout;
reg ready;
reg din,din1,din2;
reg syncbitcnt; //synchronize the clock bit divider
reg [3:0] bitcnt; //divide by sixteen bit counter
reg bitenable; //indicate bit time
reg shiftenable; //enable shifter
reg start; //indicates a start condition
reg done; //indicate all bits shifted in
reg busy;
reg [3:0] NS;
reg [3:0] CS;
reg [7:0] datain; //data in shift register
reg loadout; //transfers data from datain to dout
assign frame = 0; assign overrun = 0;
//----------------------------------------------------------- // Start bit detection logic //-----------------------------------------------------------
always @(posedge clk or posedge reset) begin if(reset) begin din <= 1; din1 <= 1; din2 <= 1; end else begin if (bclk) begin din <= din1; //shift din1 <= din2; din2 <= rxd; end else begin din <= din; //hold din1 <= din1; din2 <= din2; end
end
end
always @(din or din1 or bclk) begin start <= din & !din1 & bclk; //indicates we have a start condition end
//--------------------------------------------------------- // status bit indicates if we are in the process of getting // a byte in //---------------------------------------------------------
always @ (posedge clk or posedge reset) begin if(reset) busy <= 0; else begin if(start) busy <= 1; else if (done) busy <= 0; end end
//--------------------------------------------------------- // this bit will go true for one clock cycle indicating that // the output holding register has a byte in it ready for // use //---------------------------------------------------------
always @ (posedge clk) ready <= done;
//-------------------------------------------------------- // when we get a start condition and we are not busy, // resync the bit counter //--------------------------------------------------------
always @ (start or busy) begin if(start && !busy) syncbitcnt <= 1; else syncbitcnt <= 0; end
always @(posedge clk or posedge reset) //------------------------------------------------------- // this is the divider for the 16x clock // syncbitcnt is used to syncronize this counter with the // start bit //------------------------------------------------------- begin if (reset) bitcnt <= 4'b0; //initialize counter else begin
if (syncbitcnt) //synchronize
bitcnt <= 4'b0;
else if(bclk)
bitcnt <= bitcnt + 1; //count
else
bitcnt <= bitcnt; //hold
end
end
always @(bitcnt or bclk) //---------------------------------------------- // we want to check the serial stream right in // the middle of the bit time //---------------------------------------------- begin if(bitcnt == 4'b1000) // if count == 8 bitenable <= bclk; else bitenable <= 0; end
//---------------------------------------------------- // data shift register //----------------------------------------------------
always @(posedge clk or posedge reset) begin if(reset) begin datain <= 0; //reset shift register to zero end else if(shiftenable) datain <= {din,datain7:1}; //shift when told to else datain <= datain; //hold that thought. end
//---------------------------------------------------- // output register //----------------------------------------------------
always @ (posedge clk or posedge reset) begin if(reset) dout <= 0; else if (loadout) dout <= datain; end
//---------------------------------------------------- // UART rx State Machine // as it turns out...this looks an awful lot like the // transmit state machine :-) // // it should be noted, the LSB is the first bit to // be transmitted...the states would seem to imply // that we start at BIT7...well, that is wrong // //----------------------------------------------------
parameter 3:0 //synopsys enum STATE_TYPE UART_IDLE = 4'b0000, UART_STARTBIT = 4'b0001, UART_BIT7 = 4'b0010, UART_BIT6 = 4'b0011, UART_BIT5 = 4'b0100, UART_BIT4 = 4'b0101, UART_BIT3 = 4'b0110, UART_BIT2 = 4'b0111, UART_BIT1 = 4'b1000, UART_BIT0 = 4'b1001, UART_STOPBIT = 4'b1010;
always @ (posedge clk or posedge reset)
begin
if (reset) CS <= UART_IDLE;
else CS <= NS;
end
always @ (CS or bitenable or start)
begin
case (CS) //synopsys full_case
UART_IDLE: begin
if(start)
begin
NS = UART_STARTBIT;
shiftenable = 0;
done = 0;
loadout = 0;
end
else
begin
NS = UART_IDLE; //hold
shiftenable = 0;
done = 0;
loadout = 0;
end
end
UART_STARTBIT: begin
if(bitenable)
begin
NS = UART_BIT7;
shiftenable = 1;
loadout = 0;
done = 0;
end
else
begin
NS = UART_STARTBIT; //hold
shiftenable = 0;
loadout = 0;
done = 0;
end
end
UART_BIT7: begin
if(bitenable)
begin
NS = UART_BIT6;
shiftenable = 1;
done = 0;
loadout = 0;
end
else
begin
NS = UART_BIT7; //hold
shiftenable = 0;
done = 0;
loadout = 0;
end
end
UART_BIT6: begin
if(bitenable)
begin
NS = UART_BIT5;
shiftenable = 1;
done = 0;
loadout = 0;
end
else
begin
NS = UART_BIT6; //hold
shiftenable = 0;
done = 0;
loadout = 0;
end
end
UART_BIT5: begin
if(bitenable)
begin
NS = UART_BIT4;
shiftenable = 1;
done = 0;
loadout = 0;
end
else
begin
NS = UART_BIT5; //hold
shiftenable = 0;
done = 0;
loadout = 0;
end
end
UART_BIT4: begin
if(bitenable)
begin
NS = UART_BIT3;
shiftenable = 1;
done = 0;
loadout = 0;
end
else
begin
NS = UART_BIT4; //hold
shiftenable = 0;
done = 0;
loadout = 0;
end
end
UART_BIT3: begin
if(bitenable)
begin
NS = UART_BIT2;
shiftenable = 1;
loadout = 0;
done = 0;
end
else
begin
NS = UART_BIT3; //hold
shiftenable = 0;
done = 0;
loadout = 0;
end
end
UART_BIT2: begin
if(bitenable)
begin
NS = UART_BIT1;
shiftenable = 1;
loadout = 0;
done = 0;
end
else
begin
NS = UART_BIT2; //hold
shiftenable = 0;
done = 0;
loadout = 0;
end
end
UART_BIT1: begin
if(bitenable)
begin
NS = UART_BIT0;
shiftenable = 1;
done = 0;
loadout = 0;
end
else
begin
NS = UART_BIT1; //hold
shiftenable = 0;
done = 0;
loadout = 0;
end
end
UART_BIT0: begin
if(bitenable)
begin
NS = UART_STOPBIT;
shiftenable = 1;
loadout = 0;
done = 0;
end
else
begin
NS = UART_BIT0; //hold
shiftenable = 0;
done = 0;
loadout = 0;
end
end
UART_STOPBIT: begin
if(bitenable)
begin
NS = UART_IDLE;
shiftenable = 0;
done = 1; //this will clear busy status
loadout = 1;
end
else
begin
NS = UART_STOPBIT; //hold
shiftenable = 0;
done = 0;
loadout = 0;
end
end
default: begin
NS = UART_IDLE;
shiftenable = 0;
done = 0;
loadout = 0;
end
endcase
end
endmodule
Type your text here