//1、底层代码源代码发送10位数据 module uart_pr( clk, reset_n, send_go, data, baud_set, tx_done, uart_tx ); input clk; input reset_n; input send_go; input [7:0]data; input [2:0]baud_set; output reg tx_done; output reg uart_tx; //再书写关于bps_DR的选择计算 reg [17:0] bps_DR; always@(*) case(baud_set) 0:bps_DR=50000000/9600; 1:bps_DR=50000000/19200; 2:bps_DR=50000000/38400; 3:bps_DR=50000000/57600; 4:bps_DR=50000000/115200; default:bps_DR=50000000/9600; endcase reg send_en; always@(posedge clk or negedge reset_n) if(!reset_n) send_en<=0; else if(send_go)//记住这边只能用顶层的计数counter,不能用底层的div_cnt以及bps_cnt; send_en<=1; else if(tx_done) send_en<=0; //存储数据 reg [7:0]r_data; always@(posedge clk or negedge reset_n)//这里为什么不需要复位的下降沿 if(!reset_n) r_data<=0; else if(send_go) r_data<=data; else r_data<=r_data; //首先书写对应波特率的计数,分频div_cnt //根据最低的波特率来确定div_cnt的宽度 reg [17:0]div_cnt; always@(posedge clk or negedge reset_n) if(!reset_n) div_cnt<=0; else if(send_en)begin if(div_cnt==bps_DR-1) div_cnt<=0; else div_cnt<=div_cnt+1'b1; end else div_cnt<=0; wire bps_clk; assign bps_clk=(div_cnt==1); //开始书写下一个计数bps_cnt,来实现10为数据的发送 reg [3:0] bps_cnt; always@(posedge clk or negedge reset_n) if(!reset_n) bps_cnt<=0; else if(send_en)begin if(bps_clk)begin if(bps_cnt==11) bps_cnt<=0; else bps_cnt<=bps_cnt+1'b1; end end else bps_cnt=0; //开始书写发送10位的数据 always@(posedge clk or negedge reset_n) if(!reset_n) uart_tx<=1; else case(bps_cnt) 1:uart_tx<=0; 2:uart_tx<=r_data[0]; 3:uart_tx<=r_data[1]; 4:uart_tx<=r_data[2]; 5:uart_tx<=r_data[3]; 6:uart_tx<=r_data[4]; 7:uart_tx<=r_data[5]; 8:uart_tx<=r_data[6]; 9:uart_tx<=r_data[7]; 10:uart_tx<=1; 11:uart_tx<=1; default:uart_tx<=1; endcase always@(posedge clk or negedge reset_n) if(!reset_n) tx_done<=0; else if((bps_cnt==10)&&(bps_clk==1)) tx_done<=1; else tx_done<=0; endmodule //2、底层代码仿真文件 `timescale 1ns / 1ps module uart_pr_tb(); reg clk; reg reset_n; reg send_en; reg [7:0]data; reg [2:0]baud_set; wire tx_done; wire uart_tx; uart_pr uart_pr_tb( .clk(clk), .reset_n(reset_n), .send_en(send_en), .data(data), .baud_set(baud_set), .tx_done(tx_done), .uart_tx(uart_tx) ); initial clk=1; always#10 clk=!clk; initial begin reset_n=0; data=0; send_en=0; baud_set=4; #201; reset_n=1; #20; data=8'h57; send_en=1; @(posedge tx_done) send_en=0; #2000; data=8'h75; send_en=1; @(posedge tx_done) send_en=0; #20000; $stop; end endmodule 3、顶层代码源文件 //每10ms以115200的波特率发送一个数据,每次发送的 //数据比前一个数据大一(计数器) //顶层设计模块 module uart_test1( clk, reset_n, uart_tx ); input clk; input reset_n; output uart_tx; reg send_go;//这是顶层的send_en放在下面会出错 reg [7:0] data; //先将发送10位数据的uart进行例化 uart_pr uart_pr_inst0( .clk(clk), .reset_n(reset_n), .send_go(send_go), .data(data), .baud_set(3'd4), .tx_done(tx_done), .uart_tx(uart_tx) ); //先写出一个10ms的计数器 reg [18:0]counter; always@(posedge clk or negedge reset_n) if(!reset_n) counter<=0; else if(counter==499999) counter<=0; else counter<=counter+1'b1; //书写发送信号send_en //底层不是控制过send_en了吗??怎么这里还写控制send_en //因为底层控制send_en在testbench中控制的,最后不会在板级验证的时候起作用 //那只在testbench中也就是仿真波形中会出现。 always@(posedge clk or negedge reset_n) if(!reset_n) send_go<=0; else if(counter==1)//记住这边只能用顶层的计数counter,不能用底层的div_cnt以及bps_cnt; send_go<=1; else //设置send_go的时候一定要注意,什么时候开始,什么时候结束要形成闭环。 send_go<=0;//else还是要加,只不过不用带tx_done因为tx_done已经在顶层模块说明过了 //书写data的每次加1; always@(posedge clk or negedge reset_n) if(!reset_n) data<=0; else if(tx_done) data<=data+1'b1; endmodule 4、顶层代码仿真文件 `timescale 1ns / 1ps module uart_test1_tb(); reg clk; reg reset_n; wire uart_tx; uart_test1 uart_test1_inst0( .clk(clk), .reset_n(reset_n), .uart_tx(uart_tx) ); initial clk=1; always #10 clk=!clk; initial begin reset_n=0; #201; reset_n=1; #50000000; $stop; end endmodule
标签:tx,send,vivado,bps,串口,发送数据,input,DR,50000000 From: https://www.cnblogs.com/wangwin4/p/17174943.html