📄 uart_rx.txt
字号:
`timescale 1ns/1ps
//------------------------------------------------------------------------------
// 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,datain[7: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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -