UART接收器

UART发送器
先看UART发送器模块再看本文!
这两个模块可以仿真通过,代码文末贴上。

UART发送器简介
UART接收器负责接受串行比特流,去除起始位并且以并行格式将数据保存到主机数据相连接的寄存器中。
在这里插入图片描述
接受器的时钟信号是发送器时钟信号的八倍,这样使得接受器可以在发送器对应一个时间间隔内工作。
输入为低电平后连续采样到0值表明起始位到来,而且增加三次采样来确定起始位是否有效,此后的8个连续位在每个发送时钟周期内被采样。
UART接收器中控制器和数据通道之间的接口信号描述如图
在这里插入图片描述
各个信号意义如下
在这里插入图片描述
接收器状态机控制器的状态一共有三个:idle,starting,receiving,状态之间的转移由Sample_clk时钟来同步。

低有效的同步复位输入使得状态机进入idle状态,直到信号Ser_in_0的信号变为低电平进入starting状态。
在starting状态下,状态机重复采样Serial_in以确定第一位是否是有效起始位0,在Sample_clk的下一个时钟有效沿,inc_sample_count,clr_sample_counter需要根据采样值确定是增加计数值还是清零:如果接下来Serial_in的连续三个采样值都为0,则认为有效起始位到达,状态机转移到receiving状态并且将Sample_counter清零。
在receiving状态下inc_Sample_counter有效时,状态机进入八次连续采样,Bit_counter增加。如果采样的位不是最后一个校验位,则inc_Bit_counter和shift保持有效,信号shift有效时采样值将载入接收器移位寄存器RCV_shftreg的MSB位,而且寄存器最左边的7位向LSB移动。

在采样完成后,状态机将输出到主机的握手信号read_not_ready_out置为有效并且清除位寄存器,同时检查数据完整性和主机状态:如果read_not_ready_in有效则表明主机未准备好接受数据(Error1有效),如下一位不是停止位(Serial_in_0=1)则说明接收数据的格式错误(Error2),最后load信号有效时移位寄存器中的内容将以并行格式发送到与data_bus直接相连接的主机数据寄存器RCV_datareg中。

实现代码如下

module UART_RCVR #(parameter word_size = 8, half_word = word_size/2)(
	output [word_size-1:0] 	RCV_datareg,
	output					read_not_ready_out,
							Error1,Error2,
	input					Serial_in,
							read_not_ready_in,
							Sample_clk,
							rst_b
);
	Control_Unit M0(
		read_not_ready_out,
		Error1,Error2,
		clr_Sample_counter,
		inc_Sample_counter,
		clr_Bit_counter,
		inc_bit_counter,
		shift,
		load,
		read_not_ready_in,
		Ser_in_0,
		SC_eq_3,
		SC_It_7,
		BC_eq_8,
		Sample_clk,
		rst_b
	);

	Datapath_Unit M1(
		RCV_datareg,
		Ser_in_0,
		SC_eq_3,
		SC_It_7,
		BC_eq_8,
		Serial_in,
		clr_Sample_counter,
		inc_Sample_counter,
		clr_Bit_counter,
		inc_bit_counter,
		shift,
		load,
		Sample_clk,
		rst_b
	);
	
endmodule

module Control_Unit #(parameter
	word_size = 8, half_word = word_size/2, Num_state_bits = 2,
	idle = 2'b00, starting = 2'b01, receiving = 2'b10
)(
	output reg 	read_not_ready_out,
				Error1,Error2,
				clr_Sample_counter,
				inc_Sample_counter,
				clr_Bit_counter,
				inc_bit_counter,
				shift,
				load,
	input		read_not_ready_in,
				Ser_in_0,
				SC_eq_3,
				SC_It_7,
				BC_eq_8,
				Sample_clk,
				rst_b
);

	reg		[word_size-1:0] RCV_shftreg;
	reg		[Num_state_bits-1:0]	state,next_state;
	
	always@(posedge Sample_clk)
		if(rst_b == 1'b0) state <= idle; else state <= next_state;
		
	always@(state,Ser_in_0,SC_eq_3,SC_It_7,read_not_ready_in)begin
		read_not_ready_out = 0;
		clr_Bit_counter = 0;
		clr_Sample_counter = 0;
		inc_Sample_counter = 0;
		inc_bit_counter = 0;
		shift = 0;
		Error1 = 0;
		Error2 = 0;
		load = 0;
		next_state = idle;
		case(state)
			idle:		if(Ser_in_0 == 1'b1)next_state = starting;
						else next_state = idle;
			starting:	if(Ser_in_0 == 1'b0)begin
							next_state = idle;
							clr_Sample_counter = 1;
						end else
						if(SC_eq_3 == 1'b1)begin
							next_state = receiving;
							clr_Sample_counter = 1;
						end else begin
							inc_Sample_counter = 1;
							next_state = starting;
						end
			receiving:	if(SC_It_7 == 1'b1)begin
						inc_Sample_counter = 1;
						next_state = receiving;
						end
						else begin
							clr_Sample_counter = 1;
							if(!BC_eq_8)begin
								shift = 1;
								inc_bit_counter = 1;
								next_state = receiving;
							end
							else begin
								next_state = idle;
								read_not_ready_out = 1;
								clr_Bit_counter = 1;
								if(read_not_ready_in == 1'b1)Error1 = 1;
								else if(Ser_in_0 == 1'b1)Error2 = 1;
								else load = 1;
							end
						end
			default:	next_state = idle;
		endcase
	end
endmodule

module Datapath_Unit #(parameter
	word_size = 8,half_word = word_size/2,Num_counter_bits = 4
)(
	output reg		[word_size-1:0]		RCV_datareg,
	output								Ser_in_0,
										SC_eq_3,
										SC_It_7,
										BC_eq_8,
	input								Serial_in,
										clr_Sample_counter,
										inc_Sample_counter,
										clr_Bit_counter,
										inc_bit_counter,
										shift,
										load,
										Sample_clk,
										rst_b
);

	reg		[word_size-1:0]			RCV_shftreg;
	reg		[Num_counter_bits-1:0]	Sample_counter;
	reg		[Num_counter_bits:0]	Bit_counter;
	
	assign	Ser_in_0 = (Serial_in == 0);
	assign  BC_eq_8 = (Bit_counter == word_size);
	assign  SC_It_7 = (Sample_counter < word_size-1);
	assign  SC_eq_3  = (Sample_counter == half_word - 1);
	
	always@(posedge Sample_clk)
		if(rst_b == 1'b0)begin
			Sample_counter <= 0;
			Bit_counter <= 0;
			RCV_datareg <= 0;
			RCV_shftreg <= 0;
		end
		else begin
			if(clr_Sample_counter == 1) Sample_counter <= 0;
			else if(inc_Sample_counter == 1)Sample_counter <= Sample_counter + 1;
			
			if(clr_Bit_counter == 1) Bit_counter <= 0;
			else if(inc_bit_counter == 1)Bit_counter <= Bit_counter + 1;
			
			if(shift == 1) RCV_shftreg <= {Serial_in,RCV_shftreg[word_size-1:1]};
			if(load == 1) RCV_datareg <= RCV_shftreg;
		end
endmodule 

测试代码如下

module test_UART_receiver();
  parameter	word_size = 8;
  parameter jump = 2*word_size;
  reg  Serial_in;
  reg rst_b, read_not_ready_in;
  wire [word_size - 1:0] RCV_datareg;
  wire read_not_ready_out, Error1, Error2;
  wire Sample_clk;

  UART_RCVR M3(RCV_datareg, read_not_ready_out, Error1, Error2, Serial_in, read_not_ready_in, Sample_clk, rst_b);

Clock_Unit M4 (Sample_clk);

initial #5000 $finish;
initial begin #1 rst_b = 1; #4 rst_b = 0; #5 rst_b = 1; end
initial begin #4 read_not_ready_in = 0; end  // change to 1 for test
initial begin   

  #1 Serial_in = 1;		// stopped	
  #14	Serial_in = 0;	
  #jump Serial_in = 1;	// start bit
  #jump Serial_in = 0;	// word: hb5
  #jump Serial_in = 1;
  #jump Serial_in = 1;
  #jump Serial_in = 0;
  #jump Serial_in = 1;
  #jump Serial_in = 0;
  #jump Serial_in = 1;
  #jump Serial_in = 1;  // stop bit


/*

#2 Serial_in = 1;		// stopped		
  #4 Serial_in = 0;	// start bit
  #jump Serial_in = 1;	// word: h55
  #jump Serial_in = 0;
  #jump Serial_in = 1;
  #jump Serial_in = 0;
  #jump Serial_in = 1;
  #jump Serial_in = 0;
  #jump Serial_in = 1;
  #jump Serial_in = 0;	//parity bit
  #jump Serial_in = 1;  // stop bit
*/
/*
  #2 Serial_in = 1;
  #6 Serial_in = 0;
  #22 Serial_in = 1;
  #38 Serial_in = 0;
  #54 Serial_in = 1;
  #70 Serial_in = 0;
  #86 Serial_in = 1;
  #118 Serial_in = 0;
  #134 Serial_in = 1;
  //#154 Serial_in = 0;	// error - missing stop bit

  #200 Serial_in = 0;
  #300 Serial_in = 1; */


end //join
endmodule

module Clock_Unit(output reg Clock);
parameter delay = 0;
parameter Pulse_Width = 1;
initial begin #delay Clock = 0; forever #Pulse_Width Clock = ~Clock;end
endmodule

仿真结果与书一致
在这里插入图片描述

### 回答1: Zynq PS UART接收是指使用赛灵思公司的Zynq系列处理器的处理系统(PS)模块中的通用异步收发器(UART),接收外部设备(如传感器或其他控制器)发送的数据流。在使用Zynq PS UART接收时,需要确定接收的数据格式和波特率,并将它们配置为与接收设备发送的数据格式和波特率匹配。 Zynq PS UART接收的实现过程如下。首先,将PS UART接收器连接到外部设备,确保UART接收器的概念正确地引脚和电气特性与外部设备相匹配。然后,设置UART接收器的波特率和数据格式,可以使用赛灵思开发套件提供的软件工具来实现这个任务。接下来,编写PS模块的驱动程序,申请合适的缓冲区,使能UART接收器,并启动数据接收流程。在接收数据时,需要注意不同于传统的线性处理器,Zynq的两个处理器核心(即ARM和FPGA)在协作完成处理任务。因此,在处理和缓冲数据时,需要确保双方间数据传输或数据拷贝的完整性和一致性,以防止数据的丢失和重复发送。 以上是Zynq PS UART接收的一般过程和注意事项,该过程通常需要通过一定的开发和调试才能完成。最终,使用PS UART接收器可以实现从外部设备接收数据,并实现对数据的存储、处理和响应等功能,极大地扩展了Zynq处理器的应用范围。 ### 回答2: Zynq是一种嵌入式处理器,具有高度集成的特点。在Zynq PS中,UART是一种通信接口,可以用于串行通信。在UART接收数据之前,必须先进行配置。首先需要确定波特率(Baud Rate),波特率是指每秒钟传输的位数,通常情况下,波特率的选择应该与发送方的波特率一致。在Zynq中,可以通过控制寄存器的设置来实现波特率的设置,并且还需要确定校验码和数据位数。 当UART接收数据时,其实就是在接收连续的字节。数据从数据线一位位地传输,不同的位通过不同的电平来区分。一般情况下,使用RX寄存器来接收数据,通过判断RX FIFO是否为空,来确定是否有数据要接收。当RX FIFO不为空时,可以通过读取RX寄存器中的值来获取接收到的数据。同时,还需要检查RX寄存器的状态位,以便进一步判断接收是否完成。在数据接收完毕后,需要对数据进行解析和处理,以便进行后续的操作。 总的来说,在Zynq PS中,实现UART接收需要进行波特率的配置和状态位的判断,同时需要注意数据的解析和处理。只有这样,才能做到正确的数据接收,并能够进行后续的操作。 ### 回答3: Zynq PS UART接收是指在Zynq系列芯片的处理系统(PS)中通过UART(通用异步收发传输)接口进行数据接收的过程。UART是一种通信协议,它可以通过串口进行全双工、半双工或单向的数据传输,常用于微处理器和外设之间的通讯。 在Zynq PS中,UART接口可以通过寄存器配置来实现数据接收方式的设置。首先需要配置UART的参数,包括波特率、字节长度、停止位和校验位等,以便与发送端进行匹配。然后可以通过使用读取寄存器的方法,从接收队列中读取数据。如果接收队列中有可用数据,则读取寄存器中的值为已接收数据的字节,如果接收队列无数据,则读取寄存器中的值为0。 在进行UART接收时,需要注意以下几点:首先,需要保证两端通讯的波特率、字节长度等参数设置相同,否则无法正常通讯。其次,应对接收缓冲区进行管理,避免接收到大量数据时导致缓冲区溢出,而程序无法正常工作。最后,需要注意异常情况的处理,例如接收到错误数据或超时等情况,应该进行相应的处理,确保程序的稳定性和可靠性。 综上所述,Zynq PS UART接收需要对参数进行设置,并进行队列管理和异常处理,最终才能实现可靠的数据接收。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值