FPGA之UART(一)

UART( Universal Asynchronous Receiver/Transmitter)指通用异步收发器。UART电平有TTL电平和RS232电平。TTL电平一般以3.3V居多。RS232是负电平逻辑,+5V—+12V为低电平,而-12V—-5V为高电平。然而FPGA引脚电平一般为TTL电平或者COMS电平,UART外接电平为RS232电平,这就需要将TTL转换为RS232电平的电平转换芯片,如MAX3232,MAX232等。有的电路还用UART转USB芯片,如CP2102、CH340等。
UART通讯协议分析如下:
UART通讯协议一般包括起始位、数据位、校验位和停止位。如下图所示:
FPGA之UART(一)_第1张图片
一帧数据从一个低位起始位开始。数据位可以是7位也可以是8位。有一个可用的数据位,一个或者几个高位停止位。
如下分析uart_tx.v代码:
module uart_tx
#(
parameter CLK_FRE = 50,
parameter BAUD_RATE = 115200
)
(
input clk,
input rst_n,
input[7:0] tx_data,
input tx_data_valid,
output reg
tx_data_ready,
output tx_pin
);
模块uart_tx说明如下:
CLK_FRE 代表系统设置时钟。
BAUD_RATE表示UART通讯波特率。
clk表示输入时钟引脚。
rst_n表示复位引脚。
tx_data表示8位数据输入。
tx_data_valid为发送使能引脚,高电平表示UART为发送状态,低电平表示UART为接收状态。
tx_data_ready表示准备发送数据寄存器。
tx_pin表示发送引脚。
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1’b0)
state <= S_IDLE;
else
state <= next_state;
end
此代码的意思是复位后uart_tx模块处于空闲状态,否则更新为next_state状态。

always @(*)

begin

 case(state)

 S_IDLE:

 if(tx_data_valid == 1'b1)

            next_state <= S_START;

        else

            next_state <= S_IDLE;

    S_START:

        if(cycle_cnt == CYCLE - 1)

            next_state <= S_SEND_BYTE;

        else

            next_state <= S_START;

    S_SEND_BYTE:

        if(cycle_cnt == CYCLE - 1&& bit_cnt == 3'd7)

            next_state <= S_STOP;

        else

            next_state <= S_SEND_BYTE;

    S_STOP:

        if(cycle_cnt == CYCLE - 1)

            next_state <= S_IDLE;

        else

            next_state <= S_STOP;

    default:

        next_state <= S_IDLE;

endcase

end

此代码描述的是uart_tx模块发送数据时的状态机,分别为空闲态、开始态、发送态和停止态。复位后使得要发送数据时处于空闲态。

  1. 在空闲态时,检测tx_data_valid是否为1,如果为1,把next_state赋值为开始态,否则next_state继续为空闲态。

  2. 在开始态时,如果时钟计数值(cycle_cnt)达到1位传输时间(CYCLE - 1)时,next_state设置为发送态,否则为开始态。

  3. 在发送态时,如果时钟计数值(cycle_cnt)达到1位传输时间(CYCLE - 1)同时接收完本程序中设定的8位数据后next_state设置为停止态,否则为发送态。

  4. 在停止态时,如果时钟计数值(cycle_cnt)达到1位传输时间(CYCLE - 1)时,next_state设置为空闲态,否则next_state设置为停止态。

  5. 其他情况为空闲态。

always @(posedge clk or negedge rst_n)

begin

if(rst_n == 1'b0)
begin
	tx_data_ready <= 1'b0;
end
else if(state == S_IDLE)
	if(tx_data_valid == 1'b1)
		tx_data_ready <= 1'b0;
	else
     		tx_data_ready <= 1'b1;
	else if(state == S_STOP && cycle_cnt == CYCLE - 1)
		tx_data_ready <= 1'b1;
end

此代码意思为复位状态时tx_data_ready设置为0;在空闲态时,如果tx_data_valid为1,则把tx_data_ready设置为0;,等到停止态结束时设置为1。

always @(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
	begin
		tx_data_latch <= 8'd0;
	end
	else if(state == S_IDLE && tx_data_valid == 1'b1)
		tx_data_latch <= tx_data;
end

此代码表示复位时8位tx_data_latch寄存器清零,在发送状态且处于空闲态时,把tx_data的输入值赋给tx_data_latch。

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

此段代码表示uart_tx模块在发送数据状态时,每发送1位数据计数标记加1。其他状态或复位状态时,计数标记清零。

always @(negedge clk or posedge rst_n)
begin
	 if(rst_n == 1'b0)
		cycle_cnt <= 16'd0;
	else if((state == S_SEND_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(1位发送时间)时清零或状态变化时清零。其他情况时cycle_cnt计数加1。

always @(negedge clk or posedge rst_n)
begin
	 if(rst_n == 1'b0)
		tx_reg <= 1'b1;
	else
		case(state)
			S_IDLE,S_STOP:
				 tx_reg <= 1'b1;
			S_START:
				tx_reg <= 1'b0;
			S_SEND_BYTE:
				 tx_reg <= tx_data_latch[bit_cnt];
		default:
			tx_reg <= 1'b1;
		 endcase
end

此代码的意思为:开始态发送的时候,开始位为0;发送态时,tx_data_latch寄存器的值按位送到tx_reg,通过assign tx_pin = tx_reg送到tx_pin输出引脚输出。

你可能感兴趣的:(FPGA)