Verilog 之《设计与验证VerilogHDL》- RTL级建模

FPGA-ZYNQ 专栏收录该内容
11 篇文章 3 订阅

1. RTL与综合

RTL级是可综合的描述, 综合(Synthesize)是指将HDL语言, 原理图等设计输入翻译成门级连接,并根据设计目标及要求优化所生成的逻辑连接,输出门级网表文件.


2. RTL级设计基本要素及步骤

  • RTL设计包含
    • 时钟域描述
      • 描述设计中使用的所有时钟 \ 时钟之间的主从及派生关系以及时钟域之间的转换
    • 时序逻辑描述 (寄存器描述)
      • 根据时钟沿的变化, 描述寄存器之间的数据传输方式
    • 组合逻辑描述
      • 描述电平敏感信号的组合方式和逻辑功能
  • RTL代码设计顺序
    • 功能定义与模块划分
      • 根据系统功能的定义和控制划分
    • 定义所有模块的接口
      • 定义每个模块接口, 完成每个模块信号列
    • 设计时钟域
      • 确认异步时钟域之间的数据交换, 确认全局时钟使用PLL的分频, 倍频等
      • 确认全局时钟资源布线, 第二全局时钟资源布线
      • 全局时钟资源特点 : 几乎没有clock skew \ clock delay \ 驱动能力最强,以此类推,逐级递减,递增
    • 考虑设计的关键路径
      • 关键路径是指设计中时序要求最难满足的路径
      • 设计的时序要求主要体现在频率, 建立时间 , 保持时间等时序指标上
    • 顶层设计
      • 自顶向下的设计方式
    • FSM设计
      • 有限状态机( FSM )是逻辑设计中最重要的内容
    • 时序逻辑设计
      • 根据时钟选好寄存器组描述传输方式
    • 组合逻辑设计
      • 组合逻辑与时序逻辑分离

3. 阻塞赋值 \ 非阻塞赋值 \ 连续赋值

  • 对于时序逻辑,即always 模块的敏感列表为沿敏感信号 (时钟或者复位的上下沿),统一使用非阻塞赋值 “<=”
  • 对于always模块的敏感列表为电平信号的组合逻辑,统一使用阻塞赋值 “=”
  • 对于assign关键字描述的组合逻辑 (通常为连续赋值语句) ,统一使用 “=” ,变量定义为 wire 型变量
    注:在后两项中使用 “=” 主要原因在于避免产生组合逻辑环, 其会导致在时序路径无法被工具分析从而使不同批次器件逻辑功能发生一定概率的错误

4. 寄存器电路建模

  • 数字逻辑电路两大基本因素 : 寄存器 和 组合逻辑 ,寄存器一般和同步时序逻辑关联,一般在时钟上下沿发生 状态改变.
    • 寄存器信号声明 : 寄存器被定义为reg型, , 但是被定义为reg 型的变量不一定是寄存器, 只有当信号被定义为reg型 且出里该信号的always 敏感列表为posedge or negedge沿敏感时才会被实现为寄存器
  • 同步复位 / 置位 : 任何寄存器都可以实现同步复位/置位, 指定同步复位/置位时,always 敏感列表中仅有时钟沿信号,当复位信号发生之后当时钟边沿采到同步复位/置位的有效电平时才会在时钟沿到达时刻进行复位
  • 异步复位 / 置位 : 无论时钟沿是否有效,当复位信号到达时立即发生复位 ,实现方式为在敏感列表中加入复位信号有效沿
  • 尽量不使用双边沿,在可使用PLL进行倍频使用

5.组合逻辑建模

  • 组合逻辑的特点在于输出的变化仅仅与输入变化有关,而与时钟沿无关, 主要分为两类 : 其一为always 模块的敏感表为电平敏感信号的电路 , 其二为assign等关键字描述的组合逻辑电路
    • always模块的敏感列表为电平信号的组合逻辑电路
      • 注意敏感列表的完整性, 尽量使用阻塞赋值 ‘=’,且reg 型不会被真正实现为寄存器
      • 不考虑代码的复杂性,几乎所有组合逻辑电路都可以实现
    • assign语句描述的组合逻辑电路
      • 适合相对简单的逻辑电路,信号定义为wire型,

6.双向端口与三态信号建模

  • 双向总线应该在顶层模块中实例化三态信号,而不能在顶层意外的其他子层次实例化三态信号.这样是为了避免仿真和综合实现结果不一致
  • 将双向总线分为输入总线和输出总线使用
module bibus (clk, rst, sel, data_bus, addr);
input       clk, rst, sel;
input [7:0] addr;
inout [7:0] data_bus;
wire [7:0] data_in, data_out;
assign data_in = data_bus;
assign data_bus = (sel) ? data_out : 8'bZ;
//sel为控制信号,sel为低时data_bus为高阻,为输入状态,反之为输出状态,


7.Mux建模

  • 简单的Mux用 "?"建模,信号定义wire型,使用 ? 表达式的判断条件描述Mux选择端的逻辑关系
  • 复杂的Mux用case或嵌套if else建模,信号定义reg型,判断分支均分别对应Mux的某路选择输出

8.存储器建模

  • 单口RAM,双口RAM及ROM型存储器, Verilog语法中最基本的存储单元定义如下:
reg [datawitch] MemoryName [addresswidth] 
reg [7:0] RAM8x86 [0:63] 数据位宽为8,地址为63位的RAM
  • 在使用存储单元时不能直接使用类似C语言访问二维数组的形式,而应该讲存储单元赋值给一个寄存器,在对寄存器进行位操作.
  • 一般不使用语法建立存储单元
    • 内嵌IP生成
    • 在没有BRAM或者DRAM等专用存储单元或者熟悉综合器类推算法,并能通多综合器的相关约束属性,指定所需使用的底层硬件RAM资源可以考虑使用语法建立存储单元

9.时钟分频电路

  • 一般使用官方IP,在图形界面直接配置PLL \ DLL参数
  • 当器件没有内嵌PLL \ DLL时钟电路及受限于资源时可以使用一些自定义电路,对时钟的处理多为分频及移相.
    • 偶数分频,高速时钟做同步计数器,在相应bit位抽头
    • 移相 通过高速时钟调整相位,或通过时钟反向调整相位
module clk_even_phase (rst, clk_200K, clk_100K, clk_50K, clk_25K);
input        clk_200K;
input        rst;
output       clk_100K, clk_50K, clk_25K;
wire         clk_100K, clk_50K, clk_25K;
reg [2:0] cnt;  
always @ (posedge clk_200K or negedge rst)
   if (!rst)
      cnt <= 3'b000;
   else
      cnt <= cnt + 1;
assign clk_100K = ~cnt [0];
assign clk_50K  = ~cnt [1];
assign clk_25K  = ~cnt [2];
endmodule
//需要调整所有时钟的相位,对计数器的每个bit进行取反,保证分频后时钟初相完全一致,与原生时钟的相位存在微小误差,误差来自寄存器固有Tco(Clock to Output)和计数器累加的组合逻辑,其值在1~2ns,

  • 奇数分频 可以使用case结构或者使用简单状态机 (FSM)描述,要着重注意如何通过组合逻辑调整分频时钟占空比
module clk_3div (clk,reset,clk_out);
 input clk, reset;
 output clk_out;
 reg[1:0] state;
 reg clk1;
   always @(posedge clk or negedge reset)
     if(!reset)
        state<=2'b00;
     else
       case(state)
         2'b00:state<=2'b01;
         2'b01:state<=2'b11;
         2'b11:state<=2'b00;
         default:state<=2'b00;
       endcase
       
 always @(negedge clk or negedge reset)
     if(!reset)
        clk1<=1'b0;
     else
        clk1<=state[0];
        
 assign clk_out=state[0]&clk1;
endmodule 


10.串并转换建模

  • 根据数据排序和数量要求,数据量较小的时候可以使用移位寄存器实现 ; 对排列顺序有规定的串并转换可以使用case语句判断实现 ; 更复杂的设计可以使用状态机,按照业务需求而定

11.同步复位和异步复位

  • 复位电路工作
    • 仿真是电路进入初始状态或预工作状态,
    • 综合实现的电路通过复位进入初始状态或预工作状态
    • 任何寄存器, 存储器, 逻辑单元等结构都必须附加复位逻辑
    • 常用复位为低电平有效, 外部引脚接上拉电阻, 以只能加复位电路的抗干扰性能
  • 同步复位电路建模
    • 当复位信号发生变化时,电路并不理复位,当有效时钟沿采样到已变化的复位信号才对所有寄存器复位
    • 一般在电路中使用 if else结构, 复位电路在第一个if下进行描述, 其他电路在else 等分支中描述
    • 优势
      • 同步复位利于周期机制的仿真器进行仿真
      • 同步复位可以设计100%的同步时序设计,有利于时序设计,其综合结果的频率一般较高
      • 同步复位仅在时钟的有效沿生效, 可以有效避免因复位电路毛刺造成的亚稳态和错误,
    • 劣势
      • 目标器件和ASIC库的触发器本身并不包含同步复位端口,使用同步复位会增加逻辑资源
      • 需要复位信号有效时间, 至少大于一个采样周期,同时要保证同步复位信号树相关逻辑路径的延迟, 以及由于时钟布线产生的偏斜.
  • 异步复位电路建模
    • 复位信号产生作用不受控于时钟采样边沿, 大多数目标器件(FPGA \ CPLD)和ASCI库触发器都包含异步复位端口, 异步复位会直接到触发器的异步复位端口
    • 优势
      • 因为器件多有异步复位端口,所以比同步复位节省复位资源2异步复位设计简单
      • 多数FGPA会有专用全局异步复位 \ 置位资源 ( GSR, Global Set Reset)使用GSR资源,异步复位到达所有寄存器的偏斜 (Skew)最小
    • 缺点
      • 异步复位的作用和释放与时钟沿无关, 当释放异步复位时与时钟有效沿到达一致就容易造成亚稳态,形成逻辑错误
      • 如果异步复位逻辑树的逻辑产生毛刺,而毛刺的有效沿会误触发触发器复位,形成逻辑错误
      • 综上 ,优先使用异步复位,同步释放
reg reset_reg;
always @ (posedge clk)
     reset_reg <= rst_;
always @ (posedge clk or negedge reset_reg)
   if (!rst_)
       	………
   else
  		……

12.case 和 if~ else~ 建模

  • case结构每个分支的条件判断和执行都是并行的, 没有优先级 ; if~ else if~ else结构同样为无优先级判断结构 ; if~ if~ if~结构为具有优先级的判断结构
  • 优先级判断结构会消耗组合逻辑单元,非必要尽量少用

本文仅为个人记录 做理解之用.

  • 0
    点赞
  • 0
    评论
  • 2
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:技术黑板 设计师:CSDN官方博客 返回首页

打赏作者

yb_voyager

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值