赞
踩
verilog主要的模块之间都是并行执行的,例如各个always之间 如果你在一个always中要对a赋值,而在另一个always中要使用a的值,这时候就要注意了,两者并行的,处理先后不能确定。 你当前处理的a,是这个时钟被赋值的还是上一时钟被赋值的,意义可能完全不同,这就是并行需要考虑的问题。
而在always内部,一般使用了begin…end。这里面的内容都是顺序执行的,比如b=a; c=b,先执行一条,再执行下一条,那就是c=a了 如果里面有两组if/else,就是先执行前一组,再执行后一组。但是如果是非阻塞,那就要特殊对待,多个非阻塞赋值是在一个块结束时一起执行的,比如b<=a; c<=b,那就跟之前不同了,当执行c<=b 时b还没有变化成a的值,因此 这个赋值的结果是b被赋值前的值,这两条语句其实是独立的、并行的。好处是放得先后顺序没关系,只要在一个块内,随便写。这个不是很好理解,怎么说了begin…end之间是顺序,到了非阻塞就又变成并行执行的呢。 不好理解也没办法, 另外掌握几条原则:组合逻辑用阻塞赋值,时序逻辑用非阻塞赋值,同一个模块中不要既用阻塞又用非阻塞…
掌握一条思路:verilog是硬件,是电路。所以调试的时候不能设置断点 所以所有模块都是并行,毕竟一上电整个板子都有电了,你不能说让它没电就没电,但是你可以在代码中加个控制,让它到了特定时候才干活。
看完上面的就知道为啥run-all会让s_num加1(明明没有到1s,却自增了1)
verilog代码:
- //2023/3/29 lzp
- //秒计数器 0-9循环, 24M HZ
- `timescale 1ns/10ps
- module s_counter(clk, res, s_num);
- input clk, res;
- output[3:0] s_num; //输出的秒\
-
- parameter frequency_clk=24; //24M Hz;
-
- reg[3:0] s_num;
- reg[24:0] con_t; //24M可以用25位2机制数来存,秒脉冲分频计数器;
- reg s_pulse; //秒脉冲尖;
-
- always@(posedge clk or negedge res) begin
- //计数
- if(~res) begin
- con_t<=0;
- s_pulse<=0;
- s_num<=0;
- end
- else begin
- if(con_t == frequency_clk*1000000-1) begin
- con_t<=0;
- end
- else begin
- con_t<=con_t+1;
- end
-
- //脉冲尖
- if(con_t==0) begin
- s_pulse<=1;
- end
- else begin
- s_pulse<=0;
- end
-
- //秒自增
- if(s_pulse) begin
- if(s_num == 9) begin
- s_num<=0;
- end
- else begin
- s_num<=s_num+1;
- end
- end
- end
-
- end
-
- endmodule
-
- //秒计数器,testbench
- module s_counter_tb;
- reg clk, res;
- wire[3:0] s_num;
-
- s_counter s_counter(.clk(clk), .res(res), .s_num(s_num));
-
- initial begin
- clk<=0;
- res<=0;
- #10;
- res<=1;
- #1000;
- $stop;
- end
-
- always#(5) clk=~clk;
- endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。