首次提交
This commit is contained in:
199
apb_uart/uart_rx.sv
Normal file
199
apb_uart/uart_rx.sv
Normal file
@@ -0,0 +1,199 @@
|
||||
|
||||
module uart_rx (
|
||||
input logic clk_i,
|
||||
input logic rstn_i,
|
||||
input logic rx_i,
|
||||
input logic [15:0] cfg_div_i,
|
||||
input logic cfg_en_i,
|
||||
input logic cfg_parity_en_i,
|
||||
input logic cfg_even_parity_i,
|
||||
input logic [1:0] cfg_bits_i,
|
||||
// input logic cfg_stop_bits_i,
|
||||
output logic busy_o,
|
||||
output logic parity_error_o,
|
||||
output logic overrun_o,
|
||||
input logic err_clr_i,
|
||||
output logic [7:0] rx_data_o,
|
||||
output logic rx_valid_o,
|
||||
input logic rx_ready_i
|
||||
);
|
||||
|
||||
enum logic [2:0] {IDLE,START_BIT,DATA,PARITY,STOP_BIT} CS, NS;
|
||||
|
||||
logic [7:0] reg_data;
|
||||
|
||||
logic [2:0] reg_rx_sync;
|
||||
|
||||
|
||||
logic [2:0] reg_bit_count;
|
||||
|
||||
logic [2:0] s_target_bits;
|
||||
|
||||
logic parity_bit;
|
||||
|
||||
logic [15:0] baud_cnt;
|
||||
logic baudgen_en;
|
||||
logic bit_done;
|
||||
|
||||
logic start_bit;
|
||||
logic s_rx_fall;
|
||||
|
||||
|
||||
assign busy_o = (CS != IDLE);
|
||||
|
||||
always_comb begin
|
||||
case(cfg_bits_i)
|
||||
2'b00:
|
||||
s_target_bits = 3'h4;
|
||||
2'b01:
|
||||
s_target_bits = 3'h5;
|
||||
2'b10:
|
||||
s_target_bits = 3'h6;
|
||||
2'b11:
|
||||
s_target_bits = 3'h7;
|
||||
endcase
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
NS = CS;
|
||||
baudgen_en = 1'b0;
|
||||
start_bit = 1'b0;
|
||||
|
||||
case(CS)
|
||||
IDLE: begin
|
||||
if (s_rx_fall) begin
|
||||
NS = START_BIT;
|
||||
baudgen_en = 1'b1;
|
||||
start_bit = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
START_BIT: begin
|
||||
baudgen_en = 1'b1;
|
||||
start_bit = 1'b1;
|
||||
if (bit_done)
|
||||
NS = DATA;
|
||||
end
|
||||
|
||||
DATA: begin
|
||||
baudgen_en = 1'b1;
|
||||
|
||||
if (bit_done) begin
|
||||
if (reg_bit_count == s_target_bits) begin
|
||||
if (cfg_parity_en_i)
|
||||
NS = PARITY;
|
||||
else
|
||||
NS = STOP_BIT;
|
||||
end
|
||||
end
|
||||
end
|
||||
PARITY: begin
|
||||
baudgen_en = 1'b1;
|
||||
if (bit_done) begin
|
||||
NS = STOP_BIT;
|
||||
end
|
||||
end
|
||||
STOP_BIT: begin
|
||||
baudgen_en = 1'b1;
|
||||
if (bit_done) begin
|
||||
NS = IDLE;
|
||||
end
|
||||
end
|
||||
default:
|
||||
NS = IDLE;
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rstn_i)
|
||||
begin
|
||||
if (rstn_i == 1'b0) begin
|
||||
CS <= IDLE;
|
||||
reg_data <= 8'hFF;
|
||||
reg_bit_count <= 'h0;
|
||||
parity_bit <= 1'b0;
|
||||
parity_error_o <= 1'b0;
|
||||
rx_valid_o <= 1'b0;
|
||||
overrun_o <= 1'b0;
|
||||
end else begin
|
||||
if(cfg_en_i)
|
||||
CS <= NS;
|
||||
else
|
||||
CS <= IDLE;
|
||||
|
||||
rx_valid_o <= 0;
|
||||
case (CS)
|
||||
START_BIT:
|
||||
parity_bit <= ~cfg_even_parity_i;
|
||||
DATA:
|
||||
if (bit_done) begin
|
||||
parity_bit <= parity_bit ^ reg_rx_sync[2];
|
||||
case(cfg_bits_i)
|
||||
2'b00:
|
||||
reg_data <= {3'b000,reg_rx_sync[2],reg_data[4:1]};
|
||||
2'b01:
|
||||
reg_data <= {2'b00,reg_rx_sync[2],reg_data[5:1]};
|
||||
2'b10:
|
||||
reg_data <= {1'b0,reg_rx_sync[2],reg_data[6:1]};
|
||||
2'b11:
|
||||
reg_data <= {reg_rx_sync[2],reg_data[7:1]};
|
||||
endcase
|
||||
|
||||
if (reg_bit_count == s_target_bits)
|
||||
reg_bit_count <= 'h0;
|
||||
else
|
||||
reg_bit_count <= reg_bit_count + 1;
|
||||
end
|
||||
PARITY:
|
||||
if (bit_done)
|
||||
if(parity_bit != reg_rx_sync[2])
|
||||
parity_error_o <= 1'b1;
|
||||
else
|
||||
parity_error_o <= 1'b0;
|
||||
STOP_BIT:
|
||||
if (bit_done) begin
|
||||
rx_valid_o <= 1'b1;
|
||||
overrun_o <= ~rx_ready_i;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
assign s_rx_fall = ~reg_rx_sync[1] & reg_rx_sync[2];
|
||||
|
||||
always_ff @(posedge clk_i or negedge rstn_i) begin
|
||||
if (rstn_i == 1'b0)
|
||||
reg_rx_sync <= 3'b111;
|
||||
else begin
|
||||
if (cfg_en_i)
|
||||
reg_rx_sync <= {reg_rx_sync[1:0],rx_i};
|
||||
else
|
||||
reg_rx_sync <= 3'b111;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rstn_i) begin
|
||||
if (rstn_i == 1'b0) begin
|
||||
baud_cnt <= 'h0;
|
||||
bit_done <= 1'b0;
|
||||
end else begin
|
||||
if(baudgen_en) begin
|
||||
if(!start_bit && (baud_cnt == cfg_div_i)) begin
|
||||
baud_cnt <= 'h0;
|
||||
bit_done <= 1'b1;
|
||||
end else if(start_bit && (baud_cnt == {1'b0,cfg_div_i[15:1]})) begin
|
||||
baud_cnt <= 'h0;
|
||||
bit_done <= 1'b1;
|
||||
end else begin
|
||||
baud_cnt <= baud_cnt + 1;
|
||||
bit_done <= 1'b0;
|
||||
end
|
||||
end else begin
|
||||
baud_cnt <= 'h0;
|
||||
bit_done <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign rx_data_o = reg_data;
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user