一、串口接收模块
module uart_rx #(
parameter CLK_PERIOD = 0,
parameter BAUD_RATE = 0,
parameter CHECK_MODE = "NONE"
)(
input clk,
input rst_n,
input rxd,
output reg rx_finish,
output [7:0] data_r
);
parameter BAUD_COUNTER = 1000_000_000 / CLK_PERIOD / BAUD_RATE;
parameter BAUD_COUNTER_HALF = BAUD_COUNTER / 2;
reg [3:0] rx_num;
reg rx_start;
reg [7:0] data_temp;
reg [7:0] data_rr;
reg [7:0] counter;
reg rx_clk_bps;
reg rxd_r;
reg rxd_rr;
wire rxd_neg;
reg check;
assign rxd_neg = !rxd_r && rxd_rr;
assign data_r = data_rr;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
rxd_r <= 1'b0;
rxd_rr <= 1'b0;
end
else
begin
rxd_r <= rxd;
rxd_rr <= rxd_r;
end
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
rx_finish <= 1'b0;
rx_start <= 1'b0;
end
else if(rxd_neg)
begin
rx_finish <= 1'b0;
rx_start <= 1'b1;
end
else if((rx_num == 4'd10 && CHECK_MODE == "NONE") || (rx_num == 4'd11 && (CHECK_MODE == "ODD" || CHECK_MODE == "EVEN")))
begin
rx_finish <= 1'b1;
rx_start <= 1'b0;
end
else
begin
rx_finish <= 1'b0;
rx_start <= rx_start;
end
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
counter <= 8'd0;
end
else if(counter == BAUD_COUNTER || !rx_start)
begin
counter <= 8'd0;
end
else
begin
counter <= counter + 1'd1;
end
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
rx_clk_bps <= 1'b0;
end
else if(counter == BAUD_COUNTER_HALF)
begin
rx_clk_bps <= 1'b1;
end
else
begin
rx_clk_bps <= 1'b0;
end
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
rx_num <= 4'd0;
data_temp <= 8'd0;
data_rr <= 8'd0;
end
else if(rx_start)
begin
if(rx_clk_bps)
begin
rx_num <= rx_num + 1'd1;
case(rx_num)
4'd1: data_temp[0] <= rxd;
4'd2: data_temp[1] <= rxd;
4'd3: data_temp[2] <= rxd;
4'd4: data_temp[3] <= rxd;
4'd5: data_temp[4] <= rxd;
4'd6: data_temp[5] <= rxd;
4'd7: data_temp[6] <= rxd;
4'd8: data_temp[7] <= rxd;
4'd9: ;
default:;
endcase
end
else if((rx_num == 'd10 && CHECK_MODE == "NONE") || (rx_num == 'd11 && (CHECK_MODE == "ODD" || CHECK_MODE == "EVEN")))
begin
rx_num <= 4'd0;
data_rr <= data_temp;
end
end
end
endmodule
二、串口发送模块
module uart_tx #(
parameter CLK_PERIOD = 0,
parameter BAUD_RATE = 0,
parameter CHECK_MODE = "NONE"
)(
input clk,
input rst_n,
output txd,
input tx_en,
output tx_finish,
input [7:0] data_t
);
parameter BAUD_COUNTER = 1000_000_000 / CLK_PERIOD / BAUD_RATE;
reg [7:0] counter;
reg [3:0] tx_num;
reg tx_start;
reg txd_r;
reg tx_finish_r;
reg tx_en_r;
reg tx_en_rr;
wire tx_en_pos;
wire check_odd;
wire check_even;
assign txd = txd_r;
assign tx_finish = tx_finish_r;
assign check_even = data_t[7] + data_t[6] + data_t[5] + data_t[4] + data_t[3] + data_t[2] + data_t[1] + data_t[0];
assign check_odd = check_even + 1'b1;
assign tx_en_pos = tx_en_r && !tx_en_rr;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
tx_en_r <= 1'b0;
tx_en_rr <= 1'b0;
end
else
begin
tx_en_r <= tx_en;
tx_en_rr <= tx_en_r;
end
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
tx_start <= 1'b0;
tx_finish_r <= 1'b0;
end
else if(tx_en_pos)
begin
tx_start <= 1'b1;
tx_finish_r <= tx_finish_r;
end
else if((CHECK_MODE == "ODD" || CHECK_MODE == "EVEN") && tx_num == 'd10 && counter == BAUD_COUNTER - 'd1)
begin
tx_start <= 1'b0;
tx_finish_r <= 1'b1;
end
else if((CHECK_MODE == "NONE") && tx_num == 'd9 && counter == BAUD_COUNTER - 'd1)
begin
tx_start <= 1'b0;
tx_finish_r <= 1'b1;
end
else
begin
tx_start <= tx_start;
tx_finish_r <= 1'b0;
end
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
counter <= 8'd0;
tx_num <= 4'd0;
end
else if(tx_start)
begin
if(counter == BAUD_COUNTER - 1'd1)
begin
counter <= 8'd0;
if(CHECK_MODE == "NONE" && tx_num == 4'd9)
begin
tx_num <= 4'd0;
end
else if((CHECK_MODE == "ODD" || CHECK_MODE == "EVEN") && tx_num == 4'd10)
begin
tx_num <= 4'd0;
end
else
begin
tx_num <= tx_num + 1'd1;
end
end
else
begin
counter <= counter + 1'd1;
tx_num <= tx_num;
end
end
else
begin
counter <= 8'd0;
tx_num <= 4'd0;
end
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
txd_r <= 1'b1;
end
else if(tx_start)
begin
if(CHECK_MODE == "ODD" || CHECK_MODE == "EVEN")
begin
case(tx_num)
4'd0: txd_r <= 1'b0;
4'd1: txd_r <= data_t[0];
4'd2: txd_r <= data_t[1];
4'd3: txd_r <= data_t[2];
4'd4: txd_r <= data_t[3];
4'd5: txd_r <= data_t[4];
4'd6: txd_r <= data_t[5];
4'd7: txd_r <= data_t[6];
4'd8: txd_r <= data_t[7];
4'd9:
begin
if(CHECK_MODE == "ODD")
txd_r <= check_odd;
else
txd_r <= check_even;
end
4'd10: txd_r <= 1'b1;
default:txd_r <= 1'b1;
endcase
end
else if(CHECK_MODE == "NONE")
begin
case(tx_num)
4'd0: txd_r <= 1'b0;
4'd1: txd_r <= data_t[0];
4'd2: txd_r <= data_t[1];
4'd3: txd_r <= data_t[2];
4'd4: txd_r <= data_t[3];
4'd5: txd_r <= data_t[4];
4'd6: txd_r <= data_t[5];
4'd7: txd_r <= data_t[6];
4'd8: txd_r <= data_t[7];
4'd9: txd_r <= 1'b1;
default:txd_r <= 1'b1;
endcase
end
else
begin
txd_r <= 1'b1;
end
end
else
begin
txd_r <= 1'b1;
end
end
endmodule
三、串口顶层模块
module uart_top(
input clk,
input rst_n,
input rxd,
output txd,
input tx_en,
input [7:0] data_t,
output tx_finish,
output rx_finish,
output [7:0] data_r
);
parameter CLK_PERIOD = 20;
parameter BAUD_RATE = 115200;
parameter CHECK_MODE = "ODD";
uart_rx #(
.CLK_PERIOD (CLK_PERIOD),
.BAUD_RATE (BAUD_RATE),
.CHECK_MODE (CHECK_MODE)
)
uart_r(
.clk (clk),
.rst_n (rst_n),
.rxd (rxd),
.rx_finish (rx_finish),
.data_r (data_r)
);
uart_tx #(
.CLK_PERIOD (CLK_PERIOD),
.BAUD_RATE (BAUD_RATE),
.CHECK_MODE (CHECK_MODE)
)
uart_t(
.clk (clk),
.rst_n (rst_n),
.txd (txd),
.tx_en (tx_en),
.tx_finish (tx_finish),
.data_t (data_t)
);
endmodule