//此代码的注意事项,首先这个代码不能仿真成功会出现一定的时间延迟, //因为在做板级验证的时候把时间改成了100ms发送一次,要想仿真成功,把时间改成499999 //使用上一节课设计的发送模块,设计一个数据发送器, //每10ms以115200的波特率发送一个数据,每次发送的 //数据比前一个数据大一(计数器) //首先是发送八位数据的uart_byte_tx的更改的源代码 //1、这里我使用的是(uart_p==uart_byte_tx) //这两个是底层模块 module uart_p( clk, reset_n, send_go, data, baud_set, uart_tx, tx_done ); input clk; input reset_n; input send_go; input [7:0] data; input [2:0]baud_set; output reg uart_tx; output reg tx_done; //书写不同波特率对应的模式 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) send_en<=1; else if(tx_done) send_en<=0; //书写关于data的寄存问题 reg [7:0] r_data; always@(posedge clk) if(send_go) r_data<=data; else r_data<=r_data; //先写一个适合波特率的定时 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);//放在上面就不行,还跟位置有关系。 //将时间拼接为11个时间段 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; //这里一定要注意不加else bps_cnt<=0;因为条件是div_cnt==bps_DR-1,如果else就会出现bps_cnt一直为0的怪情况。 always@(posedge clk or negedge reset_n) if(!reset_n) uart_tx<=1'b1; 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_clk==1)&&(bps_cnt==10)) tx_done<=1; else tx_done<=0; endmodule //2、uart_byte_tx_tb仿真代码(这里我使用的是uart_p_tb==uart_byte_tx_tb) `timescale 1ns / 1ns module uart_p_tb(); reg clk; reg reset_n; reg send_en; reg [7:0] data; reg [2:0]baud_set; wire uart_tx; wire tx_done; uart_p uart_p_inst0( .clk(clk), .reset_n(reset_n), .send_en(send_en), .data(data), .baud_set(baud_set), .uart_tx(uart_tx), .tx_done(tx_done) ); initial clk=1; always #10 clk=~clk; initial begin reset_n=0; send_en=0; data=0; baud_set=4; #201; reset_n=1; #20; send_en=1; data=8'h57; @(posedge tx_done) send_en=0; #2000; send_en=1; data=8'h75; #20; @(posedge tx_done) send_en=0; #200000; $stop; end endmodule //3、uart_test仿真代码,这里面是顶层模块 module uart_test( clk, reset_n, uart_tx ); input clk; input reset_n; output uart_tx; reg [26:0] counter; reg send_go; reg [7:0]data; //先进行底层模块的例化 //例化只用写对应的端口和连接 uart_p uart_p_inst0( .clk(clk), .reset_n(reset_n), .send_go(send_go), .baud_set(3'd4), .data(data), .uart_tx(uart_tx), .tx_done(tx_done) ); //先书写10ms的定时器 always@(posedge clk or negedge reset_n) if(!reset_n) counter<=0; else if(counter==4999999) counter<=0; else counter<=counter+1; //开始书写发送信号send_en always@(posedge clk or negedge reset_n) if(!reset_n) send_go<=0; else if(counter==1) send_go<=1; else send_go<=0; //为什么不管tx_done?????? //开始书写发送的数据,让其执行每次加一的操作。 always@(posedge clk or negedge reset_n) if(!reset_n) data<=0; else if(tx_done) data<=data+1'b1; endmodule //4、uart_test_tb仿真代码,这里面是顶层模块 `timescale 1ns / 1ps module uart_test_tb(); reg clk; reg reset_n; wire uart_tx; uart_test uart_test_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,uart,bps,串口,发送数据,input,DR,小梅哥,50000000 From: https://www.cnblogs.com/wangwin4/p/17173771.html