一. 簡(jiǎn)介
這是FPGA之旅的第四個(gè)設(shè)計(jì)實(shí)例了,,在上一例中,,也就是第三例,,串口通信,,實(shí)現(xiàn)了單byte的傳輸,。也就是每次只能傳輸一個(gè)btye的數(shù)據(jù),。在實(shí)際使用過(guò)程中,,需要發(fā)送多byte的數(shù)據(jù)為一包數(shù)據(jù),,里面包含各種信息,,例如最常見(jiàn)的包頭和包尾,。本例將在第三例的基礎(chǔ)上,實(shí)現(xiàn)多byte的接收實(shí)例,以滿足具體的需求,。
二. 實(shí)現(xiàn)方法
在串口通信中數(shù)據(jù)一般為:1 bit的起始位 + 5,6,7,8bit的數(shù)據(jù)位 + 1 bit的停止位,。最多一包數(shù)據(jù)為 10 bit。
其實(shí)串口協(xié)議中,,并沒(méi)有規(guī)定數(shù)據(jù)位為5,6,7,8,,理想情況下可以為任意位。例如,,兩塊FPGA之間通過(guò)串口通信,,就可以自定義。但是呢,?上位機(jī)軟件支持位數(shù)只有這么幾種,。為了通用性,還是以上位機(jī)軟件為標(biāo)準(zhǔn),。
假如說(shuō)我要一次性發(fā)送5 bytes的數(shù)據(jù) 或者 一次性接收 5 bytes的數(shù)據(jù),,然后交給FPGA進(jìn)行處理,那么該怎么做呢,?其實(shí)也是比較容易的,。只需要再設(shè)計(jì)一個(gè)模塊,重復(fù)調(diào)用 5 次串口發(fā)送模塊,,和串口接收模塊接收了 5 bytes的數(shù)據(jù)后,,再進(jìn)行對(duì)應(yīng)的處理,就可以了,。
基礎(chǔ)的串口通信模塊完成后,,就只需要完成這個(gè)多bytes 的模塊了。
三. Verilog 代碼實(shí)現(xiàn)
先來(lái)看一下發(fā)送的頂層模塊,,頂層模塊,,可以說(shuō)和普通的串口發(fā)送模塊一樣,,只是多出了一個(gè)參數(shù),,來(lái)控制發(fā)送字節(jié)的位寬,具體定義如下,。MulTXNum通過(guò)這個(gè)參數(shù)可以在實(shí)例化這個(gè)模塊的時(shí)候,,自行確定每次測(cè)試字節(jié)的個(gè)數(shù),非常靈活,。
module UART_MulTX #(
parameter MulTXNum = 3) /*每次發(fā)送的字節(jié)數(shù)*/
(
input sys_clk,
input rst_n,
input uart_tx_req, /*串口發(fā)送請(qǐng)求*/
output uart_txs_done, /*串口發(fā)送完成*/
input[MulTXNum*'d8 - 'd1:0] idats, /*發(fā)送的數(shù)據(jù)*/
output uarttx /*uart tx數(shù)據(jù)線*/
);
2. 在這個(gè)頂層模塊中調(diào)用基本的串口發(fā)送模塊,。波特率也通過(guò)參數(shù)進(jìn)行控制,在實(shí)例化的時(shí)候,,方便修改波特率,。
UART_TX #(
.UARTBaud(115200) /*設(shè)置波特率*/
)UART_TXHP
(
.sys_clk (sys_clk), /*系統(tǒng)時(shí)鐘 50M*/
.rst_n (rst_n), /*系統(tǒng)復(fù)位 低電平有效*/
.uart_tx_req (UART_TX_Reg), /*串口發(fā)送請(qǐng)求*/
.uart_tx_done (uart_tx_done), /*串口發(fā)送完成*/
.idat (txdata), /*發(fā)送數(shù)據(jù)*/
.uarttx (uarttx) /*uart tx數(shù)據(jù)線*/
);
3. 串口接收模塊定義也一樣,,具體的實(shí)現(xiàn)過(guò)程可以看完整的過(guò)程項(xiàng)目,就不粘貼上來(lái)了,。需要的可以自行獲取。簡(jiǎn)單看看模塊圖吧,!
四. testbeach編寫(xiě)
寫(xiě)完各個(gè)模塊后,,怎么能少得了仿真呢?也是調(diào)了幾次才沒(méi)有bug,,嗐,,直接上仿真。這里測(cè)試的是每次發(fā)送3個(gè)字節(jié)的數(shù)據(jù),,每次發(fā)送完成后,,發(fā)送完成后,發(fā)送數(shù)據(jù)加上2323,,然后繼續(xù)發(fā)送,,具體的可以看看仿真波形。
`timescale 1ns/1ps
module testbeach();
reg clk;
reg rst;
reg uart_tx_req;
wire uart_txs_done;
reg[23:0] idats;
wire uart;
wire[23:0] odats;
wire uart_rxs_done;
always #50 clk = ~clk;
initial begin
clk = 1'b1;
rst = 1'b1;
idats = 'd12256;
uart_tx_req = 1'b0;
#100
rst = 1'b0; /*手動(dòng)復(fù)位*/
#100
rst = 1'b1;
#100
uart_tx_req <= 1'b1;
end
always@(posedge clk)
if(uart_txs_done == 1'b1)
idats <= idats + 'd2323;
UART_MulRX #(
.MulRXNum (3)
)UART_MulRXHP(
.sys_clk (clk), /*系統(tǒng)時(shí)鐘 50M*/
.rst_n (rst), /*系統(tǒng)復(fù)位*/
.uart_rxs_done (uart_rxs_done), /*串口接收完成*/
.odats (odats), /*接收數(shù)據(jù)*/
.uartrx (uart) /*uart rx數(shù)據(jù)線*/
);
UART_MulTX #(
.MulTXNum(3)) /*每次發(fā)送的比特?cái)?shù)*/
UART_MulTXHP(
.sys_clk (clk), /*系統(tǒng)時(shí)鐘 50M*/
.rst_n (rst), /*系統(tǒng)復(fù)位*/
.uart_tx_req (uart_tx_req), /*串口發(fā)送請(qǐng)求*/
.uart_txs_done (uart_txs_done), /*串口發(fā)送完成*/
.idats (idats), /*發(fā)送的數(shù)據(jù)*/
.uarttx (uart) /*uart tx數(shù)據(jù)線*/
);
endmodule
通過(guò)波形可以看到,,程序編寫(xiě)正確?。?!(已上板驗(yàn)證)
需要完整代碼的可以在公眾號(hào)FPGA之旅中回復(fù) :FPGA之旅設(shè)計(jì)99例之第四例
更多信息可以來(lái)這里獲取==>>電子技術(shù)應(yīng)用-AET<<
電子技術(shù)應(yīng)用專(zhuān)欄作家FPGA之旅
原文鏈接:https://mp.weixin.qq.com/s/-SgBkJTbW-nRkG_eqjatWQ