这次学习跑马灯,使用四种方法实现,其中新的语法包括:移位(<<),模块复用和参数化。
如想要8个灯循环亮灭,可以使用3-8译码器,通过3位寄存器来控制8个灯输出,这里就不必再写一遍3-8译码器了(当然我尝试了,也可以写)
always@(*)
case(counter2) //{a,b,c}是一个三位的信号,位拼接
3'b000: led <= 8'b0000_0001;
3'b001: led <= 8'b0000_0010;
3'b010: led <= 8'b0000_0100;
3'b011: led <= 8'b0000_1000;
3'b100: led <= 8'b0001_0000;
3'b101: led <= 8'b0010_0000;
3'b110: led <= 8'b0100_0000;
3'b111: led <= 8'b1000_0000;
endcase
模块复用
引用的话,需要把引用的文件放到当前文件夹下,如把decorder_3_8.v文件从相同位置复制到D:\vivado_project\led_run\led_run.srcs\sources_1\new处,然后在Vivado中添加source即可,语句格式:
decorder_3_8 ddd(
.a(counter2[2]),
.b(counter2[1]),
.c(counter2[0]),
.out(led)
);
其中注意的是,当底层文件out已经定义为reg时,顶层文件led不需要再定义为reg。
参数化
另外,当把某个量定义为参数后,可以在仿真文件中引用为其他值,实现仿真和跑板不一样参数同时实现,源文件:
parameter MCNT = 24999999;
仿真文件引用:
led_run ledtry(
.Clk(Clk),
.Reset_n(Reset_n),
.led(led)
);
defparam ledtry.MCNT = 2499;
或者
led_run
#(
.MCNT(2499)
)
ledtry(
.Clk(Clk),
.Reset_n(Reset_n),
.led(led)
);
仿真结果中MCNT就是2499.
例如,可以定义一个led闪烁的模块,然后再来一个模块引用并更改相关参数,实现8个灯以不同频率亮灭。
另外,赋值时使用的<= 和=的区别:
<=:非阻塞赋值,时序逻辑,看到posedge用;
=:阻塞赋值,组合逻辑(什么意思),看到assign用;
注意一个always块里面只能有一种赋值方法,这些是查到的,有补充的话再说吧。