f4pga-examples/xc7/additional_examples/uart_tx-rx/reciever.sv

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