从本节开始我们讨论Verilog语法中可综合代码的基本知识。模块是实现一定功能的Verilog代码块,例如可以将一个加法、乘法、除法、多路选择器等都可以作为一个模块,一个模块可以嵌入到其他模块中,较高级别的模块可以使用输入输出端口与较低模块之间通信。简单的说就像PCB板上的IC芯片可以利用PCB上的布线与其他芯片相连满足一定的功能。
如图1所示,模块必须包含在“module”和“endmodule”关键字内,即module是起点标志、endmodule是结束标志,所有的操作只能在两者之间进行。
①、模块必须有模块名,模块名要放在module关键字的后面,中间用空格分开。模块名有一定的命名规则,这个可以百度搜一下就好,这里要说的是模块名最好取个能清晰表达该模块功能的名字,在以后的复杂系统中例化该模块时容易理解模块的功能,便于阅读代码。
②、模块名后面的小括号里是用于声明端口的,当端口个数大于1个时,两个端口之间用逗号隔开(特别注意所有端口必须在英文环境下输入),最后一个端口后面没逗号。
③、括号里面的操作需要定义成输入类型、输出类型还是三态等,输入类型的关键字“input”、输出类型的关键字“output”、三态类型“inout”。
④、Verilog中主要有两种变量类型,wire型和reg型,wire可以理解成FPGA内部的布线将两个硬件连接起来,reg可以理解成寄存器,可以存储数据的。对于输入信号而言默认是wire类型,可以不做说明;输出信号如果是reg型必须声明;
⑤、如果数据位宽是1bit可以不用定义,如果是多位bit需要在中括号"[]"中定义位宽,比如:
"reg[8-1:0] a;"表示数据类型是reg型、位宽是8bit变量a。图1中表述了模块的基本内容框架,就是一套模板,直接套用就好。
图 1
有了上述的准备工作,接下才是模块的核心部分:逻辑功能的定义。
1、assign声明语句(连续赋值)
“assign”,后面再加一个方程式即可,如图2所示。
图 2
2、always过程块
模板如下面的代码所示,当敏感信号表达式的值改变时候,就执行一遍块内语句,同时always过程块是不能够嵌套使用的。即always块中不能再出现always,在过程块中用 if语句和case语句描述逻辑功能。
always @()begin//过程赋值//if语句 //case语句end
建模的依据不同,可以分成组合逻辑和时序逻辑两个模型。
组合逻辑模型:敏感信号里用“*”表示块里出现的所有敏感信号,在这里我们只实现组合逻辑,与时钟无关。在组合的RTL代码中使用阻塞赋值“=”,使用阻塞赋值方式对一个变量进行赋值时,此变量的值在赋值语句执行完后之后就立即改变。
always @(*)begin dout = a + b ;//--注释end
时序逻辑模型:敏感信号里我们只有时钟上升沿信号或者复位的下降沿信号,即时钟的上升沿来一次块里的代码执行一遍,按照时间的脉动运行。在时序块的RL代码中使用非阻塞赋值“<=”。非阻塞赋值在块结束后才完成赋值操作。后面我们会对这两种模型进行仿真和综合出的电路详细的分析。
always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin //-- end else begin //-- endend
得到金句:努力工作很重要,但我觉得每个人都害怕承认运气有多重要。--《赛未点》 引用得到APP产品得到金句。