学习使用Vivado和SDK进行Xilinx ZYNQ FPGA开发 | (十三)Verilog程序设计:Verilog HDL程序的基本结构 | 2023.11.7/星期二/天气晴

系列文章目录

专栏系列文章:学习Xilinx ZYNQ FPGA开发



摘要

以一个触发器输出选择电路为例,了解Verilog程序的基本结构和基本特性。包括:

  • module的组成
  • 硬件描述语言的描述风格

一、案例:触发器输出选择电路

例题

设计一个触发器输出选择电路,如下图所示。
在这里插入图片描述

设计思路

自底向上,先设计D触发器my_dff.v、二选一选择器mux_2_1.v,再由两个D触发器和一个二选一选择器组成顶层的触发器输出选择器dff_sel.v。

程序编写

将上一次的工程文件直接复制一份,改名为有意义的名字,打开里面的工程,删除上一次的源文件,创建并编写新的源文件。
在这里插入图片描述

D触发器my_dff.v

// D触发器模块
module my_dff(d, clk, q);	// 模块描述开始
    input d, clk;	// 模块输入端口说明
	output q;		// 模块输出端口说明
	reg	q;			// 数据类型说明
	
	// 行为描述过程块
	always @(posedge clk)	// 判断clk 的上升沿触发
		q = d;
endmodule

二选一选择器mux_2_1.v

// 二选一选择器模块
module mux_2_1(ma, mb, s, mout);	// 模块描述开始
	input ma, mb;	// 选择器的两个输入
	input s;		// 选择器的选择信号
	output mout;	// 选择器的输出
	
	// 数据流描述
	assign mout = s?ma:mb;	// 条件连续赋值:当s=1时,mout=ma;否则,mout=mb
endmodule

触发器输出选择器dff_sel.v

// 触发器输出选择器模块
module dff_sel(da, db, sel, clk, q); 	// 模块描述开始
	input da, db, sel, clk;
	output q;
	wire qa, qb;
	
	// 实例化语句描述模块内部组成结构
	my_dff u0(.d(da), .q(qa), .clk(clk));				// 名字实例化语句
	my_dff u1(db, clk, qb);								// 位置(顺序)实例化语句
	mux_2_1 u2(.ma(qa), .mb(qb), .s(sel), .mout(q));	// 名字实例化语句
endmodule

RTL Analysis

在这里插入图片描述

Simulation

testbench

`timescale 1ns / 1ps
module tb_dff_sel();
    reg da, db, sel, clk;
    wire q;
    
    initial
    begin
        da = 0;
        db = 0;
        sel = 0;
        clk = 0;
        
        #100 sel = 1;
    end
    
    always
        #20 clk = !clk;
        
    always
        #40 da = !da;
        
    always
        #50 db = !db;

    dff_sel uut(da, db, sel, clk, q); 
    
endmodule

仿真结果
在这里插入图片描述

二、Verilog程序的基本结构

Verilog是以模块集合的形式来描述硬件系统的,模块是Verilog的基本单元,它用于描述某个设计的功能或结构及其与其他模块的外部接口。模块可以代表从简单门元件到复杂系统的任何一个硬件电路。每一个模块都有接口部分,用于描述与其他模块之间的连接关系。Verilog的各个模块之间是并行运行的。通常设计的硬件系统有一个顶层模块,该顶层模块的输入输出分别代表系统的输入输出,顶层模块可以由若干个子模块组成,每个子模块代表着系统中具有特定功能的一个功能单元,各个子模块通过端口相互连接起来,从而实现分层设计。
模块的基本组成结构如下:

module <模块名> (<端口列表>);
	端口说明(input, output, inout)
	参数定义(可选)(parameter)
	数据类型定义(wire, reg等)
	连续赋值语句(assign)
	过程块语句(initial, always)(包括条件、选择、循环等行为描述语句或语句块)
	底层模块实例引用(module instantiations)
	函数和任务(function, task)
endmodule

Verilog程序是由模块组成的,每个模块的内容都包含在“module”和“endmodule”两个语句之间,Verilog一行可以写多条语句,也可以一条语句分成多行写,每条语句以分好结束,但endmodule语句后面不必写分号。

三、Verilog程序的基本特性

Verilog作为一种硬件描述语言,语句从物理上可以分为两种:一种语句只能用于硬件设计仿真,这些语句不能进行逻辑综合,也就是不能变成有关硬件;另一种语句是真的用于实现硬件的语句,它进行逻辑综合后会变成对应的硬件电路。
根据语句执行顺序可分为顺序语句和并行语句,但从本质上来讲,所有语句都是并行运行的,这是因为硬件的运行特征就是并行运行,而在实际应用中有时又要求顺序进行,因此如果我们对硬件附加控制条件,那么硬件的运行就可以是顺序的。
Verilog的并行语句包括连续赋值语句(assign)、模块实例引用(module instantiations)、always和initial过程块语句。而顺序语句(行为语句)包括条件语句、选择语句、循环语句等,这些顺序 语句只能用在always过程块语句中。

四、Verilog程序的描述风格

在Verilog中,模块的内部组成和逻辑功能可用不同的语句类型和描述方式来表达,这些描述方式(建模方法)称为描述风格,通常可归纳为三种:结构描述、数据流描述(寄存器传输级RTL)描述、行为描述。在实际应用中,为了能兼顾整个设计的功能、资源、性能几方面的因素,通常混合使用这三种描述方式。
结构描述: 所谓结构描述,是指描述该设计单元的硬件结构,即该硬件是如何构成的。它主要使用元件或模块实例化语句来描述系统内各元件或模块的互联关系,其中各组件的连接媒介是线网。结构化描述可通过内置门原语(门级)、开关级原语(晶体管级)、用户自定义的原语(门级)、模块化实例(层次结构)等方式进行结构建模。利用结构描述可以用不同类型的结构,来完成多层次的工程,即从简单的门到非常复杂的元件(包括各种已完成的设计实体子模块)来描述整个系统。元件间的连接是通过定义的端口界面来实现的,其风格最接近实际的硬件结构,即设计中的元件是互联的。
数据流描述: 数据流描述也称RTL描述,它类似于寄存器传输级的方式描述数据额度传输和变换,以规定设计中的各种寄存器形式为特征,然后在寄存器之间插入组合逻辑。这类寄存器或者显式地通过元件具体装配,或者通过推论作隐含的描述。数据流描述主要使用并行运行的连续赋值语句assign,既显式表示了该设计单元的行为,又隐含了该设计段元的结构。
连续赋值语句的使用格式为

assign [延迟时间] 网络名 = 表达式;

当右边表达式发生变化时,左边网络名的值将在设定的延迟时间后变成新的值。认为数据是从一个设计中流出,从输入到输出的观点称为数据流风格。数据流描述方式能比较直观地表述底层逻辑行为。
行为描述: 如果Verilog的逻辑描述只描述了所希望电路的功能或者说电流行为,而没有直接指明或设计实现这些行为的硬件结构,则称为行为描述。行为描述只表示输入与输出间的转换行为,它不包含任何结构信息。行为描述主要是使用initial和always语句来进行的。这里所谓的硬件结构,是指具体硬件电路的连接结构、逻辑门的组成结构、元件或其他各种功能单元的层次结构等。
混合描述: 混合描述就是将结构描述、数据流描述和行为描述方式混合起来使用。在设计中,可以含有连续赋值语句、always语句、initial语句、内置门原语、开关级原语、用户自定义原语、模块化实例等语句。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值