亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Industrial programming >> Verilog

使用 Verilog always 块实现时序逻辑

前文展示了用 always 块实现组合逻辑的示例。always 块也主要用于实现时序逻辑,包含可保持值的触发器等存储元件。

JK 触发器

JK 触发器是存储值的多种触发器之一,有两个数据输入 j 和 k,以及复位 rstn 和时钟 clk。真值表如下,通常用与非门实现。

rstnjkq注释
0000复位有效时输出恒为 0
100保持值j=k=0 时输出保持不变
1011k=1 时输出变 1
1100k=0 时输出变 0
111翻转值j=k=1 时输出翻转当前值

JK 触发器行为 Verilog 代码如下:

module jk_ff (
    input j,      // Input J
    input k,      // Input K
    input rstn,   // Active-low async reset
    input clk,    // Input clk
    output reg q  // Output Q
);
always @ (posedge clk or negedge rstn) begin
    if (!rstn) begin
        q <= 0;
    end else begin
        q <= (j & ~q) | (~k & q);
    end
end
endmodule

测试平台

先声明测试平台所有变量,用简单 always 块启动时钟驱动设计。实例化设计并连接端口与测试平台变量。注意 q 为 wire 类型,因连接到设计输出主动驱动它。所有其他设计输入为 reg 类型,以便在 initial 等过程块中驱动。

激励先将所有设计输入初始化为 0,延时后释放复位。用 for 循环在随机时间驱动 j 和 k 不同值。循环结束后再等待一段时间结束仿真。

module tb;
reg j, k, rstn, clk;
wire q;
integer i;
reg [2:0] dly;
always #10 clk = ~clk;
jk_ff u0 ( .j(j), .k(k), .clk(clk), .rstn(rstn), .q(q));
initial begin
    {j, k, rstn, clk} <= 0;
    #10 rstn <= 1;
    for (i = 0; i < 10; i = i+1) begin
        dly = $random;
        #(dly) j <= $random;
        #(dly) k <= $random;
    end
    #20 $finish;
end
endmodule

仿真波形显示:在时钟上升沿,输出 q 根据输入 j 和 k 状态按真值表变化。

模 10 计数器

模 (MOD) 计数器计数到某数后归零。MOD-N 计数器从 0 计到 N-1 再归零重新计数。此类计数器通常需 log2N 个触发器保持计数值。下面是 MOD-10 计数器 Verilog 代码,只要复位 rstn 释放,每个时钟 clk 向上计数。

可用 Verilog 参数制作更通用的 MOD-N 计数器。

module mod10_counter (
    input clk,
    input rstn,
    output reg[3:0] out
);
always @ (posedge clk) begin
    if (!rstn) begin
        out <= 0;
    end else begin
        if (out == 10) out <= 0;
        else out <= out + 1;
    end
end
endmodule

测试平台

测试平台声明变量赋值驱动设计输入。计数器模块实例化并连接测试平台信号,后在激励中驱动值。因计数器需时钟,测试平台用 always 块建模时钟。激励在 0ns 设默认值,10ns 后释放复位,运行一段时间。

module tb;
reg clk, rstn;
reg [3:0] out;
mod10_counter u0 ( .clk(clk), .rstn(rstn), .out(out));
always #10 clk = ~clk;
initial begin
    {clk, rstn} <= 0;
    #10 rstn <= 1;
    #450 $finish;
end
endmodule

可见计数器模块从 0 计到 9,归零后重新计数。

4 位左移寄存器

下面是 4 位左移寄存器,接受输入 d 进入 LSB,所有其他位左移 1 位。例如 d 为 0 且寄存器初值 0011,下一时钟沿变为 0110。

module lshift_4b_reg (
    input d,
    input clk,
    input rstn,
    output reg [3:0] out
);
always @ (posedge clk) begin
    if (!rstn) begin
        out <= 0;
    end else begin
        out <= {out[2:0], d};
    end
end
endmodule

测试平台

测试平台遵循类似模板:声明变量、实例化设计、连接信号、启动时钟、在 initial 块驱动激励。此例中需验证不同 d 值,用 for 循环迭代 20 次施加随机值。

module tb;
reg clk, rstn, d;
wire [3:0] out;
integer i;
lshift_4b_reg u0 ( .d(d), .clk(clk), .rstn(rstn), .out(out));
always #10 clk = ~clk;
initial begin
    {clk, rstn, d} <= 0;
    #10 rstn <= 1;
    for (i = 0; i < 20; i=i+1) begin
        @(posedge clk) d <= $random;
    end
    #10 $finish;
end
endmodule

注意每位左移 1 位,d 新值施加到 LSB。

Verilog

  1. 开关控制电路实战:从原理图到面包板的基础电路构建
  2. 集成电路:数字逻辑门基础
  3. 可编程逻辑控制器(PLC):工业系统的现代数字控制
  4. 理解布尔代数:从逻辑基础到数字电路
  5. 精通卡诺图逻辑化简
  6. 带反馈的数字逻辑:从确定性门到多谐振荡器
  7. 以冈本精密磨床实现完美表面光洁度
  8. 精通VHDL与Verilog:编写整洁组合与时序逻辑
  9. Verilog 模 N 计数器设计:参数化模块与测试平台
  10. Verilog 格雷码计数器模块:4 位格雷码生成器
  11. 全 CMOS 兼容 4T2R nv-SRAM:基于 STI-RRAM 自抑制负载实现零静态功耗高速运行
  12. 原子层沉积 HfAlOx RRAM:低电压高性能,赋能存内计算