自己编写的串口UART的接收Verilog模块
源代码在线查看: rxd.v
/*
自己编写的串口UART的接收程序,在工程应用中测试通过。
支持中断和查询模式,基本的设计思路是:先用比波特率高16倍的速率检测串行输入数据,
如果检测到连续的低电平,则认为收到了起始位,接着按照波特率的速率,检测输入串行数据,
完成指定位数的数据接收后,将数据锁存在输出锁存器中(这样有一个字节的数据缓冲能力,同样也可以将数据写入外部的FIFO),
并且产生中断信号。
该设计对串行输入信号的畸变(经过光耦或线路的传输电容较大)的情况均能较好的适应。
由于是初学Verilog时编写的,条理和移植性较差,但总算能正确运行,希望批评指正。liyzz99@163.com。
*/
module uart_rx(clk,txd,rd,check,outd,int);
input clk; 输入时钟60mhz
input txd; 输入串行线
input rd; 读取接收到的数据,高有效,读取数据会使outd[9]位自动清零
input check; 查询是否有数据接收到 在outd[9]位检测,为“1”时有数据到。
output [9:0]outd; 输出数据
output int; 中断输出
reg [9:0]d; 内部数据暂存
wire bps; 波特率计数溢出线
reg [3:0]bps_cnt; 波特率计数器
reg [8:0]start_check; 起始位检测移位器
reg start; 起始位有效标记
reg [9:0]shift; 串并转换移位器
reg [2:0]rd_clr; rd信号下沿延时
reg [3:0]bit_cnt; 接收到的数据位计数器
wire clr_out; rd信号下沿后的清零信号
reg [6:0]s; 16倍波特率的时钟计数器。
wire xx; 16倍波特率的时钟计数器溢出信号
wire end_rxd;
assign xx = (s[6]&s[5]&s[0])?1:0; /*(0x61+1) = 97 = 60,000,000/38400/16 */
assign bps = (bps_cnt[3]&bps_cnt[2]&bps_cnt[1]&bps_cnt[0]&xx);
assign end_rxd = bit_cnt[3]&bit_cnt[0]&bps; /*8bit data 2bit stop,如果没有校验位,则需要将个数减小到9位*/
assign clr_out = (~rd_clr[2]&rd_clr[1]);
assign outd = (rd|check)?d:10'bzzzzzzzzzz;
assign int = ~d[9];
always @(posedge(clk))
begin
rd_clr rd_clr[0] if(clr_out)
d[9] else
begin
if(end_rxd)
begin
d[0] d[1] d[2] d[3] d[4] d[5] d[6] d[7] d[8] d[9] /*
如果没有校验位,则程序变为。
d[0] d[1] d[2] d[3] d[4] d[5] d[6] d[7] d[8] d[9] */
end
end
if(xx | ~start&txd)
s else
begin
s end
if(~start)
bps_cnt else
begin
if(xx)
bps_cnt end
if(end_rxd)
begin
start_check start end
else
begin
if(xx)
begin
start_check start_check[0] start &start_check[6]&start_check[5]
&start_check[4]&start_check[3]
&start_check[2]&start_check[1]
&start_check[0]));
end
end
if(~start)
bit_cnt else
begin
if(bps)
bit_cnt end
if(bps)
begin
shift shift[0] end
end
endmodule