0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Verilog系统函数和边沿检测

FPGA之家 来源:时沿科技 作者:Nemo_Yxc 2022-03-15 13:34 次阅读

“本文主要分享了在Verilog设计过程中一些经验与知识点,主要包括Verilog仿真时常用的系统任务、双向端口的使用(inout)、边沿检测

01

仿真时常用的系统任务($display,$fopen,$fscanf,$fwrite($fdisplay),$fclose,$random,$stop)

在RTL设计过程中,仿真的时候需要用一些系统函数,这边笔整理了部分Verilog设计中常用的系统函数:$display,$fopen,$fscanf,$fwrite($fdisplay),$fclose,$random,$stop。

  • $display

这个函数系统任务的作用是用来在控制台输出信息

  • $display("!!! Start Simulation !!!");直接显示字符串

  • $display("data_display = %h hex %d decimal",100, 100); //显示data_display 的16进制 ,10进制

  • $display("data_display = %o otal %b binary",100, 100);//显示data_display 的8进制 2进制

  • $display("data_display = %d otal next line %bbinary", 100, 100);//主要展示换行操作

  • $display("simulation time is %t",$time);//显示系统仿真时间

具体代码如下:

regflag;//******************************  系统显示  $display  *******************************reg[31:0]data_display;  initial    begin      data_display  =  32'd100;      flag   =   0;          $display("!!! Start  Simulation !!!");      #10;        //显示16进制  10进制        $display("data_display = %h hex %d decimal", 100, 100);      #10;        //显示8进制   2进制        $display("data_display = %o otal %b binary", 100, 100);      #10;        //ASCII码        $display("data_display has %c ascii character value",64);      #10;        //显示10进制  换行 2进制        $display("data_display = %d otal next line 
 %b binary", 100, 100);      #10         //显示系统仿真时间        $display("simulation time is %t",$time);      flag   =   1;      end

仿真结果如下图所示:

a3351bf2-9199-11ec-952b-dac502259ad0.png

在第五行展示了换行功能;为了验证系统仿真时间,笔者这边用flag参数拉高来测试时间,时间结果如下图显示,和显示时间一致;

a35253ca-9199-11ec-952b-dac502259ad0.png

  • $fopen

用法:<文件句柄>=$fopen("<文件名>"); 句柄就是任务$fopen返回的多通道描述符,默认为32位,最低位(第0位)默认被设置1,默认开放标准输出通道,即transcript窗口。 每一次使用$fopen函数后都打开了一个新的通道,并且返回了一个设置为1的位相对应。默认应该是0001,以上每调用分别设置为0010 ,0100,1000(只考虑最低四位)。

a376a964-9199-11ec-952b-dac502259ad0.png

  • $fscanf

函数功能:读取txt(.dat)文件数据,具体代码如下:
//******************************   读文件  $fscanf  *******************************  //宏定义,定义数据长度  `define  DATA_LENGTH 8  //定义RAM大小  reg  signed   [15:0]  Sig0  [`DATA_LENGTH-1:0];reg    [15:0]Sig1[`DATA_LENGTH-1:0];  //定义句柄  integer   data_file0;integerdata_file1;integeri;  //读取函数  initial    begin      #200;      //打开句柄      data_file0 = $fopen("file/rd_data0_fpga.txt","r");       data_file1 = $fopen("file/rd_data1_fpga.txt","r");       for(i = 0;i < `DATA_LENGTH; i = i + 1)         begin          $fscanf(data_file0,"%d",Sig0[i]); //读取十进制          $fscanf(data_file1,"%h",Sig1[i]); //读取十六进制        end      $fclose(data_file0); ////关闭这个句柄      $fclose(data_file1); ////关闭这个句柄    end

仿真结果如下图所示:

a38e896c-9199-11ec-952b-dac502259ad0.png

  • $fwrite$fdisplay

代码如下所示:

//**************************   写文件  $fwrite($fdisplay)  *************************  //******  $fwrite  写下一个数不会自动转行,所以要加
  //将读取的Sig0,Sig1重新写进两个新的txt中  //定义句柄  integer   data_wr0;  integer   data_wr1;  integer  m;  //读取函数  initial    begin#400;      //打开句柄      data_wr0 = $fopen("file/wr_data1_fpga.txt","w"); data_wr1=$fopen("file/wr_data2_fpga.txt","w");      for(m = 0;m < `DATA_LENGTH; m = m + 1)         begin          @(clk);          $fwrite(data_wr0,"%d
",Sig0[m]); //向txt写十进制    写下一个数不会自动转行,所以要加
          $fwrite(data_wr1,"%h
",Sig1[m]); //向txt写十六进制   写下一个数不会自动转行,所以要加
end      //关闭这个句柄      $fclose(data_wr0);      $fclose(data_wr1);    end
仿真结果如下所示

a3b20ed2-9199-11ec-952b-dac502259ad0.png

$fwrite和$fdisplay的区别,$fwrite写下一个数不会自动转行,可以加 来转行,$fdisplay则会自动转行。
  • $fdisplay

代码如下所示:
//******  $fdisplay  //将读取的Sig0,Sig1重新写进两个新的txt中  //定义句柄  integer   data_wr2;  integer   data_wr3;  integer  j;  //读取函数  initial    begin#600;      //打开句柄      data_wr2 = $fopen("file/wr_data3_fpga.txt","w"); data_wr3=$fopen("file/wr_data4_fpga.txt","w");      for(j = 0;j < `DATA_LENGTH; j = j + 1)         begin          @(clk);          $fdisplay(data_wr2,"%d",Sig0[j]); //向txt写十进制    写下一个数会自动转行,所以不需要加
          $fdisplay(data_wr3,"%h",Sig1[j]); //向txt写十六进制   写下一个数会自动转行,所以不需要加
end      //关闭这个句柄      $fclose(data_wr2);      $fclose(data_wr3);    end
仿真结果如下图所示:

a3df4e06-9199-11ec-952b-dac502259ad0.png

  • $fclose

fclose();关闭文件,为所获得的句柄。
  • $stop

暂停仿真。

02

双向端口的使用(inout)

根据Verilog的语法定义,IO的端口可以定义为三种类型input、output和inout,其中inout为双向端口。双向端口通过控制三态门来实现,其结构框图如下所示。

a40af4d4-9199-11ec-952b-dac502259ad0.png

  • 当T为1的时候,I端忽略(高阻),O端电平 = IO端电平;

  • 当T为0的时候,IO端电平=I端电平=O端电平;

真值表如下:

a4241464-9199-11ec-952b-dac502259ad0.png

实现代码如下:
  assign    io  = ( !t ) ? i : 1'bz ;  assign    o   =  io;
同样,Xilinx也有三态门的源语

参考:Xilinx 7 Series FPGA Libraries Guide for HDL Design

  IOBUF #(    .DRIVE         (  12         ), // Specify the output drive strength    .IBUF_LOW_PWR  (  "TRUE"     ), // Low Power - "TRUE", High Performance = "FALSE"    .IOSTANDARD    (  "DEFAULT"  ), // Specify the I/O standard    .SLEW          (  "SLOW"     ) // Specify the output slew rate  ) IOBUF_inst (.O(o1 ),//Bufferoutput.IO(io),//Bufferinoutport(connectdirectlytotop-levelport).I(i1),//Bufferinput    .T             (  t          ) // 3-state enable input, high=input, low=output  );
仿真结果如下:

a443e83e-9199-11ec-952b-dac502259ad0.png

可以看出:

  • T=1的时候,O端电平=IO端电平;

  • T=0的时候,O端电平=IO端电平=I端电平。

高阻,即可以认为没有输出,作为输出端口,对下级电路没有任何影响。悬空,是针对输入口而言,就是说没有接输入。在HDL语言中,高阻和悬空都是Z。

03

边沿检测

在程序设计过程中,经常需要检测一个脉冲信号的上升沿或者下降沿,下面给大家介绍如何使用Verilog实现对脉冲信号的边沿进行检测。时钟信号与脉冲信号如下图所示。

a4601d10-9199-11ec-952b-dac502259ad0.png

Verilog代码如下:

module edge_detection(  input        wire        clk,  input        wire        rst,  input        wire        sin_pulse,  output      wire        sout_r,  //上升沿检测  output      wire        sout_f   //下降沿检测    );//--------------------------------------------------------------------------------  reg              sin_reg0,sin_reg1;  //--------------------------------------------------------------------------------  always@(posedge  clk or posedge    rst)    begin      if(rst)        begin          sin_reg0 <= 0;          sin_reg1 <= 0;        end      else        begin          sin_reg0 <= sin_pulse;          sin_reg1 <= sin_reg0;        end    end//--------------------------------------------------------------------------------  assign  sout_r = sin_reg0 & (~sin_reg1); //上升沿检测assignsout_f=(~sin_reg0)&sin_reg1;//下降沿检测//--------------------------------------------------------------------------------
上述程序经过综合后,其RTL结构如下图所示,由两个D触发器和两个与门组成。

a476de92-9199-11ec-952b-dac502259ad0.png

仿真后的结果如下图所示,可以看出sout_r为上升沿检测结果,sout_f为下降沿检测结果。

a4901a2e-9199-11ec-952b-dac502259ad0.png

审核编辑:郭婷

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Verilog
    +关注

    关注

    28

    文章

    1351

    浏览量

    110065
  • 代码
    +关注

    关注

    30

    文章

    4774

    浏览量

    68503

原文标题:Verilog基础知识学习笔记(一)

文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    FPGA设计经验之边沿检测

    在同步电路设计中,边沿检测是必不可少的!
    发表于 03-01 09:59 5103次阅读

    FPGA设计经验:边沿检测

    在同步电路设计中,边沿检测是必不可少的!
    发表于 08-16 15:19 1905次阅读
    FPGA设计经验:<b class='flag-5'>边沿</b><b class='flag-5'>检测</b>

    verilog常用系统函数以及例子

    verilog常用系统函数以及例子
    发表于 08-15 15:49

    fpga应用篇(二):边沿检测

    `fpga应用篇(二):边沿检测上一篇介绍了阻塞赋值与非阻塞赋值,这次我们利用非阻塞赋值产生一个简单的应用即边沿检测边沿
    发表于 04-06 21:28

    边沿检测设计报告

    边沿检测设计报告
    发表于 09-26 15:38

    关于FPGA进行外部边沿检测检测不准确问题?

    程序边沿检测下降沿并统计数量(数量到达2后重新计数,并发送动作信号),但是最终发现检测结果不准确,有时候能检测到,有时候检测不到。万分感谢您
    发表于 08-21 12:58

    边沿检测与提取-轮廓跟踪知识详解

    边沿检测与提取程序
    发表于 01-29 14:56 0次下载

    边沿检测的目的及电路原理分析

    边沿检测电路(edge detection circuit)是个常用的基本电路。所谓边沿检测就是对前一个clock状态和目前clock状态的比较,如果是由0变为1,能够
    的头像 发表于 11-19 07:09 1.1w次阅读

    Verilog HDL语言中任务与函数的比较

    其中,返回值的类型和位宽是可选项,如果缺省会返回一位寄存器类型数据。Verilog HDL认为函数的定义隐式地声明了与函数同名的寄存器。函数的定义把
    的头像 发表于 07-02 10:24 2318次阅读

    剖析verilog2005的骚操作之对数函数

    小技巧分享: verilog下取对数其实可用$clog2这个系统函数,和自己找代码里面写入function是同样的效果,但是方便的多。这是verilog 2005就开始支持的标准,所以
    的头像 发表于 10-09 15:29 4380次阅读
    剖析<b class='flag-5'>verilog</b>2005的骚操作之对数<b class='flag-5'>函数</b>

    FPGA学习-边沿检测技术

    所谓边沿检测,就是检测输入信号即上升沿或者下降沿的检测边沿检测的电路很好实现:上一时刻为低电
    的头像 发表于 11-26 10:20 1762次阅读

    Verilog边沿检测的基本原理和代码实现

    本文将从Verilog边沿检测的基本概念入手,介绍Verilog边沿检测的原理和应用代码示例。
    的头像 发表于 05-12 17:05 3917次阅读
    <b class='flag-5'>Verilog</b><b class='flag-5'>边沿</b><b class='flag-5'>检测</b>的基本原理和代码实现

    什么是边沿检测

    1、什么是边沿检测 边沿检测用于检测信号的上升沿或下降沿,通常用于使能信号的捕捉等场景。 2、采用1级触发器的
    的头像 发表于 06-17 14:26 2520次阅读
    什么是<b class='flag-5'>边沿</b><b class='flag-5'>检测</b>

    Verilog实现边沿检测的原理

    边沿检测大致分为:上升沿检测,下降沿检测和,双沿检测。原理都是通过比输入信号快很多的时钟去采集信号,当出现两个连续的采集值不等的时候就是
    的头像 发表于 06-28 15:19 3095次阅读
    <b class='flag-5'>Verilog</b>实现<b class='flag-5'>边沿</b><b class='flag-5'>检测</b>的原理

    verilog function函数的用法

    Verilog 是一种硬件描述语言 (HDL),主要用于描述数字电子电路的行为和结构。在 Verilog 中,函数 (Function) 是一种用于执行特定任务并返回一个值的可重用代码块。函数
    的头像 发表于 02-22 15:49 5456次阅读