Vivado中UART收发无输出:测试台改100MHz时钟后数据恒为0
问题根因排查
1. 波特率生成模块硬编码位宽不匹配
你现在100MHz时钟下,计算得到的参数:
- RX_ACC_MAX = 100000000/(9600*16) ≈ 651,位宽需要至少10位
- TX_ACC_MAX = 100000000/9600 ≈ 10417,位宽需要至少14位
但代码里硬写死了增量和判断的位宽:
assign rxclk_en = (rx_acc == 5'd0); // 仅判断低5位,高位被忽略 rx_acc <= rx_acc + 5'b1; // 仅累加低5位,高位不会正常计数 assign txclk_en = (tx_acc == 9'd0); // 仅判断低9位,高位被忽略 tx_acc <= tx_acc + 9'b1; // 仅累加低9位,高位不会正常计数
这就导致波特率使能信号完全不会按照预期生成,收发逻辑拿不到正确的采样使能,自然无法正常工作。
2. 测试台的写使能脉冲宽度不够
100MHz时钟的周期是10ns,但是你测试台里写使能只拉了2ns:
enable <= 1'b1; #2 enable <= 1'b0;
这个脉冲宽度远小于时钟周期,不会被发送模块的时钟沿采样到,发送逻辑根本没收到发送触发信号,自然不会启动发送。
修复方案
第一步:修改波特率生成模块的硬编码位宽
把固定位宽的写法替换成基于参数位宽的自适应写法:
// 修改baud_rate_gen模块的对应逻辑 assign rxclk_en = (rx_acc == 'd0); // 去掉固定位宽,匹配rx_acc的实际位宽 assign txclk_en = (tx_acc == 'd0); // 去掉固定位宽,匹配tx_acc的实际位宽 always @(posedge clk_50m) begin if (rx_acc == RX_ACC_MAX[RX_ACC_WIDTH - 1:0]) rx_acc <= 0; else rx_acc <= rx_acc + 1'b1; // 去掉固定5位限制,自动匹配位宽 end always @(posedge clk_50m) begin if (tx_acc == TX_ACC_MAX[TX_ACC_WIDTH - 1:0]) tx_acc <= 0; else tx_acc <= tx_acc + 1'b1; // 去掉固定9位限制,自动匹配位宽 end
第二步:修改测试台的写使能脉冲宽度
把使能脉冲拉长到至少一个时钟周期以上,保证被时钟采样到:
initial begin $dumpvars(0, uart_tx_test); enable <= 1'b1; #15 enable <= 1'b0; // 15ns大于10ns的时钟周期,保证被采样到 end always @(posedge rdy) begin #2 rdy_clr <= 1; #2 rdy_clr <= 0; if (rxdata != data) begin $display("FAIL: rx data %x does not match tx %x", rxdata, data); $finish; end else begin if (rxdata == 8'hff) begin $display("SUCCESS: all bytes verified"); $finish; end data <= data + 1'b1; enable <= 1'b1; #15 enable <= 1'b0; // 同样拉长后续发送的使能脉冲 end end
可选优化
建议把模块输入端口的clk_50m名称改成clk避免误解,毕竟现在时钟已经调整为100MHz。
内容的提问来源于stack exchange,提问作者Coolo
相关产品推荐
相关产品推荐

