FPGA之UART(二)

这篇笔记主要记录对uart_rx模块的理解:
module uart_rx
#(
parameter CLK_FRE = 50,
parameter BAUD_RATE = 115200
)
(
input clk,
input rst_n,
output reg[7:0] rx_data,
output reg rx_data_valid,
input rx_data_ready,
input rx_pin
);
模块引脚说明:
CLK_FRE表示时钟频率。
BAUD_RATE表示通讯波特率。
Clk表示时钟输入引脚。
rst_n表示复位引脚。
rx_data表示8位输出寄存器。
rx_data_valid表示输出寄存器。
rx_data_ready表示输入,准备接收数据。
rx_pin表示输入脚。
assign rx_negedge = rx_d1 && ~rx_d0;
检测下降沿,当输入为下降沿时rx_negedge为1。

always @(posedge clk or negedge rst_n)
begin
	if(rst_n == 0)
		begin
			rx_d0 <= 1'b0;
			rx_d1 <= 1'b0;
		end
	else
		begin
			rx_d0 <= rx_pin;
			rx_d1 <= rx_d0;
		end
end

代码含义:如果复位,rx_d0和rx_d1为0;否则rx_d0接收输入引脚的电平状态,并把接收到的状态赋给rx_d1。

always @(posedge clk or negedge rst_n)
begin
	if(rst_n == 0)
		state <= S_IDLE;  
	else
		state <= next_state;
end

代码含义:复位后uart_rx模块处于空闲状态,否则更新为next_state状态。

always @(*)
begin
 	case(state)
		S_IDLE:
			if(rx_negedge)
				next_state <= S_START;
			else
				next_state <= S_IDLE;
		S_START:
			if(cycle_cnt == CYCLE -1)
				next_state <= S_REC_BYTE;
			else
				next_state <= S_START;
		S_REC_BYTE:
				if(cycle_cnt == CYCLE -1 && bit_cnt == 3'd7)
					next_state <= S_STOP;
				else
					next_state <= S_REC_BYTE;
		S_STOP:
				if(cycle_cnt == CYCLE / 2 -1)
					next_state <= S_DATA;
				else 
					next_state <= S_STOP;
		S_DATA:
				if(rx_data_ready)
					next_state <= S_IDLE;
				else
					next_state <= S_DATA;
		default:
			next_state <= S_IDLE;
	endcase
end     

代码含义:
uart_rx模块的接收状态机分为空闲态、开始态、接收态、停止态和数据态。
空闲态:上电处于空闲态,如果检测到低电平,则next_state设置为开始态。
开始态:如果接收1位数据的时间等于波特率设置的数据传输位时间,next_state设置为接收态。
接收态:如果接收时间到并且接收完8位数据,next_state设置为停止态。
数据态:将接收到的数据送到其他模块,完成后next_state进入空闲态。

always @(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
		rx_data_valid <= 1'b0;
	else if(state == S_STOP && next_state != state)
		rx_data_valid <= 1'b1;
	else if(state == S_DATA && rx_data_ready)
		rx_data_valid <= 1'b0;
end

代码含义:当从停止态转变到下一个状态时表示接收到的串口数据有效并设rx_data_valid设置为高,高电平有效。

always @(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
		rx_data <= 8'd0;
	else if(state == S_STOP && next_state != state)
		rx_data <= rx_bits;
end

代码含义:当从停止态转变到下一个状态时把接收到的数据给到8位数据输出引脚rx_data。

always @(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
		begin
			bit_cnt <= 3'd0;
		end
	else if(state == S_REC_BYTE)
		if(cycle_cnt == CYCLE -1)
			bit_cnt <= bit_cnt + 3'd1;
		else
			bit_cnt <= bit_cnt;
	else
		bit_cnt <= 3'd0;
end

代码含义:在接收态时,每当位周期到达时,接收计数值加1。

always @(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
		cycle_cnt <= 16'd0;
	else if((state == S_REC_BYTE && cycle_cnt == CYCLE -1) || 		next_state != state)
		cycle_cnt <= 16'd0;
	else
		cycle_cnt <= cycle_cnt + 16'd1;        
end

代码含义:复位时cycle_cnt清0,接收态cycle_cnt计数到CYCLE -1(位周期)时清零或状态变化时清零。其他情况时cycle_cnt计数加1。

always @(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
		rx_bits <= 8'd0;
	else if(state == S_REC_BYTE &&cycle_cnt == CYCLE / 2 - 1)
		rx_bits[bit_cnt] <= rx_pin;
	else
		rx_bits <= rx_bits;
end

代码含义:在接收态,当接收数据到半位周期时候,rx_bits开始记录接收线的状态。为什么在半位周期记录接收线状态呢?这样做是为了满足采样定理,接收数据时每一个数据都在采用周期的时间中点进行采样。

猜你喜欢

转载自blog.csdn.net/csdnqiang/article/details/106047508