實驗十二:串口模塊① — 發送
串口固然是典型的實驗,想必許多同學已經作爛,不過筆者還要循例介紹一下。我們知道串口有發送與接收之分,實驗十二的實驗目的就是實現串口發送,然而不同的是 ... 筆者會用另一種思路去實現串口發送。
圖12.1 PS/2發送時序與串口發送時序。
如圖12.1所示,串口發送時序相較PS/2發送時序,串口發送時序就像斷了翅膀的小鳥般,沒有時鍾信號控制整個傳輸協議。除此之外,串口發送時序與PS/2發送時序近似的地方也非常驚人 ... 默認下,一幀PS/2數據有11位,對此一幀串口數據也有11位,其中位分配如表12.1所示:
表12.1 一幀串口數據的位分配。
位分配 |
位定義 |
[0] |
起始位 |
[8:1] |
數據位 |
[9] |
校驗位 |
[10] |
停止位 |
如表12.1所示,[0]為拉低的起始位,[8:1]為任意填充的數據位,[9]為任意填充的校驗位,[10]為拉高的停止位。
圖12.2 FPGA發送一幀串口數據(無視波特率)。
假設我們無視波特率,並且利用FPGA發送一幀串口數據的話 ... 如圖12.2所示,一幀有11位的串口數據,一共使用了11個上升沿發送出去,為此Verilog則可以這樣表示,結果如代碼12.1所示:
reg [10:0]D1;
always @(posedge CLOCK)
case(i)
0,1,2,3,4,5,6,7,8,9,10:
begin TXD <= D1[i]; i <= i + 1'b1; end
......
endcase
代碼12.1
如代碼12.1所示,寄存器D為11位寬的寄存器,並且驅動TXD輸出口,期間步驟0~11公按照i的位尋址,將D1的內容逐個發送出去。
雖然串口傳輸協議極為類似PS/2傳輸協議,但是串口傳輸協議也有區別的地方。其一串口傳輸協議有波特率的概念,而且串口協議有各種各樣的波特率,常用的波特率有9600 bps或者115200 bps,波特率最低為 110 bps,最高為 256000 bps(目前暫定)。所謂波特率就是一秒內,串口可以發送多少位數據,此外波特率也是一位數據的周期,或者說是一位數據的保持時間,就拿115200 bps為例:
1/115200 = 8.68E-6
115200波特率的一位數據周期為 8.68us,如果用50Mhz 的時鍾頻率去量化的話:
( 1/115200 ) / (1/50E+6) = 8.68E-6 / 20E-9
= 434
圖12.3 FPGA發送一幀串口數據(考慮波特率)。
如果圖12.3考慮115200的波特率,結果如圖12.3所示,每一位數據都保持434個時鍾
,為此Verilog可以這樣表示,如代碼12.2所示:
reg [10:0]D1;
reg [8:0]C1;
always @(posedge CLOCK)
case(i)
0,1,2,3,4,5,6,7,8,9,10:
if( C1 == 9’d434 -1 ) begin C1 <= 9’d0; i <= i + 1’b1; end
else begin TXD <= D1[i]; C1 <= C1 + 1'b1; end
......
endcase
代碼12.1
如代碼12.1所示,步驟0~10不再保持一個時鍾,換之每個步驟都保持434個時鍾,因此每位TXD的發送數據也保持 8.68us。
除此此外,串口傳輸協議不僅可以自定義波特率,串口傳輸協議也可以自定義一幀數據的位寬,自定義內容如表12.2所示:
表12.2 自定義一幀數據。
自定義數據位 |
自定義內容 |
數據位 |
5~9 |
校驗位 |
有/無 |
停止位 |
1~2 |
如表12.2所示,可以自定義的數據其中便包含數據位,默認下為1字節,自定義內容則是5~9位,校驗位也可以設置為有或者無(默認下是有),停止位也可以增至2位(默認下是1位)。不管怎么樣,表12.2是比較官方的自定義內容 ... 只要讀者歡喜,任何畸形的自定義內容也有可能實現。
理解完畢以后,我們便可以開始建模了。
圖12.4 實驗十二的建模圖。
圖12.4是實驗十二的建模圖,不過內容較為寒酸 ... 組合模塊 tx_demo 內容包括一段核心操作,還有一只TX功能模塊。核心操作負責TX功能模塊的調用,亦即控制溝通信號還有Data的輸入。TX功能模塊被使能以后,便將iData經由TXD輸出端發送出去
,完后便反饋完成信號以示一次性的操作已經完畢。
tx_funcmod.v
圖12.5 TX功能模塊的建模圖。
如圖12.5所示,該模塊的左方有問答信號,還有8位的iData,至於右方則是 TXD 頂層信號。此外,一幀數據的波特率為 115200 bps。
1. module tx_funcmod
2. (
3. input CLOCK, RESET,
4. output TXD,
5. input iCall,
6. output oDone,
7. input [7:0]iData
8. );
9. parameter B115K2 = 9'd434; // formula : ( 1/115200 )/( 1/50E+6 )
以上內容為相關的出入端聲明,第9行則是波特率為115200的常量聲明。
11. reg [3:0]i;
12. reg [8:0]C1;
13. reg [10:0]D1;
14. reg rTXD;
15. reg isDone;
16.
17. always @( posedge CLOCK or negedge RESET )
18. if( !RESET )
19. begin
20. i <= 4'd0;
21. C1 <= 9'd0;
22. D1 <= 11'd0;
23. rTXD <= 1'b1;
24. isDone <= 1'b0;
25. end
以上內容為相關的寄存器聲明以及復位操作。
26. else if( iCall )
27. case( i )
28.
29. 0:
30. begin D1 <= { 2'b11 , iData , 1'b0 }; i <= i + 1'b1; end
31.
32. 1,2,3,4,5,6,7,8,9,10,11:
33. if( C1 == B115K2 -1 ) begin C1 <= 8'd0; i <= i + 1'b1; end
34. else begin rTXD <= D1[i - 1]; C1 <= C1 + 1'b1; end
35.
36. 12:
37. begin isDone <= 1'b1; i <= i + 1'b1; end
38.
39. 13:
40. begin isDone <= 1'b0; i <= 4'd0; end
41.
42. endcase
43.
以上內容為部分核心操作。第26行的if( iCall ) 表示該模塊不使能就不工作。步驟0用來准備發送數據,其中 2’b11 是停止位與校驗位(隨便填),1’b0則是起始位。步驟1~11用來發送一幀數據。步驟12~13用來反饋完成信號並返回步驟。
44. assign TXD = rTXD;
45. assign oDone = isDone;
46.
47. endmodule
以上內容為驅動輸出的聲明。
tx_demo.v
連線部署直接看代碼比較具體一點。
1. module tx_demo
2. (
3. input CLOCK, RESET,
4. output TXD
5. );
6. wire DoneU1;
以上內容是相關的出入端聲明。
8. tx_funcmod U1
9. (
10. .CLOCK( CLOCK ),
11. .RESET( RESET ),
12. .TXD( TXD ),
13. .iCall( isTX ),
14. .oDone( DoneU1 ),
15. .iData( D1 )
16. );
以上內容是TX功能模塊的實例化,其中isCall由isTX驅動,iData由D驅動。
18. reg [3:0]i;
19. reg [7:0]D1;
20. reg isTX;
21.
22. always @ ( posedge CLOCK or negedge RESET )
23. if( !RESET )
24. begin
25. i <= 4'd0;
26. D1 <= 8'd0;
27. isTX <= 1'b0;
28. end
以上內容是相關的寄存器聲明,第23~28行則是這些寄存器的復位操作。
29. else
30. case( i )
31.
32. 0:
33. if( DoneU1 ) begin isTX <= 1'b0; i <= i + 1'b1; end
34. else begin isTX <= 1'b1; D1 <= 8'hA1; end
35.
36. 1:
37. if( DoneU1 ) begin isTX <= 1'b0; i <= i + 1'b1; end
38. else begin isTX <= 1'b1; D1 <= 8'hA2; end
39.
40. 2:
41. if( DoneU1 ) begin isTX <= 1'b0; i <= i + 1'b1; end
42. else begin isTX <= 1'b1; D1 <= 8'hA3; end
43.
44. 3: // Stop
45. i <= i;
46.
47. endcase
48.
49. endmodule
以上內容是核心操作的內容,步驟0發送數據 8’hA1,步驟1發送數據8’hA2,步驟2發送數據 8’hA3。
編譯完畢便下載程序,並且將串口線連接至電腦與開發板。打開串口調試助手,波特率設為115200,數據位為8,校驗位隨便,停止位為1位 ... 事后,顯示方式設置為HEX(十六進制)。當程序下載完畢以后,串口調試助手便會出現 A1,A2與A3。
細節一: 完整的個體模塊
實驗十二的TX功能模塊已經是完整的個體,可以直接拿來調用。