小梅哥课程学习——串口发送应用之发送数据(适用于板级验证,时间间隔位100ms)

2023-03-16,,

//此代码的注意事项,首先这个代码不能仿真成功会出现一定的时间延迟,
//因为在做板级验证的时候把时间改成了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

小梅哥课程学习——串口发送应用之发送数据(适用于板级验证,时间间隔位100ms)的相关教程结束。

《小梅哥课程学习——串口发送应用之发送数据(适用于板级验证,时间间隔位100ms).doc》

下载本文的Word格式文档,以方便收藏与打印。