1开发板串口简介
DE23-Lite开发板提供了一个UART通信接口(物理接口是下图的Type C接口),用户能够通过主机与Agilex 3 FPGA进行串口通信。

该接口使用DE23-Lite板载的USB Blaster III电路中的FT2232H芯片作为UART转USB的桥梁。将USB线连接到DE23-Lite板的Type-C接口和主机之间,即可启用USB Blaster III和FPGA UART功能,此时无需串行驱动程序,但用户在使用UART功能前需要确保已安装USB Blaster III驱动程序。

连接USB线后,通常在PC设备管理器中会显示USB Blaster III和一个COM端口号。

2实验任务
设计一个串口回环实验,实现上位机发送数据给开发板串口,串口接收数据后又通过串口发送给上位机。

串口时序图如下:

要求:数据位为8位, 停止位1位,无校验位,波特率115200bps。
3模块设计
DE23-Lite的串口回环设计主要是2个模块:串口发送模块(发送数据时将并行的数据转换成串行数据进行传输)和串口接收模块(在接收数据时将接收到的串行数据转换成并行数据)。

系统时钟是50MHz,波特率是115200bps,那么串口发送和接收时,数据的每个位将占用50000000/115200 ≈ 434个时钟周期。
在串口接收模块设置一个4状态的状态机:
空闲状态:在空闲状态下,检测起始位(低电平)。一旦检测到起始位,进入START状态,并设置计数器在半位时间后采样,这样可以确保在位的中心点采样,提高抗噪能力。
起始位检测状态:等待半个位周期后,再次检查线路状态。如果仍然是低电平,确认是有效的起始位,进入DATA状态;否则认为是噪声干扰,返回IDLE状态。
数据位接收状态:在每个位周期的中心点采样数据位,并存入移位寄存器。接收完8位数据后,进入STOP状态。
停止位处理状态:等待一个完整的位周期(停止位),然后将接收到的数据输出,并产生一个时钟周期的接收完成信号。

接收模块工程代码:
moduleuart_rx( input clk, input rst_n, input uart_rx, output reg [7:0] rx_data, output reg rx_done ); parameterCLK_FREQ=50000000; parameterBAUD_RATE=115200; //波特率计数器 localparam BAUD_CNT_MAX=CLK_FREQ/BAUD_RATE; localparam HALF_BAUD_CNT=BAUD_CNT_MAX/2; reg [15:0] baud_cnt; //状态定义 localparam IDLE=2'd0; localparam START = 2'd1; localparam DATA=2'd2; localparam STOP = 2'd3; reg [1:0] state; reg [2:0] bit_cnt; reg [7:0] rx_reg; reg uart_rx_sync1, uart_rx_sync2; //同步输入信号 always @(posedge clkornegedge rst_n)begin if(!rst_n)begin uart_rx_sync1<= 1'b1; uart_rx_sync2 <= 1'b1; end else begin uart_rx_sync1 <= uart_rx; uart_rx_sync2 <= uart_rx_sync1; end end // 状态机 always @(posedge clk or negedge rst_n) begin if(!rst_n) begin state <= IDLE; rx_data <= 8'd0; rx_done <= 1'b0; baud_cnt <= 0; bit_cnt <= 0; rx_reg <= 0; end else begin rx_done <= 1'b0; case (state) IDLE: begin if(uart_rx_sync2 == 1'b0) begin // 检测起始位 state <= START; baud_cnt <= HALF_BAUD_CNT - 1; // 半位时间后采样 end end START: begin if(baud_cnt == 0) begin if(uart_rx_sync2 == 1'b0) begin // 确认起始位 state <= DATA; baud_cnt <= BAUD_CNT_MAX - 1; bit_cnt <= 0; end else begin state <= IDLE; // 假起始位 end end else begin baud_cnt <= baud_cnt - 1; end end DATA: begin if(baud_cnt == 0) begin rx_reg[bit_cnt] <= uart_rx_sync2; if (bit_cnt == 3'd7) begin state <= STOP; end else begin bit_cnt <= bit_cnt + 1; end baud_cnt <= BAUD_CNT_MAX - 1; end else begin baud_cnt <= baud_cnt - 1; end end STOP: begin if(baud_cnt == 0) begin rx_data <= rx_reg; rx_done <= 1'b1; state <= IDLE; end else begin baud_cnt <= baud_cnt - 1; end end endcase end end endmodule
串口发送模块同样设置了一个4状态的状态机:
空闲状态:空闲状态保持高电平。
起始位发送状态:发送起始位,低电平。
数据发送状态:数据位从最低位(LSB)开始发送,这是UART的标准格式。
停止位发送状态:发送停止位,高电平。

串口发送模块的工程代码:
module uart_tx( input clk, input rst_n, input tx_start, input [7:0] tx_data, output reg uart_tx, output tx_busy ); parameterCLK_FREQ =50000000; parameterBAUD_RATE =115200; // 波特率计数器 localparam BAUD_CNT_MAX = CLK_FREQ / BAUD_RATE; reg [15:0] baud_cnt; wire baud_tick = (baud_cnt ==0); // 状态定义 localparam IDLE =2'd0; localparam START = 2'd1; localparamDATA=2'd2; localparam STOP = 2'd3; reg [1:0] state; reg [2:0] bit_cnt; reg [7:0] tx_reg; // 波特率计数器 always@(posedge clk or negedge rst_n)begin if(!rst_n)begin baud_cnt <= 0; end elseif(state != IDLE) begin if(baud_cnt == 0) begin baud_cnt <= BAUD_CNT_MAX - 1; end else begin baud_cnt <= baud_cnt - 1; end end else begin baud_cnt <= 0; end end // 状态机 always @(posedge clk or negedge rst_n) begin if(!rst_n) begin state <= IDLE; uart_tx <= 1'b1; bit_cnt <= 0; tx_reg <= 0; end else begin case(state) IDLE: begin uart_tx <= 1'b1; if (tx_start) begin state <= START; tx_reg <= tx_data; end end START: begin if(baud_tick) begin uart_tx <= 1'b0; state <= DATA; bit_cnt <= 0; end end DATA: begin if(baud_tick) begin uart_tx <= tx_reg[bit_cnt]; if (bit_cnt == 3'd7) begin state <= STOP; end else begin bit_cnt <= bit_cnt + 1; end end end STOP: begin if(baud_tick) begin uart_tx <= 1'b1; state <= IDLE; end end endcase end end assign tx_busy = (state != IDLE); endmodule
top文件代码要完成的任务是:
只有在检测到接收完成信号的上升沿时才启动发送
只有在发送器不忙时才启动新的发送
实现了接收数据到发送数据的无缝衔接
moduleDE23_Lite_uart( input clk, input rst_n, input uart_rx, output uart_tx ); /* synthesis keep */wire [7:0] rx_data; wire rx_done; wire rx_done_rise,tx_start; wire tx_busy; // UART接收模块 uart_rx#( .CLK_FREQ(50000000), .BAUD_RATE(115200) ) uart_rx_inst ( .clk(clk), .rst_n(rst_n), .uart_rx(uart_rx), .rx_data(rx_data), .rx_done(rx_done) ); // UART发送模块 uart_tx#( .CLK_FREQ(50000000), .BAUD_RATE(115200) ) uart_tx_inst ( .clk(clk), .rst_n(rst_n), .tx_start(tx_start), .tx_data(rx_data), .uart_tx(uart_tx), .tx_busy(tx_busy) ); // 回环控制逻辑 reg rx_done_reg; always @(posedge clkornegedge rst_n)begin if(!rst_n) begin rx_done_reg <= 1'b0; end else begin rx_done_reg <= rx_done; end end // 检测接收完成的上升沿 assign rx_done_rise = rx_done && !rx_done_reg; // 发送启动信号 assign tx_start = rx_done_rise && !tx_busy; endmodule
仿真代码:
`timescale1ns/1ps
module DE23_Lite_uart_tb;
// 输入
reg clk;
reg rst_n;
reg uart_rx;
// 输出
wire uart_tx;
// 测试参数
parameter CLK_PERIOD =20; // 50MHz时钟周期
parameter BIT_PERIOD =8680;// 115200波特率的位周期(1/115200 ≈ 8.68μs)
// 实例化顶层模块
DE23_Lite_uartuut(
.clk(clk),
.rst_n(rst_n),
.uart_rx(uart_rx),
.uart_tx(uart_tx)
);
// 时钟生成
always begin
clk =0;
#(CLK_PERIOD/2);
clk =1;
#(CLK_PERIOD/2);
end
// 测试任务:发送一个字节
task send_byte;
input [7:0] data;
integer i;
begin
// 发送起始位
uart_rx =0;
#(BIT_PERIOD);
// 发送8个数据位
for(i =0; i < 8; i = i + 1) begin
uart_rx = data[i];
#(BIT_PERIOD);
end
// 发送停止位
uart_rx = 1;
#(BIT_PERIOD);
end
endtask
// 主测试程序
initial begin
// 初始化
rst_n = 0;
uart_rx = 1;
// 复位
#100;
rst_n = 1;
#100;
// 测试1:发送字节 8'h55
send_byte(8'h55);
// 测试2:发送字节 8'hAA
send_byte(8'hAA);
// 测试3:发送字节 8'hF0
send_byte(8'hF0);
// 测试4:发送字节 8'h0F
send_byte(8'h0F);
// 结束仿真
#10000;
$stop;
end
endmodule
modelsim仿真波形:

可以看到:
第一个波特位时间内,rx先发送低电平起始位,然后发送8bit数据01010101(低位在前,8'h55),最后发送高电平停止位;tx则一直是高电平。
第二个波特位时间内,rx先发送低电平起始位,然后rx发送第二个测试数据10101010(低位在前,8'hAA),最后发送高电平停止位;tx则接收到8bit数据01010101。
第三个波特位时间内,rx先发送低电平起始位,然后rx接收第二个测试数据11110000(低位在前,8'hF0),最后发送高电平停止位;tx则接收到8bit数据10101010。
第四个波特位时间内,rx先发送低电平起始位,然后rx接收第二个测试数据00001111(低位在前,8'h0F),最后发送高电平停止位;tx则接收到8bit数据11110000。
第五个波特位时间内,rx保持高电平;tx则接收到8bit数据00001111。
Quartus版本选择:25.1,具体操作参考文章最新版Quartus Prime Pro 25.1 的安装和使用演示(含Questa仿真)
引脚分配:

4下板测试

打开串口工具比如Putty或者是下面截图所示的XCOM,然后按照如下操作去测试:
选择正确的COM口
波特率设置为115200
停止位设置为1位
无校验位
点击打开串口
在发送窗口随便发送数据,可以看到上面接收窗口得到同样的数据显示,表示测试成功。

-
FPGA
+关注
关注
1655文章
22287浏览量
630317 -
接口
+关注
关注
33文章
9446浏览量
156146 -
串口通信
+关注
关注
34文章
1657浏览量
57639 -
开发板
+关注
关注
25文章
6125浏览量
113381 -
Agilex
+关注
关注
0文章
26浏览量
3981
原文标题:2-基于FPGA开发板DE23-Lite的串口通信设计 (FT2232H)
文章出处:【微信号:友晶FPGA,微信公众号:友晶FPGA】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
基于FPGA开发板TSP的串口通信设计
基于FPGA开发板DE10-Standard和T-Core的串口通信设计
出售DE2-70 FPGA开发板
Altera DE2 开发板测试说明
基于FPGA了解DE2开发板
fpga开发板用途,fpga开发板价格
ALTERA公司的DE1 SoC FPGA开发板的培训教程免费下载
基于STM32F4开发板的激光测距模块串口通信(三)

基于FPGA开发板DE23-Lite的串口通信设计
评论