文章目录
1. 实验设计
1.1 硬件
本次UART实验使用了type-c接口,而不是传统的DB9接口,因此在主板上使用了一块CH340C芯片作为U转串的芯片。
1.2 实验方法
- 以笔记本电脑作为上位机,FPGA作为下位机
- 笔记本电脑给FPGA发送数据,FPGA接收数据后再发送回串口
2. 程序设计
2.1 系统模型
- 接收模块:接收数据,并把数据一位以为存到一个寄存器中,存完给一个信号
- 环回模块:协调接收模块与发送模块,确保接收和发送不会互相打断
- 发送模块:将接收的数据按照时序一位一位发给上位机
2.2 协议设计
数据位为8位,停止位为1位,无校验位。波特率为115200bps
时序图如下
- sys_clk:系统时钟
- uart_rxd:FPGA接收的数据
- start_flag:当接收到start bit时,抓一个上升沿,抓到后让rx_flag拉高
- rx_flag:拉高代表正在接收中
- clk_cnt:时钟周期计数,通过十的九次方ns除以波特率除以20ns(50M的一个时钟周期),本次实验中,每满434判断数据发送了一个字节
- rx_cnt:接收到的字节个数
- uart_done:当接收完八位数据位时拉高,接收过程结束,即rx_flag拉低后拉低
- uart_data:接收到的值
3.程序编写
编写了uart_loop.v,uart_loopback_top.v,uart_recv.v,uart_send.v,uart.xdc,源码如下所示
3.1 uart_loop.v
module uart_loop(
input sys_clk,
input sys_rst_n,
input recv_down,
input [7 : 0] recv_data,
input tx_busy,
output reg send_en,
output reg [7 : 0] send_data
);
reg recv_down_d0;
reg recv_down_d1;
reg tx_ready;
wire recv_down_flag;
assign recv_down_flag = (~recv_down_d1) & recv_down_d0;
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin
recv_down_d0 <= 1'd0;
recv_down_d1 <= 1'd0;
end
else begin
recv_down_d0 <= recv_down;
recv_down_d1 <= recv_down_d0;
end
end
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin
send_en <= 1'd0;
send_data <= 8'd0;
tx_ready <= 1'd0;
end
else begin
if(recv_down_flag) begin
tx_ready <= 1'd1;
send_en <= 1'd0;
send_data <= recv_data;
end
else if((~tx_busy)&&tx_ready) begin
tx_ready <= 1'd0;
send_en <= 1'd1;
end
end
end
endmodule
3.2 uart_loopback_top.v
module uart_loopback_top(
input sys_clk,
input sys_rst_n,
input uart_rxd,
output uart_txd
);
wire uart_en;
wire [7 : 0] uart_din;
wire [7 : 0] uart_data;
wire uart_done;
wire uart_tx_busy;
uart_recv uart_recv_u(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.uart_rxd (uart_rxd),
.</