FPGA实现序列检测(训练testbench写法)
電路設計與狀態機
-
FPGA的基礎概念
Cyclone IV器件采用了M9K的嵌入式塊RAM,即每個嵌入式存儲器塊的容量為9216bit。4個PLL,一個PLL可以最多支持5路輸出。
cyclone IV E中,除了EP4CE6和EP4CE10兩個容量等級的器件只含有兩個PLL單元以外,其它容量的器件均含有4個PLL。
M9K存儲器,見名思意,該存儲器每個M9K,存儲容量是9Kbit,
這些存儲器可以配置為FIFO,RAM等
18*18硬件乘法器,這些硬件乘法器的輸入位寬都是18位。
-
序列檢測
功能:實現檢測序列:Welcom
為什么這些資源為0呢,因為我們的輸出,還沒有被賦予值,這時候資源就是0.
好,下面我們來正式看如何檢測序列;
module Sequence_detection ( input clk, input rst_n, input data_valid,//信號輸入有效標志信號 input [7:0]data, output [3:0]num,//計數檢測到多少個序列 output reg flag//檢測完畢標志信號 );reg [2:0] state=3'b0; reg [3:0] counter=4'b0; localparam CHECK_W=3'd0; localparam CHECK_E=3'd1; localparam CHECK_L=3'd2; localparam CHECK_C=3'd3; localparam CHECK_O=3'd4; localparam CHECK_M=3'd5;always @(posedge clk or negedge rst_n) beginif(!rst_n)beginstate<=CHECK_W;counter<=4'b0;flag<=1'b0;endelse if(data_valid)begincase(state)CHECK_W://檢測Wbeginif(data=="w")beginstate<=CHECK_E;flag<=0;endelsebeginstate<=CHECK_W;flag<=0;endendCHECK_E://檢測ebeginif(data=="e")state<=CHECK_L;else if(data=="w")state<=CHECK_E;elsestate<=CHECK_W;endCHECK_L://檢測lbeginif(data=="l")state<=CHECK_C ; else if(data=="w")state<=CHECK_E;elsestate<=CHECK_W;endCHECK_C://檢測cbeginif(data=="c")state<=CHECK_O;else if(data=="w")state<=CHECK_E;elsestate<=CHECK_W;endCHECK_O://檢測obeginif(data=="o")state<=CHECK_M;else if(data=="w")state<=CHECK_E;elsestate<=CHECK_W;endCHECK_M://檢測mbeginif(data=="m")begincounter<=counter+1;flag<=1'b1;state<=CHECK_W;endelse if(data=="w")state<=CHECK_E;elsestate<=CHECK_W;enddefault: state<=CHECK_W;endcaseendelse beginstate<=CHECK_W;endend assign num=counter; endmodule測試文件testbench:
`timescale 1 ns/ 1 ns `define clk_period 20 module Sequence_detection_vlg_tst(); reg clk; wire [7:0] data; reg data_valid; reg [511:0] reg_shift; reg rst_n; // wires wire flag; wire [3:0]num;// assign statements (if any) Sequence_detection i1 (.clk(clk),.data(data),.data_valid(data_valid),.flag(flag),.num(num),.rst_n(rst_n) ); initial begin clk=1; end always #(`clk_period/2) clk=~clk; wire [511:0] data_to_send ; assign data_to_send="whwecomdwhusardwhuwelcomwhusdardwwelcomdwhusdardwhusdardwhusdard";always @(posedge clk or negedge rst_n) begin if(!rst_n) reg_shift<=512'd0; else if (data_valid) reg_shift<=reg_shift<<8; elsereg_shift<=data_to_send; endassign data=(data_valid==1)?reg_shift[511:504]:8'bz;initial begin rst_n=0; data_valid=0; #(`clk_period*20); rst_n=1; #(`clk_period*20); data_valid=1; #(`clk_period*64); data_valid=0; #(`clk_period*10); $stop; end endmodule
首先,代碼不用解釋了,入了門的,都看得懂,下面說說一些注意的地方:
3. 快捷鍵的使用:ctrl+F查找
ctrl+H替換
4. 報告沒有消耗邏輯資源,說明輸出端口沒有被賦予值。
5.
狀態機每一個都返回W狀態和E狀態,為什么會返回E狀態呢?
因為,比如WELWELCOM,如果在L狀態了,發現下一個狀態是W,不是我們要的C,于是,下個時鐘,跳轉到W狀態,但此時,在W狀態,就會檢測是否此狀態是否是E,發現不符合,就會出現漏檢,因為出現一個跳轉時鐘,耽誤了,所以導致出現漏檢。(因為我們送來檢測的時序是,一個時鐘,檢測一次)
所以,我們在每個狀態,我們還要檢測一下是否此字母是W,如果是W,就跳轉到E,避免出現漏檢。
我們可以看到L跳轉到E的狀態是1110111==h77
我們查一下ASCII ,正是我們小寫的w
另外字也可以賦予到寄存器中,這也是我以前不太知道的,我以為只有數能賦予到寄存器中,字符根據ASCII碼表。
我們對其是打雙引號。data定義為8個位。
Testbench寫法
宏定義
在module外定義宏 `define a 8 //無等號無分號
此處我們宏定義時鐘周期20ns
`define clk_period 20
我們在tb里面寫的clk_period都寫的是‘clk_period
輸入都是reg???!!
對于我們這個也不是輸入就是定死的reg類型,這也是一般初學者的誤區。
其實我們寫TB就是給輸入寫值,把它當成寄存器來寫,所以我們都是把實例中的input,在TB里面寫成reg,這樣我們就能對其賦值。
但是,如果我們在TB里面,自己定義個別的寄存器,然后,assign到如上圖所示的data,我們就不需要非得把data變成reg
initial的寫法
其他就按照always@(posedge or negedge)來寫即可
wire也可賦予初值
modisim遇見no design不要怕
選中simulate就可以查看到TB的語法錯誤了。
另外最后提醒一點,更改了頂層文件的輸入輸出端口過后,一定要記得更改TB的輸入輸出端口。
總結
以上是生活随笔為你收集整理的FPGA实现序列检测(训练testbench写法)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SOPC第四课 按键中断
- 下一篇: verilog基础-状态机之FPGA独立