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独立