verilog 串口数据接收 同名、异名例化

<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


UART_RXer.v:


// 2022-1-23 verilog 学习
// 串口接收
`timescale 1ns/10ps
module UART_RXer(
								clk,
								res,
								RX,
								data_out,
								en_data_out
								);
									
input							clk;
input							res;	
input							RX;
output[7:0]						data_out;    // 接收字节输出
output							en_data_out; // 输出使能

reg[7:0]						data_out; 
reg[7:0]						state;  // 主状态机
// con用于计算比特宽度 时钟频率24M,1s传4800bits,则1bit占宽5000
reg[12:0]						con;  // 用于计算比特宽度 24M,24000000/4800=5000=0001 0011 1000 1000,1.5倍5000算8000 = 0001 1111 0100 0000
reg[3:0]						con_bits; // 用于计算比特数

reg								RX_delay; // RX延时
reg								en_data_out;

always@(posedge clk or negedge res)
if(~res)begin
	state <= 0; con <=0; con_bits<=0; RX_delay<=0;data_out<=0; 
end
else begin
	RX_delay <= RX;  // RX延时
	case(state)
	0:// 等空闲
	begin
		if(con==5000-1)begin // 接收了1bit
			con<=0;
		end
		else begin 
			con<=con+1;     // 数频率
		end
		
		if(con==0)begin
			if(RX)begin
				con_bits <= con_bits+1;
			end
			else begin
				con_bits <= 0;
			end
		end
		
		if(con_bits == 12)begin
			state <=1;
		end
	end
	
	1://等起始位
	begin
		en_data_out<=0;
		if(~RX & RX_delay)begin
			state <= 2;
		end
	end	
	
	2: // 收最低位b0
	begin
		if(con==7500-1)begin  // 1.5个bit
			con <= 0;
			data_out[0] <= RX;  // 第0位
			state <= 3;
		end
		else begin
			con <= con+1; 
		end
	end	
	
	3: // 收b1
	begin
		en_data_out <= 0;
		if(con==5000-1)begin  // 1个bit
			con <= 0;
			data_out[1] <= RX;  // 
			state <= 4;
		end
		else begin
			con <= con+1; 
		end
	end	

	4: // 收b2
	begin
		if(con==5000-1)begin 
			con <= 0;
			data_out[2] <= RX;  // 
			state <= 5;
		end
		else begin
			con <= con+1; 
		end
	end		

	5: // 收b3
	begin
		if(con==5000-1)begin  
			con <= 0;
			data_out[3] <= RX;  // 
			state <= 6;
		end
		else begin
			con <= con+1; 
		end
	end		

	6: // 收b4
	begin
		if(con==5000-1)begin  // 
			con <= 0;
			data_out[4] <= RX;  // 
			state <= 7;
		end
		else begin
			con <= con+1; 
		end
	end	

	7: // 收b5
	begin
		if(con==5000-1)begin  
			con <= 0;
			data_out[5] <= RX;  // 
			state <= 8;
		end
		else begin
			con <= con+1; 
		end
	end	
	
	8: // 收b6
	begin
		if(con==5000-1)begin  
			con <= 0;
			data_out[6] <= RX;  // 
			state <= 9;
		end
		else begin
			con <= con+1; 
		end
	end	

	9: // 收b7
	begin
		if(con==5000-1)begin  
			con <= 0;
			data_out[7] <= RX;  // 
			state <= 10;
		end
		else begin
			con <= con+1; 
		end
	end	

	10: // 结束位 产生使能脉冲
	begin
		en_data_out <= 1;
		state <= 1;
	end	
	
	default: // 万一case>10
	begin
		state <= 0;
		con <= 0;
		con_bits <= 0;
		en_data_out <= 0;
	end
	
	endcase
end

endmodule


// testbench  测试台
module UART_RXer_tb;

reg								clk,res;
wire							RX;  // 已经预设好,不需要变化
wire[7:0]						data_out;
wire							en_data_out;

reg[25:0]						RX_send;  // 里面装有串口字节发送数据
assign							RX = RX_send[0];  // 连接RX

reg[12:0]						con;

// 同名例化 reg变量命名和UART_RXer UART_RXer();块中变量命名相同,则块中不用.clk(clk)
// 异名例化 reg变量命名和UART_RXer UART_RXer();块中变量命名不同,则块中不用.clk(reg/wire中命名)
UART_RXer UART_RXer(
									clk,
									res,
									RX,
									data_out,
									en_data_out
									);
									
// 初值
initial begin
									clk<=0;res<=0;con<=0;RX_send<={1'b1,8'haa,1'b0,16'hffff};  //结束位,字节,起始位,空闲(往右输出)
					#17 			res<=1;
					#4000000		$stop;
end

always #5 clk = ~clk;
always@(posedge clk)begin
	if(con==5000-1)begin
		con <= 0;
	end
	else begin
		con <= con + 1;
	end
	
	if(con==0)begin
			RX_send[24:0] <= RX_send[25:1];  // 右移
			RX_send[25] <= RX_send[0];   // 循环右移
	end
end

endmodule

16’hffff:16位的十六进制,f:16,即1111
8’haa:16位的十六进制 a:10,即1010
1’b0:1位二进制,即0
1’b1:1位二进制,即1
{1’b1, 8’haa, 1’b0, 16’hffff}:1_1010_1010_0_1111_1111_1111_1111
空闲12位以上,识别到空闲:1111_1111_1111_1111,识别到第12个1时,开始等待起始位;
… …
第15个1:RX=1,RX_delay=1(等于上一个时刻的RX);
第16个1:RX=1,RX_delay=1(等于上一个时刻的RX);
RX=1’b0时刻:RX=0,RX_delay=1(等于上一个时刻的RX)。此时 ~RX & RX_delay = 1&1 = 1,识别到起始位,转状态2;
状态2:等待1.5个bit (时钟周期为7500),开始接收b[0];
… …


modelsim:

在这里插入图片描述


在这里插入图片描述

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Verilog中,串口接收数据通常是通过串口接收器(UART Receiver)模块来实现的。根据引用,串口发送端口空闲时为高,发送端口拉低表示数据传送即将开始,字节数据低位先发,字节发送后拉高表示字节传送结束。常用的波特率有4800、9600、115200等。 根据引用中的测试代码,UART_RXer_tb模块通过将串口接收数据RX连接到RX_send来模拟串口接收数据。在该测试代码中,RX_send表示接收到的串口数据的最低位。通过将RX_send[24:0]右移一位并将RX_send[25]设置为RX_send的值来模拟接收到连续的串口数据。 根据引用的说明,这个Verilog程序完成的是接收来自上位机发送的多字节串口数据,并将不同的字节分配给不同的寄存器,以完成相应的控制工作。 因此,Verilog中的串口接收数据是通过串口接收器模块来实现的,该模块根据发送端口的状态来接收串口数据,并将接收到的数据存储在相应的寄存器中进行后续处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Verilog——串口数据接收(状态机)](https://blog.csdn.net/weixin_41788560/article/details/118444413)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [串口接收多字节 Verilog程序](https://download.csdn.net/download/zq18362902766/10361036)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值