首先记住:Verilog HDL 默认的类型是 wire 型。 内部电路模块中:输入的输入端口:线网型,输出的驱动端口:线网型、寄存器型。 外部连接电路模块时:连接输入端的:线网型、寄存器型,连接输出端的:线网型。
我们通过一个【优秀】的案例来看看【错误】代码的编译
//2输入与门电路 module TEST(a,b,c,d,o1,o2); input a,b,c,d; output o1,o2; reg a,b,c,d; reg o1; wire o2; assign o1=c&&d; //与门实现形式1 always@(a or b) //与门实现形式2 begin if(a) o2=b; else o2=1'b0; end endmodule编译后出现下图错误:
可以看出 a、b、c、d 不能声明为 reg 型(因为这四个都是 input 输入端口)
那么我们就把 reg a,b,c,d; 这一句注释掉就变成了 wire 型(Verilog HDL 默认的类型就是 wire 型),重新修改后编译得到:
可以看出 assign 这种连续赋值语句,被赋值的数据类型必须是 wire 型。 在 always 这种过程赋值语句,被赋值的数据类型必须是 reg 型。
那么我们把 reg o1; wire o2;改成 wire o1; reg o2; 重新修改后编译得到: 完结,撒花✿✿ヽ(°▽°)ノ✿
刚刚在思考一个问题,下面这行代码中, if 后的圆括号内, 程序会把Q赋值成 16’hE 呢?还是只进行小于等于的判断?
always@(*) if(Q<=16'hE) Q<=16'h0;实践是检验真理的唯一标准,通过一个小代码测试后(对Verilog HDL中的小于等于号的检验测试),得知:在if () 圆括号内,程序只进行了小于等于的判断,并没有赋值。 ---------------------------------------------------分割线------------------------------------------------------------ 2020/11/4更新: 小于等于号后的变量后是分号;的就是赋值语句。
当有多条赋值语句紧紧连续的时候,阻塞赋值与非阻塞赋值才体现出区别。
阻塞赋值 =: 写在前面的语句先执行,写在后面的语句后执行,也就是说,它是顺序执行的。一般用于组合逻辑电路。非阻塞赋值 <=:写在前面的语句与后面的语句同时执行,也就是说,它是并行执行的,跟书写顺序没有关系。一般用于时序逻辑电路。当仿真上面代码时,可选设计端口如下所示,仅有in,out两个,并没有out_temp、q这些其他变量:
这是因为,在设计Verilog HDL语言时,module 后括号内容的 端口列表 中并没有出现out_temp、q 这些其他变量。
将第一行更改为:
module TEST(in,out,out_temp);出现报错:
可见,out_temp 这个端口并没有声明端口类型是输出( output)、输入( input)、 还是双向端口( inout )。
再将代码修改,最终代码为:
module TEST(in,out,out_temp); input wire in; output reg out,out_temp; reg [1:0] q; always@(posedge in) begin q=q+1; if(q==3) begin q<=0; out_temp=~out_temp; out=~out; end end endmodule编译成功,如下图所示,可选设计端口也包括了out_temp。
---------------------------------------------------分割线------------------------------------------------------------ 2020/12/18更新: 一些内部端口也可以在不声明成input、output的情况下,添加至仿真列表中,但是有些可能不会出现在最终的仿真报告中。(Quartus9.0环境测试) 故最好应该先添加至仿真列表,再观察仿真报告中是否会出现响应端口,若未出现,则应在源文件中声明并放在输入输出端口列表。
当不考虑阻塞赋值和非阻塞赋值时。 在 Verilog HDL中,不同语句块之间是并行执行的(当其有效时),在同一语句块中的子语句块相互间也是并行执行的。 当这两个 always 语句响应的敏感信号都发生变化时,两个always语句是并行执行的。