通辽市北京网站建设,企业推广方案,南昌网站建设策划,水泥网站营销方案怎么做小梅哥串口部分学习part1 串口通信发送原理串口通信发送的Verilog设计与调试串口发送应用之发送数据串口发送应用之采用状态机实现多字节数据发送串口通信发送原理
1#xff1a;串口通信模块设计的目的是用来发送数据的#xff0c;因此需要有一个数据输入端口 2#xff1a;…
小梅哥串口部分学习part1 串口通信发送原理串口通信发送的Verilog设计与调试串口发送应用之发送数据串口发送应用之采用状态机实现多字节数据发送串口通信发送原理
1串口通信模块设计的目的是用来发送数据的因此需要有一个数据输入端口 2串口通信支持不同的波特率所以需要一个波特率设置端口 3串口通信的本质就是将8位并行数据通过一根信号线在不同的时刻传输并行数据的不同位通过多个时刻最终将8位并行数据全部传出 4串口通信以1位的低电平标志串行传输的开始待8位数据传输完成之后在1位的高电平标志传输的结束 5控制信号控制并转串模块什么时候开始工作什么时候一个数据发送完成须有一个发送开始信号以及一个发送完成信号 注图中少了一个波特率设置端口
串口通信发送的Verilog设计与调试
1波特率为300起对应的计算公式为1000 000 000/3003 333 333ns 3 333 333ns/20166 666次 对应的是18位所以一般有关波特率设置的端口设置的最大值为18位计数 源代码 module uart_byte_tx(input [7:0]Data,input Send_en,input Clk,input Reset_n,input [2:0]Baud_set,output reg uart_tx,output reg Tx_done);//Baud_set0 就让波特率9600//Baud_set1 就让波特率19200//Baud_set2 就让波特率38400//Baud_set3 就让波特率57600//Baud_set4 就让波特率115200reg [17:0]bps_DR;always(*)begincase(Baud_set)0:bps_DR1000000000/9600/20;1:bps_DR1000000000/19200/20;2:bps_DR1000000000/38400/20;3:bps_DR1000000000/57600/20;4:bps_DR1000000000/115200/20;default:bps_DR1000000000/9600/20;endcaseendwire bps_clk;assign bps_clk (div_cnt 1);reg [17:0]div_cnt;always(posedge Clk or negedge Reset_n)beginif(!Reset_n)div_cnt0;else if(Send_en)beginif(div_cntbps_DR-1)div_cnt0;elsediv_cntdiv_cnt1b1;endelsediv_cnt0;endreg [3:0]bps_cnt;always(posedge Clk or negedge Reset_n)beginif(!Reset_n)bps_cnt0;else if(Send_en)beginif(bps_clk)beginif(bps_cnt11)bps_cnt0;elsebps_cntbps_cnt1;endendelsebps_cnt1b1;end//并串转换always(posedge Clk or negedge Reset_n)beginif(!Reset_n)beginuart_tx1b0;Tx_done1b0;endelse begincase(bps_cnt)1:begin uart_tx1b0;Tx_done1b0;end2:uart_txData[0];3:uart_txData[1];4:uart_txData[2];5:uart_txData[3];6:uart_txData[4];7:uart_txData[5];8:uart_txData[6];9:uart_txData[7];10:uart_tx1b1;11:begin uart_tx1b1;Tx_done1b1; end default: uart_tx1b1;endcaseendendendmodule
测试文件
timescale 1ns / 1ns
module uart_byte_tx_tb();reg [7:0]Data;reg Send_en;reg Clk;reg Reset_n;reg [2:0]Baud_set;wire uart_tx;wire Tx_done;uart_byte_tx uart_byte_tx(.Data(Data),.Send_en(Send_en),.Clk(Clk),.Reset_n(Reset_n),.Baud_set(Baud_set),.uart_tx(uart_tx),.Tx_done(Tx_done));initial Clk0;always#10 Clk!Clk;initial beginReset_n0;Send_en0;Data0;Baud_set4;#201;Reset_n1;Data8h57;Send_en1;#20;//下面的意思是一直在等待Tx_done变量没有等到的话就不往下进行(posedge Tx_done);Send_en0;#20000;Data8h75;Send_en1;#20;(posedge Tx_done);Send_en0;#20000;$stop;endendmodule
仿真截图
收获 1在有多级if else的时候要记得加上begin end 否则可能造成识别不出来导致结果错误~ 2在主代码中为了模拟实际电路中的赋值情况可以设置#10代表延时时间上面记得加timescale 1ns/1ns因为在下载到电路板上以及vivado识别的时候会自动略去这里的延时但是这么写对实际电路仿真的时候却又非常有用
串口发送应用之发送数据
题目使用上面的串口发送模块设计一个数据发送器每10ms以115200的波特率发送一个数据每次发送的数据比前一个数据大一计数器 uart_byte_tx代码 module uart_byte_tx(input [7:0]Data,input Send_Go,input Clk,input Reset_n,input [2:0]Baud_set,output reg uart_tx,output reg Tx_done);reg Send_en;always(posedge Clk or negedge Reset_n)beginif(!Reset_n)Send_en0;else if(Send_Go)Send_en1;else if(Tx_done)Send_en 0;endreg [7:0]r_Data;always(posedge Clk)beginif(Send_Go)r_DataData;elser_Datar_Data;end//Baud_set0 就让波特率9600//Baud_set1 就让波特率19200//Baud_set2 就让波特率38400//Baud_set3 就让波特率57600//Baud_set4 就让波特率115200reg [17:0]bps_DR;always(*)begincase(Baud_set)0:bps_DR1000000000/9600/20;1:bps_DR1000000000/19200/20;2:bps_DR1000000000/38400/20;3:bps_DR1000000000/57600/20;4:bps_DR1000000000/115200/20;default:bps_DR1000000000/9600/20;endcaseendwire bps_clk;assign bps_clk (div_cnt 1);reg [17:0]div_cnt;always(posedge Clk or negedge Reset_n)beginif(!Reset_n)div_cnt0;else if(Send_en)beginif(div_cntbps_DR-1)div_cnt0;elsediv_cntdiv_cnt1b1;endelsediv_cnt0;endreg [3:0]bps_cnt;always(posedge Clk or negedge Reset_n)beginif(!Reset_n)bps_cnt0;else if(Send_en)beginif(bps_clk)beginif(bps_cnt11)bps_cnt0;elsebps_cntbps_cnt1;endendelsebps_cnt1b0;end//并串转换always(posedge Clk or negedge Reset_n)beginif(!Reset_n)beginuart_tx1b0;endelse begincase(bps_cnt)1:uart_tx1b0;2:uart_txr_Data[0];3:uart_txr_Data[1];4:uart_txr_Data[2];5:uart_txr_Data[3];6:uart_txr_Data[4];7:uart_txr_Data[5];8:uart_txr_Data[6];9:uart_txr_Data[7];10:uart_tx1b1;11: uart_tx1b1;default: uart_tx1b1;endcaseendendalways(posedge Clk or negedge Reset_n)beginif(!Reset_n)Tx_done1b0;else if((bps_cnt10)(bps_clk1))Tx_done1b1;else Tx_done1b0;end
endmodule
uart_tx_test代码顶层模块 module uart_tx_test(input Clk,input Reset_n,output uart_tx);reg [7:0]Data;reg Send_Go;wire Tx_done;uart_byte_tx uart_byte_tx(.Data(Data),.Send_Go(Send_Go),.Clk(Clk),.Reset_n(Reset_n),.Baud_set(3d4),.uart_tx(uart_tx),.Tx_done(Tx_done));//首先计时10msreg [18:0] cnt;always(posedge Clk or negedge Reset_n)beginif(!Reset_n)cnt0;else if(cnt499999)cnt0;elsecntcnt1b1;end//接着设计何时Send_Go开始发送数据always(posedge Clk or negedge Reset_n)beginif(!Reset_n)Send_Go0;else if(cnt1)Send_Go1;//这里需要注意本来的Send_en是一段时间的信号比较长但是Send_Go属于脉冲信号就一下else Send_Go0;end//接着设计数据变化always(posedge Clk or negedge Reset_n)beginif(!Reset_n)Data0;else if(Tx_done)DataData1;endendmodule
uart_tx_test_tb测试文件
timescale 1ns / 1ns
module uart_tx_test_tb();reg Clk;reg Reset_n;wire uart_tx;
uart_tx_test uart_tx_test(.Clk(Clk),.Reset_n(Reset_n),.uart_tx(uart_tx));initial Clk0;always #10 Clk!Clk;initial begin Reset_n0;#201;Reset_n1;#50000000;$stop;endendmodule
仿真截图
收获 1对于一些很重要的控制信号最好单独拿出来写参杂在一些其他功能中很可能会产生其他的影响例如Tx_done 2Go一般是单脉冲信号en是电平信号
串口发送应用之采用状态机实现多字节数据发送
有些人会了8位的串口传送数据但是总会有一些问题例如 1.ADC采样的结果是12位的怎么使用串口发送 2.16位的数据怎样通过串口发送 3.有多个字节的数据通过串口发送 不能直接将8位改成12位、16位因为UART规定了发送的数据位只能有6、7、8位所以应该把大于8位的字节分成多个字节进行发送
三种情况 1没有开始发送上一次的已经发送完成新的40位数据的发送请求没有出现 2来了发送40位数据的请求信号 3依次发送数据的状态
第一个状态第一种情况的时候咱干什么事情等待传输请求Trans_Go的到来Data40[7:0]给到uart_byte_tx的Data并同时产生Send_Go信号启动第一个字节的发送 接着应该等待等待Tx_Done信号的到来 40位数据是否发完了发完了回到第一个状态继续等Trans_Go没发完启动下一个8位数据的发送
源代码
//该模块完成的功能是采用状态机实现多字节数据发送
module uart_tx_data(input Clk,input Reset_n,input [39:0]Data40,input Trans_Go,//表示合适开始发送数据即传输请求output reg Trans_Down,//表示一次40位的数据传输完成output uart_tx);reg [7:0]Data;reg Send_Go;wire Tx_done;uart_byte_tx uart_byte_tx(.Data(Data),.Send_Go(Send_Go),.Clk(Clk),.Reset_n(Reset_n),.Baud_set(3h4),.uart_tx(uart_tx),.Tx_done(Tx_done));reg [2:0]state;always(posedge Clk or negedge Reset_n)beginif(!Reset_n)beginstate0;Data0;Send_Go0;Trans_Down0;end//下面部分也可以用case语句实现记得加default~else if(state0)beginTrans_Down0;if(Trans_Go)beginDataData40[7:0];state1;Send_Go1;endelse beginDataData;state0;Send_Go0;endendelse if(state1)beginif(Tx_done)beginDataData40[15:8];state2;Send_Go1;endelse beginDataData;state1;Send_Go0;endendelse if(state2)beginif(Tx_done)beginDataData40[23:16];state3;Send_Go1;endelse beginDataData;state2;Send_Go0;endendelse if(state3)beginif(Tx_done)beginDataData40[31:24];state4;Send_Go1;endelse beginDataData;state3;Send_Go0;endendelse if(state4)beginif(Tx_done)beginDataData40[39:32];state5;Send_Go1;endelse beginDataData;state4;Send_Go0;endend else if(state5)beginif(Tx_done)beginstate0;Trans_Down1;Send_Go0;endelse beginDataData;state5;Send_Go0;endend endendmodule
测试文件
timescale 1ns / 1nsmodule uart_tx_data_tb();reg Clk;reg Reset_n;reg [39:0]Data40;reg Trans_Go;wire Trans_Down;wire uart_tx;uart_tx_data uart_tx_data(Clk,Reset_n,Data40,Trans_Go,//表示合适开始发送数据即传输请求Trans_Down,//表示一次40位的数据传输完成uart_tx);initial Clk0;always #10 Clk!Clk;initial beginReset_n0;Data400;Trans_Go0;#201Reset_n1;#201Data4040h123456789a;Trans_Go1;(posedge Trans_Down);Trans_Go0;#201Data4040ha987654321;Trans_Go1;(posedge Trans_Down);#200000$stop;end
endmodule
仿真截图
任务 1优化状态机实现只要2个或3个状态实现发送的功能并易于修改为发送任意个字节的数据加个计数器进行二级验证~ 2思考不使用状态机实现的方法
任务一代码已进行仿真
//该模块完成的功能是采用状态机实现多字节数据发送
module uart_tx_data2(input Clk,input Reset_n,input [39:0]Data40,input Trans_Go,//表示合适开始发送数据即传输请求output reg Trans_Down,//表示一次40位的数据传输完成output uart_tx);reg [7:0]Data;reg Send_Go;wire Tx_done;uart_byte_tx uart_byte_tx(.Data(Data),.Send_Go(Send_Go),.Clk(Clk),.Reset_n(Reset_n),.Baud_set(3h4),.uart_tx(uart_tx),.Tx_done(Tx_done));reg [2:0]state;//用来记录当前发送到第几个字节了reg [2:0]cnt;always(posedge Clk or negedge Reset_n)beginif(!Reset_n)begincnt0;end else if(Tx_done) beginif(cnt4)cnt0;elsecntcnt1;endendalways(posedge Clk or negedge Reset_n)beginif(!Reset_n)beginstate0;Data0;Send_Go0;Trans_Down0;end//下面部分也可以用case语句实现记得加default~else if(state0)beginTrans_Down0;if(Trans_Go)beginTrans_Down0;if(Tx_done)begincase(cnt)0:begin DataData40[7:0]; state0;end 1:begin DataData40[15:8];state0;end2:begin DataData40[23:16];state0;end3:begin DataData40[31:24];state0;end4:begin DataData40[39:32];state1;enddefault:DataData;endcaseSend_Go1;endelse beginDataData;state0;Send_Go0;endendend else if(state1)beginif(Tx_done)beginstate0;Trans_Down1;Send_Go0;endelse beginDataData;state1;Send_Go0;endend endendmodule