Created
June 6, 2023 14:58
-
-
Save nickelpro/3435df24c7ce8b236e4ddcc892ca15f8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module EdgeSync ( | |
input clk, | |
input nReset, | |
input in, | |
output rise, | |
output fall, | |
output logic out | |
); | |
logic sync, cmp; | |
assign rise = out & ~cmp; | |
assign fall = ~out & cmp; | |
always_ff @(posedge clk, negedge nReset) begin | |
if (!nReset) begin | |
cmp <= 0; | |
out <= 0; | |
sync <= 0; | |
end else begin | |
cmp <= out; | |
out <= sync; | |
sync <= in; | |
end | |
end | |
endmodule | |
module UartRx #( | |
int Oversample = 16 | |
) ( | |
input clk, | |
input nReset, | |
input in, | |
output logic [7:0] data, | |
output logic done, | |
output logic err | |
); | |
localparam sampleWidth = $clog2(Oversample); | |
localparam fullSampleCount = sampleWidth'(Oversample - 1); | |
localparam halfSampleCount = sampleWidth'((Oversample / 2) - 1); | |
// verilog_format: off | |
enum { | |
IDLE, | |
START, | |
DATA_A, | |
DATA_B, | |
STOP, | |
ERROR | |
} curState, nextState; | |
// verilog_format: on | |
logic rise, fall, syncOut; | |
EdgeSync es ( | |
.*, | |
.out(syncOut) | |
); | |
logic edgeDetect = fall || rise; | |
logic [sampleWidth-1:0] sampleCount; | |
logic [7:0] readBuf; | |
logic [2:0] readCount; | |
logic edgeCmp; | |
logic badSync = edgeDetect && edgeCmp && (sampleCount >= halfSampleCount); | |
logic reSync = edgeDetect && (sampleCount < halfSampleCount); | |
logic advance = reSync || (sampleCount == 0); | |
always_ff @(posedge clk, negedge nReset) begin | |
if (!nReset) begin | |
sampleCount <= fullSampleCount; | |
edgeCmp <= 0; | |
curState <= IDLE; | |
end else begin | |
curState <= nextState; | |
if (curState != nextState) begin | |
edgeCmp <= 0; | |
sampleCount <= fullSampleCount; | |
end else begin | |
edgeCmp <= edgeDetect ? 1 : edgeCmp; | |
sampleCount <= sampleCount - 1; | |
end | |
end | |
end | |
always_ff @(posedge clk, negedge nReset) begin | |
if (!nReset) begin | |
readCount <= 7; | |
done <= 0; | |
end else begin | |
if (readCount == 0) begin | |
data <= readBuf; | |
done <= 1; | |
end else begin | |
done <= 0; | |
end | |
if (nextState != DATA_A && nextState != DATA_B) begin | |
readCount <= 7; | |
end else if (sampleCount == halfSampleCount) begin | |
readCount <= readCount - 1; | |
readBuf <= {readBuf[7:1], syncOut}; | |
end | |
end | |
end | |
always_ff @(posedge clk, negedge nReset) begin | |
if (!nReset || nextState != ERROR) begin | |
err <= 0; | |
end else begin | |
err <= 1; | |
end | |
end | |
always_comb begin | |
case (curState) | |
IDLE: | |
if (fall) begin | |
nextState = START; | |
end else begin | |
nextState = curState; | |
end | |
START: | |
if (rise && (sampleCount >= halfSampleCount)) begin | |
nextState = ERROR; | |
end else if (advance) begin | |
nextState = DATA_A; | |
end | |
DATA_A: | |
if (badSync) begin | |
nextState = ERROR; | |
end else if (advance && (readCount > 0)) begin | |
nextState = DATA_B; | |
end else begin | |
nextState = STOP; | |
end | |
DATA_B: | |
if (badSync) begin | |
nextState = ERROR; | |
end else if (advance && (readCount > 0)) begin | |
nextState = DATA_A; | |
end else begin | |
nextState = STOP; | |
end | |
STOP: | |
if (badSync || (fall && (sampleCount >= halfSampleCount))) begin | |
nextState = ERROR; | |
end else if (fall) begin | |
nextState = START; | |
end else begin | |
nextState = IDLE; | |
end | |
ERROR: nextState = IDLE; | |
endcase | |
end | |
endmodule |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment