第1個虛擬項目 1. 前言 點燈開啟了我們的FPGA之路,那麼我們來繼續沙盤演練。 用一個虛擬項目,來入門練習,以此步入數字邏輯的大門。 Key Words:FIFO 、SOF 、EOF、計數器、緩存、時序圖、方案設計 2. 項目要求 1) 輸入報文長度64~2048位元組; 2) 輸入報文之間最小間 ...
第1個虛擬項目
1. 前言
點燈開啟了我們的FPGA之路,那麼我們來繼續沙盤演練。
用一個虛擬項目,來入門練習,以此步入數字邏輯的大門。
Key Words:FIFO 、SOF 、EOF、計數器、緩存、時序圖、方案設計
2. 項目要求
1) 輸入報文長度64~2048位元組;
2) 輸入報文之間最小間隔為兩拍;
3) 輸出報文的前兩拍添加16bit報文長度信息;第1拍為報文長度高8位;第2拍為報文長度低8位;第3拍開始為輸入報文;
信號 |
I/O |
位寬 |
描述 |
系統介面信號 |
|||
i_sys_clk |
I |
1 |
系統時鐘,125Mhz |
i_rst_n |
I |
1 |
硬複位,低有效 |
輸入介面信號 |
|||
i_sop_in |
I |
1 |
輸入報文頭指示信號,高有效 |
i_eop_in |
I |
1 |
輸入報文尾指示信號,高有效 |
i_vld_in |
I |
1 |
輸入報文數據有效信號,高有效 |
i_data_in |
I |
8 |
輸入報文數據 |
輸出介面信號 |
|||
o_sop_out |
O |
1 |
輸出報文頭指示信號,高有效 |
o_eop_out |
O |
1 |
輸出報文尾指示信號,高有效 |
o_vld_out |
O |
1 |
輸出報文數據有效信號,高有效 |
o_data_out |
O |
8 |
輸出報文數據 |
輸入介面時序
輸出介面時序
3. 項目方案設計
3.1. 項目需求
1) 輸出報文;
2) 輸出報文長度;
3) 報文與報文長度輸出滿足時序要求;
3.2. 項目方案
1) 要求輸出報文,且報文輸出在報文長度輸出之後,所以需要先對輸入報文進行緩存,根據輸入報文的位寬和長度範圍,此處選擇合適的同步FIFO即可;(如果是IC,那麼就需要自己寫FIFO,可以參考本博客的FIFO介紹)
² 這裡項目提出了第1個要求,掌握FIFO的使用。
2) 要求輸出報文長度,所以需要對輸入報文長度進行計數,並將其緩存;
² 此處有坑,若只用寄存器對長度進行緩存,存在被後續報文長度覆蓋的風險,故需要第2個FIFO對報文長度進行緩存。
3) 要求先輸出報文長度然後緊跟著輸出報文,此處需要對時序進行設計,需要掌握FIFO的讀寫時序,需要理解fpga的時鐘沿採樣。
² 理解:時鐘沿採樣及數據下一時鐘沿變化。
3.3. 項目代碼
module zmj0001( input sys_clk, input rst_n, input sop_in, input eop_in, input vld_in, input [7:0] data_in, output sop_out, output eop_out, output vld_out, output [7:0] data_out );
FPGA項目沙盤演練-基礎版報文收發(vivado2017.4)資源-CSDN文庫
當然這不是唯一的設計方案,可以先自行考慮設計及驗證。
項目重難點:
- FIFO的使用及時序的設計
- 考慮包間隔2 clk cycle
- 考慮長包+超短包的情況
時序設計可以用TimingDesigner軟體,簡單易用,需要的可以下載。
3.4. 模擬驗證
可以使用計數器來產生數據源data_in;
`timescale 1ns / 1ps module zmj0001_tb(); reg sys_clk ; reg rst_n ; reg [7 :0] data_in ; reg vld_in ; reg sop_in ; reg eop_in ; reg [11 :0] cnt ; wire sop_out ; wire eop_out ; wire vld_out ; wire [7:0] data_out ; initial begin sys_clk = 0; rst_n = 0; #100 rst_n = 1; end always #5 sys_clk = ~sys_clk; //100Mhz //用計數器來產生data_in always @(posedge sys_clk or negedge rst_n)begin if(~rst_n) cnt <= 12'b0; else if(cnt > 2048) cnt <= cnt; else cnt <= cnt + 12'b1; end always @(posedge sys_clk or negedge rst_n)begin if(~rst_n)begin data_in <= 8'b0; sop_in <= 1'b0; eop_in <= 1'b0; vld_in <= 1'b0; end else begin data_in <= 8'b0; sop_in <= 1'b0; eop_in <= 1'b0; vld_in <= 1'b0; if((cnt > 'd10 && cnt <= 'd60)|(cnt > 'd68 && cnt <= 'd668))begin data_in <= data_in + 1'b1; vld_in <= 1'b1; end if((cnt == 'd11)|(cnt == 'd69)) sop_in <= 1'b1; if((cnt == 'd60)|(cnt == 'd668)) eop_in <= 1'b1; if((cnt == 'd62) | (cnt == 'd63))begin //63 66 data_in <= data_in + 1'b1; vld_in <= 1'b1; sop_in <= 1'b1; eop_in <= 1'b1; end end end zmj0001 u_zmj0001( .sys_clk (sys_clk ), .rst_n (rst_n ), .sop_in (sop_in ), .eop_in (eop_in ), .vld_in (vld_in ), .data_in (data_in ), .sop_out (sop_out ), .eop_out (eop_out ), .vld_out (vld_out ), .data_out (data_out ) ); endmodule
具體modelsim使用及與vivado的聯合模擬,腳本編寫請參考其他博文,後續FPGA其他專欄再考慮寫相關內容。
輸入:
共4包數據,長包+超短包+超短包+長包,包間隔均為2clk cycle
data_in : 第1包:1-50的累加數;第2包:1;第3包:1;
輸出:
若包間隔<2 clk?
輸入:
輸出:
可以看到,本設計甚至支持背靠背的超短包輸入。
4. 項目收穫
- 方案設計的重要性:任何項目都是始於方案設計,前期需要花大量的功夫去理清思路,方案設計完成,代碼實現只不過是水到渠成的事情。
- 模擬的學習:通過本項目,完成了testbench的編寫,模擬驗證,是對自己設計的一次檢驗,是實際項目縮短調試時間的最佳利器。
- 對xilinx IP的使用,對datasheet的閱讀學習。
- 對時序的理解,時鐘是FPGA的心跳:任何時序操作都是發生在時鐘的跳變沿。當採樣發生在當前上升沿時刻,數據變化是發生在下一時刻的上升沿。
- 繪畫時序圖,TimingDesigner的使用。有了時序圖,代碼就很容易實現了。
5. 進階考慮
本次虛擬項目旨在用最簡單的例子帶大家瞭解數字邏輯設計的一些基本概念,所以很多東西是沒有考慮的。比如:
- 如果包間隔小於2個時鐘周期怎麼辦? -----握手與反壓
- 如果輸入數據有錯誤怎麼辦? -----CRC校驗
- 如果需要跨時鐘域傳輸呢? -----CDC處理
- 報文只是簡單轉發,如果需要做處理呢?-----數據處理
- ...
所以,下一篇將沿著這個思路展開,進階版的虛擬項目,同樣可以作為公司的入職培訓。
咱們下期見!