1、时钟分频实现12位流水灯
module led(
input clk, //输入时钟
output [11:0] led //led输出
);
reg[11:0] led_state=12'b0000_0000_0001;//led初始状态
reg[31:0] divclk_cnt=0; //32为计数器
reg divclk=0; //分频时钟
assign led=led_state;
parameter halfduty_cntvalue=1;//0,1为半个周期计两个数,一个周期计4个数,这是4分频
always@(posedge clk)
begin
if(divclk_cnt == halfduty_cntvalue)//分频计数
begin
divclk = ~divclk;
divclk_cnt=0;
end
else
divclk_cnt = divclk_cnt+1;
end
/*每个上升沿反转一次,这是2分频,与上面的4分频只能留一个
always@(posedge clk)
begin
divclk = ~divclk;
end
*/
always@(posedge divclk)
begin
if(led_state[11]==1)
led_state=12'b0000_0000_0001;
else
led_state=led_state<<1;
end
endmodule
testbench 如下:
module led12_fixture;
// Inputs
reg clk;
// Outputs
wire [11:0] led;
// Instantiate the Unit Under Test (UUT)
led uut (
.clk(clk),
.led(led)
);
initial begin
// Initialize Inputs
clk = 0;
// Wait 100 ns for global reset to finish
#10;//这里没有写复位信号,可以自行添加
// Add stimulus here
end
always #10 clk=~clk;
endmodule
仿真结果如下:
2、通过计数器累加实现4位流水灯
module jishuqi(
input clk,
input rst_n,
output reg[3:0] led_o
);
reg[2:0] cnt;//这里为什么计数这么少呢?因为软件默认仿真时长只有1us,计数值一大就
//会出现只有第一个状态,并不跳变的情况。这个鬼玩意困扰了我一天,我一直以为是我的程
//序哪里出错了,后来我才发现是这个仿真时长限制的问题。如果要设置较大的计数值一定要
//修改仿真时长
always@(posedge clk or negedge rst_n)//计数器计数5个上升沿
begin
if(!rst_n)
cnt<=0;
else if(cnt==4)
cnt<=0;
else
cnt<=cnt+1;
end
always@(posedge clk or negedge rst_n)//LED控制逻辑
begin
if(!rst_n)
led_o<=4'b0001;
else if(led_o==4'b1000 && cnt==4)
led_o<=4'b0001;
else if(cnt==4)
led_o<=led_o<<1;
end
/*这是LED控制逻辑的另一种实现方式
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
led_o<=4'b0001;
else if(cnt==4)
led_o<={led_o[2:0],led_o[3]};//位拼接实现循环移位
else
led_o<=led_o;
end
*/
endmodule
testbench 如下:
module jishuqi_tb;
// Inputs
reg clk;
reg rst_n;
// Outputs
wire [3:0] led_o;
// Instantiate the Unit Under Test (UUT)
jishuqi uut (
.clk(clk),
.rst_n(rst_n),
.led_o(led_o)
);
initial begin
// Initialize Inputs
clk = 0;
rst_n = 0;
// Wait 20 ns for global reset to finish
#20;
rst_n = 1;
// Add stimulus here
end
always #10 clk=~clk;
endmodule
仿真结果如下:
注意图中红圈处的移位跳变。