时序逻辑与组合逻辑
组合逻辑
功能上:任意时刻的输出仅仅取决于该时刻的输入,与电路原来的状态无关。或者说没有记忆功能
电路上:只有逻辑门构成,不含记忆元件(存储),输出与输入间无反馈
时序逻辑
功能上:当前的输出不仅与该时刻输入有关,还与电路之前的状态有关。带有记忆功能
电路上:有存储元件,(触发器)
时序逻辑基础–D触发器
D端口输入数据,Q端口输出数据,CK为时钟输入端口
D触发器作用:在特定时刻读入的D会保存下来,在下一个特定时刻到来前,D端口的值不论怎么变化,Q输出的还是之前保存的值。这个特定时刻一般都是时钟信号的上升沿。
在CLK的上升沿到来时,Q存储并输出D的当前值,其余时刻D变化,但Q还是保持。
控制LED亮
复位信号低有效时,led = 0,灯灭,复位信号为高时,遇到时钟上升沿就亮灯,并保持不变。
设计_核心代码
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 0 )
led <= 0;
else
led <= 1;
end
仿真_核心代码
always #10 clk = ~clk;
initial
begin
clk=0;rst_n = 0;#20;
rst_n = 1;#60;
rst_n = 0;#10;
#20 $stop;
end
仿真图
计数器原理
每隔一个时钟周期,对前一时刻保存的值+1。要知道前一时刻的值,就需要用到触发器。
计数器,即计时器,可以实现灯的交替闪烁,亮灭。
实现500ms灯亮led = 1,500ms灯灭 led = 0。
所用开发板芯片工作频率 50M。即每秒钟发50M次时钟信号
1/50M = 20ns,20ns为一个时钟周期。
灯状态持续500ms,一个时钟周期为20ns,则500ms/20ns = 25_000_000
25_000_000用二进制表示需要25位,所以定义一个25位宽的计数器,每次计数到最大值,则表示过了500ms
设计代码
module led_twinkle(
clk,
rst_n,
led);
input clk,rst_n;
output reg led;
reg [24:0] cnt;
always@(posedge clk or negedge rst_n)
if(!rst_n)
cnt <= 0;
else if (cnt == 25_000_000-1)
cnt <= 0;
else
cnt <= cnt + 1’d1;
always@(posedge clk or negedge rst_n)
if(!rst_n)
led <= 0;
else if (cnt == 25_000_000-1)
led <= ~led;
else led <= led;
endmodule
仿真代码
`timescale 1ns/1ns
module led_twinkle_tb;
reg clk,rst_n;
wire led;
led_twinkle inst0(
.clk(clk),
.rst_n(rst_n),
.led(led)
);
always #10 clk = ~clk;
initial
begin
rst_n = 0;clk = 0;#21;
rst_n = 1;#100_000_000;
$stop;
end
endmodule
仿真波形
遇到的问题
本次在一个工程中写了两个顶层,对第二个led_twinkle时,要在file里设置为顶层文件
仿真时间过长,计数器缩短了3个数量级。