Verilog HDL always语句

转载出处: https://www.cnblogs.com/SummerSunnyDay/p/11543929.html

如有侵权,请告之。

在本篇里,我们讨论 Verilog 语言的综合问题,Verilog HDL (Hardware Description Language) 中文名为硬件描述语言,而不是硬件设计语言。这个名称提醒我们是在描述硬件,即用代码画图。

在 Verilog 语言中,always 块是一种常用的功能模块,也是结构最复杂的部分。笔者初学时经常为 always 语句的编写而苦恼,不知道使用哪种赋值语句,不了解两种赋值之间的区别。究其本质是对 always 语句的综合一知半解,常年使用软件思维编写代码所致。

现在我总结出:always 块的综合可以分为至少三类电路,由于历史原因,三种电路均使用 always 关键字。

此外 reg 关键字也存在一些迷惑性,综合器并不一定生成寄存器。
reg 在 verilog 语法中的定义为变量,它有可能是寄存器,也有可能是连线

第一类就是组合逻辑,如代码 1-1 和 代码 1-2

// 1-1 组合逻辑 
always @ (*)
begin
    if(a>b)
        q = 1;
    else    
        q = 0;
end

代码 1-1 是展示了一个简单组合逻辑的 always 块,它应该被综合成一个一位的比较器。

// 1-2 组合逻辑,缺少敏感信号
always @ (a)
begin
    if(a>b)
        q = 1;
    else    
        q = 0;
end

代码 1-2 也是一个组合逻辑,与 1-1 不同的是,敏感信号列表中没有 b。

我们知道,在 Verilog 语法中, always 块的含义是一个重复执行的语句。

那么 1-2 会综合成一个比较器:

  • 当 a 发生变化时,q 发生变化
  • 当 b 发生变化,由于 b 不再敏感信号列表中,所以 q 不变

这是一个彻头彻尾的软件思维,世界上不存在这种电路,综合器多半会综合一个与代码 1-1 一样的电路,然后报一个警告。

编写组合逻辑的 always 块,使用 * 代替敏感信号列表是一个简单方便而且不容易出错的好办法。

第二类就是时序逻辑

// 2-1 时序逻辑
reg [1:0] q;
always @ (posedge clk)
begin
    q <= q + 1'b1;
end

注意:这里使用的是阻塞赋值,我们的 q 这个时候被综合成一个寄存器,而不是一个软件上的变量。

代码 2-1 是一个时序逻辑单元,它应该被综合成一个计数器,每当时钟的上升沿,q 自增一。综合后的 部分 RTL 图如下:

我们可以看到,q 通过了一个加法器,加法器是两位的。

而关键的 always 块的综合结果如下图所示:

我们可以看到,always 块综合了一个时钟上升沿触发的 D 触发器。每当时钟的上升沿,D 触发器就把输入 D 传递到另一侧 Q。

综合器就这样完成了我们的设计意图:D 的左侧总是等于 Q+1,只有在 时钟的上升沿,才完成值的传递。完整的RTL 图如下:

// 2-2 时序逻辑,带异步复位
reg [1:0] q;
always @ (posedge clk or negedge rst_n)
begin
    if(!rst_n)
        q <= 2'b00;
    else
        q <= q + 1'b1;
end

综合后的 RTL 图如下:

代码2-2综合成一个带有清零端的 D 触发器,其余与 2-1 无异。

// 2-3 时序逻辑,带同步置位
reg [1:0] q;
always @ (posedge clk or posedge set)
begin
	if(set)
		q <= 2'b11;
	else    
		q <= q + 1'b1;
end

代码 2-3 综合成一个带有同步置位的 D 触发器,其余与 2-1 无异。

// 2-4 时序逻辑,带同步置位和异步复位
reg [1:0] q;
always @ (posedge clk or posedge set or negedge rst_n)
begin
	if(!rst_n)
		q <= 2'b00;
	else if(set)
		q <= 2'b11;
	else    
		q <= q + 1'b1;
end

RTL 图:

可以看到多了个与门,代码 2-4 是代码 2-2 和 代码 2-3 的组合结果。

当然咯,这里的综合是指的逻辑综合,而实际上的综合和具体实现与逻辑无关。比如在 FPGA 芯片使用的是查找表LUT,并没有独立的组合逻辑。而仿真器则使用编译方法,仿真器把 verilog 语言编译为 x86 汇编并直接在 CPU 上运行。

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
VerilogHDL语言中,语句是描述数字电路的基本单位,用于表示电路的行为和结构。以下是VerilogHDL常用的语句: 1. 模块声明语句(Module Declaration Statement):用于定义模块的名称、输入输出端口和内部信号等。例如:module module_name (input in1, input in2, output out1); 2. 连续赋值语句(Continuous Assignment Statement):用于将一个表达式赋值给一个变量或信号。例如:assign out1 = in1 & in2; 3. 顺序语句(Sequential Statement):用于描述电路的行为和控制流程,包括if、case、for、while等。例如: - if语句:用于根据条件选择不同的操作。例如:if (condition) begin ... end - case语句:用于根据不同的值选择不同的操作。例如:case (value) 1: ... 2: ... default: ... - for语句:用于执行指定次数的操作。例如:for (i = 0; i < 10; i = i + 1) begin ... end - while语句:用于根据条件执行操作。例如:while (condition) begin ... end 4. 非阻塞赋值语句(Non-blocking Assignment Statement):用于将一个表达式赋值给一个变量或信号,但不会立即生效,而是在当前时钟周期结束后才生效。例如:out1 <= in1 & in2; 5. 时序语句(Timing Statement):用于描述数字电路中的时序行为,包括always、posedge、negedge等。例如: - always语句:用于指定一段代码始终执行。例如:always @ (in1 or in2) begin ... end - posedge语句:用于在信号上升沿触发一段代码。例如:always @ (posedge clk) begin ... end - negedge语句:用于在信号下降沿触发一段代码。例如:always @ (negedge clk) begin ... end 以上语句VerilogHDL常用的语句,可以用于描述数字电路的行为和结构。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值