You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
5.8 KiB
Coq

module uart_rx(
input wire sys_clk, // U18
input wire sys_rst, //J15
input wire rxd, // tx,
output reg rx_done, //
output reg [7:0] rx_data //
);
parameter CLK_FREQ = 5000_0000;
parameter BPS = 115200;
// parameter MAX = 434; // 115200 50m434 1s/115200
localparam B_MAX = CLK_FREQ / BPS;
//
reg rxd_d0;
reg rxd_d1;
reg rxd_d2;
always @(posedge sys_clk or negedge sys_rst) begin
if (sys_rst == 1'b0) begin
rxd_d0 <= 'b0;
rxd_d1 <= 'b0;
rxd_d2 <= 'b0;
end
else begin
rxd_d0 <= rxd;
rxd_d1 <= rxd_d0;
rxd_d2 <= rxd_d1;
end
end
reg rx_busy; // , rx_flag, 216 (434/2)-1=216
wire start_en = rxd_d2 && !rxd_d1 && !rx_busy; // 使(), rx2 rx1 rx沿, , , ,
reg [3:0]rx_d_cnt; // , , , 10, 1~8 8
reg [15:0] baud_cnt; // , n , rx_busy ,
reg [7:0] temp_rx_data; //
// rx_d_cnt baud_cnt rx_busy
// start_en , 使 busy start_en
// start_en busy , , 沿
always @(posedge sys_clk or negedge sys_rst) begin
if (sys_rst == 1'b0) begin
rx_busy <= 'b0;
end
else if(start_en) begin // , (rx_busy, start_en)
rx_busy <= 'b1;
end
// 9(), (216),
// ,
else if(rx_d_cnt == 'b1001 && baud_cnt == B_MAX>>1 - 1) begin
rx_busy <= 'b0;
end
else begin
rx_busy <= rx_busy;
end
end
//
always @(posedge sys_clk or negedge sys_rst) begin
if (sys_rst == 1'b0) begin
baud_cnt <= 'b0;
end
//
else if (rx_busy) begin
if (baud_cnt == B_MAX-'b1) begin // 0 0~433 434
baud_cnt <= 'b0;
end
else begin
baud_cnt <= baud_cnt + 'b1;
end
end
else begin
baud_cnt <= 'b0;
end
end
//
always @(posedge sys_clk or negedge sys_rst) begin
if (sys_rst == 1'b0) begin
rx_d_cnt <= 'b0;
end
//
else if (rx_busy) begin
// , bit, 1
if (baud_cnt == B_MAX-'b1) begin
rx_d_cnt <= rx_d_cnt + 'b1;
end
else begin
rx_d_cnt <= rx_d_cnt;
end
end
else begin
rx_d_cnt <= 'b0;
end
end
// rx_d_cnt rxd bit
//
always @(posedge sys_clk or negedge sys_rst) begin
if (sys_rst == 1'b0) begin
temp_rx_data <= 'b0;
end
else if (rx_busy) begin
// ,
if (baud_cnt == B_MAX>>1 - 1) begin
case (rx_d_cnt)
'b0001: temp_rx_data[0] <= rxd_d2;
'b0010: temp_rx_data[1] <= rxd_d2;
'b0011: temp_rx_data[2] <= rxd_d2;
'b0100: temp_rx_data[3] <= rxd_d2;
'b0101: temp_rx_data[4] <= rxd_d2;
'b0110: temp_rx_data[5] <= rxd_d2;
'b0111: temp_rx_data[6] <= rxd_d2;
'b1000: temp_rx_data[7] <= rxd_d2;
default :;
endcase
end
else begin
temp_rx_data <= temp_rx_data;
end
end
else begin
//
temp_rx_data <= 'b0;
end
end
// ,
always @(posedge sys_clk or negedge sys_rst) begin
if (sys_rst == 1'b0) begin
rx_done <= 'b0;
rx_data <= 'b0;
end
// busy , busy,, done(1)
else if(rx_d_cnt == 'b1001 && baud_cnt == B_MAX>>1 - 1) begin
rx_done <= 'b1;
rx_data <= temp_rx_data;
end
else begin
// done(busy rx_d_cntbaud_cnt )
rx_done <= 'b0;
// data, done rx_data, , done, data
rx_data <= rx_data;
end
end
endmodule