verilog笔记
- 格式:doc
- 大小:5.67 MB
- 文档页数:12
⾃⼰整理的:学习verilogDHL问题笔记——Quartus常见错误我初学verilog语⾔,很多细节都没注意,按着⾃⼰的思想就写了,编译的时候才发现各种问题。
这些都是我在学习中遇到的问题,还是很常见的。
1.Error (10028): Can't resolve multiple constant drivers for net ……解析:不能在两个以上always内对同⼀变量赋值,这个细节⼀般看书看资料会看到,但是编程时,就是没想到。
2.Error (10158): Verilog HDL Module Declaration error at clkseg.v(1): port "XXXX" is not declared as port解析:⼤意了,端⼝类型还没定义啊!3.Error (10110): variable "en" has mixed blocking and nonblocking Procedural Assignments -- must be all blocking or all nonblocking assignments解析:en在程序中有时⽤⾮阻塞赋值,有时⽤阻塞赋值,这是禁⽌的。
在初学的时候,可能分得不是很清楚,所以在检查时,⼀定要⼀步步观察慢慢来。
4.Error (10161): Verilog HDL error at clkseg.v(36): object "count" is not declared解析:这个错误应该很明显啦,只要能读得懂。
5.Error (10170): Verilog HDL syntax error at clkseg.v(37) near text "***"; expecting ";"解析:意思应该也很简单,就是检查的时候要细⼼点。
Verilog笔记.5.同步、异步在数字电路中经常有同步synchronism、异步asynchronism的概念。
异步指输⼊信号和时钟⽆关;同步指输⼊信号和时钟信号有关,实际上就是输⼊信号和时钟信号进⾏了与运算或者与⾮运算。
实际开发中,经常有同步清零、异步清零、同步复位、异步复位等概念,下⾯就给与相关代码演⽰。
简单的异步复位1always @ (posedge clk or negedge rst_n)2if(!rst_n) b <= 1'b0;3else b <= a;简单的同步复位1always @ (posedge clk)2if(!rst_n) b <= 1'b0;3else b <= a;PS:同步复位信号RST必须⾄少长于⼀个时钟周期CLK,否则,这个复位信号引起的变化是不会被检测到的!异步复位、同步释放1always @ (posedge clk)2 rst_nr <= rst_n; //现将异步复位信号⽤同步时钟打⼀拍34always @ (posedge clk or negedge rst_nr)5if(!rst_nr) b <= 1'b0;6else b <= a;78always @ (posedge clk or negedge rst_nr)9if(!rst_nr) c <= 1'b0;10else c <= b;同步复位和异步复位的区别就在于前者的复何信号不能出现在always语句的敏感信号表中,⽆论是同步复位还是异步复位,always语句的结构都是if(Reset)...else... ,否则,综合⼯具将不能正确的综合所有always语句中的赋值最好采⽤⾮阻塞赋值语,否则,可能会导致仿真与综合的不⼀致”。
学习verilog DHL问题笔记——Quartus常见错误我初学verilog语言,很多细节都没注意,按着自己的思想就写了,编译的时候才发现各种问题。
这些都是我在学习中遇到的问题,还是很常见的。
1.Error (10028): Can't resolve multiple constant drivers for net ……解析:不能在两个以上always内对同一变量赋值,这个细节一般看书看资料会看到,但是编程时,就是没想到。
2.Error (10158): Verilog HDL Module Declaration error at clkseg.v(1): port "XXXX" is not declared as port解析:大意了,端口类型还没定义啊!3.Error (10110): variable "en" has mixed blocking and nonblocking Procedural Assignments -- must be all blocking or all nonblocking assignments解析:en在程序中有时用非阻塞赋值,有时用阻塞赋值,这是禁止的。
在初学的时候,可能分得不是很清楚,所以在检查时,一定要一步步观察慢慢来。
4.Error (10161): Verilog HDL error at clkseg.v(36): object "count" is not declared解析:这个错误应该很明显啦,只要能读得懂。
5.Error (10170): Verilog HDL syntax error at clkseg.v(37) near text "***"; expecting ";"解析:意思应该也很简单,就是检查的时候要细心点。
FPGA之有限状态机学习笔记有限状态机(FSM)是由寄存器组合组合逻辑构成的硬件时序电路。
FSM 的状态只可能在同一时钟跳变沿的情况下才能从一个状态转向另一个状态。
Mealy型FSM的下一个状态不仅取决于当前所在状态,还取决于各个输入值。
Moore型FSM的下一个状态只取决于当前状态。
Verilog HDL可以用很多方法描述FSM,最常用的是用always语句和case 语句。
FSM常用模型有Gray和独热码两种,对于用FPGA实现的FSM建议采用独热码。
因为采用独热码可省下许多组合电路的使用,提高电路的速度和可靠性,且总的单元数并无显著增加。
用Verilog语言描述FSM,可以充分发挥硬件描述语言的抽象建模能力。
有限状态机设计的一般步骤:(1)、逻辑抽象,得出状态转换图(2)、状态化简(3)、状态分配(4)、选定触发器的类型并求出状态方程、驱动方程和输出方程(5)、按照方程得出逻辑图以下就是分别用独热码和Gray码实现上述状态的源程序:采用独热码源程序:module fsm(Clock,Reset,A,B,C,D,E,Multi,Contig,Single);input Clock;input Reset;input A,B,C,D,E;output Multi,Contig,Single;reg Multi;reg Contig;reg Single;parameter [6:0]S1=7'b0000001,S2=7'b0000010,S3=7'b0000100,S4=7'b0001000,S5=7'b0010000,S6=7'b0100000,S7=7'b1000000;parameter U_DL Y=1;reg [6:0] curr_st;reg [6:0] next_st;always @(posedge Clock or posedge Reset) beginif(!Reset)curr_st=S1;elsecurr_st= #U_DL Y next_st;endalways @(curr_st or A or B or C or D or E) begincase(curr_st)S1:beginMulti =1'b0;Contig =1'b0;Single =1'b0;if(A&~B&C)next_st =S2;else if(A&B&~C)next_st =S4;elsenext_st =S1;endS2:beginMulti =1'b1;Contig =1'b0;Single =1'b0;if(!D)next_st =S3;elsenext_st =S4;endS3:beginMulti =1'b0;Contig =1'b1;Single =1'b0;if(A|D)next_st =S4;elsenext_st =S3;endS4:beginMulti =1'b1;Contig =1'b1;Single =1'b0;if(A&B&~C)next_st =S5;elsenext_st =S4;endS5:beginMulti =1'b1;Contig =1'b0;Single =1'b0;next_st =S6;endS6:beginMulti =1'b0;Contig =1'b1;Single =1'b1;if(!E)next_st =S7;elsenext_st =S6;endS7:beginMulti =1'b0;Contig =1'b1;Single =1'b0;if(E)next_st =S1;elsenext_st =S7;enddefault:next_st =S1;endcaseendendmoduleModelsim仿真激励文件程序如下:`timescale 1 ns/ 1 psmodule fsm_vlg_tst();// constants// general purpose registersreg eachvec;// test vector input registersreg A;reg B;reg C;reg Clock;reg D;reg E;reg Reset;// wireswire Contig;wire Multi;wire Single;// assign statements (if any)fsm i1 (// port map - connection between master ports and signals/registers .A(A),.B(B),.C(C),.Clock(Clock),.Contig(Contig),.D(D),.E(E),.Multi(Multi),.Reset(Reset),.Single(Single));initialbeginClock=0;forever #10Clock=~Clock;endinitialbeginReset=0;#100Reset=1;endinitialbegin//{A,B,C,D,E}=5'b10101;//# 10// {A,B,C,D,E}=5'b11000;{A,B,C,D,E}=5'b10111;//A=1;//B=0;//C=1;#100//{A,B,C,D,E}=5'b10101;D=0;#50//{A,B,C,D,E}=5'b10111;A=1;D=1;#50//{A,B,C,D,E}=5'b11011;A=1;B=1;C=0;#100//{A,B,C,D,E}=5'b11010;E=0;#50//{A,B,C,D,E}=5'b11011;E=1;endendmodule注:initial块中语句是顺序执行的,因此在需要延时的时候,按相对时间延时。
(笔记)关于Verilog中的⼀元约简运算符从毕业到现在已经接触Verilog有段时间了,然后今⽇在⼀个⽂件中见到⼀段Verilog代码,让我有些摸不着头,代码内容如下:if (&compare_valid & rdata_valid_flag_reg & pnf_persist_compare)pnf_persist1 <= 1'b1;elsepnf_persist1 <= 1'b0;对于第⼀个运算符硬是没想起来怎么⽤到如此⽤法,实为惭愧。
只好借助强⼤的⾕歌了,经查后得知,原来这个叫⼀元约简运算符。
具体解释是这样的:⼀元约简运算符是单⽬运算符,其运算规则类似于位运算符中的与、或、⾮,但其运算过程不同。
约简运算符对单个操作数进⾏运算,最后返回⼀位数,其运算过程为:⾸先将操作数的第⼀位和第⼆位进⾏与、或、⾮运算;然后再将运算结果和第三位进⾏与、或、⾮运算;依次类推直⾄最后⼀位。
常⽤的约简运算符的关键字和位操作符关键字⼀样,仅仅由单⽬运算和双⽬运算的区别。
如果看到这⾥依然不能理解的我给出⼀个⼀元简约运算符的 Verilog 实例如下:wire [3 : 0] wire1;wire wire2;assign wire1 = 4'b1010;assign wire2 = &wire1; //&即为⼀元约简运算符“与”其等效为:wire [3 : 0] wire1;wire wire2;assign wire1 = 4'b1010;assign wire2 = wire1[0] & wire1[1] & wire1[2] & wire1[3]; //即为⼀元约简运算符“与” 等效效果相信这些可以让更多⼈理解了吧。
LCD1602显示源程序如下:module lcd1602(input clk, //60Minput rst_n,output lcd_p, //Backlight Source + lcd屏幕背光output lcd_n, //Backlight Source -output reg lcd_rs, //0:write order; 1:write dataoutput lcd_rw, //0:write data; 1:read dataoutput reg lcd_en, //negedge 在lcd_en下降沿需保证数据有效output reg [7:0] lcd_data);mux16mul(.rst_n(rst_n),.clk(clk),.start(start),.ain(data0),.bin(data1),.yout(data2),.done(done));//端口名称关联//--------------------lcd1602 order----------------------------parameter Mode_Set = 8'h31, //功能设置,Cursor_Set = 8'h0c, //光标设置Address_Set = 8'h06, //输入模式设置Clear_Set = 8'h01; //清屏设置/****************************LCD1602 Display Data****************************/ wire [7:0] data_r0,data_r1,data_r2; //乘数、被乘数wire [15:0]data0,data1; //结果显示wire [31:0]data2;wire [7:0] addr; //write addresswire start,done;assign data_r0 = 8'h30 + data0[7:0] ; // 8'h30在LCD1602上显示值为0。
总线是运算部件之间数据流通的公共通道。
在硬件逻辑构成的运算电路中只要电路的规模允许,我们可以比较自由地来确定总线的位宽,因此可以大大提高数据流通的速度。
适当的总线位宽,配合适当并行度的运算逻辑和步骤,就能显著地提高专用信号处理逻辑电路的运算能力。
各运算部件和数据寄存器组可以通过带控制端的三态门与总线的连接。
通过对控制端电平的控制来确定在某一时间片段内,总线归哪两个或哪几个部件使用(任何时间片段只能有一个部件发送,但可以有一个或几个接受)。
用Verilog描述总线和总线操作是非常简单的。
下面是一个简单的与总线有借口的模块是如何对总线进行操作的例子:module SampleOfBus ( DataBus, link_bus, write);inout [11:0] DataBus; //12位宽的总线双向端口input link_bus; //向总线输出数据的控制电平reg [11:0] outsigs; //模块内12位宽数据寄存器assign DataBus = (link_bus) ? outsigs : 12'hzzz;//当link_bus为高电平时通过总线把储存在outsigs的计算结果输出always @( posedge write) //每当write信号上跳沿时begin //接受总线上数据并乘以outsigs <=DataBus*5; //把计算结果存入outsigs endendmodule问题:(1)always里面必须是寄存器型,所以mc要改成寄存器型(2)assign必须是用网线型,所以可以改用mc部分赋值的方法给端口(3)case语句里面含有无关量“x" 要用casex,否则case里面永远不能匹配(4)输入输出端口像你样写,S被理解成8位的输入,同理,gs,es被理解成3位输出(5)always后的敏感变量列表中要加上smodule en(incode,outcode,s,gs,es);wire对应于连续赋值,如assign,只用一次reg对应于过程赋值,如always,initial具体就是将一条机器指令编写成一段微程序。
verilog中的位运算符,缩位运算符和逻辑运算符的说明
1,位运算符
按位运算的运算符是位运算符,原来的操作数有几位,结果就有几位,若两个操作数位数不同,则位数短的操作数左端会自动补0(两个数右端对齐,位数少的操作数会在相应的高位补0)。
(1),按位取反:~
(2),按位与:&
(3),按位或:|
(4),按位异或:^
(5),按位同或:^~或~^
2,缩位运算符(又称归约运算符)
缩位运算符是单目运算符,按位进行逻辑运算,结果是一位值!
(1),与缩位运算符:&
(2),或缩位运算符:|
(3),异或缩位运算符:^
(4),与,或,异或运算符和非运算符组成的复合运算符:~&,~|,~^
3,逻辑运算符(逻辑关系运算)
(1),逻辑与:&&
(2),逻辑或:||
(3),逻辑非:!
其中,逻辑与和逻辑或是双目运算符,逻辑非是单目运算符。
如果操作数是多位的,则将操作数看做整体,若操作数中每一位都是0值则为逻辑0值,若操作数当中有1,则做位逻辑1值。
4,相等与全等运算符
(1),==
(2),!=
(3),===
(4),!==
== 、!= 、===、!== 符号之间不能有空格。
“==”和“!=”称作逻辑等式运算符,其结果由两个操作数的值决定。
由于操作数可能是x或z,其结果可能为x;
“===”和“!==”常用于case表达式的判别,又称作cae等式运算符。
其结果只为0和1.如果操作数中存在x和z,那么操作数必须完全相同结果才为1,否则为0.
逻辑等式运算符和case等式运算符的区别:。
FPGA笔记之verilog语言(基础语法篇)笔记之verilog语言(基础语法篇)写在前面:verilogHDL语言是面对硬件的语言,换句话说,就是用语言的形式来描述硬件线路。
因此与等软件语言不同,假如想要在实际的中实现,那么在举行verilog语言编写时,就需要提前有个硬件电路的构思和主意,同时,在编写verilog语言时,应当采纳可综合的语句和结构。
1. verilog 的基础结构1.1 verilog设计的基本单元——module在数字电路中,我们经常把一些复杂的电路或者具有特定功能的电路封装起来作为一个模块用法。
以后在运用这种模块化的封装时,我们只需要知道:1.模块的输入是什么;2.模块的输出是什么;3.什么样的输入对应什么样的输出。
而中间输入是经过什么样的电路转化为输出就不是我们在用法时需要特殊重视的问题。
当无数个这样的模块互相组合,就能构成一个系统,解决一些复杂的问题。
verilog语言的基础结构就是基于这种思想。
verilog中最基本的模块是module,就可以看做是一个封装好的模块,我们用verilog来写无数个基本模块,然后再用verilog描述多个模块之间的接线方式等,将多个模块组合得到一个系统。
那么一个module应当具有哪些要素呢?首先对于一个module,我们应当设计好其各个I/O,以及每个I/O的性质,用于与模块外部的信号相联系,让用法者知道如何连线。
第二,作为开发者,我们需要自己设计模块内部的线路来实现所需要的功能。
因此需要对模块内部浮现的变量举行声明,同时通过语句、代码块等实现模块的功能。
综上所述,我们把一个module分成以下五个部分:模块名端口定义I/O解释第1页共9页。
Systemverilog数据类型l 合并数组和非合并数组1)合并数组:存储方式是连续的,中间没有闲置空间。
例如,32bit的寄存器,可以看成是4个8bit的数据,或者也可以看成是1个32bit 的数据。
表示方法:数组大小和位,必须在变量名前指定,数组大小必须是【msb:lsb】Bit[3:0] [7:0] bytes ;(2)二维数组和合并数组识别:合并数组:bit [3:0] [7:0] arrys; 大小在变量名前面放得,且降序二维数组:int arrays[0:7] [0:3] ; 大小在变量名后面放得,可降序可升序位宽在变量名前面,用于识别合并和非合并数组,位宽在后面,用于识别数组中元素个数。
3)非合并数组一般仿真器存放数组元素时使用32bit的字边界,byte、shortint、int都放在一个字中。
、非合并数组:字的地位存放变量,高位不用。
表示方法:Bit [7:0] bytes;4)合并数组和非合并数组的选择(1)当需要以字节或字为单位对存储单元操作。
(2)当需要等待数组中变化的,则必须使用合并数组。
例如测试平台需要通过存储器数据的变化来唤醒,需要用到@,@只能用于标量或者合并数组。
Bit[3:0] [7:0] barray[3] ; 表示合并数组,合并数组中有3个元素,每个元素时8bit,4个元素可以组成合并数组可以使用barry[0]作敏感信号。
¥l 动态数组随机事物不确定大小。
使用方法:数组在开始是空的,同时使用new[]来分配空间,在new[n]指定元素的个数。
Int dyn[];Dyn = new[5]; Ref int array[ ]);If(len<0) begin$display(“Bad len”);【Returun;rant,.request,.rst,.clk);Test t1(arbif);Endmodule[l Modport背景:端口的连接方式包含了方向信息,编译器依次来检查连续错误;接口使用无信号的连接方式。
可综合的verilog 语法子集
常用的 RTL 语法结构如下:
模块声明: module…endmodule。
端口声明:input,output,inout(inout 的用法比较特殊,需要注意)。
信号类型:wire,reg,tri 等,integer 常用语for 语句中(reg,wire
是最常用的,一般tri 和integer 用在测试脚本里)。
参数定义:parameter定义参数,只在文件中有效,define。
在整个
运算操作符:各种逻辑操作符、移位操作符、算术操作符大多时可综合
的(注:===与!==是不可综合的)。
比较判断:if…else,case(casex,casez)…default…endcase。
连续赋值:assign,问号表达式(?:)。
always 模块:(敏感表可以为电平、沿信号posedge/negedge;通常和
@连用)。
begin…end(通俗的说,它就是 C 语言里的“{ }”)。
任务定义:task…endtask。
循环语句:for(用的也比较少,但是在一些特定的设计中使用它会起
到事半功倍的效果)。
赋值符号:= 和 <= (阻塞和非阻塞赋值,在具体设计中时很有讲究的)。