串行接收器的Verilog实现不像模拟(事实上,它什么都不做)

时间:2014-06-09 03:49:42

标签: hardware verilog fpga state-machine uart

我使用Verilog设计了一个简单的UART接收器实现。我是使用状态机方法完成的。

这是我的代码:

module my_serial_receiver(
    input clk,
    input reset_n,
    input Rx,
    output reg [7:0] received_byte,
    output reg byte_ready
);

parameter IDLE = 4'd0, BIT_0 = 4'd1, BIT_1 = 4'd2,
                BIT_2 = 4'd3, BIT_3 = 4'd4, BIT_4 = 4'd5, BIT_5 = 4'd6, 
                BIT_6 = 4'd7, BIT_7 = 4'd8, BYTE_READY = 4'd9;

reg [3:0] state = 0;
reg [8:0] baud_clock = 0;
reg baud_sync = 0;
reg baud_tick = 0;
reg baud_reset = 0;

always @(posedge clk) begin
    if (baud_reset) baud_clock <= 9'd1;
    else if (baud_sync) begin
        if (baud_clock == 9'd322) baud_clock <= 0;
        else baud_clock <= baud_clock + 9'd1;
    end
    else begin
        if (baud_clock == 9'd215) baud_clock <= 0;
        else baud_clock <= baud_clock + 9'd1;
    end
end

always @(*) begin
    baud_tick <= ~|baud_clock;
end

always @(posedge clk or negedge reset_n) begin
    if (~reset_n) begin
        state <= IDLE;
        received_byte <= 8'h0;
    end
    else begin
    case(state)
        IDLE: begin
             byte_ready <= 0;
             if (Rx == 0) begin
                state <= BIT_0;
                baud_reset <= 1;
                baud_sync <= 1;
             end
        end
        BIT_0: begin
            baud_reset <= 0;
            if (baud_tick) begin
                baud_sync <= 0;
                received_byte[0] <= Rx;
                state <= BIT_1;
            end
        end
        BIT_1: begin
             if (baud_tick) begin
                received_byte[1] <= Rx;
                state <= BIT_2;
            end
        end
        BIT_2: begin
             if (baud_tick) begin
                received_byte[2] <= Rx;
                state <= BIT_3;
            end
        end
        BIT_3: begin
             if (baud_tick) begin
                received_byte[3] <= Rx;
                state <= BIT_4;
            end
        end
        BIT_4: begin
             if (baud_tick) begin
                received_byte[4] <= Rx;
                state <= BIT_5;
            end
        end
        BIT_5: begin
             if (baud_tick) begin
                received_byte[5] <= Rx;
                state <= BIT_6;
            end
        end
        BIT_6: begin
             if (baud_tick) begin
                received_byte[6] <= Rx;
                state <= BIT_7;
            end
        end
        BIT_7: begin
             if (baud_tick) begin
                received_byte[7] <= Rx;
                state <= BYTE_READY;
            end
        end
        BYTE_READY: begin
            if (baud_tick) begin
             byte_ready <= 1;
             state <= IDLE;
            end
        end
        default: state <= IDLE;
    endcase
    end
end 

endmodule 

这是一个picture of my simulation results

waveform1

对于模拟,我发送了字节0x55,0x11,0x32,0x63和0xFF。 byte_ready信号在每个字节(正好一个时钟周期)的正确时间被置位。我的模拟效果似乎很好。

我甚至模拟了波特率的不同误差。 (注意:我的设计工作波特率为 115200 。模拟仍能正常工作。

我甚至使用Signaltap逻辑分析仪来确认输入的Rx信号。我甚至使用Signaltap观察系统的状态进展,但状态从未改变过。它始终保持正确,即使我看到FPGA接收到Rx。

我甚至将其更改为显示不同的LED闪烁以显示接收的状态或字节。什么都没有亮起。

看起来设计根本没有反应。

关于下一步该怎么做,我完全迷失了。任何帮助将不胜感激。

编辑:

我设法让LED发生反应。然而现在看来我收到的字节是完全随机的。探究信号我意识到状态的LSB(状态[0])正在以错误的方式进行,与模拟进行比较。

应该为每个接收到的Rx位切换,但Signaltap显示它正在做其他事情。

Signaltap and Modelsim waves(ModelSim是应该发生的事情):

signal-tap-waveform model-sim-waveform

如何解决这种差异?

1 个答案:

答案 0 :(得分:0)

建议在使用之前注册RX输入。使用它的逻辑可以在不同的时间(相对于时钟)看到它,有些触发器可能会像RX改变状态一样切换,而其他可能不会。

此外,建议不要将同一个始终块中异步复位的信号与不是的块一起分配。