107 lines
1.9 KiB
Systemverilog
107 lines
1.9 KiB
Systemverilog
|
|
module rx #(parameter CLK_FREQUENCY = 100000000, BAUD_RATE =
|
|
19200)(
|
|
input wire logic clk, odd, rx_in,
|
|
output logic[7:0] dout,
|
|
output logic data_strobe, error, busy
|
|
);
|
|
logic ResetTimer, EnableTimer, LastCycle, HalfCycle, LastBit, NextBit = 0,
|
|
ResetCounter,
|
|
Shift, Stop, Parity;
|
|
localparam ONE_BIT_CNT = CLK_FREQUENCY / BAUD_RATE;
|
|
localparam HALF_CNT = ONE_BIT_CNT / 2;
|
|
function integer clogb2;
|
|
input [31:0] value;
|
|
begin
|
|
value = value - 1;
|
|
for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) begin
|
|
value = value >> 1;
|
|
end
|
|
end
|
|
endfunction
|
|
|
|
localparam NUM_BITS_FULL_CNT = clogb2(ONE_BIT_CNT);
|
|
logic[NUM_BITS_FULL_CNT - 1:0] count = 0;
|
|
|
|
always_ff@ (posedge clk)
|
|
begin
|
|
if(ResetTimer || count == ONE_BIT_CNT)
|
|
count <= 0;
|
|
else if(EnableTimer)
|
|
count <= count + 1;
|
|
end
|
|
assign LastCycle = (count == ONE_BIT_CNT) ? 1'b1:1'b0;
|
|
|
|
assign HalfCycle = (count == HALF_CNT) ? 1'b1:1'b0;
|
|
|
|
assign error = ~(((^dout)^odd)==Parity)||(~Stop);
|
|
logic[3:0] countBit = 0;
|
|
always_ff @(posedge clk)
|
|
begin
|
|
if(NextBit)
|
|
countBit <= countBit + 1;
|
|
else if(ResetCounter || LastBit)
|
|
countBit <= 0;
|
|
end
|
|
assign LastBit = (countBit == 4'b1011) ? 1'b1:1'b0;
|
|
|
|
logic[9:0] shift = 10'b1111111111;
|
|
always_ff @(posedge clk)
|
|
begin
|
|
if(Shift)
|
|
shift <= {rx_in, shift[9:1]};
|
|
end
|
|
assign Stop = shift[9];assign Parity = shift[8];
|
|
assign dout = shift[7:0];
|
|
|
|
typedef enum {IDLE, HALF, FULL, LOAD} stateType;
|
|
stateType ns, cs;
|
|
always_comb
|
|
begin
|
|
ns = cs;
|
|
Shift = 0;
|
|
busy = 1;
|
|
EnableTimer = 0;
|
|
ResetTimer = 0;
|
|
ResetCounter = 0;
|
|
data_strobe = 0;
|
|
NextBit = 0;
|
|
case(cs)
|
|
IDLE:
|
|
begin
|
|
ResetTimer = 1;ResetCounter = 1;
|
|
busy = 0;
|
|
if(!rx_in)
|
|
ns = HALF;
|
|
end
|
|
HALF:
|
|
begin
|
|
EnableTimer = 1;
|
|
if(!HalfCycle && rx_in)
|
|
ns = IDLE;
|
|
else if(HalfCycle)
|
|
ns = LOAD;
|
|
end
|
|
LOAD:
|
|
begin
|
|
busy = 1;
|
|
Shift = 1;
|
|
NextBit = 1;ResetTimer = 1;
|
|
ns = FULL;
|
|
end
|
|
FULL:
|
|
begin
|
|
busy = 1;
|
|
EnableTimer = 1;
|
|
if(LastCycle)
|
|
ns = LOAD;
|
|
else if(LastBit)
|
|
begin
|
|
data_strobe = 1;
|
|
ns = IDLE;
|
|
end
|
|
end
|
|
endcase
|
|
end
|
|
always_ff @(posedge clk)
|
|
cs <= ns;endmodule |