本原创教程由深圳市小眼睛科技有限公司创作,版权归本公司所有,如需转载,需授权并注明出处(www.meyesemi.com)
第十六练:reg型存储器声明(二维数组)
题目:声明一个位宽为8,深度为32的二维数组变量ram
答案:reg [7:0]ram[31:0];
解析:reg [wordsize :0] array_name [arraysize :0];wordsize表示位宽,arraysize表示深度
第十七练:reg型存储器应用(二维数组)
题目:用verilog将变量ram_in的数值赋值给ram的arraysize为1的单元
答案:
解析:arraysize表示深度,此处ram也可理解为32个位宽为8的变量。
第十八练:generate-for语句的使用
题目:若信号test_in[7:0]表示8bit测试信号,需定义8个计数器对每1bit输入信号进行计数,若其中1bit测试信号为高电平,则对应的计数器累加1,若输入为低电平则停止计数。
答案:
解析:generate-for语句主要应用于需重复描述语句的复制
genvar声明一个正整数变量,用作for循环的判断;begin_end需要有一个类似于模块名的名字,instance_name为实例名,generate-for语句中generate块可以命名也可以不命名;begin……end语句内为需要复制的代码。
第十九练:变量命名原则
题目:以下变量名定义不正确的是:
A、clk B、8counter C、_net D、bus_A
答案:B
解析:verilog变量的命名由字母、下划线和数字三种字符构成,并且以英文字母或下划线开始,不能数字开始,且不能与关键字一致
第二十练:case语句的使用
题目:用case语句实现8段数码管对应数字显示的控制,4bit的dig信号表示应显示的数字(0~9),8bit的seg信号表示数码管8段led的控制,且数码管为共阳数码管,[7:0]seg从高位到低位分别表示DP、A、B、C、D、E、F、G
答案:
解析:共阳数码管低电平点亮,参考case语法:
若condition1为真,则执行true_statement1;若condition1为假且condition2 为真,则执行 true_statement2;若所有列出的 condition 都为假,则执行 default_statement 语句。
第二十一练:parameter声明常量
题目:时钟频率是中代码计时计数器的重要参数,为提高代码的可读性及移植性,可通过一个参数定义时钟频率参数,请用parameter定义CLK_FRE为50MHz的时钟频率参数。
答案:
方式一:
方式二:
解析:参数parameter的声明可以在模块名后面声明(参考答案方式一),也可以在模块内部声明(参考答案方式二)。
第二十二练:参数传递
题目:基于上一题目模块中定义的parameter参数,在例化该模块时实现参数传递
答案:
解析:通过模块例化可实现参数传递,若模块中的参数不需要其他模块修改,则模块例化时不需要添加参数;若需要在该模块以外修改参数,则通过模块例化进行参数传递方法如下。另外,在参数定义中通常使用大写字母表示,与变量名称作区分。
在上一题目中module_name模块定义变量为50_000_000,本题目在例化该模块时参数传递使用数值为20_000_000,在整个设计中CLK_FRE参数的实际值为20_000_000。
第二十三练:条件编译的使用
题目:请用verilog实现时钟频率的参数CLK_FRE在仿真的条件下数值为500,在实际条件下数值为50_000_000
答案:
解析:在编译工程中只编译满足条件的部分,在仿真条件下,需`define SIM满足条件编译中的仿真条件,若实际条件下可修改为`define NO_SIM
第二十四练:变量位宽截取语法
题目:使用变量[起始地址 +: 数据位宽],变量[结束地址 -: 数据位宽] 的语法截取变量部分的位宽,如以下代码:
请写出以下位宽截取的数值:
(1)big_vect[3+:8]
(2)big_vect[15-:8]
(3)little_vect[3+:8]
(4)little_vect[15-:8]
答案:
(1)8’b11000111
(2)8’b11000110
(3)8’b00110001
(4)8’b00111001
解析: +: 表示升序,-:表示降序,width_expr表示位宽,需注意变量定义的大小端格式,位宽截取不改变大小端格式
第二十五练:function的使用
题目:用function实现a,b,c三个输入数据取最大值
答案:
解析:function函数定义语法如下:
若需使用参考答案中的函数,参考代码如下:
实现data_1,data_2,data_3三个变量中的最大值赋值给result
第二十六练:task语法
题目:请用task语句实现a,b,c三个变量取其最大值,并做调用示例
答案:
解析:
在定义一个task时,必须注意以下几点:
(1)task不能出现在任何一个过程块内;
(2)一个task可以没有输入/输出端口,也可以有;
(3)一个task可以没有返回值,也可以通过输出端口或双向端口返回一个或多个值;
在调用任务时,需要注意以下几点:
(1)task调用是过程性语句,因此只能出现在always过程块和initial过程块中,调用task的输入与输出参数必须是寄存器类型的;
(2)task调用语句中的列表必须与任务定义时的输入、输出和双向端口参数说明的顺序相匹配;
(3)在调用task时,参数要按值传递,而不能按地址传递(和其他语言的不同);
(4)在一个task中,可以直接访问上一级调用模块中的任何寄存器;
(5)可以使用循环中断控制语句disable来中断任务执行,在task被中断后,程序流程将返回到调用task的地方继续向下执行。
第二十七练:Testbench的仿真时间单位和仿真精度
题目:请用timescale定义仿真时间单位和仿真精度,并实现仿真开始前20ns的reset信号为1,20ns之后reset信号一直为0
答案:
解析:`timescale 1 ns / 1ps定义时间单位1ns,时间精度1ps。绝对时间激励以仿真时刻0为基准,‘#’用于指定等待的延迟时间,之后才会执行下一个激励。
第二十八练:Testbench的时钟信号的产生
题目:请结合timescale定义和#的语法,生成周期为20ns的时钟信号clk
答案:
方法一:
方法二:
解析:方法一及方法二通过#每延时10ns时间clk信号取反一次,产生周期为20ns的时钟信号。
第二十九练:testbench编写基本结构
题目:根据如下模块,编写对应的testbench文件
答案:
解析:testbench基本结构:
1.仿真时间单位/时间精度
`timescale 1 ns / 1ps
2.仿真模块建立
建立测试module,无输入输出信号;
3.例化测试模块
例化带测试module时,定义reg变量连接其输入,wire变量连接其输出;
4.生成时钟信号
5.生成测试激励信号
第三十练:repeat(n)@(posedge clk)和“#”控制仿真信号延时的区别
题目:请描述以下两种方法产生的信号有何区别
答案:“#”是按仿真时间单位来控制rst_n信号的变化;repeat(n)@(posedge clk)是按时钟上升沿计数来控制rst_n信号的变化,使rst_n信号与clk同步。
解析:可通过仿真验证,在第五个时钟上升沿处,#(n)的写法,modelsim认为test信号已经为高电平,repeat(n)@(posedge clk)的写法认为此时test信号仍为低电平,在信号“打拍”识别信号边沿的仿真过程中注意两种写法的细节区别。