本文来自《小梅哥FPGA视频》的笔记整理
不要眼高手低,一定一定要实践,自己动手去敲一遍!!!
时序逻辑电路是指电路任何时刻的稳态输出不仅取决于当前的输入,还与前一时刻输入
形成的状态有关。这跟组合逻辑电路相反,组合逻辑的输出只会跟目前的输入成一种函数关
系。换句话说,时序逻辑拥有储存元件来存储信息,而组合逻辑则没有。
计数器的核心元件是触发器,基本功能是对脉冲进行计数,其所能记忆脉冲最大的数目
称为该计数器的模/值。 计数器常用在分频、定时等处。计数器的种类很多,按照计数方式的
不同可以分为二进制计数器、十进制计数器以及任意进制计数器,按照触发器的时钟脉冲信
号来源可分为同步计数器与异步计数器。按照计数增减可分为加法计数器、减法计数器以及
可逆计数器。
现象:500毫秒间隔闪烁(低电平点亮)。我使用的板子是ACX720,晶振为50MHZ,20ns为一周期。
module led_flash(
clk,
reset_n,
led
);
input clk;
input reset_n;
output led;
reg led;
wire end_flag;
//计数器
parameter ms500_CNT=25000000;//500 000 000 / 20 = 25000000
reg [24:0]counter;
//时钟上升沿有效,复位检测下降沿
always@(posedge clk or negedge reset_n)begin
if(!reset_n)
//时序逻辑赋值 <=是非阻塞赋值的意思
counter<=0;
else if(end_flag)
counter<=0;
else
counter<=counter+1'b1;
end
assign end_flag= (counter==ms500_CNT-1);
always@(posedge clk or negedge reset_n)begin
if(!reset_n)
led<=1;//上电 亮
else if(end_flag)
led<=~led;
end
endmodule
上板的话500ms完全是可以的,不过如果仿真依旧是500ms,属实没有必要,仿真时我们只需要在激励文件中将设计文件中的参数改为250,也就是5us,led输出反转一次
`timescale 1ns/1ns
module led_flash_tb;
reg clk;
reg reset_n;
wire led;
led_flash
#(
//改变模块里面的参数
.ms500_CNT(250)
)
led_flash(
.led(led),
.clk(clk),
.reset_n(reset_n)
);
initial clk =1;
always #10 clk = !clk;
initial begin
reset_n =0;
#201;
reset_n=1;
#50000;
$stop;
end
endmodule
八个LED灯以一秒的延迟轮流点亮,我使用的板子是ACX720,晶振为50MHZ,20ns为一周期。
module led_run(
clk,
reset_n,
led
);
input clk;
input reset_n;
output led;
reg [7:0] led;
//计数器 1s
parameter MCNT=50000000;//1000000000 / 20 = 50000000
reg [25:0] counter;
wire end_cnt;
always@(posedge clk or negedge reset_n)begin
if(!reset_n)
counter<=0;
else if(end_cnt)
counter<=0;
else
counter<=counter+1'b1;
end
assign end_cnt=(counter==MCNT-1);
//流水灯 使用拼接符
wire add_led;
always@(posedge clk or negedge reset_n)begin
if(!reset_n)
led<=8'b0000_0001;//初始 led0亮,其余led灭
else if(add_led)
led<={led[6:0],led[7]};//使用拼接,来切换led
else
led<=led;
end
assign add_led = end_cnt;
/**
//流水灯 使用移位运算符
wire add_led;
alway@(posedge clk or negedge reset_n)begin
if(!reset_n)
led<=8'b0000_0001;//初始 led0亮,其余led灭
else if(add_led)
led<=led<<1;
else
led<=led;
end
assign add_led=end_cnt;
*/
endmodule
使用3_8译码器来实现流水灯
注意:在使用38译码器模块之前,需要将之前写好的38译码器模块代码复制到流水灯工程内,并且在软件内部添加到流水灯工程中,才可以使用。
3_8译码器的链接------》FPGA_38译码器_安赫’的博客-CSDN博客
module led_run2(
clk,
reset_n,
led
);
input clk;
input reset_n;
output [7:0] led;
//计数器 1s
parameter MCNT=50000000;//1000000000 / 20 = 50000000
reg [25:0] counter;
wire end_cnt;
always@(posedge clk or negedge reset_n)begin
if(!reset_n)
counter<=0;
else if(end_cnt)
counter<=0;
else
counter<=counter+1'b1;
end
assign end_cnt=(counter==MCNT-1);
//流水灯 使用3_8译码器
reg [2:0] decoder_3_8_r;
wire add_led;
always@(posedge clk or negedge reset_n)begin
if(!reset_n)
decoder_3_8_r<=3'b000;//初始 led0亮,其余led灭
else if(add_led)
decoder_3_8_r<=decoder_3_8_r+1'b1;
else
decoder_3_8_r<=decoder_3_8_r;
end
assign add_led=end_cnt;
//使用38译码器
decoder_3_8 decoder_3_8(
.a(decoder_3_8_r[2]),
.b(decoder_3_8_r[1]),
.c(decoder_3_8_r[0]),
.out(led)
);
endmodule
仿真时使用5ms,切换led灯,所以MCNT=250
`timescale 1ns/1ns
module led_run_tb;
reg clk;
reg reset_n;
wire [7:0] led;
//使用隐身例化
led_run
#(
.MCNT(250)
)led_run8(
clk,
reset_n,
led
);
initial clk=1;
always #10 clk=~clk;
initial begin
reset_n=0;
#21;
reset_n=1;
#50000;
$stop;
end
endmodule
3_8译码器流水灯的激励文件
`timescale 1ns/1ns
module led_run2_tb;
reg clk;
reg reset_n;
wire [7:0] led;
//使用隐身例化
led_run2
#(
.MCNT(250)
)led_run8(
clk,
reset_n,
led
);
initial clk=1;
always #10 clk=~clk;
initial begin
reset_n=0;
#21;
reset_n=1;
#50000;
$stop;
end
endmodule
3_8译码器流水灯的仿真图