This repository has been archived on 2021-01-21. You can view files and clone it, but cannot push or open issues or pull requests.
hdmi.old/src/serial_rx.v
2020-09-19 23:42:44 +02:00

94 lines
2.4 KiB
Verilog

module serial_rx #(
parameter CLK_PER_BIT = 50
)(
input clk,
input rst,
input rx,
output [7:0] data,
output new_data
);
// clog2 is 'ceiling of log base 2' which gives you the number of bits needed to store a value
parameter CTR_SIZE = $clog2(CLK_PER_BIT);
localparam STATE_SIZE = 2;
localparam IDLE = 2'd0,
WAIT_HALF = 2'd1,
WAIT_FULL = 2'd2,
WAIT_HIGH = 2'd3;
reg [CTR_SIZE-1:0] ctr_d, ctr_q;
reg [2:0] bit_ctr_d, bit_ctr_q;
reg [7:0] data_d, data_q;
reg new_data_d, new_data_q;
reg [STATE_SIZE-1:0] state_d, state_q = IDLE;
reg rx_d, rx_q;
assign new_data = new_data_q;
assign data = data_q;
always @(*) begin
rx_d = rx;
state_d = state_q;
ctr_d = ctr_q;
bit_ctr_d = bit_ctr_q;
data_d = data_q;
new_data_d = 1'b0;
case (state_q)
IDLE: begin
bit_ctr_d = 3'b0;
ctr_d = 1'b0;
if (rx_q == 1'b0) begin
state_d = WAIT_HALF;
end
end
WAIT_HALF: begin
ctr_d = ctr_q + 1'b1;
if (ctr_q == (CLK_PER_BIT >> 1)) begin
ctr_d = 1'b0;
state_d = WAIT_FULL;
end
end
WAIT_FULL: begin
ctr_d = ctr_q + 1'b1;
if (ctr_q == CLK_PER_BIT - 1) begin
data_d = {rx_q, data_q[7:1]};
bit_ctr_d = bit_ctr_q + 1'b1;
ctr_d = 1'b0;
if (bit_ctr_q == 3'd7) begin
state_d = WAIT_HIGH;
new_data_d = 1'b1;
end
end
end
WAIT_HIGH: begin
if (rx_q == 1'b1) begin
state_d = IDLE;
end
end
default: begin
state_d = IDLE;
end
endcase
end
always @(posedge clk) begin
if (rst) begin
ctr_q <= 1'b0;
bit_ctr_q <= 3'b0;
new_data_q <= 1'b0;
state_q <= IDLE;
end else begin
ctr_q <= ctr_d;
bit_ctr_q <= bit_ctr_d;
new_data_q <= new_data_d;
state_q <= state_d;
end
rx_q <= rx_d;
data_q <= data_d;
end
endmodule