实用模型以及方法总结
1. 一种采集信号上升沿的方法
reg a_0;
reg a_1;
always @(posedge clk)
begin
a_0 <= a;
a_1 <= a_0;
end
assign pos_a = (~a_1) & a_0;
2. 一个很好用的分频小技巧
reg[N - 1:0] count;
always @(posedge clk)
if(reset)
count <= 0;
else
count <= count + 1;
always @(count[N - 1],count[N - 2] //得到一个clk/2^(N-2)的时钟频率
begin
....
end
3. 一个好用的节拍器(我称它为数据延时器)
module dapaiqi(clk,data,data1);
input clk;
input data;
output data1;
reg data0;
reg data1;
always@(posedge clk)
begin
data0<=data;
data1<=data0;
end
endmodule
4. 不调用IP核实现乘法运算的一种方法
top_60 <= {top,6'b000000} - {top,2'b00};//60 = 2^6 - 2^2
巧妙的拼接运算实现了top*60
5.提供一种写testbench的时候经常会用到0/1随机赋值的方法
reg a;
always
begin
a = {$random} % 2;
end
注意事项
1. always块里面的非阻塞赋值是同时进行的,这和c语言的串行执行的思维完全不一样,有时候看程序会看的很迷糊,如果用并行的思想,很有可能一瞬间豁然开朗,还有就是各变量在赋值的时候赋的都是时钟沿前一瞬间的值,但是检测的是触发条件前一瞬间的值
2. FPGA内的寄存器,如果不赋初值,默认为0;
但是在仿真软件中(如modelsim),寄存器如果不赋初值,默认为不dao定态(x),仿真是无法进行的。
因为存在门延时,所以data1的数据不是理想的延后两个时钟周期
3. 对于循环变量只能用integer,今天用了reg型变量作为循环遍量,电脑内存直接爆炸,虽然不知道啥原因。
4. parameter 和 localparam的区别
parameter可用作在顶层模块中例化底层模块时传递参数的接口
localparam的作用域仅仅限于当前module,不能作为参数传递的接口
5. 使用FIFO或者其他IP的时候注意reset复位信号很有可能是高电平复位,所以需要把复位信号取反再连接到IP模块例化的复位信号上
6. ILA的IP使用有关注意事项
- Monitor Type 监控类型:也就是选择接口类型,这里选Native
- Number of Probes 探针数量:建议一个信号对应一个probes。
- Sample Data Depth: 用于设置采样深度,也就是采样点数,在每个采样时钟下,ILA 都会将捕获到的探针信号的值送入FPGA的RAM 中。
- Probe Width:用于设置每个信号的深度,也就是位宽