FPGA_学习_04_Verilog基础语法和Modelsem仿真

这篇具有很好参考价值的文章主要介绍了FPGA_学习_04_Verilog基础语法和Modelsem仿真。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言:对于以前学过C/C++/C#的作者来讲,Verilog的基础语法算是特别简单的。本文主要介绍Verilog的基础语法和Modelsem仿真。

Verilog的基础语法

1 模块声明

FPGA开发是以模块为基础的,每个可综合的.v文件都是一个模块,模块由moduleendmodule来声明。在这两个关键字的内部,完成模块功能的实现。

在Vivado的一个空项目中,新建一个.v源文件,会自动生成以下代码(我把多余的注释删除了)

`timescale 1ns / 1ps	// 这行以后代码经常会见,表示时间单位是1ns,精度是1ps    


module verilog_base(	// module 模块名(
	...		            // 定义模块的输入输出接口
);			            // );
endmodule		        // endmodule

 下面以一个与门为例,进一步演示如何声明一个模块。

`timescale 1ns / 1ps	        // 这行以后代码经常会见,表示时间单位是1ns,精度是1ps    


module verilog_base(
	input		wire		a,	// input表示这是模块的输入接口  wire是变量类型 a是变量名,除最后一个变量定义外,都以‘,’结束
	input		wire		b,
	output		wire		c	// output表示这是模块的输出接口 wire是变量类型 c是变量名,最后一个变量定义,不以‘,’结束
);

assign c = a & b;				// 完成与门的组合逻辑幅值

endmodule

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

2 变量类型

在Verilog开发中有两种数据类型,一种是wire (线),一种是reg (寄存器)。在数字电路中信号只有两种形态,一种是传输,一种是存储。传输是通过连接线,存储是用寄存器,因此也就清楚了在Verilog中常用了wire和reg变量了。wire和reg变量模型如下图所示:

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

wire型变量在物理结构上只是一根线,在Verilog描述时,对线型变量赋值用assign即可,相对简单。

C语言赋值我直接 a = b;   Verilog赋值得在前面加关键字。  assign a = b;

reg型变量左端有一个输入端口D,右端有一个输出端口Q,并且reg型存储数据需要在clk(时钟)沿的控制下完成。 clk也即是我们常说的方波,它由晶振产生,是我们描述数字电路是最基本的时间单元,它周期固定,占空比一般为50%(高电平占整个周期的比例)。clk的低电平用数字0表示,高电平用1表示,从低电平转变到高电平的过程叫做上升沿,从高电平转变到低电平的过程叫做下降沿。

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

 在对reg型变量赋值时,必须在always块内完成,可以选择用时钟上升沿,也可以选择时钟下降沿,具体用上升沿还是下降沿可以根据需要定。下面尝试把第一节给出的与门例子的输出定义成reg型,实现两个输入相与之后将结果传输给寄存器的功能。即

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 Verilog代码如下:

`timescale 1ns / 1ps	// 这行以后代码经常会见,表示时间单位是1ns,精度是1ps    


module verilog_base(
	input		wire		clk,	// 系统时钟输入,由晶振提供
	input		wire		a,
	input		wire		b,
	output		reg		    c	    // 将输出的类型改成reg
);

// reg型变量的赋值必须要在always块里面,注意:赋值符号不是'=',而是 '<='。
always @(posedge clk) begin
	c <= a & b;
end

endmodule

在always块中,@(posedge clk)表示的是,每当遇到clk的上升沿时,执行always块中的语句。

c <= a & b;中的'<='表示的是非阻塞赋值。Verilog中有两种赋值方式:

        1  '<=' 非阻塞赋值 适用于给reg变量赋值,always块 - 时序逻辑

        2  ‘=’ 阻塞赋值 适用于给wire变量赋值,assign块 – 组合逻辑

阻塞赋值时,输入改变输出是同时改变,在非阻塞赋值中,只有在时钟变化的时候,输出才会发生变化。

begin-end其作用与C C++ C#中的{}是一样的,在Verilog中,就可以视begin-end为{}

3 多位宽数据表示

在数字电路中,所有数据最终都是以二进制形式呈现的,二进制和十进制都只是一种数据的表达方式,同一个数据无论用二进制还是十进制来表达,本质上代表的值是一样的。十进制数据是0到9组成,二进制是0,1组成。 比如5,它的二进制是3’b101,十进制是’d5。二进制的每一个0/1叫做1位,若想知道数据是多少位。可以用计算器看。

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

如果我要表示53698745这个数,就需要26个位。 那么在定义的时候就要像下面这样定义

wire [25:0] data;
reg [25:0] data;
wire [26:1] data;
reg [26:1] data;

一般推荐最低位都是从0开始,也就是[25:0]这种写法。

4 赋值语句

前面第二小节已讲了一些相关内容。assign 和 always分别用于组合逻辑的赋值 和 时序逻辑的赋值。 还有一种initial,一般仅用于仿真文件中。

initial 语句是初始化语句,会在上电(电路刚刚运行时)执行一次,不会循环执行。在电路中只有可以存储数据的寄存器才有初始化的必要,所以initial 语句中被赋值的变量也必须为reg。 某些第三方综合软件认为initial 是不可以被综合的,也就是说不可以被写到功能文件中的,所以为了代码的兼容性,我们尽量只在测试文件中写initial 语句。示例代码如下所示。

reg	clk;
initial begin
	clk = 0;
	forever #(5) clk = ~clk;    // forever和always的区别是 forever仅用于仿真
end

示例代码产生的是周期为10ns的时钟信号。

5 运算符

5.1 关系运算符(< 、<= 、== 、>= 、> 、!=)

C语言中可以用if(2<a<6),但Verilog只能用if(a>2 && a<6),其余一致

5.2 逻辑运算符(&& 、||、 !)

逻辑运算符与C 语言中一致:对于&& 只有参与运算的两个数据都为真时,结果才为真,对于|| 只要参与运算的两个数据由一个为真,结果就为真。(!)进行的时逻辑取反。

5.3 位运算符(& 、|、 ~)

位运算是对二进制的运算,运算时,需要将数据都转换位二进制后才能进行计算。当位宽不一样时,位宽少的在高位补0。

5.4 条件运算符

如:assign a = (b>6)?1’b1:1’b0;

当b 大于6 时,a 等于1,否则a 等于0;

5.5 赋值运算符

前面已经介绍过Verilog 中的赋值运算符,<= 和=,其中<= 是非阻塞赋值,用于时序逻辑,=是阻塞赋值,用于组合逻辑。

5.6 移位运算符(<< >>)

>>为向右移位,每次右移一位,数据高位补零,向下溢出的数据丢弃。<<与之相反。

5.7 位拼接运算符({}

位拼接运算符,可以将不同数据的位拼接成一个新的数据。

reg[3:0] a = 4'b0110;
reg[4:0] b = 5'b10110;
reg[4:0] c;

always@(posedge clk) begin
	c <= {b[1],a[1:0],b[3],b[1]};
end

拼接完成后,c = 5’b11001;

6 条件判断

同一个变量可以在不同的情况下获得不同的值,不同的情况需要判断语句来描述。Verilog HDL 中经常使用的判断语句有if else 语句和case endcase 语句,两种判断语句必须写在always 语句中,不能写在assign 中。

6.1 If-else

if-else 语句与C 语言当中的使用方法类似。

always@(posedge clk)begin
	if(a==1) begin
		b <= 1;
	end
	else if(a==2) begin
		b <= 2;
	end		
	else if(a==3) begin
		b <= 3;
	end
	else if(a==4) begin
		b <= 4;
 	end
 	else if(a==5) begin
 		b <= 5;
 	end
 end

if else 叠加不易过多,不然可能造成线路的延时过多。每一个if else 语句都会生成一选择器,当if else 过多时,选择器链路就会很长,而每两级选择器之间都会有线路的延时,当链路过多时,造成的延时就会很多,这样对于描述的电路的时序影响会很大,时序出问题时,就算是功能仿真正确,下板后电路也是不正确的。

FPGA_学习_04_Verilog基础语法和Modelsem仿真

使用if-else 语句时需要考虑优先级的顺序,优先执行的条件放在上方,优先级较低的条件放在后方。最好还是用case吧。

6.2 Case 语句

Verilog的case语句和C语言的switch case类似,在if-else 级数过多的情况下,也可以使用case 语句,case 语句生成的是多路器

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

always@(posedge clk) begin
	case(a)
		0: 
			b <= 0;
		1: 
			b <= 1;
		2: 
			b <= 2;
		default:
			b <= 0;
	endcase
end

Case 语句以case 开始,以endcase 结尾,在其之间,列出要判断的条件,根据条件的值,执行对应的代码。

Modelsem仿真

1 编写仿真程序

新建一个空白的项目的流程在上一篇博客中已经讲过了,这里不在赘述。 按照下面的操作流程,新建一个仿真文件。

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

FPGA_学习_04_Verilog基础语法和Modelsem仿真

FPGA_学习_04_Verilog基础语法和Modelsem仿真 

 Sublime Text (编辑软件)可以利用 源文件 自动生成 仿真文件。

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

FPGA_学习_04_Verilog基础语法和Modelsem仿真

FPGA_学习_04_Verilog基础语法和Modelsem仿真 

 

仿真程序输入要用reg型输出要用wire型
 

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 再次强调initial语句也常用在仿真文件,请尽量不要在实际的功能模块中使用。

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

`timescale 1ns/1ps
module tb_verilog_base (); /* this is automatically generated */

    reg  a;
    reg  b;
    wire  c;

    verilog_base inst_verilog_base (.a(a), .b(b), .c(c));


    initial begin
        a = 0;
        b = 0;

        #100; // 延时100ns

        a = 1;
        b = 0;

        #100; 

        a = 0;
        b = 1;

        #100;
        a = 1;
        b = 1;
    end
endmodule

2 Vivado仿真流程

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 从仿真中我们可以看到,assign赋值是立即生效的。

3 Modelsem仿真流程

Modelsem软件安装及编译相关的库文件等操作,请参考Vivado:【1】Vivado 2018.3 配置ModelSim仿真_Alex-YiWang的博客-CSDN博客

 

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

正常人都能看出来Modelsem的原始界面是比vivado丑的,但Modelsem的界面是可以配置的,可自行查找相关资料。

4 时序逻辑仿真

源文件

`timescale 1ns / 1ps	// 这行以后代码经常会见,表示时间单位是1ns,精度是1ps    


module verilog_base(
	input		wire		clk,	// 系统时钟输入
	input		wire		a,
	input		wire		b,
	output		reg		    c	    // 将输出的类型改成reg
);


// reg型变量的赋值必须要在always块里面,注意:赋值符号不是'=',而是 '<='。
always @(posedge clk) begin
	c <= a & b;
end

endmodule

仿真文件

`timescale 1ns/1ps
module tb_verilog_base (); /* this is automatically generated */

    reg  clk;
    reg  a;
    reg  b;
    wire  c;

    verilog_base inst_verilog_base (
        .clk(clk), 
        .a(a), 
        .b(b), 
        .c(c)
    );

    initial begin
        clk = 0;
        forever #(5) clk = ~clk;
    end


    initial begin
        a = 0;
        b = 0;

        #100; // 延时100ns

        a = 1;
        b = 0;

        #100; 

        a = 0;
        b = 1;

        #100;
        a = 1;
        b = 1;
    end

endmodule

仿真结果

FPGA_学习_04_Verilog基础语法和Modelsem仿真

时序逻辑赋值,并不是立即生效,而是在相应的“沿”信号处执行。

把源文件的always块修改成下降沿触发  always @(negedge clk) begin

把仿真文件的最后一个#100改成#33。

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 把仿真文件的 #33 改回 #100。

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

5 Modelsem小技巧

打开以下这个文件

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

FPGA_学习_04_Verilog基础语法和Modelsem仿真

 

你修改源文件或者修改仿真文件保存后,可以不用重新在vivado点击仿真。 可以在Modelsem的命令行执行以下三个命令。

        1 do tb_verilog_base_compile.do 重新编译一遍

        2 restart 有弹窗没关系,直接回车键默认Ok

        3 run 运行仿真

这样可以快速修改代码,高效率仿真。

最后愿我们共同进步! 感谢您的阅读,欢迎留言讨论、收藏、点赞、分享。文章来源地址https://www.toymoban.com/news/detail-453621.html

到了这里,关于FPGA_学习_04_Verilog基础语法和Modelsem仿真的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 【FPGA学习记录3-1】Verilog语法之Verilog的数据类型

    写在前面 本科时学过FPGA的相关课程,因此对于Verilog相关语法的学习重在回顾。 1.Verilog的数据类型 Verilog 最常用的 2 种数据类型就是 线(wire)与寄存器(reg) ,其余类型可以理解为这两种数据类型的扩展或辅助。 1.1wire类型 wire 类型表示硬件单元之间的物理连线,由其连接

    2024年02月02日
    浏览(46)
  • FPGA学习笔记-知识点3-Verilog语法1

    按其功能可分为以下几类: 1) 算术运算符(+,-,×,/,%) 2) 赋值运算符(=,=) 3) 关系运算符(,,=,=) 4) 逻辑运算符(,||,!) 5) 条件运算符( ? :) 6) 位运算符(,|,^,,^) 7) 移位运算符(,) 8) 拼接运算符({ }) 9) 其它 按其所带操作数的个数运算符可分为三种: 1) 单目运算符(unary operator):可以带一个

    2024年02月06日
    浏览(56)
  • 【FPGA】verilog语法的学习与应用 —— 位操作 | 参数化设计

    学习新语法,争做新青年 计数器实验升级,让8个LED灯每个0.5s的速率循环闪烁,流水灯ahh好久不见~ 去年光这个就把我折磨够呛。。我肉眼可见的脱发就是从那时候开始的。。在那两个月我直接掉了10斤啊喂~ (没节食、没运动、没失恋哈哈哈 产生0.5s周期的计数器 为了避免仿

    2024年02月11日
    浏览(45)
  • 【FPGA】verilog基础语法与应用:位操作 / 模块调用——流水灯(跑马灯)

    今天的实验是计数器实验的升级,设计让8个LED灯以每个0.5s的速率循环闪烁 1 移位法实现 1.1 移位方法1 每个LED灯代表一位,共8位,亮为1,灭为0 如何实现这样的逻辑呢? 移位操作即可! 怎么样才能移位呢? 第一个状态需满足最低位为1,然后每次左移1个 源代码 仿真代码 功

    2024年01月16日
    浏览(49)
  • Gowin FPGA学习记录——前言

            好久没有写博客了,想想是不是又该写点啥东西了么,准备写点国产FPGA的使用经历吧                  得益于目前国内的政策对国产化芯片扶持,越来越要求核心器件能够自主可控,因此作为核心芯片FPGA,国产FPGA的势头也发展很快。          现在FPGA的这

    2024年02月16日
    浏览(43)
  • FPGA学习实践之旅——前言及目录

    很早就有在博客中记录技术细节,分享一些自己体会的想法,拖着拖着也就到了现在。毕业至今已经半年有余,随着项目越来越深入,感觉可以慢慢进行总结工作了。趁着2024伊始,就先开个头吧,这篇博客暂时作为汇总篇,记录在这几个月以及之后从FPGA初学者到也算有一定

    2024年02月03日
    浏览(58)
  • FPGA | Verilog仿真VHDL文件

    VHDL模块代码 Verilog仿真代码

    2024年02月10日
    浏览(42)
  • 【FPGA入门】第一篇、Verilog基本语法常识

    目录 第一部分、不同的变量类型 1、wire和reg的区别  2、如何对变量进行赋值呢? 3、什么是阻塞?什么是非阻塞? 第二部分、变量位宽的定义 1、各种系统默认情况 2、变量位宽声明方式 3、表明位宽的情况下,赋值方式 4、两个模块之间例化,不定义变量直接用的方式 5、常

    2024年02月04日
    浏览(52)
  • FPGA/Verilog HDL/AC620零基础入门学习——第一个项目按键控制LED

    最近要考试了,所以我赶紧补习FPGA,我们用的是小梅哥的AC620开发板,软件是Quartus。推荐看这个视频教程:零基础轻松学习FPGA,小梅哥FPGA设计思想与验证方法视频教程 用按键控制LED灯的亮灭就是一个二选一多路器,两个IO,a、b,可以是高电平,也可以是低电平。 输入按键

    2024年02月05日
    浏览(57)
  • FPGA设计——verilog实现乒乓操作并modelsim仿真

    乒乓操作是FPGA设计中常用的一种技巧,它通过数据流控制实现按节拍相互配合的切换,来提高数据处理效率,达到无缝缓冲和处理的效果。本文针对乒乓操作进行学习总结。 完整工程 一、原理图如下 : 1、二选一控制器来对缓冲模块1和2进行选择。 2、数据缓冲模块一般就是

    2023年04月08日
    浏览(48)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包