概念:
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_outputoutput reg po_flag
);// parameterparameter MAX_BPS_CNT = `CLOCK/`BPS ,//434 ,MAX_BIT_CNT = `BIT_CHACK ;//10 ; localparam RX_MOD = 1'b1 ,CHECK_MOD = `EVEN ;// reg signal definereg 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 definewire nege ;/*******************************************************************/// // reg signal define// reg rx_r1 ;always @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) rx_r1 <= 1'b1 ;elserx_r1 <= rx ;end// reg rx_r2 ;always @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) rx_r2 <= 1'b1 ;elserx_r2 <= rx_r1 ;end// reg work ;always @(posedge sys_clk or negedge sys_rst_n) beginif(~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) beginif(~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 ; 应该会归0always @(posedge sys_clk or negedge sys_rst_n) beginif(~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) beginif(~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 ;endcaseend elsedata_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) beginif(~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) beginif(~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_outputalways @(posedge sys_clk or negedge sys_rst_n) beginif(~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) beginif(~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
);// parameterparameter MAX_BPS_CNT = `CLOCK/`BPS ,MAX_BIT_CNT = `BIT_CHACK + 1;localparam CHECK_MOD = `EVEN ;// reg signal definereg [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) beginif(~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) beginif(~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) beginif(~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) beginif(~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 @(*) beginif(~sys_rst_n)tx = 1'b1 ;else if(work) begincase (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 ;enddefault: tx = 1'b1 ;endcaseend 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 instantiationswire 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