1. 实验内容
- 学习UART解析模块代码逻辑
- 根据实验手册中提供的波形图,自行完成回环功能,并使用串口调试助手完成回环功能的测试
2. 实验要求
- 给出完整的回环程序代码
- 验收串口调试助手的回环显示
- 提交完整的实验报告
3. 实验过程
1. 添加样例代码
2. 添加 IP 核
3. 开始编写代码
根据UART的逻辑,编写了以下回环代码:
module uart_top#(
parameter baudrate = 115200
)(
input wire CLK,
input wire RSTN,
input wire rx_i, // Receiver input
output wire tx_o // Transmitter output
);
localparam baud_div = 434 ;
// receive buffer register, read only
(*mark_debug="true"*)wire [7:0] rx_data;
(*mark_debug="true"*)wire [7:0] tx_data;
// parity error
wire parity_error;
wire [3:0] IIR_o;
reg [3:0] clr_int;
// tx flow control
(*mark_debug="true"*)wire tx_ready;
// rx flow control
(*mark_debug="true"*)wire rx_valid;
reg fifo_tx_valid;
(*mark_debug="true"*)reg tx_valid;
wire fifo_rx_valid;
reg fifo_rx_ready;
(*mark_debug="true"*) wire rx_ready;
(*mark_debug="true"*) wire fifo_wren;
(*mark_debug="true"*) wire fifo_rden;
(*mark_debug="true"*)wire fifo_full;
(*mark_debug="true"*)wire fifo_empty;
uart_rx u_uart_rx(
.clk_i ( CLK ),
.rstn_i ( RSTN ),
.rx_i ( rx_i ),
.cfg_en_i ( 1'b1 ), // 涓插彛妯″潡浣胯兘
.cfg_div_i ( 16'd0431 ), // 姣忎竴浣嶆暟鎹帴鏀堕渶瑕佺殑鍛ㄦ湡鏁?
.cfg_parity_en_i ( 1'b0 ), // 濂囧伓鏍¢獙浣胯兘
.cfg_parity_sel_i ( 2'b00 ), // 濂囧伓鏍¢獙绫诲瀷浣胯兘
.cfg_bits_i ( 2'b11 ), // 鏁版嵁浣嶉?夋嫨锛?2'b00 -> 5bit, 2'b01 -> 6bit, 2'b10 -> 7bit, 2'b11 -> 8bit
// .cfg_stop_bits_i ( regs_q[(LCR * 8) + 2] ),
.busy_o ( ),
.err_o ( parity_error ),
.err_clr_i ( 1'b0 ),
.rx_data_o ( rx_data ),
.rx_valid_o ( rx_valid ),
.rx_ready_i ( rx_ready )
);
uart_tx u_uart_tx(
.clk_i ( CLK ),
.rstn_i ( RSTN ),
.tx_o ( tx_o ),
.busy_o ( ),
.cfg_en_i ( 1'b1 ), // 涓插彛妯″潡浣胯兘
.cfg_div_i ( 16'd0431 ), // 姣忎竴浣嶆暟鎹帴鏀堕渶瑕佺殑鍛ㄦ湡鏁?
.cfg_parity_en_i ( 1'b0 ), // 濂囧伓鏍¢獙浣胯兘
.cfg_parity_sel_i ( 2'b00 ), // 濂囧伓鏍¢獙绫诲瀷浣胯兘
.cfg_bits_i ( 2'b11 ), // 鏁版嵁浣嶉?夋嫨锛?2'b00 -> 5bit, 2'b01 -> 6bit, 2'b10 -> 7bit, 2'b11 -> 8bit
.cfg_stop_bits_i ( 1'b1 ), // 鏄惁鏈夊仠姝綅
.tx_data_i ( tx_data ),
.tx_valid_i ( tx_valid ),
.tx_ready_o ( tx_ready )
);
// loop
fifo_8b u_fifo_8b (
.clk(CLK), // input wire clk
.srst(~RSTN), // input wire srst
.din(rx_data), // input wire [7 : 0] din
.wr_en(fifo_wren), // input wire wr_en
.rd_en(fifo_rden), // input wire rd_en
.dout(tx_data), // output wire [7 : 0] dout
.full(fifo_full), // output wire full
.empty(fifo_empty) // output wire empty
);
// your code here
assign fifo_wren = (rx_valid &&!fifo_full);
assign fifo_rden = (!fifo_empty && tx_ready);
assign rx_ready=(!fifo_full);
always @(posedge CLK or negedge RSTN) begin
if (!RSTN) begin
tx_valid <= 1'b0; // 在复位时应清零 tx_valid
end else begin
if (!fifo_empty && fifo_rden) begin
tx_valid <= 1'b1;
end else begin
tx_valid <= 1'b0;
end
end
end
// your code end
endmodule
为了验证UART回环功能的实现,编写了测试模块 uart_loop_tb
。该模块用于生成时钟信号,初始化UART模块,并模拟数据传输过程。
module uart_loop_tb;
// Internal signals
parameter clk_freq = 10;
reg clk;
reg rst_n;
reg tx_release;
reg [7:0] rx_data;
reg rx_valid;
wire rx_ready;
wire [7:0] tx_data;
reg tx_valid;
reg tx_ready;
wire fifo_wren;
wire fifo_rden;
wire fifo_full;
wire fifo_empty;
// Clock process to generate clock signals
always begin
# (clk_freq / 2) clk = ~clk;
end
// Reset signals
initial begin
clk = 1'b1;
rst_n = 1'b0;
#50 rst_n = 1'b1;
end
// DUT instantiation
fifo_8b u_fifo_8b (
.clk(clk), // input wire clk
.srst(~rst_n), // input wire srst
.din(rx_data), // input wire [7 : 0] din
.wr_en(fifo_wren), // input wire wr_en
.rd_en(fifo_rden), // input wire rd_en
.dout(tx_data), // output wire [7 : 0] dout
.full(fifo_full), // output wire full
.empty(fifo_empty) // output wire empty
);
// simulation code
initial begin
rx_data = 8'h25;
rx_valid = 1'b0;
tx_ready = 1'b1;
tx_release = 1'b0;
// oper after rst release
#80 tx_release = 1'b0;
// your code here
rx_valid=1'b1;
#10;
rx_valid=1'b0;
// your code end
// this signal used for release tx_ready
#80 tx_release = 1'b1;
#10 tx_release = 1'b0;
end
always @(posedge clk) begin
if(tx_valid)
tx_ready <= 1'b0;
else if (tx_release)
tx_ready <= 1'b1;
end
// loop code here
assign fifo_wren = (rx_valid &&!fifo_full);
assign fifo_rden = (!fifo_empty && tx_ready);
assign rx_ready=(!fifo_full);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
tx_valid <= 1'b0; // 在复位时应清零 tx_valid
end else begin
if (!fifo_empty && fifo_rden) begin
tx_valid <= 1'b1;
end else begin
tx_valid <= 1'b0;
end
end
end
// loop code end
endmodule
4. 结果分析
利用Vivado得到仿真波形如图:
通过使用串口调试助手进行测试,验证了UART回环功能。测试时输入的每个字节都能够通过UART正确回传,显示在调试助手的接收窗口中,验证了代码逻辑的正确性,结果如图:
5. 总结
本次实验通过学习和实现UART的回环功能,加深了对串口通信的理解。通过实验,我们掌握了如何使用FIFO缓冲区处理接收到的数据以及如何通过UART模块进行数据的发送和接收。同时,测试结果表明我们实现的回环功能符合预期,为今后更复杂的串口通信打下了基础。