📄 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<<1;
rd_clr[0] <= rd;
if(clr_out)
d[9] <= 0; //清楚数据接收好标记
else
begin
if(end_rxd)
begin
d[0] <= shift[8];
d[1] <= shift[7];
d[2] <= shift[6];
d[3] <= shift[5];
d[4] <= shift[4];
d[5] <= shift[3];
d[6] <= shift[2];
d[7] <= shift[1];
d[8] <= shift[0]; //这位是校验位,也可以将校验的结果直接锁存在这一位。
d[9] <= 1;
/*
如果没有校验位,则程序变为。
d[0] <= shift[7];
d[1] <= shift[6];
d[2] <= shift[5];
d[3] <= shift[4];
d[4] <= shift[3];
d[5] <= shift[2];
d[6] <= shift[1];
d[7] <= shift[0];
d[8] <= 0;
d[9] <= 1;
*/
end
end
if(xx | ~start&txd)
s <= 0;
else
begin
s <= s+1;
end
if(~start)
bps_cnt <=0;
else
begin
if(xx)
bps_cnt <= bps_cnt+1;
end
if(end_rxd)
begin
start_check <=0;
start <=0;
end
else
begin
if(xx)
begin
start_check <= start_check<<1;
start_check[0] <= ~txd;
start <=(start|(~start_check[8]&start_check[7]
&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 <=0;
else
begin
if(bps)
bit_cnt <= bit_cnt+1;
end
if(bps)
begin
shift <= shift<<1;
shift[0] <= txd;
end
end
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -