Verilog HDL 数字系统设计及实践 第5章_时序逻辑建模_

更新时间:2023-07-17 17:31:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

Verilog HDL 数字系统设计及实践第5章 时序逻辑建模

学习指南【知识目标】 (1) 掌握时序电路的基本概念和含义; (2) 掌握如何用Verilog行为描述语句表示寄存器和锁存器; (3) 掌握如何用Verilog描述有限状态机; (4) 理解同步时序逻辑设计的概念; (5) 掌握多种典型时序电路的Verilog描述。 【技能目标】 (1) 熟练使用Verilog构建各种寄存器、锁存器和基本的存储单元; (2) 熟练使用Verilog描述各种同步有限状态机电路; (3) 理解同步实现逻辑设计的重要性。 【重点难点】 (1) 如何避免在设计中产生意外的产生锁存器; (2) 如何设计可综合的时序逻辑; (3) 充分理解使用同步时序逻辑进行设计的意义和优缺点。

5.1 时序逻辑建模概述时序逻辑电路,是指在Verilog HDL所描述的电路中,包含一个或多个存储单元。 这些存储单元可以是边沿触发的寄存器,或者是电平触发的锁存器。由于引入了 存储单元,时序逻辑电路具有“记忆”功能,可以记录当前时刻之前的输入激励情况 以及电路状态。因此,与组合逻辑不同的是,时序逻辑的输出同时取决于当前时刻 和以前时刻的输入。寄存器 D Q 组合逻辑 寄存器 D 寄存器 D Q 组合逻辑 Q 组合逻辑

图5.1 组合逻辑和时序逻辑共同构建数字系统

5.2 寄存器和锁存器的设计

寄存器和锁存器是时序逻辑电路中最基本的存储单元。本书中描述的锁存器和寄存器, 分别特指数字电路课程中介绍过的D锁存器和边沿触发的D触发器。 5.2.1寄存器设计实例 【例5.1】利用Verilog HDL设计一个简单寄存器。该寄存器在时钟信号i_clk上升沿触 发,其数据输入信号为i_din。 // example_5_1: A simple register module dff ( input i_clk, input i_din, output reg o_dout ); // 在always语句的敏感列表@()中加入边沿敏感的时钟信号i_clk always @ (posedge i_clk) o_dout <= i_din; endmodule

5.2 寄存器和锁存器的设计

寄存器和锁存器是时序逻辑电路中最基本的存储单元。本书中描述的锁存器和寄存器, 分别特指数字电路课程中介绍过的D锁存器和边沿触发的D触发器。5.2.1寄存器设计实例 【例5.1】利用Verilog HDL设计一个简单寄存器。该寄存器在时钟信号i_clk上升沿触 发,其数据输入信号为i_din。 // example_5_1: A simple register module dff ( input i_clk, input i_din, output reg o_dout ); // 在always语句的敏感列表@( )中加入边沿敏感的时钟信号i_clk always @ (posedge i_clk) o_dout <= i_din; endmodule

5.2 寄存器和锁存器的设计dff i_din D Q o_dout

i_ clk

图5.2 example5_1代码所示电路 5.2.2锁存器设计实例 【例5.3】用Verilog HDL描述一个简单的锁存器。该锁存器在控制信号i_en为高电平时开 启,为低电平

时锁存当前值。 // example_5_3: A simple latch module latch ( input i_en, input i_din, output reg o_dout ); // 敏感列表中没有边沿触发的信号

5.2 寄存器和锁存器的设计always @ (i_din or i_en) if (i_en) o_dout <= i_din; // 没有与'if'语句对应的'else'语句,生成 锁存器,否则生成组合逻辑。 endmodule

latch i_din D EN i_ en图5.4 example_5_3代码所示电路

o_dout Q

5.3 寄存器和锁存器的推断5.3.1寄存器的推断 不带复位端口的简单寄存器可以由一个在always语句中被赋值的变量描述,并且该 always语句的敏感列表中只包含一个边沿敏感的信号。在描述寄存器的always语句中, 应该使用非阻塞赋值(Non-blocking assignment)来给变量 赋值,以保证生成正确的寄存器 电路,并且在仿真中避免产生竞争(Simulation race)。

带异步复位或置位端口的寄存器可以由一个在always语句中被赋值的变量描述,并且 该always语句的敏感列表中包含至少两个边沿敏感的信号,但不包含任何电平敏感的信号。 此外,该always语句必须包含一个if条件语句,来指定寄存器的第一个异步赋值行为(如异 步复位、置位等等),以及可选的else if嵌套条件语句来指定额外的异步赋值行为。最后一 个else语句用于指定同步的寄存器赋值行为。异步赋值语句的输入信号通常连接到寄存器的 复位或置位端口,而同步赋值语句的输入信号则连接在寄存器的数据输入端口,即通常所说 的D端口。 5.3.2锁存器的推断 锁存器可以由一个在always语句中被赋值的变量描述,并且在该always语句的敏感列表 中应只包含电平敏感的触发信号。同时,该变量在always语句中存在有没有赋值的情况。

5.3 寄存器和锁存器的推断// 变量q描述一个锁存器 reg q; ... always @ (enable or d) // 当enable为低电平时,q锁存当前值。 if (enable) q <= d; // 变量q不会生成锁存器,而是生产组合逻辑,因为在always语句中 // q未存在不被赋值的情况,即条件判别的所以分支都给q指定了赋值语句。 reg q; ... always @ (enable or d) if (enable) q <= d; else q <= 1'b0;

在描述锁存器时,always语句中所有赋值表达式等号右边参与赋值的信号必须全部在敏 感列表中列出,并且应该使用非阻塞赋值(Non-blocking assignment)来给变量赋值。

5.4 存储器的设计与建模存储器一般分为只读存储器(ROM)和随机访问存储器(RAM)。ROM存储的 数据信息在电路初始化的时候获得固定值,并且在之后不能被修改,只能进行读取。 ROM一般用于存储电路的配置信息。与ROM不同的是,RAM存储的信息在运行时可 以被修改,可以用来存储电路工作时产生的数据信息。 5.4.1ROM建模 【例5.4】代码example_5_4描述了一个简单的ROM模型。 // example_5_4: A simple RO

M model // 变量z描述了一个ROM,信号sel是ROM的地址选择信号。 module rom_case ( input [2:0] i_sel, // ROM地址信号。ROM深度为8 output reg [3:0] o_dat ); always @ (i_sel) case (i_sel) 3'b000: o_dat = 4'b1001; 3'b001: o_dat = 4'b1011;

5.4 存储器的设计与建模3'b010: o_dat = 4'b0010; 3'b011: o_dat = 4'b0011; 3'b100: o_dat = 4'b1110; default: o_dat = 4'b0000; // 其它地址 均输出全0 endcase endmodule 由上述电路所示的ROM模型可知,由于ROM不需要在运行时被修改,因此ROM的建 模可以通过组合逻辑完成。 5.4.2 RAM建模 RAM的建模需要用到Verilog HDL的数组变量。RAM既可以通过信号的电平变 化来触发,也可以通过边沿变化来触发。 【例5.6】用Verilog HDL描述了一个电平变化触发的16位宽RAM模型。当控制信号i_we为 高电平时,RAM将输入数据存储到当前地址i_addr所指向的存储空间。

5.4 存储器的设计与建模// example_5_6: A simple level-sensitive RAM model // 变量mem描述了一个电平触发的RAM模型,即一个锁存器组。 module ram_latch ( input i_we, input [6:0] i_addr, input [15:0] i_dat, output [15:0] o_dat ); // 用数组定义一个16x128的存储器。 reg [15:0] mem [127:0]; always @ (i_we or i_dat) if (i_we) mem[i_addr] <= i_dat; assign o_dat = mem[i_addr]; endmodule

5.5 在设计中使用同步时序逻辑对数据在各个组合逻辑间的流动进行有序控制,是时序逻辑的主要功能。 同步时序逻辑中的所有存储单元都利用一个全局分布的时钟进行周期性的同步, 因此所有组合逻辑路径都在同一时刻开始进行计算,并且在经过一段相同的延迟 之后,其结果值被写入到存储单元中。d1

D

R1

Q

d2

组合逻辑

d3

D

R2

Q

d4

全局时钟 clk

图5.5 同步互连方法

5.5.1利用同步时序逻辑消除冒险对于实际的组合逻辑,输入数据发生变化时,输入数据总要等待一段延迟才会 发生变化。组合逻辑实现的功能越复杂,综合后产生的门单元就越多,则该路径的 电路延迟就越大(如乘法器的延迟往往比同位宽的加法器大许多)。

5.5 在设计中使用同步时序逻辑电路中的组合逻辑往往包含大量的分支,这些分支路径的延迟通常各不相同,这就造 成了组合逻辑冒险(Hazard)的产生。组合逻辑的冒险可以分为静态冒险(Static hazard) 和动态冒险(Dynamic hazard)。T = 5ns

D

R1

Q

C1

D

R3

QT = 7ns C3

D

R5

Q

T = 12ns

D

R2

Q

C2

D

R4

Q

clk

图5.6 电路系统组合逻辑路径的不同延迟时间 图5.6所示为典型的同步实现电路结构图。组合逻辑C1、C2和C3都可能产生冒险, 但是它们的输出值分别在5ns,12ns和7n后保持稳定,并且在之后的时间里,寄存器都 可以对它们进行正确的读取。

5.5 在设计中使用同步时序逻辑5.5.2利用流水线提高同步时序逻辑性能

使用同步设计,虽然可以减小设计的复杂度,但往往电路的性能比异步逻辑差。

在长延迟组合逻辑中插入寄存器来加速电路整体工作频率的方法,我们称之为流水线技术。

利用流行线技术改进图5.6所示的同步时序电路,改进后的电路结构图如图5.7所示。T = 3ns T = 2ns

D

R1

Q

C1-1

D

R3-1

Q

C1-2

D

R3

QT = 7ns

clk T = 6ns T = 6ns

C3 R2 R4-1 R4

D

R5

Q

D

Q

C2-1

D

Q

C2-2

D

Q

clk

图5.7 利用流行线改进同步时序逻辑电路

5.6 同步有限状态机同步有限状态机分为两种。第一种被称为Mealy机,即状态机的输出不仅决定于状态机 的当前状态,还决定于当前时刻的输入

输入

计算下一状 态的组合逻 下一状态 辑 F

状态寄存器 当前状态

输出组合逻 辑 G

输出

clk

时钟

图5.8 Mealy状态机结构示意图

Mealy状态机的逻辑表达式可以写为: 下一状态 = F(当前状态, 输入) 输出 = G(当前状态, 输入)

5.6 同步有限状态机与Mealy状态机不同的是,Moore机的输出只决定于状态机的当前状态,与当前输入没 有关系。输入 计算下一状 态的组合逻 下一状态 辑 F 状态寄存器 当前状态 输出组合逻 辑 G 输出

clk

时钟

图5.9 Moore状态机结构示意图 Moore状态机的逻辑表达式可以写为: 下一状态 = F(当前状态, 输入) 输出 = G(当前状态)

5.6 同步有限状态机【例5.9】根据图5.10所示的状态转换图,用Verilog HDL设计有限状态机。!rst_n

Reset

rst_n

!rst_n Idle write && sel Write

!write && sel

ok

Read

Delay !ok

图5.10 典型的总线操作控制器状态转移图

5.6 同步有限状态机// example_5_9: A sample bus controller FSM module fsm_bus_control ( input i_clk, input i_rst_n, input i_write, input i_sel, input i_ok, // 直接输出状态机的当前状态和下一个状态 output [2:0] o_stat_current, output [2:0] o_stat_next ); parameter Reset = 3'b000; parameter Idle = 3'b001; parameter Read = 3'b010; parameter Write = 3'b011; parameter Delay = 3'b100; reg [2:0] cur_stat; reg [2:0] nxt_stat;

5.6 同步有限状态机// 状态存储器总是在时钟上升沿采集下一个状态的值。 always @ (posedge i_clk or negedge i_rst_n) if (! i_rst_n) cur_stat <= Reset; else cur_stat <= nxt_stat; // 计算下一个状态的组合逻辑F always @ (cur_stat or i_write or i_sel or i_ok or i_rst_n) begin case (cur_stat) Reset: if (! i_rst_n) nxt_stat = Reset; else nxt_stat = Idle;

5.6 同步有限状态机Idle: if (i_write && i_sel) nxt_stat = Write; else if (!i_write && i_sel) nxt_stat = Read; else nxt_stat = Idle; Write: nxt_stat = Delay; Read: nxt_stat = Delay; Delay: if (i_ok) nxt_stat = Idle; else nxt_stat = Delay; default: nxt_stat = Reset; endcase end // 输出组合逻辑G。该设计直接输出当前和 下一个状态值,因此只需要一条线将 // 内部的状态存储器连接

到模块端口。 assign o_stat_current = cur_stat; assign o_stat_next = nxt_stat; endmodule

本文来源:https://www.bwwdw.com/article/5981.html

Top