This repository has been archived on 2024-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
study/uart_tx _copy/rtl/uart_tx.v
2020-06-09 15:48:03 +08:00

263 lines
6.2 KiB
Verilog

module uart_tx(
clk,
rst_n,
en,
rx,
baud_set,
tx_data,
tx,
tx_done,
rx_done,
rx_data
);
input clk;
input rst_n;
input en;
input rx;
input [1:0] baud_set;
input [7:0] tx_data;
output reg tx;
output reg tx_done;
output reg rx_done;
output reg [7:0] rx_data;
reg [1:0] baud_set_r;
reg [12:0] tx_bps_cnt,tx_bps_cnt_max;
reg [7:0] tx_data_r;
reg tx_clk,rx_clk;
reg tx_en,rx_en;
reg [3:0] tx_cnt;
reg [9:0] rx_bps_cnt,rx_bps_cnt_max;
reg [2:0] rx_data_r[9:0];
reg [6:0] rx_cnt;
always @ (posedge clk or negedge rst_n)//tx使能
if(!rst_n)
tx_en <= 1'b0;
else if(en)
tx_en <= 1'b1;
else if(tx_done)
tx_en <= 1'b0;
always @ (posedge clk or negedge rst_n)//rx使能
if(!rst_n)
rx_en <= 1'b0;
else if(en)
rx_en <= 1'b1;
always @ (posedge clk or negedge rst_n) //同步波特率
if(!rst_n)
baud_set_r <= 2'd0;
else if(en)
baud_set_r <= baud_set;
else
baud_set_r <= baud_set_r;
always @ (posedge clk)//发送波特率
if(tx_en)
case(baud_set_r)
2'b00: tx_bps_cnt_max = 13'd5207; //9600
2'b01: tx_bps_cnt_max = 13'd1301; //38400
2'b10: tx_bps_cnt_max = 13'd867; //57600
2'b11: tx_bps_cnt_max = 13'd433; //115200
endcase
always @ (posedge clk)//接收波特率,12倍采样
if(rx_en)
case(baud_set_r)
2'b00: rx_bps_cnt_max = 10'd433; //9600
2'b01: rx_bps_cnt_max = 10'd108; //38400
2'b10: rx_bps_cnt_max = 10'd71; //57600
2'b11: rx_bps_cnt_max = 10'd35; //115200
endcase
always @ (posedge clk or negedge rst_n)//发送bps计数器
if(!rst_n)
tx_bps_cnt <= 13'd0;
else if(tx_en)
begin
if(tx_bps_cnt == tx_bps_cnt_max)
tx_bps_cnt <= 13'd0;
else
tx_bps_cnt <= tx_bps_cnt + 13'd1;
end
always @ (posedge clk or negedge rst_n)//接收bps计数器
if(!rst_n)
rx_bps_cnt <= 10'd0;
else if(rx_en)
begin
if(rx_bps_cnt == rx_bps_cnt_max)
rx_bps_cnt <= 10'd0;
else
rx_bps_cnt <= rx_bps_cnt + 10'd1;
end
always @ (posedge clk)//发送时钟生成
if(tx_en)
begin
if(tx_bps_cnt == tx_bps_cnt_max)
tx_clk <= 1'b1;
else
tx_clk <= 1'b0;
end
always @ (posedge clk)//接收时钟生成
if(rx_en)
begin
if(rx_bps_cnt == 1'b1)
rx_clk <= 1'b1;
else
rx_clk <= 1'b0;
end
always @ (posedge clk or negedge rst_n)//发送次数计数器
if(!rst_n)
tx_cnt <= 4'd0;
else if(tx_en)
begin
if(tx_cnt == 4'd11)
tx_cnt <= 4'd0;
else if(tx_bps_cnt == tx_bps_cnt_max)
tx_cnt <= tx_cnt +4'd1;
end
always @ (posedge clk or negedge rst_n)//接收次数计数器
if(!rst_n)
rx_cnt <= 7'd0;
else if(rx_en)
begin
if((rx_cnt == 7'd118) | (rx_cnt == 8'd8 && (rx_data_r[0] > 3'd2)))
rx_cnt <= 7'd0;
else if(rx_bps_cnt == rx_bps_cnt_max)
rx_cnt <= rx_cnt +7'd1;
end
always @ (posedge clk) //发送数据寄存
if(tx_en)
tx_data_r <= tx_data;
always @ (posedge clk or negedge rst_n)//发送数据
if(!rst_n)
tx <= 1'b1;
else if(tx_clk)
begin
case(tx_cnt)
4'd0 : tx <= 1'b1;
4'd1 : tx <= 1'b0;
4'd2 : tx <= tx_data_r[0];
4'd3 : tx <= tx_data_r[1];
4'd4 : tx <= tx_data_r[2];
4'd5 : tx <= tx_data_r[3];
4'd6 : tx <= tx_data_r[4];
4'd7 : tx <= tx_data_r[5];
4'd8 : tx <= tx_data_r[6];
4'd9 : tx <= tx_data_r[7];
4'd10: tx <= 1'b1;
default : tx <= 1'b1;
endcase
end
else
tx <= tx;
always @ (posedge clk or negedge rst_n)//发送完成标志
if(!rst_n)
tx_done <= 1'b0;
else if(tx_en)
begin
if(tx_cnt == 4'd11)
tx_done <= 1'd1;
else
tx_done <= 1'd0;
end
always @ (posedge clk or negedge rst_n)//接收数据
if(!rst_n)
begin
rx_data_r[0] <= 3'd0;
rx_data_r[1] <= 3'd0;
rx_data_r[2] <= 3'd0;
rx_data_r[3] <= 3'd0;
rx_data_r[4] <= 3'd0;
rx_data_r[5] <= 3'd0;
rx_data_r[6] <= 3'd0;
rx_data_r[7] <= 3'd0;
rx_data_r[8] <= 3'd0;
rx_data_r[9] <= 3'd0;
end
else if(rx_clk)
begin
case(rx_cnt)
0 :
begin
rx_data_r[0] <= 3'd0;
rx_data_r[1] <= 3'd0;
rx_data_r[2] <= 3'd0;
rx_data_r[3] <= 3'd0;
rx_data_r[4] <= 3'd0;
rx_data_r[5] <= 3'd0;
rx_data_r[6] <= 3'd0;
rx_data_r[7] <= 3'd0;
rx_data_r[8] <= 3'd0;
rx_data_r[9] <= 3'd0;
end
3, 4, 5, 6, 7, 8 : rx_data_r[0] <= rx_data_r[0] + rx;
15,16,17,18,19,20: rx_data_r[1] <= rx_data_r[1] + rx;
27,28,29,30,31,32: rx_data_r[2] <= rx_data_r[2] + rx;
39,40,41,42,43,44: rx_data_r[3] <= rx_data_r[3] + rx;
51,52,53,54,55,56: rx_data_r[4] <= rx_data_r[4] + rx;
63,64,65,66,67,68: rx_data_r[5] <= rx_data_r[5] + rx;
75,76,77,78,79,80: rx_data_r[6] <= rx_data_r[6] + rx;
87,88,89,90,91,92: rx_data_r[7] <= rx_data_r[7] + rx;
99,100,101,102,103: rx_data_r[8] <= rx_data_r[8] + rx;
111,112,113,114,115: rx_data_r[9] <= rx_data_r[9] + rx;
default :
begin
rx_data_r[0] <= rx_data_r[0];
rx_data_r[1] <= rx_data_r[1];
rx_data_r[2] <= rx_data_r[2];
rx_data_r[3] <= rx_data_r[3];
rx_data_r[4] <= rx_data_r[4];
rx_data_r[5] <= rx_data_r[5];
rx_data_r[6] <= rx_data_r[6];
rx_data_r[7] <= rx_data_r[7];
rx_data_r[8] <= rx_data_r[8];
rx_data_r[9] <= rx_data_r[9];
end
endcase
end
always @ (posedge clk or negedge rst_n)
if(!rst_n)
rx_data <= 8'd0;
else if((rx_cnt == 7'd118) & (rx_data_r[9][2]))
begin
rx_data[0] <= rx_data_r[1][2];
rx_data[1] <= rx_data_r[2][2];
rx_data[2] <= rx_data_r[3][2];
rx_data[3] <= rx_data_r[4][2];
rx_data[4] <= rx_data_r[5][2];
rx_data[5] <= rx_data_r[6][2];
rx_data[6] <= rx_data_r[7][2];
rx_data[7] <= rx_data_r[8][2];
end
always @ (posedge clk or negedge rst_n)//发送完成标志
if(!rst_n)
rx_done <= 1'b0;
else if(rx_en)
begin
if(rx_cnt == 7'd118)
rx_done <= 1'd1;
else
rx_done <= 1'd0;
end
endmodule