赞
踩
uart_tx=起始位+data[7:0]+结束位
module uart_byte_tx( input [7:0] data, input Send_en, input Clk, input Reset_n, input [2:0] Baud_set,//假设只支持8种波特率 output reg uart_tx, output reg Tx_Done ); reg [17:0] div_cnt; //计算不同波特率时计数的次数 //Baud_set=0,则波特率=9600, //Baud_set=1,则波特率=19200, //Baud_set=2,则波特率=38400, //Baud_set=3,则波特率=57600, //Baud_set=4,则波特率=115200 reg [17:0] bps_DR; always@(*)begin case(Baud_set) 0:bps_DR=1000000000/9600/20; 1:bps_DR=1000000000/19200/20; 2:bps_DR=1000000000/38400/20; 3:bps_DR=1000000000/57600/20; 4:bps_DR=1000000000/115200/20; default:bps_DR=1000000000/9600/20; endcase end //计数基本时间单元 always@(posedge Clk or negedge Reset_n)begin if(!Reset_n)begin div_cnt<=0; end else if(Send_en)begin if(div_cnt == bps_DR-1) begin div_cnt<=0; end else begin div_cnt<=div_cnt+1'b1; end end else div_cnt<=0; end reg [3:0] bps_cnt; //发送10个段:开始+8数据+结束,一共需要11个clk确定 always@(posedge Clk or negedge Reset_n)begin if(!Reset_n)begin bps_cnt<=0; end else if(Send_en)begin if(div_cnt == bps_DR-1) begin if(bps_cnt==11) bps_cnt<=0; else bps_cnt<=bps_cnt+1'b1; end end else bps_cnt<=0; end always@(posedge Clk or negedge Reset_n)begin if(!Reset_n)begin Tx_Done<=1'b0; uart_tx<=1'b1; end else begin case(bps_cnt) 0:begin uart_tx<=1'b0;Tx_Done<=0;end 1:uart_tx<=data[0]; 2:uart_tx<=data[1]; 3:uart_tx<=data[2]; 4:uart_tx<=data[3]; 5:uart_tx<=data[4]; 6:uart_tx<=data[5]; 7:uart_tx<=data[6]; 8:uart_tx<=data[7]; 9:uart_tx<=1'b1; 10:begin uart_tx=1'b1;Tx_Done<=1;end default:uart_tx=1'b1; endcase end end endmodule
1、当Send_en从0变成1时,代表开始传递数据。uart_tx初始为1,所以当send_en上升沿时,uart_tx应该同时变成0,代表传输START(低电平)位。
但是由图片可知,uart_tx大概早了将近1位的时间就将其拉为低电平。
改完之后的波形图如上图所示,当bps_cnt=1时,才将uart_tx=0,传输开始位。
2、两个蓝色的marker标志在这个空闲时间中,是让uart_tx一直保持为1。但是这个有必要吗?如何进行更改?
if(div_cnt == bps_DR-1) begin
if(bps_cnt==11)
bps_cnt<=0;
else
bps_cnt<=bps_cnt+1'b1;
end
if(div_cnt == 1) begin
if(bps_cnt==11)
bps_cnt<=0;
else
bps_cnt<=bps_cnt+1'b1;
end
使用前面设计的串口发送模块,设计一个数据发送器,每10ms以115200的波特率发送一个数据,每次发送的数据比前一个数据大一(计数器)
//每隔10ms发送一个数据 always @(posedge Clk or negedge Reset_n) begin if (!Reset_n) begin counter<=0; end else if (counter == 500000-1) begin counter<=0; end else counter<=counter+1; end always @(posedge Clk or negedge Reset_n) begin if (!Reset_n) begin Send_en<=0; end else if (counter==1) begin Send_en<=1; end else if(Tx_Done) begin Send_en<=0; end end always @(posedge Tx_Done or negedge Reset_n) begin if (!Reset_n) begin data<=0; end else begin data <= data+1'b1; end end
波形图:1、Tx_Done一直为1,导致poedeg Tx_Done检测不到,所以data无法进行自加
2、继续分析,Tx_Done什么时候0->1,1->0
看E://uart_byte_tx,当bps_cnt=1时,Tx_Done=1,当bps_cnt=11时,Tx_Done=1。
当Tx_Done=1时,Send_En就会变成0.此时bps_cnt就不会再+1.由此成了一个死循环.
修改:可以从波形图看到,bps_cnt是从0->a,然后就一直持续为0.刚好我们前面有一个为0的状态位没有用到。此时就将bps_cnt=0时,
分析:为什么是3个周期?
当bps_cnt=11时,Tx_Done=1.此时,Send_En从1->0.但在下一个节拍才能变为0(非阻塞赋值)。再到下一个节拍才能知晓已经为0,此时bps_cnt才从11变成0.当bps_cnt=0时,再过一个节拍Tx_Done=0.
修改:
always@(posedge Clk or negedge Reset_n)begin if(!Reset_n)begin Tx_Done<=1'b0; uart_tx<=1'b1; end else begin case(bps_cnt) 0:Tx_Done<=0; 1:uart_tx<=1'b0; 2:uart_tx<=data[0]; 3:uart_tx<=data[1]; 4:uart_tx<=data[2]; 5:uart_tx<=data[3]; 6:uart_tx<=data[4]; 7:uart_tx<=data[5]; 8:uart_tx<=data[6]; 9:uart_tx<=data[7]; 10:uart_tx<=1'b1; 11:uart_tx=1'b1; default:uart_tx=1'b1; endcase end end always @(posedge Clk or negedge Reset_n)begin if(!Reset_n) Tx_Done<=0; else if((bps_cnt==10)&&(bps_clk==1)) Tx_Done<=1; else Tx_Done<=0; end
最后上板子调试,发现一直接收的是00,后看了一篇博客发现是在不同的always块中对同一个信号进行赋值。这是不允许的!!!!!
这是那篇博客/提问链接:https://ask.csdn.net/questions/7737125
串口之数据传输
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。