目录
实现功能:
1.接收uart串行数据,输出并行数据(1byte)。
2.输入并行数据(1byte),输出uart串行数据。
3.完成uart传输的1次环回。
uart协议的1帧数据传输
模块封装-port设置
Verilog代码实现
1.uart接收模块:接收串行数据,输出并行数据和其有效标志。
仿真结果:
2.uart发送模块:接收并行数据,发送串行数据。
仿真结果:
3.uart环回测试。
仿真验证:
仿真结果:
FPGA系统集成-RTL框图
实现功能:
1.接收uart串行数据,输出并行数据(1byte)。
2.输入并行数据(1byte),输出uart串行数据。
3.完成uart传输的1次环回。
uart协议的1帧数据传输
模块封装-port设置
Verilog代码实现
1.uart接收模块:接收串行数据,输出并行数据和其有效标志。
module uart_rx#(parameter UART_BPS='d9600 , //波特率:1s传输9600个bitparameter CLK_FREQ='d50_000_000 //时钟频率:50MHz
)(input wire clk ,input wire rst_n ,input wire rx , //接收的串行数据output reg [7:0] po_data , //输出并行数据output reg po_flag //输出有效并行数据的标志信号
);
首先对rx进行时钟同步,消除亚稳态,以及打拍处理提取下降沿;
always@(posedge clk or negedge rst_n)if(!rst_n) beginrx_d1<=1'b1;rx_d2<=1'b1;rx_d3<=1'b1;endelse beginrx_d1<=rx; //时钟同步,消除亚稳态rx_d2<=rx_d1; //时钟同步,消除亚稳态rx_d3<=rx_d2; //打拍处理endassign rx_fall = ~rx_d2 & rx_d3 ; //提取rx下降沿
然后需要数据帧的有效信号,以便知道什么时候计数;
always@(posedge clk or negedge rst_n)if(!rst_n) frame_val<=1'b0;else if((bit_cnt==BIT_CNT_MAX-1'b1) && bit_flag) //接收完1帧数据frame_val<=1'b0;else if(rx_fall)frame_val<=1'b1;elseframe_val<=frame_val;
1码元符号(1bit)所需的计数器;
always@(posedge clk or negedge rst_n)if(!rst_n) baud_cnt<=16'd0;else if(frame_val==1'b0) //数据帧无效baud_cnt<=16'd0;else if(baud_cnt==BAUD_CNT_MAX-1'b1)baud_cnt<=16'd0;elsebaud_cnt<=baud_cnt+1'b1;
1bit稳定数据的采样标志信号;
always@(posedge clk or negedge rst_n)if(!rst_n) bit_flag<=1'b0;else if(baud_cnt==BAUD_CNT_MAX_HALF-1'b1) //采样需要在中间数据才稳定bit_flag<=1'b1;elsebit_flag<=1'b0;
对采样到的bit数据进行计数;
always@(posedge clk or negedge rst_n)if(!rst_n) bit_cnt<=4'd0;else if((bit_cnt==BIT_CNT_MAX-1'b1) && bit_flag) //10bit数据采样完毕bit_cnt<=4'd0;else if(bit_flag) //采样到1bit数据bit_cnt<=bit_cnt+1'b1;elsebit_cnt<=bit_cnt;
将接收到的串行数据rx转化为并行数据po_data_t;
always@(posedge clk or negedge rst_n)if(!rst_n) po_data_t<=8'b0;else if((bit_cnt>=4'd1) && (bit_cnt<BIT_CNT_MAX-1'b1) && bit_flag) //8bit数据po_data_t<={rx_d3,po_data_t[7:1]}; //起始位后接的是低位elsepo_data_t<=po_data_t;
并行数据全部拼接完成的标志信号;
always@(posedge clk or negedge rst_n)if(!rst_n) po_flag_t<=1'b0;else if((bit_cnt==BIT_CNT_MAX-1'b1) && bit_flag)po_flag_t<=1'b1;elsepo_flag_t<=1'b0;
输出并行数据和输出有效并行数据的标志信号。
always@(posedge clk or negedge rst_n)if(!rst_n) po_data<=8'b0;else if(po_flag_t)po_data<=po_data_t;elsepo_data<=po_data;//po_flag_t延迟1拍与po_data同步
always@(posedge clk or negedge rst_n)if(!rst_n) po_flag<=1'b0;elsepo_flag<=po_flag_t;
仿真结果:
2.uart发送模块:接收并行数据,发送串行数据。
module uart_tx#(parameter UART_BPS='d9600 , //波特率:1s传输9600个bitparameter CLK_FREQ='d50_000_000 //时钟频率:50MHz
)(input wire clk ,input wire rst_n ,input wire pi_flag , //输入并行数据input wire [7:0] pi_data , //输入有效并行数据的标志信号output reg tx //输出串行数据
);
首先同样是uart 1帧数据的有效信号;
always@(posedge clk or negedge rst_n)if(!rst_n) frame_val<=1'b0;else if((bit_cnt==BIT_CNT_MAX-1'b1) && bit_flag) //发送完1帧数据frame_val<=1'b0;else if(pi_flag) //接收到有效的并行数据frame_val<=1'b1;elseframe_val<=frame_val;
1码元符号(1bit)所需的计数器;
always@(posedge clk or negedge rst_n)if(!rst_n) baud_cnt<=16'd0;else if(frame_val==1'b0) //数据帧无效baud_cnt<=16'd0;else if(baud_cnt==BAUD_CNT_MAX-1'b1)baud_cnt<=16'd0;elsebaud_cnt<=baud_cnt+1'b1;
1bit数据的发送标志信号;
always@(posedge clk or negedge rst_n)if(!rst_n) bit_flag<=1'b0;else if(frame_val && !baud_cnt)bit_flag<=1'b1;elsebit_flag<=1'b0;
对bit数据的发送进行计数;
always@(posedge clk or negedge rst_n)if(!rst_n) bit_cnt<=4'd0;else if((bit_cnt==BIT_CNT_MAX-1'b1) && bit_flag) //10bit数据计数完毕bit_cnt<=4'd0;else if(bit_flag) //发送完1bit数据bit_cnt<=bit_cnt+1'b1;elsebit_cnt<=bit_cnt;
输出串行数据。
always@(posedge clk or negedge rst_n)if(rst_n==1'b0) tx<=1'b1; //空闲else if(bit_flag)case(bit_cnt)4'd0: tx<=1'b0; //起始位4'd1: tx<=pi_data[0]; //最低位数据4'd2: tx<=pi_data[1];4'd3: tx<=pi_data[2];4'd4: tx<=pi_data[3];4'd5: tx<=pi_data[4];4'd6: tx<=pi_data[5];4'd7: tx<=pi_data[6];4'd8: tx<=pi_data[7]; //最高位数据4'd9: tx<=1'b1; //结束位default:tx<=1'b1;endcase
仿真结果:
3.uart环回测试。
module uart_test#(parameter UART_BPS='d9600 , //波特率:1s传输9600个bitparameter CLK_FREQ='d50_000_000 //时钟频率:50MHz
)(input wire clk ,input wire rst_n ,input wire rx , //接收的串行数据output wire tx //发送的串行数据
);wire [7:0] data ;
wire data_flag ;uart_rx#(.UART_BPS(UART_BPS),.CLK_FREQ(CLK_FREQ)
)u_uart_rx(.clk (clk ),.rst_n (rst_n ),.rx (rx ),.po_data(data),.po_flag(data_flag)
);uart_tx#(.UART_BPS(UART_BPS),.CLK_FREQ(CLK_FREQ)
)u_uart_tx(.clk (clk ),.rst_n (rst_n ),.pi_data(data),.pi_flag(data_flag),.tx(tx)
);endmodule
仿真验证:
`timescale 1ns/1ns
module tb_uart_test();parameter UART_BPS='d9600 ; //波特率:1s传输9600个bit
parameter CLK_FREQ='d50_000_000 ; //时钟频率:50MHzreg clk;
reg rst_n;
reg rx;wire tx;initial
beginclk=1'b0;rst_n<=1'b0;rx<=1'b1;#20rst_n<=1'b1;
endalways #10 clk=~clk;initial
begin#200 //空闲状态rx_test();#(5208*10*20*3)#200$stop;
end//输出uart数据帧(10-13)
task rx_test(); //任务函数,类似C语言integer j;for(j=10;j<13;j=j+1)rx_8bit(j);
endtask//输入8bit并行数据,输出uart数据帧
task rx_8bit(input [7:0] data
);
integer i;for(i=0;i<10;i=i+1)
begincase(i)0:rx<=1'b0; //1帧数据1:rx<=data[0];2:rx<=data[1];3:rx<=data[2];4:rx<=data[3];5:rx<=data[4];6:rx<=data[5];7:rx<=data[6];8:rx<=data[7];9:rx<=1'b1;endcase#(5208*20); //9600波特率
end
endtaskuart_test#(.UART_BPS(UART_BPS),.CLK_FREQ(CLK_FREQ)
)u_uart_test(.clk (clk ),.rst_n (rst_n ),.rx (rx ),.tx(tx)
);endmodule