⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rxd.v

📁 自己编写的串口UART的接收Verilog模块
💻 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 + -