概念:
UART(Universal Asynchronous Receiver-Transmitter):即通用异步收发器,是一种通用串行数据总线,用于异步通信。一般UART接口常指串口。
UART在发送数据时将并行数据转换成串行数据来传输,在接收数据时将接收到的串行数据转换成并行数据。
单工通信:数据只能沿一个方向传输。
半双工通信:数据可以沿两个方向传输,但需要分时进行。
全双工通信:数据可以同时进行双向传输。
同步通信:带时钟端口的数据传输。
异步通信:没有时钟端口,发送方和接收方使用各自的时钟控制数据的收发过程。
常见串行通信接口:
模块框图:
时序图:
代码:
// uart的接收模块,要求波特率可调,回环实验
// 完成回环实验后加入校验位
// 然后加入led与蜂鸣器的控制模块
`include "para.v"
module rx (
input wire sys_clk ,
input wire sys_rst_n ,
input wire rx ,
output reg [7:0] po_data , // port_output
output reg po_flag
);
// parameter
parameter MAX_BPS_CNT = `CLOCK/`BPS ,//434 ,
MAX_BIT_CNT = `BIT_CHACK ;//10 ;
localparam RX_MOD = 1'b1 ,
CHECK_MOD = `EVEN ;
// reg signal define
reg rx_r1 ;
reg rx_r2 ;
reg [31:0] cnt_bps ;
reg work ;
reg [3:0] cnt_bit ;
reg [7:0] data_reg ;
reg check ;
reg check_reg;
// wire signal define
wire nege ;
/*******************************************************************/
// // reg signal define
// reg rx_r1 ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
rx_r1 <= 1'b1 ;
else
rx_r1 <= rx ;
end
// reg rx_r2 ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
rx_r2 <= 1'b1 ;
else
rx_r2 <= rx_r1 ;
end
// reg work ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
work <= 1'b0 ;
else if(nege)
work <= 1'b1 ;
else if((cnt_bit == ((MAX_BIT_CNT - 1))) && (cnt_bps == (MAX_BPS_CNT - 1))) // 这俩条件可以用end_cnt_XXX来代替,组合逻辑赋
work <= 1'b0 ;
else
work <= work ;
end
// reg [31:0] cnt_bps ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
cnt_bps <= 32'd0 ;
else if(work && (cnt_bps == (MAX_BPS_CNT - 1)))
cnt_bps <= 32'd0 ;
else if(work)
cnt_bps <= cnt_bps + 1'b1 ;
else
cnt_bps <= 32'd0 ;
end
// reg [3:0] cnt_bit ; 应该会归0
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
cnt_bit <= 4'd0 ;
else if (work && (cnt_bps == (MAX_BPS_CNT - 1) && cnt_bit == (MAX_BIT_CNT - 1)))
cnt_bit <= 4'd0 ;
else if (work && (cnt_bps == (MAX_BPS_CNT - 1)))
cnt_bit <= cnt_bit + 1'b1 ;
else if(work)
cnt_bit <= cnt_bit ;
else
cnt_bit <= 8'd0 ;
end
// reg [7:0] data_reg;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
data_reg <= 8'd0 ;
else if(work && cnt_bps == (MAX_BPS_CNT/2)) begin // 采样,采集数据的时刻
case (cnt_bit)
0 : data_reg <= 8'd0 ;
1 : data_reg[cnt_bit - 1] <= rx_r2 ;
2 : data_reg[cnt_bit - 1] <= rx_r2 ;
3 : data_reg[cnt_bit - 1] <= rx_r2 ;
4 : data_reg[cnt_bit - 1] <= rx_r2 ;
5 : data_reg[cnt_bit - 1] <= rx_r2 ;
6 : data_reg[cnt_bit - 1] <= rx_r2 ;
7 : data_reg[cnt_bit - 1] <= rx_r2 ;
8 : data_reg[cnt_bit - 1] <= rx_r2 ;
default: data_reg <= data_reg ;
endcase
end else
data_reg <= data_reg ;
end
// // wire signal define
// wire nege ;
assign nege = ~rx_r1 && rx_r2 ;
// reg check ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
check <= 1'b0 ;
else if(CHECK_MOD && (cnt_bit == ((MAX_BIT_CNT - 2))) && (cnt_bps == (MAX_BPS_CNT - 1)))
check <= ~^data_reg ;
else if(~CHECK_MOD && (cnt_bit == ((MAX_BIT_CNT - 2))) && (cnt_bps == (MAX_BPS_CNT - 1)))
check <= ^data_reg ;
else
check <= check ;
end
// reg check_reg;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
check_reg <= 1'b0 ;
else if((cnt_bit == ((MAX_BIT_CNT - 1))) && (cnt_bps == (MAX_BPS_CNT /2)))
check_reg <= rx_r2 ;
else
check_reg <= check_reg ;
end
// output reg [7:0] po_data , // port_output
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
po_data <= 8'd0 ;
else if((check == check_reg) && (cnt_bit == ((MAX_BIT_CNT - 1))) && (cnt_bps == (MAX_BPS_CNT - 1)))
po_data <= data_reg ;
else if(RX_MOD)
po_data <= po_data ;
else
po_data <= 8'd0 ;
end
// output reg po_flag
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
po_flag <= 8'd0 ;
else if((check == check_reg) && ((cnt_bit == ((MAX_BIT_CNT - 1))) && (cnt_bps == (MAX_BPS_CNT - 1))))
po_flag <= 1'b1 ;
else
po_flag <= 8'd0 ;
end
endmodule
// uart的数据发送模块。停止位 1bit
`include "para.v"
module tx(
input wire sys_clk ,
input wire sys_rst_n ,
input wire [7:0] pi_data ,
input wire pi_flag ,
output reg tx
);
// parameter
parameter MAX_BPS_CNT = `CLOCK/`BPS ,
MAX_BIT_CNT = `BIT_CHACK + 1;
localparam CHECK_MOD = `EVEN ;
// reg signal define
reg [7:0] data_reg ;
reg work ;
reg [31:0] cnt_bps ;
reg [3:0] cnt_bit ;
/********************************************************************/
// // reg signal define
// reg [7:0] data_reg ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
data_reg <= 8'd0 ;
else if(pi_flag)
data_reg <= pi_data ;
else
data_reg <= data_reg ;
end
// reg work ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
work <= 1'b0 ;
else if(pi_flag)
work <= 1'b1 ;
else if(cnt_bps == (MAX_BPS_CNT - 1) && cnt_bit == (MAX_BIT_CNT - 1))
work <= 1'b0 ;
else
work <= work ;
end
// reg [31:0] cnt_bps ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
cnt_bps <= 32'd0 ;
else if((work && (cnt_bps == (MAX_BPS_CNT - 1)))
|| (work && (cnt_bit == (MAX_BIT_CNT - 1)) && cnt_bps == (MAX_BPS_CNT - 1)))
cnt_bps <= 32'd0 ;
else if(work)
cnt_bps <= cnt_bps + 1'b1 ;
else
cnt_bps <= 32'd0 ;
end
// reg [3:0] cnt_bit ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
cnt_bit <= 4'd0 ;
else if(work && (cnt_bps == (MAX_BPS_CNT - 1)) && cnt_bit == (MAX_BIT_CNT - 1))
cnt_bit <= 4'd0 ;
else if(work && (cnt_bps == (MAX_BPS_CNT - 1)))
cnt_bit <= cnt_bit + 1'b1 ;
else if(work)
cnt_bit <= cnt_bit ;
else
cnt_bit <= 4'd0 ;
end
// output reg tx
always @(*) begin
if(~sys_rst_n)
tx = 1'b1 ;
else if(work) begin
case (cnt_bit)
4'd0: tx = 1'b0 ;
4'd1: tx = data_reg[cnt_bit - 1] ;
4'd2: tx = data_reg[cnt_bit - 1] ;
4'd3: tx = data_reg[cnt_bit - 1] ;
4'd4: tx = data_reg[cnt_bit - 1] ;
4'd5: tx = data_reg[cnt_bit - 1] ;
4'd6: tx = data_reg[cnt_bit - 1] ;
4'd7: tx = data_reg[cnt_bit - 1] ;
4'd8: tx = data_reg[cnt_bit - 1] ;
4'd9: begin
if(CHECK_MOD)
tx = ~^data_reg ;
else
tx = ^data_reg ;
end
default: tx = 1'b1 ;
endcase
end else
tx = 1'b1 ;
end
endmodule
module top(
input wire sys_clk ,
input wire sys_rst_n ,
input wire rx ,
output wire tx
);
// 例化间连线 Wiring between instantiations
wire clk_100Mhz ;
wire clk_50Mhz ;
wire locked ;
wire rst_n ;
assign rst_n = sys_rst_n && locked ;
wire [7:0] po_data ;
wire po_flag ;
pll pll_inst(
.clk_in1 ( sys_clk ) ,
.resetn ( sys_rst_n ) ,
.clk_out1 ( clk_100Mhz ) ,
.clk_out2 ( clk_50Mhz ) ,
.locked ( locked )
);
rx rx_inst(
.sys_clk ( clk_50Mhz ) ,
.sys_rst_n ( rst_n ) ,
.rx ( rx ) ,
.po_data ( po_data ) ,
.po_flag ( po_flag )
);
tx tx_inst(
.sys_clk ( clk_50Mhz ) ,
.sys_rst_n ( rst_n ) ,
.pi_data ( po_data ) ,
.pi_flag ( po_flag ) ,
.tx ( tx )
);
endmodule