目录
Verilog笔记1
本部分总结于视频教程:特权同学《Verilog边码边学》基于Xilinx FPGA的Verilog编码、仿真与调试基础教程
组合逻辑和时序逻辑电路
Verilog中组合逻辑电路的实现方式:
- 使用:
always@([敏感信号1] or [敏感信号2] or ...)begin
...(电路实现代码)
end
或:
always@(*)begin
...
end
建议使用阻塞赋值=。不管是组合还是时序电路,always中被赋值的信号必须为reg。若使用always表示组合电路,则其中的reg信号实际上在内部仍然是wire,需要定义成reg是语法上的要求。
2. 使用assign,被赋值的信号需为wire
3. 用于简单逻辑,如果过于复杂可能出现信号毛刺
时序逻辑实现方式:
使用:
always@(posedge clk)begin
...
end
建议使用非阻塞赋值<=,各种信号只可能在clk的上升沿发生变化
理解FPGA的并行性
FPGA的并行性:不同always、assign之间是并行的;同一always中,位于同一begin…end之间的不同语句也是并行的。
仿真测试脚本中,initial begin…end内的语句是顺序执行的,而非并行
同步复位和异步复位
异步复位中,变量值恰好在复位时刻改变;同步复位中,变量在复位之后第一个clk上升沿改变。推荐使用同步复位,因为异步复位中的rst_n导致变量改变时刻的不一致性;异步复位占用更多系统资源;一般的应用中允许同步复位的滞后性。
脉冲边沿检测
如图,在时序always语句中,并行地令preg1<=pulse; preg2<=preg1; pos_en<=preg1 & ~preg2, 即检测到了pulse的上升沿。
FPGA的模块化设计
模块是FPGA基本单元,相当于C语言中的函数。
一般,顶层模块接口直接对应到FPGA引脚,与外部设备交互。上层模块将下层模块例化,通过下层模块的端口定义,实现上下层之间的数据交换。
端口有input output inout三种类型,input 和 inout 只能为wire,不能为reg;output可以为wire或reg
模块定义示例:
例化示例:
通常在上层模块中,将被例化模块的端口信号都定义为wire
genereate语法
generate用于重复进行某些操作,语句格式:
genvar i;
generate
for(i=0;i<[循环次数];i=i+1) begin
...[被重复执行的语句]
end
endgenerate
其中,[循环次数]需要是常量,在编译时就确定的
总结:编译器会将generate语句,替换为若干格式相同的代码段,再下载到芯片中。
if语句格式:
if() begin
...
end
else if() begin
...
end
else begin
...
end
与C语言类似,区别是把大括号变成了begin…和end。如果只有一条语句,可以省略begin和end。缩进和换行符可以随意增加或删除。
case格式:
case([数值或表达式])
[常量1]:语句1;
[常量2]:语句2;
...
default:;
endcase
与if同理,如果case某分支后的语句多于一行,则需要在这些语句前后加上begin和end
Verilog笔记2
本部分总结于视频教程:6小时掌握Verilog语法
基本概念
综合:把代码变成电路的过程
可综合设计:可变为电路的代码
FPGA仿真:下载前仿真,可以避免bug,需要编写测试文件
Verilog语法中大部分用于仿真测试,少部分用于电路设计
常见Verilog关键词和运算符
模块相关
模块Module:组成Verilog程序的基本单元,相当于一个芯片
模块例化格式:
子模块名称 母模块内的例化名(
.子模块引脚 (母模块引脚),
.子模块引脚 (),//悬空引脚
……
.子模块引脚 (母模块引脚)
);
信号相关
信号类型:主要包括线网类型和寄存器类型
在always中设计的信号都用reg定义,其他用wire
Wire:通常由assign赋值
若信号位宽小于运算结果长度,则截取结果的低位部分
若信号位宽更大,则在高位补零
位宽误差会引起结果错误,尤其是涉及到负数时
assign和always语句
程序语句:assign和always
assign:赋值语句,相当于连线
不定态和高阻态、三态门
不定态:二进制表示的数值中可以用x或z,它们用来表示设计意图或用于仿真。
x表示不定态,即信号值无关紧要。
尽量少用不定态,用din=4’b1000 || 4’b1010代替4’10x0。
实际上综合器或仿真器会把x替换为用||表示。
Z表示高阻态,即不驱动这个信号,常用于三态门接口