輸入信號爲時鐘信號和復位信號,輸出信號爲uart_data和uart_done,並且定義寄存器類型
串口接收模塊:
module(
input sys_clk,
input sys_rst_n,
input uart_rxd,
output reg [7:0] uart_data,
output reg uart_done
)
parameter CLK_FREQ = 50_000_000;
parameter UARS_BPS = 115200;
parameter BPS_CNT = CLK_FREQ/UARS_BPS;
reg uart_rxd_d0;
reg uart_rxd_d1;
reg [15:0] clk_cnt;
reg [3:0] rx_cnt;
reg [7:0] rx_data;
reg rx_flag;
wire start_flag;
assign start_flag = uart_rxd_d1 & (~uart_rxd_d0);
//異步時鐘同步
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin
uart_rxd_d0 <= 1'b1;
uart_rxd_d1 <= 1'b1;
end
else begin
uart_rxd_d0 <= uart_rxd;
uart_rxd_d1 <= uart_rxd_d0;
end
end
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
rx_flag <= 1'b0;
else if (start_flag)
rx_flag <= 1'b1;
else if(rx_cnt == 4'd9 && clk_cnt == BPS_CNT/2 - 1'b1 )
rx_flag <= 1'b0;
end
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
clk_cnt <= 16'd0;
else
if(rx_flag) begin
if(clk_cnt < BPS_CNT - 1'b1)
clk_cnt <= clk_cnt + 1'b1;
else
clk_cnt <= 16'd0;
end
else
clk_cnt <= 16'd0;
end
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
rx_cnt <= 4'd0;
else if(rx_flag) begin
if(clk_cnt == BPS_CNT - 1'b1)
rx_cnt <= rx_cnt + 1'b1;
end
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
rx_data <= 8'd0;
else if(rx_flag && clk_cnt == BPS_CNT/2) begin
case(rx_cnt)
4'd1 : rx_data[0] <= uart_rxd_d1;
4'd2 : rx_data[1] <= uart_rxd_d1;
4'd3 : rx_data[2] <= uart_rxd_d1;
4'd4 : rx_data[3] <= uart_rxd_d1;
4'd5 : rx_data[4] <= uart_rxd_d1;
4'd6 : rx_data[5] <= uart_rxd_d1;
4'd7 : rx_data[6] <= uart_rxd_d1;
4'd8 : rx_data[7] <= uart_rxd_d1;
endcase
end
end
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin
uart_data <= 8'd0;
uart_done <= 1'b0;
end
else if(rx_cnt == 4'd9) begin
uart_data <= rx_data;
uart_done <= 1'b1;
end
else begin
uart_data <= 8'd0;
uart_done <= 1'b0;
end
end
endmodule
串口發送模塊:
module(
input sys_clk,
input sys_rst_n,
input uart_en,
output reg [7:0] uart_din,
output uart_txd
)
parameter CLK_FREQ = 50_000_000;
parameter UARS_BPS = 115200;
parameter BPS_CNT = CLK_FREQ/UARS_BPS;
reg uart_en_d0;
reg uart_en_d1;
reg [15:0] clk_cnt;
reg [3:0] tx_cnt;
reg [7:0] tx_data;
reg tx_flag;
wire en_flag;
assign en_flag = uart_en_d0 & (~uart_en_d1);
//異步時鐘同步
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin
uart_en_d0 <= 1'b0;
uart_en_d1 <= 1'b0;
end
else begin
uart_en_d0 <= uart_en;
uart_en_d1 <= uart_en_d0;
end
end
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
tx_data <= 8'b0;
else if(en_flag)
tx_data <= uart_din;
else
tx_data <= tx_data;
end
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
tx_flag <= 1'b0;
else if (en_flag)
tx_flag <= 1'b1;
else if(tx_cnt == 4'd9 && clk_cnt == BPS_CNT/2 - 1'b1 )
tx_flag <= 1'b0;
end
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
clk_cnt <= 16'd0;
else
if(tx_flag) begin
if(clk_cnt < BPS_CNT - 1'b1)
clk_cnt <= clk_cnt + 1'b1;
else
clk_cnt <= 16'd0;
end
else
clk_cnt <= 16'd0;
end
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
tx_cnt <= 4'd0;
else if(tx_flag) begin
if(clk_cnt == BPS_CNT - 1'b1)
tx_cnt <= tx_cnt + 1'b1;
end
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
uart_txd <= 1'b0;
else if(rx_flag && clk_cnt == 16'd0) begin
case(tx_cnt)
4'd0 : uart_txd <= 1'b0;
4'd1 : uart_txd <= tx_data[0];
4'd2 : uart_txd <= tx_data[1];
4'd3 : uart_txd <= tx_data[2];
4'd4 : uart_txd <= tx_data[3];
4'd5 : uart_txd <= tx_data[4];
4'd6 : uart_txd <= tx_data[5];
4'd7 : uart_txd <= tx_data[6];
4'd8 : uart_txd <= tx_data[7];
4'd9 : uart_txd <= 1'b1;
endcase
end
end
endmodule
該程序在接收發送過程中,接收到的信息會缺失,原因爲接受過程還沒結束,另一個發送過程就開始了,解決辦法有兩個:
1.增加一個迴環。
2.增加發送時間,可以選擇十分之九或者五分之四的波特率等等。
存在問題:
思考迴環設計