我使用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:
对于模拟,我发送了字节0x55,0x11,0x32,0x63和0xFF。 byte_ready信号在每个字节(正好一个时钟周期)的正确时间被置位。我的模拟效果似乎很好。
我甚至模拟了波特率的不同误差。 (注意:我的设计工作波特率为 115200 。模拟仍能正常工作。
我甚至使用Signaltap逻辑分析仪来确认输入的Rx信号。我甚至使用Signaltap观察系统的状态进展,但状态从未改变过。它始终保持正确,即使我看到FPGA接收到Rx。
我甚至将其更改为显示不同的LED闪烁以显示接收的状态或字节。什么都没有亮起。
看起来设计根本没有反应。
关于下一步该怎么做,我完全迷失了。任何帮助将不胜感激。
编辑:
我设法让LED发生反应。然而现在看来我收到的字节是完全随机的。探究信号我意识到状态的LSB(状态[0])正在以错误的方式进行,与模拟进行比较。
应该为每个接收到的Rx位切换,但Signaltap显示它正在做其他事情。
Signaltap and Modelsim waves(ModelSim是应该发生的事情):
如何解决这种差异?
答案 0 :(得分:0)
建议在使用之前注册RX输入。使用它的逻辑可以在不同的时间(相对于时钟)看到它,有些触发器可能会像RX改变状态一样切换,而其他可能不会。
此外,建议不要将同一个始终块中异步复位的信号与不是的块一起分配。