少于 1 分钟阅读 次阅读

1 题目链接

https://verilogoj.ustc.edu.cn/oj/problem/30

2 题目要求

2.1 题目要求

设计一个Verilog模块,使其输出信号始终为逻辑高电平(1),位宽为1,无输入端口。

2.2 题目代码模板

module top_module(
  output out
);
  // Write your code here
endmodule

3 题解

3.1 错误示范分析

module top_module(
  output out
);
  out <= 1'b1;  // 错误代码
endmodule

这段代码存在两个主要问题:

  1. 赋值方式错误<= 是非阻塞赋值操作符,只能在 alwaysinitial 过程块中使用
  2. 缺少过程块:非阻塞赋值不能在模块的顶层直接使用,必须包含在过程块中

3.2 正确解决方案

方案1:使用连续赋值(推荐)

module top_module(
    output out
);
    assign out = 1'b1;  // 持续驱动输出为逻辑1
endmodule

实现原理:

  • 使用 assign 连续赋值语句将输出信号 out 直接连接到高电平
  • 1'b1 表示1位二进制数,值为1
  • 这种实现方式最简洁高效,综合后生成一个直接连接到电源的电路

方案2:使用过程块(备选)

module top_module(
    output reg out  // 需要声明为reg类型
);
    always @(*) begin
        out = 1'b1;  // 阻塞赋值
    end
endmodule

alt text

  • 实测该代码会报错,原因如下: 使用 always @() 赋常量给 reg,会出现“@ 找不到敏感信号所以永不触发”的警告,并且在模块初始化/仿真开始时 out 可能是未定义(x),因为 always 块没有被触发去把 1 赋给 out。因此仿真中 time 0 时 out 为 x

3.3 电路实现原理

这个简单的电路在硬件上实现为一个直接连接到电源(VDD)的导线:

  • 不需要任何逻辑门或寄存器
  • 综合后生成一个恒定输出高电平的电路
  • 功耗极低,面积最小

4 相关知识详解

4.1 Verilog 赋值方式详解

4.1.1 连续赋值 (Continuous Assignment)

  • 语法:assign <信号> = <表达式>;
  • 用于驱动线网(wire)类型信号
  • 右侧表达式变化时立即更新左侧信号
  • 适用于组合逻辑设计

4.1.2 阻塞赋值 (Blocking Assignment)

  • 语法:<信号> = <表达式>;
  • 只能在过程块(always 或 initial)中使用
  • 立即计算并更新信号值
  • 语句按顺序执行,后续语句等待前一句完成
  • 主要用于组合逻辑设计

4.1.3 非阻塞赋值 (Non-blocking Assignment)

  • 语法:<信号> <= <表达式>;
  • 只能在过程块(always 或 initial)中使用
  • 在时钟边沿或事件触发时并行更新所有右侧表达式
  • 语句同时执行,不等待前一句完成
  • 主要用于时序逻辑设计(寄存器)

4.2 信号类型与赋值方式的关系

信号类型 可用的赋值方式 使用场景
wire 只能使用assign连续赋值 组合逻辑输出、模块间连接
reg 只能在过程块中使用=或<= 时序逻辑中的寄存器、组合逻辑中的中间变量

Verilog 规定:​​未明确声明类型的输出端口默认为 wire类型​

4.3 过程块类型与使用场景

4.3.1 always 块

  • 语法:always @(敏感列表) begin ... end
  • 敏感列表可以是电平敏感(组合逻辑)或边沿敏感(时序逻辑)
  • always @(*) 表示对块内所有输入信号敏感

4.3.2 initial 块

  • 语法:initial begin ... end
  • 仅在仿真开始时执行一次
  • 主要用于测试平台(testbench)中的初始化
  • 不可综合,不能用于实际电路设计

标签:

分类:

更新时间:

留下评论