赞
踩
声明:案例和代码来自小梅哥课程,本人仅对知识点做做笔记,如有学习需要请支持官方正版。
Verilog线性序列机点灯案例(一)
Verilog线性序列机点灯案例(二)
Verilog线性序列机点灯案例(三)
Verilog线性序列机点灯案例(四)
使用8个拨码开关控制一个LED灯,每个拨码开关负责控制0.25秒的时间,开关为1时亮,开关为0时灭。
举例:
10101010就是亮0.25秒,灭0.25秒,如此循环
10111101就是亮0.25秒,灭0.25秒,亮1秒,灭0.25秒,亮0.25秒,如此循环
counter0计数器每计数满0.25秒就向counter1计数器加1,
counter1计数器从0到7计数,
led灯根据当前counter1计数器的值,选中对应的拨码开关进行输出,用软件的写法就是
led = sw[counter1]
module led_ctrl2( clk, rst_n, led_out, sw ); input clk; input rst_n; input [7:0] sw; output reg led_out; parameter MCNT = 12500_000 - 1; reg [26:0] counter0; //第一个always块负责counter0 always@(posedge clk or negedge rst_n) begin if(!rst_n) counter0 <= 0 ; else if(counter0 == MCNT) counter0 <= 0; else counter0 <= counter0 + 1'd1; end reg [2:0] counter1; //第二个always块负责counter1 always@(posedge clk or negedge rst_n) begin if(!rst_n) counter1 <= 0 ; else if(counter0 == MCNT) begin counter1 <= counter1 + 1'd1; end else counter1 <= counter1; end //第三个always块负责根据counter1决定led_out //每0.25秒切换一个拨码输出 always@(posedge clk or negedge rst_n) if(!rst_n) led_out <= 0; else begin case(counter1) 0:led_out <= sw[0]; 1:led_out <= sw[1]; 2:led_out <= sw[2]; 3:led_out <= sw[3]; 4:led_out <= sw[4]; 5:led_out <= sw[5]; 6:led_out <= sw[6]; 7:led_out <= sw[7]; default:led_out <= led_out; endcase end endmodule
`timescale 1ns / 1ns module tb_led_ctrl2(); reg clk; reg rst_n; wire led_out; reg [7:0] sw; initial clk = 1; always #10 clk = ~clk; led_ctrl2 led_ctrl2_inst0( .clk(clk), .rst_n(rst_n), .sw(sw), .led_out(led_out) ); defparam led_ctrl2.MCNT = 12500 - 1; initial begin rst_n = 0; sw = 8'b1010_1010; #201; rst_n = 1; #4_000_000; sw = 8'b0000_0001; #4_000_000; sw = 8'b1111_0001; #20_000_000; $stop; end endmodule
总结这两张图可以看出来,counter1是在每次counter0计满12499时进1,即counter1每个值维持的时间是counter0等于0~12499,是0.25s,而led_out依赖于counter1,比counter1延迟一拍,所以led_out每个值维持时间也是0.25秒,时序正确。
Verilog线性序列机点灯案例(三)(小梅哥课程)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。