I keep getting this error for the BufferNext
register, and I have no idea why; any help is appreciated. Here is the code for the module:
`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
As far as I know, to get rid of latches, one should make sure that every if
has an else
, as well as each case
statement has a default
case. As far as I can tell, that shouldn't be the problem, as I have indeed added an else to each if, and a default
to each case
, and assigned a value to BufferNext explicitly in each one of them (Sometimes it's just BufferNext <= BufferNext just for the sake of explicitly assigning something to BufferNext). The objective here would be to get rid of that latch.
The cause of the latchs is this:
default :
begin
wFSM_Next = sIDLE;
wCnt_Next = 0;
wBit_Next = 0;
BufferNext = BufferNext;
end
Its feedback around combinational logic on BufferNext
.
You are asking it to hold its value.
As another answer pointed out, there is a serious problem that BufferNext
is driven in the combinational process and in the clocked process that infers registers.
Typical state machine style would have BufferNext
combinational only, and it would act as input to a register called Buffer
.
Another problem is the use of non-blocking assignments in a combinational process. This can cause simulation & synthesis mismatches.
Use:
BufferNext = <RHS>;
Rather than:
BufferNext <= <RHS>;
In combitational processes (like a case
statement)