UART模块和运算

Posted

技术标签:

【中文标题】UART模块和运算【英文标题】:Uart Module and op 【发布时间】:2018-05-02 19:31:28 【问题描述】:

我想使用 Verilog 在 fpga (Nexys 2) 中分别点亮 LED,但我没有在蓝牙 (hc-06) 和 fpga 之间同步。例如:我从手机发送 255 (1111 1111) 并点亮 LED 4。它应该点亮了所有 8 个 LED。

我怀疑问题是我没有正确设置波特率(蓝牙波特率默认为 9600)。

我的 Verilog 代码贴在下面。

波特率部分:

    module baud_rate_gen(input wire clk_50m,
         output wire rxclk_en,
         output wire txclk_en);

parameter RX_ACC_MAX = 50000000 / (9600 * 10);
parameter TX_ACC_MAX = 50000000 / 9600;
parameter RX_ACC_WIDTH = 9;//$clog2(RX_ACC_MAX);
parameter TX_ACC_WIDTH = 8;//$clog2(TX_ACC_MAX);
reg [RX_ACC_WIDTH - 1:0] rx_acc = 0;
reg [TX_ACC_WIDTH - 1:0] tx_acc = 0;

assign rxclk_en = (rx_acc == 5'd0);
assign txclk_en = (tx_acc == 9'd0);

always @(posedge clk_50m) begin
if (rx_acc == RX_ACC_MAX[RX_ACC_WIDTH - 1:0])
    rx_acc <= 0;
else
    rx_acc <= rx_acc + 5'b1;
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 + 9'b1;
end

endmodule

发射器和接收器部分复制自

https://github.com/jamieiles/uart/blob/master/receiver.v https://github.com/jamieiles/uart/blob/master/transmitter.v

部分ucf文件:

NET "dout<0>"  LOC = "J14"; # Bank = 1, Pin name = IO_L14N_1/A3/RHCLK7, Type = RHCLK/DUAL, Sch name = JD10/LD0
NET "dout<1>"  LOC = "J15"; # Bank = 1, Pin name = IO_L14P_1/A4/RHCLK6, Type = RHCLK/DUAL, Sch name = JD9/LD1
NET "dout<2>"  LOC = "K15"; # Bank = 1, Pin name = IO_L12P_1/A8/RHCLK2, Type = RHCLK/DUAL, Sch name = JD8/LD2
NET "dout<3>"  LOC = "K14"; # Bank = 1, Pin name = IO_L12N_1/A7/RHCLK3/TRDY1, Type = RHCLK/DUAL, Sch name = JD7/LD3
NET "dout<4>"  LOC = "E17"; # Bank = 1, Pin name = IO, Type = I/O, Sch name = LD4? s3e500 only
NET "dout<5>"  LOC = "P15"; # Bank = 1, Pin name = IO, Type = I/O, Sch name = LD5? s3e500 only
NET "dout<6>"  LOC = "F4";  # Bank = 3, Pin name = IO, Type = I/O, Sch name = LD6? s3e500 only
NET "dout<7>"  LOC = "R4";  # Bank = 3, Pin name = IO/VREF_3, Type = VREF, Sch name = LD7? s3e500 only

引脚连接器部分:

NET "tX" LOC = "L17"; # Bank = 1, Pin name = IO_L10N_1/VREF_1, Type = VREF, Sch name = JA3
NET "rx" LOC = "M15"; # Bank = 1, Pin name = IO_L07P_1, Type = I/O, Sch name = JA4

uart_top 模块:

module uart(input wire [7:0] din,
    input wire wr_en,
    input wire clk_50m,
    output wire tx,
    output wire tx_busy,
    input wire rx,
    output wire rdy,
    input wire rdy_clr,
    output wire [7:0] dout,
     output tX,
     input reset);

wire rxclk_en, txclk_en;


baud_rate_gen uart_baud(.clk_50m(clk_50m),
        .rxclk_en(rxclk_en),
        .txclk_en(txclk_en));
transmitter uart_tx(.din(din),
        .wr_en(wr_en),
        .clk_50m(clk_50m),
        .clken(txclk_en),
        .tx(tx),
        .tx_busy(tx_busy));
receiver uart_rx(.rx(rx),
     .rdy(rdy),
     .rdy_clr(rdy_clr),
     .clk_50m(clk_50m),
     .clken(rxclk_en),
     .data(dout));

     assign tX = 1;

 endmodule

【问题讨论】:

【参考方案1】:

首先想到我注意到的是接收器有==15,这意味着一个16x 过采样时钟。查看 github 评论部分证实了这一点。

您的波特率代码使用50000000 / (9600 * 10);,这是一个 10 倍波特率时钟,而不是 16。

在您的波特率代码和 git hub UART 代码中,大量使用了初始化变量。在很多情况下这不起作用。正确的方法是使用复位。

我只看了github接收器的代码,但是非常非常草率:

文件顶部没有标题来解释它是什么或做什么。 没有重置 没有同步器。 UART 数据与时钟异步到达,需要同步! rdy 写在两个地方。这里表示一个 rdy_clr 与数据字节同时到达 data 丢失数据字节。 没有溢出检测。 停止状态不检查位高。这使得未连接的线(始终为低)被视为全零的比特流。

次要点:组装接收字节是用解复用器完成的。 scratch[bitpos[2:0]] 使用移位寄存器可以做什么的很多慢逻辑。

【讨论】:

以上是关于UART模块和运算的主要内容,如果未能解决你的问题,请参考以下文章

UART串口WiFi模块的工作原理及应用

UART工作流程

CMT2380F32模块开发4-UART例程

CMT2380F32模块开发4-UART例程

树莓派3uart wifi模块调试 (浪费了我3天时间的宝贵经验)

振弦采集模块主动上传测量数据( UART)