Verilog 考试题目整理
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Verilog 考试题目整理
1、EDA设计环节过程
(1)编译:EDA首先将源HDL模型转变为基本的门级网表
(2)映射:EDA为基本门模型分配具体的cell
(3)验证:对抽象电路模型进行测试
(4)Testbench:为了进行验证,需要单独编写一段HDL代码,建立一个用于测试目的模型。
(5)仿真:EDA软件提供了一种运行Testbench的方法:即按照电路模型机制,生成需要的激励信号并观察和分析模型中的信号。
这种运行抽象模拟的方法称为仿真。
(6)综合前验证:时,Testbench加载的测试模型使是用户PTL模型,而此时验证的内容主要是测试模拟的逻辑性能,因此综合前验证又被称为功能仿真或RTL 仿真,有时也被简单地称为前仿。
(7)综合后验证:时,Testbench加载的测试模型已经是装配后的由基本门描述的模型,即网表,此时验证的内容主要是设计模型的时序性能,因此综合后验证又被称为时序仿真或门及仿真,有时也被简单的称为后防。
2、自顶向下设计与自底向上设计优缺点
(1)、传统的电子设计多采用自底向上底设计方法:首先确定最底层的元件和电路模块的功能和结构,再进行组合得到较大得模块。
如此进行,向上递推直至完成整个电路。
此方法中任何一级发生问题,通常都要返工;由于元件供应、改型等得变化往往造成重新设计
(2)、现代的EDA设计采用自顶向下的设计方法:从系统功能、结构至各门级连接,从抽象层次逐步具体化。
此方法从最开始逐级仿真、综合便于及早发现问题,即使设计中出现问题也不会从头返工。
缺点是需要先进的工具
3、IP核分类
4、可编程器件有哪几种
(1)PLA
Programmable logic arrays(PLA) 是一种可编程逻辑装置,它的与阵列(AND array)和或阵列(OR array)均为可编程,输出电路为不可组态.又叫做FPLA(field-programmable logic array)
(2)PAL
PAL(Programmable Array Logic)可编程阵列逻辑,是70年代末由MMI公司率先推出的一种低密度,一次性可编程逻辑器件,第一个具有典型实际意义的可编程逻辑器件(PLD-Programmable Logic Device)。
它采用双极型工艺制作,熔丝编
程方式。
PAL在EDA中是指一种现场可编程的门阵列逻辑器件,内部电路是在PLA基础上进行改进的。
(3)GAL
GAL是Lattice在PAL的基础上设计出来的器件,即通用阵列逻辑器件。
GAL首次在PLD上采用了EEPROM工艺,使得其具有电可擦除重复编程的特点,彻底解决了熔丝型可编程器件的一次可编程问题。
GAL在“与—或”阵列结构上沿用了PAL的与阵列可编程、或阵列固定的结构,但对PAL的I/O结构进行了较大的改进,在GAL的输出部分增加了输出逻辑宏单元OLMC。
由于GAL是在PAL的基础上设计的,与多种PAL器件保持了兼容性,可直接替换多种PAL器件,方便应用厂商升级现有产品,因此目前仍被广泛地使用。
GAL,通用阵列逻辑,英文全称:generic array logic。
GAL器件是从PAL发现过来的,其采用了EECMOS工艺使得该器件的编程非常方便,另外由于其输出采用了逻辑宏单元结构(OLMC—Output Logic Macro Cell),使得电路的逻辑设计更加灵活。
(4)FPGA:
FPGA(Field-Programmable Gate Array),即现场可编程门阵列,它是在PAL、GAL、CPLD等可编程器件的基础上进一步发展的产物。
它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电路数有限的缺点。
5、可编程逻辑器件发展历程
70年代:
出现只读存储器PROM (Programmable Read only Memory),可编程逻辑阵列器件PLA (Programmable Logic Array)
70年代末:
AMD推出了可编程阵列逻辑PAL (Programmable Array Logic)
80年代:
Lattice公司推出了通用阵列逻辑GAL ( Generic Array Logic)
80年代中:
Xilinx公司推出了现场可编程门阵列FPGA (Field Programmable GateArray )。
Altera公司推出了可擦除的可编程逻辑器件EPLD (Erase Programmable LogicDevice),集成度高,设计灵活,可多次反复编程
90年代初:
Lattice公司又推出了在系统可编程概念ISP及其在系统可编程大规模集成器件ispLSI)现以Xilinx、Altera、Lattice为主要厂商,生产的FPGA单片可达上千万门、速度可实现550MHz,采用65nm甚至更高的光刻技术。
6、verilog语言命名规则
(1)系统级信号的命名。
系统级信号指复位信号,置位信号,时钟信号等需要输送到各个模块的全局信号;系统信号以字符串Sys开头。
(2)低电平有效的信号后一律加下划线和字母n。
如:SysRst_n;FifoFull_n;
(3)经过锁存器锁存后的信号,后加下划线和字母r,与锁存前的信号区别。
如CpuRamRd信号,经锁存后应命名为CpuRamRd_r。
低电平有效的信号经过锁存器锁存后,其命名应在_n后加r。
如CpuRamRd_n信号,经锁存后应命名为CpuRamRd_nr多级锁存的信号,可多加r以标明。
如CpuRamRd信号,经两级触发器锁存后,应命名为CpuRamRd_rr。
(4)模块的命名。
在系统设计阶段应该为每个模块进行命名。
命名的方法是,将模块英文名称的各个单词首字母组合起来,形成3到5个字符的缩写。
若模块的英文名只有一个单词,可取该单词的前3个字母。
各模块的命名以3个字母为宜。
例如:Arithmatic Logical Unit模块,命名为ALU。
Data Memory Interface模块,命名为DMI。
Decoder模块,命名为DEC。
(5)模块之间的接口信号的命名。
所有变量命名分为两个部分,第一部分表明数据方向,其中数据发出方在前,数据接收方在后,第二部分为数据名称。
两部分之间用下划线隔离开。
第一部分全部大写,第二部分所有具有明确意义的英文名全部拼写或缩写的第一个字母大写,其余部分小写。
(6)模块内部信号:
模块内部的信号由几个单词连接而成,缩写要求能基本表明本单词的含义;单词除常用的缩写方法外(如:Clock-》Clk,Write-》Wr,Read-》Rd等),一律取该单词的前几个字母(如:Frequency-》Freq,Variable-》Var 等);每个缩写单词的第一个字母大写;若遇两个大写字母相邻,中间添加一个下划线(如DivN_Cntr);
7、verilog 模块设计module 有几种端口设计
Input 输入端口
Output 输出端口
Inout 输入输出/双向端口
所有的端口隐含地声明为wire类型
不能将input和inout类型的端口声明为reg数据类型,这是因为reg类型的变量是用于保存数值的,而输入端口只反映与其相连的外部信号的变化,并不能保存这些信号的值。
8、verilog语言中数据类型reg/wire区别
wire型数据常用来表示以assign关键字指定的组合逻辑信号。
模块的输入输出端口类型都默认为wire型。
默认初始值是z。
reg型表示的寄存器类型。
always模块内被赋值的信号,必须定义为reg型,代表触发器。
默认初始值是x。
1、wire型的变量综合出来一般是一根导线;
2、reg变量在always块中有两种情况:
(1)、always后的敏感表中是(a or b or c)形式的,也就是不带时钟边沿的,综合出来还是组合逻辑
(2)、always后的敏感表中是(posedge clk)形式的,也就是带边沿的,综合出来一般是时序逻辑,会包含触发器(Flip-Flop)
9、阻塞赋值与非阻塞赋值区别
简单理解就是,阻塞赋值是按需执行,非阻塞赋值是并行执行。
书P195
10、verilog时钟表示的特点规律always语句
always语句包括的所有行为语句构成了一个always语句块。
该always语句块从仿真0时刻开始执行其中的行为语句;最后一条执行完成后,再开始执行其中的第一条语句,如此往复循环,直到整个仿真结束。
因此,always语句块常用于对数字电路中一组反复执行的活动进行建模。
比如大家熟知的时间信号发生,每半个时钟周期时钟信号翻转一次。
11、任务和函数的区别
(1)函数只能与主模块共用一个仿真时间单位、而任务可以定义自己的仿真时间单位。
(2)函数不能启动任务,而任务能启动其他任务和函数
(3)函数至少要有一个输入变量,而任务可以没有或有多个任何类型的变量(4)函数返回一个值,而任务不返回值
12、生产FPGA的两大厂商
Xilinx(赛灵思)、Altera(阿尔特拉)
13、常见的硬件描述语言
VHDL /System C/ Verilog/Cynlib C++/superlog
14、条件语句一定要完整?
条件语句完整---形成组合逻辑电路
不完整条件语句—形成时序逻辑电路
15、assign—wire wire--reg
wire型用于assign的赋值,always@块下的信号用reg型。
这里的reg并不是真正的触发器,只有敏感列表内的为上升沿或下降沿触发时才综合为触发器。
时钟代码:
output [31:0] counter_out;
reg [31:0] counter_out;
always @ (posedge CLOCK_50) // on positive clock edge begin
counter_out <= #1 counter_out + 1;// increment counter end
endmodule // end of module counter
跑马灯代码:
第二种:
数码管代码:
module
my_third1(a,b,c,d,a_1,a_2,a_3,a_4,a_5,a_6,a_7,e); input
a,b,c,d;
output
a_1,a_2,a_3,a_4,a_5,a_6,a_7,e;
reg a_1,a_2,a_3,a_4,a_5,a_6,a_7;
integer e;
always @(*)
begin
if(a==0&&b==0&&c==0&&d==0)begin a_1=0;
a_2=0;
a_3=0;
a_4=0;
a_5=0;
a_6=0;
a_7=1;
e=0;
end
else
if(a==0&&b==0&&c==0&&d==1)begin a_1=1;
a_2=0;
a_3=0;
a_4=1;
a_5=1;
a_6=1;
a_7=1;
e=1;
end
else
if(a==0&&b==0&&c==1&&d==0)begin a_1=0;
a_2=0;
a_3=1;
a_4=0;
a_5=0;
a_6=1;
a_7=0;
e=2;
end
else
if(a==0&&b==0&&c==1&&d==1)begin a_1=0;
a_2=0;
a_3=0;
a_4=0;
a_5=1;
a_6=1;
a_7=0;
e=3;
end
else
a_1=1;
a_2=0;
a_3=0;
a_4=1;
a_5=1;
a_6=0;
a_7=0;
e=4;
end
else
if(a==0&&b==1&&c==0&&d==1)begin a_1=0;
a_2=1;
a_3=0;
a_4=0;
a_5=1;
a_6=0;
a_7=0;
e=5;
end
else
if(a==0&&b==1&c==1&&d==0)begin a_1=0;
a_2=1;
a_3=0;
a_4=0;
a_5=0;
a_6=0;
a_7=0;
e=6;
end
else
if(a==0&&b==1&&c==1&&d==1)begin a_1=0;
a_2=0;
a_3=0;
a_4=1;
a_5=1;
a_6=1;
a_7=1;
e=7;
end
else
a_1=0;
a_2=0;
a_3=0;
a_4=0;
a_5=0;
a_6=0;
a_7=0;
e=8;
end
else
if(a==1&&b==0&&c==0&&d==1)begin
a_1=0;
a_2=0;
a_3=0;
a_4=0;
a_5=1;
a_6=0;
a_7=0;
e=9;
end
end
endmodule
半加器的实现:
原理:半加器是由两个一位输入实现的,与全加器的区别是不带进位加,相对比较简单,其逻辑关系为:
进位输出:Ci+1=Ai*Bi
和输出:Si = Ai^Bi
其中*为与逻辑,^为异或逻辑。
verilog 实现:
module half_adder(a,b,sum,cout);
input a;
input b;
output sum;
output cout;
assign sum = a^b;assign cout = a&b;endmodule
全加器:
原理:相对与半加器带进位运算,相应的逻辑关系都是通过真值表简化得到的。
进位输出:Ci+1= AiBi+AiCi+BiCi=AiBi+(Ai+Bi)Ci
和输出:Si=Ai^Bi^Ci
以下代码是用两个半加器和一个或门写成的。
module full_adder(a,b,co,sum,cout);
input a;
input b;
input co;
output sum;
output cout;
wire sum1;
wire cout1,cout2;
half_adder half_adder1(.a(a),.b(b),.sum(sum1),.cout(cout1)); half_adder half_adder2(.a(co),.b(sum1),.sum(sum),.cout(cout2)); assign cout = cout1|cout2;
endmodule
四位加法器:
最最可爱的九日2018/12/28 23:17:40
module adderN #(parameter N=4)(
input[N-1:0] a,
input[N-1:0] b,
input cin,
output cout,
output[N-1] sum
);
assign{cout,sum)=a+b+cin;
endmodule
//一位全加器
module full_adder(a,b,Cin,sum,Cout);
input a,b;
input Cin;
output sum;
output Cout;
wire t1,t2,t3;
wire s1;
xor (s1,a,b);
xor (sum,s1,Cin);
and (t3,a,b);
and (t2,b,Cin);
and (t1,a,Cin);
or (Cout,t1,t2,t3);
endmodule
//四位全加器设计
module full_adder4(a,b,Cin,sum,Cout);
input [4:1] a,b;
input Cin;
output [4:1]sum;
output Cout;
wire Cout1,Cout2,Cout3;
full_adder f1(a[1],b[1],Cin,sum[1],Cout1); full_adder f2(a[2],b[2],Cout1,sum[2],Cout2); full_adder f3(a[3],b[3],Cout2,sum[3],Cout3); full_adder f4(a[4],b[4],Cout3,sum[4],Cout);
endmodule
//二选一多路选择器
module muxtwo(Cout,c0,c1,p);
input c0,c1,p;
output Cout;
wire np,sela,selb;
not (np,p);
and (sela,c1,np);
and (selb,c0,p);
or (Cout,sela,selb);
endmodule
一位全加器
module add1(a,b,s,co);
input a,b;
output s,co;
assign co=a & b;
assign s=a ^ b; endmodule。