设计思路:
设计代码:
module led_run( clk,rst,led ); input clk,rst; output reg [7:0] led = 8'b0000_0001; reg [24:0] cnt; parameter TIME = 24_999_999; always@(posedge clk or negedge rst) if(!rst) cnt <= 0; else if (cnt == TIME) cnt <= 0; else cnt <= cnt + 1; //通过移位实现 always@(posedge clk or negedge rst) if(!rst) led <= 8'b0000_0001; else if(cnt == TIME) begin if(led == 8'b1000_0000) led <= 8'b0000_0001; else led <= (led<<1); //led每0.5s左移一次 end else led <= led; endmodule
验证tb:
`timescale 1ns / 1ps module led_run_tb(); reg clk,rst; wire [7:0] led; led_run u_led_run( .clk(clk), .rst(rst), .led(led) ); initial clk = 1; always #10 clk = ~clk; initial begin rst = 0; #201; //错开时钟边沿 rst = 1; #5_000_000_000;//8个led,每个0.5s
$stop;
end endmodule
波形验证:
注:为了提高设计开发效率,在仿真验证的时候没必要真的用0.5s跑,比如本设计在实现时设置为500us,这样可以节省时间。
仿真结果:
可以观察到8个led依次闪烁,证明设计符合要求。
方法二:
直接用代码
led <= {led[6:0],led[7]};
就可以省略两个嵌套if的判断。
方法三:
使用上一节提到的38译码器完成设计,具体代码如下:
这里注意两点:
- 这里是将cnt设置为3位,然后调用底层模块,所以要注意这里的例化格式
- 由于在底层模块已经对reg out 了,因此这里的led就不能再reg了,要把上面的reg删掉!!