Verilog基础:在testbench中使用阻塞赋值和非阻塞赋值的区别

这篇具有很好参考价值的文章主要介绍了Verilog基础:在testbench中使用阻塞赋值和非阻塞赋值的区别。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

相关阅读

Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm=1001.2014.3001.5482


        本文详细阐述了在一个testbench中,应该如何使用阻塞赋值与非阻塞赋值。首先说结论,建议在testbench中,对时钟信号(包括分频时钟)使用阻塞赋值,对其他同步信号使用非阻塞赋值。

        下面是一个简单的D触发器模块,本文将针对它的testbench进行讨论。

module Dff(input clk, rst_n, data_in, output reg data_out);
    always@(posedge clk, negedge rst_n)begin
        if(!rst_n)
            data_out <= 1'b0;
        else
            data_out <= data_in;
    end
endmodule

        在Verilog仿真时,仿真波形与真实波形是有一定差距的,这体现在同步信号的改变与时钟沿一直是对齐的,而真实情况下,数据信号在时钟沿后需要延迟一段时间才会发生改变。

        体现在上面的模块中就是数据信号data_in的改变是与时钟信号clk同步的,data_out的改变也是与时钟信号clk同步的。

        图1展示了一个简单的仿真波形,其中信号data_in和信号data_out的改变都与时钟沿同步,需要注意的是在时钟沿处,信号data_out得到的是信号data_in在时钟沿处的原值,而不是改变后的值。

testbench非阻塞赋值,Verilog基础,fpga开发,数字IC,Verilog

图1  仿真波形

        也就是说,一个更加真实的波形可能如图2所示。

testbench非阻塞赋值,Verilog基础,fpga开发,数字IC,Verilog

图2 真实波形

        下面给出图1所示波形的testbench。

module Dff_t;
    reg rst_n = 1;
    reg clk = 0;
    reg data_in = 0;
    wire data_out;

    Dff dff(.clk(clk), .rst_n(rst_n), .data_in(data_in), .data_out(data_out));
    //时钟产生
    always begin
        #10 clk = ~clk;
    end

    //异步复位信号
    initial begin
        #3 rst_n = 0;
        #3 rst_n = 1;
    end

    //同步数据输入
    initial begin
        #10 data_in <= 1;
        #20 data_in <= 0;
        #20 data_in <= 1;
        #20 data_in <= 0;
    end
    

endmodule

        其中时钟信号和异步复位信号使用了阻塞赋值,而数据信号使用了非阻塞赋值。如果不是这样,就无法保证产生如图1所示的仿真波形,下面将分别讨论。

1、如时钟信号使用非阻塞赋值,数据信号也使用非阻塞赋值

module Dff_t;
    reg rst_n = 1;
    reg clk = 0;
    reg data_in = 0;
    wire data_out;

    Dff dff(.clk(clk), .rst_n(rst_n), .data_in(data_in), .data_out(data_out));
    //时钟产生
    always begin
        #10 clk <= ~clk;
    end

    //异步复位信号
    initial begin
        #3 rst_n = 0;
        #3 rst_n = 1;
    end

    //同步数据输入
    initial begin
        #10 data_in <= 1;
        #20 data_in <= 0;
        #20 data_in <= 1;
        #20 data_in <= 0;
    end
    

endmodule

testbench非阻塞赋值,Verilog基础,fpga开发,数字IC,Verilog

图3 错误的波形(一种可能)

        此时进行仿真,可能会出现图3所示的错误波形,信号data_out得到的是信号data_in在时钟沿处改变后的值。

       拿第一个时钟上升沿即10ns时举例,此时时钟信号clk被非阻塞赋值,同时data_in被非阻塞赋值。首先说明非阻塞赋值的过程,非阻塞赋值是分两步进行的,第一步是将赋值号<=右表达式求值,在当前仿真时间的所有赋值和非阻塞赋值右表达式求值(活跃事件)完成后,再进行第二步,即非阻塞赋值的赋值(非阻塞赋值的赋值顺序由求值顺序决定),即非阻塞赋值分为两步:求值与赋值,后文仅使用“赋值”一词代表非阻塞赋值中的赋值这个步骤,注意其与阻塞赋值的区别。

        由于initial结构和always结构是并行的,因此无法确定哪一个非阻塞赋值的右表达式求值是先进行的,但可以确定的是,信号clk的赋值和信号data_in的赋值以某种先后顺序被调度到之后(非阻塞赋值更新区)执行。当进行第二步时,clk的赋值和data_in的赋值都从非阻塞赋值更新区激活到活跃事件区执行,此时有多种执行方式:

        1、如果clk的赋值先执行(即之前clk非阻塞赋值右表达式先求值),则其又触发了@(posedge clk),接着是执行data_out非阻塞赋值右表达式求值,还是执行data_in的赋值,是不确定的,它们都是活跃事件。如果先执行data_out非阻塞赋值右表达式求值,则data_out得到的是data_in的旧值即0;如果先执行data_in的赋值,则则data_out得到的是data_in的新值即1(图3可能就是这种情况)。

        2、如果data_in的赋值先执行(即之前data_in非阻塞赋值右表达式先求值),则最后data_out得到的一定是data_in的新值即1(图3可能就是这种情况)。

2、如时钟信号使用阻塞赋值,数据信号也使用阻塞赋值

module Dff_t;
    reg rst_n = 1;
    reg clk = 0;
    reg data_in = 0;
    wire data_out;

    Dff dff(.clk(clk), .rst_n(rst_n), .data_in(data_in), .data_out(data_out));
    //时钟产生
    always begin
        #10 clk = ~clk;
    end

    //异步复位信号
    initial begin
        #3 rst_n = 0;
        #3 rst_n = 1;
    end

    //同步数据输入
    initial begin
        #10 data_in = 1;
        #20 data_in = 0;
        #20 data_in = 1;
        #20 data_in = 0;
    end
    

endmodule

testbench非阻塞赋值,Verilog基础,fpga开发,数字IC,Verilog

图4 错误的波形(一种可能)

        此时进行仿真,可能会出现图4所示的错误波形,信号data_out得到的是信号data_in在时钟沿处改变后的值。

        拿第一个时钟上升沿即10ns时举例,此时时钟信号clk被阻塞赋值,同时data_in被阻塞赋值。由于initial结构和always结构是并行的,因此无法确定哪一个阻塞赋值是先进行的,此时有多种执行方式。

        1、如果clk的阻塞赋值先进行,则其又触发了@(posedge clk),接着是执行data_out非阻塞赋值右表达式求值,还是执行data_in的阻塞赋值,是不确定的,它们都是活跃事件。如果先执data_out非阻塞赋值右表达式求值,则data_out得到的是data_in的旧值即0;如果先执行data_in的阻塞赋值,则则data_out得到的是data_in的新值即1(图4可能就是这种情况)。

        2、如果data_in的阻塞赋值先进行则最后data_out得到的一定是data_in的新值即1(图4可能就是这种情况)。

3、如时钟信号使用非阻塞赋值,数据信号使用阻塞赋值

module Dff_t;
    reg rst_n = 1;
    reg clk = 0;
    reg data_in = 0;
    wire data_out;

    Dff dff(.clk(clk), .rst_n(rst_n), .data_in(data_in), .data_out(data_out));
    //时钟产生
    always begin
        #10 clk <= ~clk;
    end

    //异步复位信号
    initial begin
        #3 rst_n = 0;
        #3 rst_n = 1;
    end

    //同步数据输入
    initial begin
        #10 data_in = 1;
        #20 data_in = 0;
        #20 data_in = 1;
        #20 data_in = 0;
    end
    

endmodule

testbench非阻塞赋值,Verilog基础,fpga开发,数字IC,Verilog

图5 错误的波形 

        此时进行仿真,一定会出现图5所示的错误波形,信号data_out得到的是信号data_in在时钟沿处改变后的值。 

        拿第一个时钟上升沿即10ns时举例,此时时钟信号clk被非阻塞赋值,同时data_in被阻塞赋值。由于initial结构和always结构是并行的,因此无法确定是非阻塞赋值的右表达式求值先进行还是阻塞赋值先进行,但是阻塞赋值一定是在非阻塞赋值的赋值前进行的(根据非阻塞赋值的定义),所以不管有多少种执行方式,此时只有一种结果。

        1、data_out得到的一定是data_in的新值即1(图5就是这种情况)。

 4、时钟信号使用阻塞赋值,数据信号使用非阻塞赋值

module Dff_t;
    reg rst_n = 1;
    reg clk = 0;
    reg data_in = 0;
    wire data_out;

    Dff dff(.clk(clk), .rst_n(rst_n), .data_in(data_in), .data_out(data_out));
    //时钟产生
    always begin
        #10 clk = ~clk;
    end

    //异步复位信号
    initial begin
        #3 rst_n = 0;
        #3 rst_n = 1;
    end

    //同步数据输入
    initial begin
        #10 data_in <= 1;
        #20 data_in <= 0;
        #20 data_in <= 1;
        #20 data_in <= 0;
    end
    

endmodule

         最后分析正确的testbench,拿第一个时钟上升沿即10ns时举例,此时时钟信号clk被阻塞赋值,同时data_in被非阻塞赋值。由于initial结构和always结构是并行的,因此无法确定是非阻塞赋值的右表达式求值先进行还是阻塞赋值先进行。

        1、如果clk的阻塞赋值先进行,则其又触发了@(posedge clk),接着是执行data_out非阻塞赋值右表达式求值,还是执行data_in非阻塞赋值右表达式求值,是不确定的,它们都是活跃事件。但是可以肯定的是,data_out得到的一定是data_in的旧值,因为非阻塞赋值的赋值一定在所有非阻塞赋值的求值后进行(根据非阻塞赋值的定义)。

        2、如果data_in非阻塞赋值右表达式求值先进行,则在之后clk阻塞赋值进行后,其又触发了@(posedge clk),接着执行data_out非阻塞赋值右表达式求值,但求值时是使用data_in的旧值,因为非阻塞赋值的赋值一定在所有非阻塞赋值的求值后进行(根据非阻塞赋值的定义)。文章来源地址https://www.toymoban.com/news/detail-844658.html

到了这里,关于Verilog基础:在testbench中使用阻塞赋值和非阻塞赋值的区别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【FPGA零基础学习之旅#8】阻塞赋值与非阻塞赋值讲解

    🎉欢迎来到FPGA专栏~阻塞赋值与非阻塞赋值 ☆* o(≧▽≦)o *☆ 嗨 ~我是 小夏与酒 🍹 ✨ 博客主页: 小夏与酒的博客 🎈该系列 文章专栏: FPGA学习之旅 文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏 📜 欢迎大家关注! ❤️ 阻塞赋值 ,操作符为 “ = ”

    2024年02月10日
    浏览(33)
  • 【0基础学会Verilog】003. 为Verilog模块编写测试模块testbench

    完成了C语言函数( function )或Verilog功能模块( module )的编写,接下来我们需要对其进行测试、仿真等手段来验证函数或模块的正确性。本篇博文介绍为一个给定的Verilog模块编写仿真模块,也就是所谓 testbench 的方法。 我们为上一篇博文【0基础学会Verilog】002. Verilog时序逻辑实现

    2024年04月17日
    浏览(21)
  • Verilog Tutorial(6)如何编写一个基础的Testbench

    在自己准备写verilog教程之前,参考了许多资料----FPGA Tutorial网站的这套verilog教程即是其一。这套教程写得不错,只是没有中文,在下只好斗胆翻译过来(加了自己的理解)分享给大家。 这是网站原文:https://fpgatutorial.com/verilog/ 这是系列导航:Verilog教程系列文章导航 本文将

    2023年04月10日
    浏览(25)
  • 【Verilog HDL】FPGA-testbench基础知识

    🎉欢迎来到FPGA专栏~testbench基础知识 ☆* o(≧▽≦)o *☆ 嗨 ~我是 小夏与酒 🍹 ✨ 博客主页: 小夏与酒的博客 🎈该系列 文章专栏: FPGA学习之旅 文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏 📜 欢迎大家关注! ❤️ 📜在开发FPGA的过程中,需要掌握V

    2024年02月12日
    浏览(29)
  • 14.9-时序和组合的混合逻辑——使用非阻塞赋值

    原则4:在同一个always块中描述时序和组合逻辑混合电路时,用非阻塞赋值。 1,在一个always块中同时实现组合逻辑和时序逻辑 将简单的组合逻辑和时序逻辑写在一起很方便。 当把组合逻辑额时序逻辑写入到一个always块中时,应遵从时序逻辑建模的原则,使用非阻塞赋值。

    2024年02月02日
    浏览(28)
  • socket 的阻塞模式和非阻塞模式

    对 socket 在阻塞和非阻塞模式下的各个函数的行为差别深入的理解是掌握网络编程的基本要求之一,是重点也是难点。 阻塞和非阻塞模式下,我们常讨论的具有不同行为表现的 socket 函数一般有如下几个,见下表: connect accept send (Linux 平台上对 socket 进行操作时也包括 write 函

    2024年02月04日
    浏览(31)
  • 什么是Java中的阻塞队列和非阻塞队列?

    首先,让我们从基础概念开始。在计算机科学中,数据结构可以分为两种:队列和管道。队列是一种先进先出(FIFO)的数据结构,你可以想象成排队买电影票的情况。你加入队伍的时候,你可以决定站在哪里,但是一旦决定站在哪里,你就不能改变位置。而一旦你到达队尾,

    2024年02月14日
    浏览(33)
  • 使用Verilator仿真基于Verilog编写的testbench并用GTKWave查看波形

    Verilator是一个开源的Verilog、SystemVerilog仿真EDA。 它进行仿真的第一步称为“verilate”,将编写好的.v/.sv文件转化成为C++编写的类和方法。 第二步则是建立C++运行环境wrapper file,在里面编写的main函数用于例化第一步里生成的和Verilator自带的仿真不可缺少的类,之后运行Verilato

    2024年02月09日
    浏览(35)
  • 5.1阻塞和非阻塞、同步和异步 5.2Unix、Linux上的五种IO模型

    典型的一次IO的两个阶段是什么?数据就绪和数据读写 数据就绪:根据IO操作的就绪状态 阻塞 非阻塞 数据读写:根据应用程序和内核的交互方式 同步 异步 陈硕:在处理IO的时候,阻塞和非阻塞都是同步IO,只有使用了特殊的API才是异步IO。 一个典型的网络接口调用,分为两

    2024年02月12日
    浏览(32)
  • m基于FPGA的Hamming汉明编译码verilog实现,包含testbench测试文件,不使用IP核

    目录 1.算法仿真效果 2.算法涉及理论知识概要 2.1 Hamming编码过程 2.2 Hamming解码与纠错 2.3 FPGA实现 3.Verilog核心程序 4.完整算法代码文件 本系统进行了Vivado2019.2平台的开发,测试结果如下:        在现代数字通信和存储系统中,错误检测和纠正(Error Detection and Correction, EDC)机

    2024年01月23日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包