我一直收到
BufferNext
寄存器的错误,我不知道为什么;任何帮助表示赞赏。这是模块的代码:
`timescale 1ns / 1ps
module uart_rx #(
parameter CLK_FREQ = 125_000_000,
parameter BAUD_RATE = 115_200,
// Example: 125 MHz Clock / 115200 baud UART -> CLKS_PER_BIT = 1085
parameter CLKS_PER_BIT = CLK_FREQ / BAUD_RATE
)
(
input wire iClk, iRst,
input wire iRxSerial,
output wire [7:0] oRxByte,
output wire oRxDone
);
localparam sIDLE = 3'b000;
localparam sSTART_DETECT = 3'b001;
localparam sRX_DATA_RECEIVE = 3'b010;
localparam sRX_END_DETECT = 3'b011;
localparam sRX_DONE = 3'b100;
// Double-register the input wire to prevent metastability issues
reg rRx1, rRx2;
reg [7:0] RxSerialBuffer, BufferNext;
// -> FSM state
reg [2:0] rFSM_Current, wFSM_Next;
// -> counter to keep track of the clock cycles
reg [$clog2(CLKS_PER_BIT):0] rCnt_Current, wCnt_Next;
// -> counter to keep track of sent bits
// (between 0 and 7)
reg [6:0] rBit_Current, wBit_Next;
always @(posedge iClk)
begin
rRx1 <= iRxSerial;
rRx2 <= rRx1;
if (iRst==1)
begin
rFSM_Current <= sIDLE;
rCnt_Current <= 0;
rBit_Current <= 0;
RxSerialBuffer <= 0;
BufferNext <= 0;
end
else
begin
rFSM_Current <= wFSM_Next;
rCnt_Current <= wCnt_Next;
rBit_Current <= wBit_Next;
BufferNext <= BufferNext;
RxSerialBuffer <= BufferNext;
end
end
always @(*)
begin
case(rFSM_Current)
sIDLE: begin
wCnt_Next = 0;
wBit_Next = 0;
if(iRxSerial == 0)
begin
wFSM_Next = sSTART_DETECT;
BufferNext <= 0;
end
else
begin
wFSM_Next = sIDLE;
BufferNext <= BufferNext;
end
end
sSTART_DETECT: begin
wBit_Next = 0;
if (rCnt_Current < (CLKS_PER_BIT - 1) )
begin
wFSM_Next = sSTART_DETECT;
wCnt_Next = rCnt_Current + 1;
BufferNext <= BufferNext;
end
else
begin
wFSM_Next = sRX_DATA_RECEIVE;
wCnt_Next = 0;
BufferNext <= BufferNext;
end
end
sRX_DATA_RECEIVE: begin
if (rCnt_Current < (CLKS_PER_BIT - 1) )
begin
if(rCnt_Current >= (CLKS_PER_BIT - 1)/2)
begin
BufferNext[rBit_Current] <= iRxSerial;
end
else
begin
BufferNext[rBit_Current] <= BufferNext[rBit_Current];
end
wFSM_Next = sRX_DATA_RECEIVE;
wCnt_Next = rCnt_Current + 1;
wBit_Next = rBit_Current;
end
else
begin
wCnt_Next = 0;
if (rBit_Current != 7)
begin
wFSM_Next = sRX_DATA_RECEIVE;
wBit_Next = rBit_Current + 1;
end
else
begin
wFSM_Next = sRX_END_DETECT;
wBit_Next = 0;
end
BufferNext <= BufferNext;
end
end
sRX_END_DETECT: begin
wBit_Next = 0;
if (rCnt_Current < (CLKS_PER_BIT - 1) )
begin
wFSM_Next = sRX_END_DETECT;
wCnt_Next = rCnt_Current + 1;
end
else
begin
wFSM_Next = sRX_DONE;
wCnt_Next = 0;
end
BufferNext <= BufferNext;
end
sRX_DONE: begin
wBit_Next = 0;
wCnt_Next = 0;
BufferNext <= BufferNext;
wFSM_Next = sIDLE;
end
default :
begin
wFSM_Next = sIDLE;
wCnt_Next = 0;
wBit_Next = 0;
BufferNext <= BufferNext;
end
endcase
end
assign oRxByte = RxSerialBuffer;
assign oRxDone = (rFSM_Current == sRX_DONE) ? 1 : 0;
endmodule
据我所知,要摆脱闩锁,应该确保每个
if
都有一个 else
,以及每个 case
语句都有一个 default
案例。据我所知,这不应该是问题所在,因为我确实为每个 if 添加了一个 else,并为每个 default
添加了一个 case
,并在其中的每一个中显式地为 BufferNext 分配了一个值(有时它只是 BufferNext <= BufferNext just for the sake of explicitly assigning something to BufferNext). The objective here would be to get rid of that latch.
问题是:
BufferNext <= BufferNext;
您必须通过以下方式更改它:
RxSerialBuffer <= BufferNext;
这一行的问题在于它没有为 BufferNext 寄存器分配任何新值。相反,它只是将寄存器的现有值分配给自己,这是多余的并且可能导致错误。这一行应该从 always 块中删除,因为它没有做任何有用的事情。
一个问题是您从 2
BufferNext
块分配给相同的信号 (always
)。您应该只分配给来自一个always
块的信号。我的猜测是你不想在第一个BufferNext
块中分配给always
。
意外锁存的另一个潜在来源是分配给信号的单个bit:
BufferNext[rBit_Current] <= ...
确保在
sRX_DATA_RECEIVE
状态下分配所有8位。
latch的原因是这样的:
default :
begin
wFSM_Next = sIDLE;
wCnt_Next = 0;
wBit_Next = 0;
BufferNext = BufferNext;
end
关于组合逻辑的反馈
BufferNext
.正如另一个答案所指出的,在组合过程和推断寄存器的时钟过程中驱动
BufferNext
存在一个严重的问题。
典型的状态机样式只有
BufferNext
组合,它将作为一个名为 Buffer
的寄存器的输入。
另一个问题是在组合过程中使用非阻塞赋值。这可能会导致模拟和综合不匹配。
使用:
BufferNext = <RHS>;
而不是:
BufferNext <= <RHS>;
在组合过程中(如
case
声明)