文档库 最新最全的文档下载
当前位置:文档库 › 我的Verilog学习笔记1

我的Verilog学习笔记1

我的Verilog学习笔记1
我的Verilog学习笔记1

Verilog学习笔记

1.我的第一个verilog程序:三态门

module three_status_device(in,out,oe);

input in,oe;

output out;

assign out = (oe)? in : 1'bz;

endmodule

其中oe为输出有效端,当oe置高则输入能顺利通过,否则输出高阻态。

查看Technology Schematic后可知three_status_device模块使用的FPGA内部资源:

分别是输入缓冲器IBUF,非门INV和三态缓冲器OBUFT。

我们还可以通过View Synthesis Report来观察到底使用了多少资源:

我们可以看出所选的芯片类型为V5系列的fx100,SPEED等级为-2,使用了1个查找表,1个Flip Flop触发器和3个IO口。

由于模块比较简单,我们直接进入后仿真阶段;

最后,我们可以通过中的View HDL Instantiation

Template看到生成的HDL模板供我们调用实例:

three_status_device instance_name (

.in(in),

.out(out),

.oe(oe)

);

小结:通过设计三态门,熟悉了verilog开发的主要流程和ise中的常用工具。

反思:

对于高阻态,一般FPGA内部是不支持判断的。现在有些比较新的FPGA内部已经带有BUFT三态门让用户直接调用(在IOB中),而对于市面上常用的FPGA则无法做到,因为内部并没有BUFT三态门,所以就需要用到slice资源中的MUX复用器,用MUX除了多占用LC/LE的资源以外,受控信号(如数据总线等)会随着驱动源的增加而使延时加大。也有说法是使用RAM或ROM的总线结构提供高阻态的输出。

在FPGA开发时,一般将不用的IO口设置为三态状态,如果IO口较多的时候既占用连线资源也占用slice资源,对系统产生延迟。

2.组合逻辑:有毛刺怎么办?

引用《数字电路基础》的描述,当一个逻辑门的两个输入端的信号同时向相反方向变化,而变化的时间有差异的现象,称为竞争。由竞争而可能产生的输出干扰脉冲的现象就叫做冒险,也就是通俗上说的毛刺。

书上还给出了常用的消除竞争冒险的方法:○1消除互补相乘项:通过人为优化逻辑表达式,消去同一信号的同反相同时存在项,降低竞争的发生几率。○2增加乘积项避免互补项相加:若组合逻辑表达式中,在某些信号取一定值的情况下,表达式可化为一个信号的同反相同时相乘或相加时,则需要人为加入相乘项以确保此时输出状态的稳定。

那么在verilog如何实现消除毛刺呢?

信号在fpga器件中通过逻辑单元连线时,一定存在延时。延时的大小不仅和连线的长短和逻辑单元的数目有关,而且也和器件的制造工艺、工作环境等有关。因此,信号在器件中传输的时候,所需要的时间是不能精确估计的,当多路信号同时发生跳变的瞬间,就产生了“竞争冒险”。这时,往往会出现一些不正确的尖峰信号,这些尖峰信号就是“毛刺”。另外,由于fpga以及其它的cpld器件内部的分布电容和电感对电路中的毛刺基本没有什么过滤作用,因此这些毛刺信号就会被“保留”并传递到后一级,从而使得毛刺问题更加突出。尽管毛刺持续时间很短,但在高速电路中,这样的毛刺足以使后一级电路产生“误动作”。

要消除毛刺,我们先要了解FPGA内部毛刺的具体特点:由于布线延迟,和器件延迟,取决于FPGA内部结构,这个涉及到约束问题,

https://www.wendangku.net/doc/f616941148.html,/shineboy19850420/blog/09-10/178252_efbd3.html,由于接触不多,不在此进行讨论。通过阅读资料,可以知道大多数毛刺都比较短(大概几个纳秒),只要毛刺不出现在时钟跳变沿,毛刺信号就不会对系统造成危害。

FPGA中消除毛刺的常用方法是:

1.触发器输出

通过添加触发器,使输出信号在clk跳变沿进行读取,并输出,能有效地降低毛刺的发生几率。但这样的话,延时也就增大。但是,毛刺的产生是不定时的,如果毛刺在时钟跳变时期产生,则使用触发器的方法无法解决问题。

2.信号延时法

信号延时法,顾名思义,延时信号处理时期,等待信号稳定时再对数据进行处理。

它的具体做法有很多:

○1信号延时检测

信号延时方法很多,如使用门级电路延时,fpga的专用延时单元lcell,毛刺的产生随机性,单凭延时是无法解决问题的。

○2时钟延时

像使用触发器的原理类似,通过增加时钟计数器,对时钟进行分频,加大时钟间隔,来保证对信号进行处理的时候信号已经稳定;或者为防止在信号检测时钟跳变时,信号发生变化,延时对信号检测时间,比如加入标志位寄存器,信号跳变后的下一个检测时钟对其检测。这针对检测时期瞬变信号导致检测错误的方法。

○3状态机检测

使用状态机对信号进行多次检测,首先第一次检测信号,进入下一状态,再次检测信号并与前面进行比较,如果不同则重新开始检测知道检测一定次数后确定信号不变动后,进行数据处理。这种方法结合了上述方法,极好地消除了竞争冒险。

信号延时法缺点是用速度换取电路的稳定性,我们只能择优而取。

下面我们来看一些例子:

按照设想out=abc+bde;

其时序图要求如下:(用TimingDesigner画图)

下面我们一一验证一下不同方法所实现的逻辑组合的效果。//方法一,直接使用assign语句(数据流)

assign out = a&b&c|d&e&b;

类似的描述组合逻辑方法还有:

always @ (a or b or c or d or e)

begin

temp1 = a&c|d&e; out = temp1&b;

end wire temp1,temp2;

and myand1(temp1,a,b,c); and myand2(temp2,d,e,b); or myor(out,temp1,temp2);

由于表达式out=abc+bde可转换成out=b(ac+de),因此b的取值至关重要,当输入信号b变为0时,输出即变为0,所以上述语句一般写成:

wire temp;

assign temp = a&c|d&e;

assign out = temp&b;

这样一来,当b变为0,输出立即变化,这就是关键路径的选取。

关键路径所生成的RTL结构如下:

与没有选取关键路径相比:

由行为仿真波形可以看出,这样的逻辑设计与设想相同:

我们通过修改仿真文件.twf 对某些输入信号进行人为的延时,观察加入延时后出来的效果:

输入信号波形代码段均写在Initial段中:(我们就在这里修改),为了保持毛刺持续时间尽量满足实际情况(一般为十几ns)所以这里设置延时均为10ns,即在`timescale 1ns/1ps 情况下,使用#10;语句进行延时动作。

initial begin

// ------------- Current Time: 490ns

#490;

a = 1'b1;

b = 1'b1;

c = 1'b1;

d = 1'b1;

// -------------------------------------

// ------------- Current Time: 1090ns

#600; a = 1'b0; c = 1'b0;

#10; e = 1'b1;

#10; b = 1'b0;

// -------------------------------------

// ------------- Current Time: 1690ns

#600; b = 1'b1;

#10; e = 1'b0;

// -------------------------------------

// ------------- Current Time: 2290ns

#600; e = 1'b1;

// -------------------------------------

// ------------- Current Time: 2690ns

#400; e = 1'b0;

// -------------------------------------

// ------------- Current Time: 3090ns

#400; e = 1'b1;

#10; b = 1'b0; c = 1'b1;

// -------------------------------------

// ------------- Current Time: 3690ns

#600; b = 1'b1;

#10; d = 1'b0;

#10; a = 1'b1;

// -------------------------------------

end

仿真出来的效果(毛刺出现了)

可见,尽管做出了关键路径的选取,组合逻辑电路还是非常容易产生毛刺。下面我们使用上面的说法,加入寄存器后观察结果。

reg out; wire temp;

assign temp = a&b&c|d&e&b;

always @ (posedge clk)

out = temp;

从RTL结构图中可以直观看到加入D触发器(即寄存器)输出:

依旧采用改动后的仿真文件,所得出的仿真波形如下:

可见,上面的毛刺完全被消除了,而且不留一点痕迹。

由于使用触发器免不了使用时钟,详细的使用放到后面的时序电路学习一节中。

小结:从本节中,实现了简单的逻辑组合,并透过阅读修改仿真文件,了解毛刺的产生;通过观察RTL结构图,了解到代码风格与生成的模型之间的联系,并通过使用D触发器消除毛刺。

反思:如果外部情况比较恶劣,延时级别大于ns级,或者输入信号的跳变在时钟跳变时期发生,会产生什么效果,这需要在后面的学习中逐步体会。

3.使用组合逻辑:加法器的设计

一个设计,其实现方案多样,而且不同的实现方案,电路结构是不一样的,这将导致速度或使用资源的差异。所以,在学习过程中,需要对不同的方法进行比较,了解各种编码风格实现的差别,对将来的系统设计有极大的帮助。下面我们以加法器的设计为引导,延伸本节的讨论。

首先,我们要知道一个加法器模型应该有的端口,他们分别为:加数,被加数,上级进位,和,进位这几个端口。注意verilog的编码规范,模块端口有高位至低位,从输出到输入进行描述:module adder(cout,sum,clk,rst,a,b,cin);

(1)实现方法一

assign { cout, sum } = a + b + cin;

这样看来,加法器的实现非常简单,从结构上看,它直接调用了一个加法器(如图):

但是对于“+”号的综合,FPGA内部是采用查找表所实现的,下面是由上述语句生成的二级查找表结构:(查找表的级数是延时的主要因素,降低查找表级数是代码优化的首要任务)

其中LUT3_E8表示3输入查找表,E8指查找表内部真值表的结果值。

由于使用查找表实现,容易出现毛刺,我们回顾下上一节所用到的方法,我们再使用一次:

再次出现了D触发器。(仿真波形就不看了,大家可以自己试试)

(2)串行加法器

wire [1:0] temp;

assign { temp[0],sum[0] } = a[0] + b[0];

assign { temp[1],sum[1] } = a[1] + b[1] + temp[0];

assign cout = temp[1];

虽然咋一看,与第一种方法相当类似,你确定是一样吗?我们看看生成的

,如下图:

我们可以看出,这样的代码,只使用了一级的LUT,这样设计有助于降低延时,而且并没有增多LUT的使用量,反而少用一个LUT。

可见资源利用率是第二种略为节省些。

(3)查找法

reg [1:0] sum; reg cout;

always @ (posedge clk or negedge rst)

begin

if(!rst)

{cout,sum}=3'bzzz;

else

case( {a,b} )

4'b00_00:{cout,sum}=3'b000; 4'b00_01:{cout,sum}=3'b001;

4'b00_10:{cout,sum}=3'b010; 4'b00_11:{cout,sum}=3'b011;

4'b01_00:{cout,sum}=3'b001; 4'b01_01:{cout,sum}=3'b010;

4'b01_10:{cout,sum}=3'b011; 4'b01_11:{cout,sum}=3'b100;

4'b10_00:{cout,sum}=3'b010; 4'b10_01:{cout,sum}=3'b011;

4'b10_10:{cout,sum}=3'b100; 4'b10_11:{cout,sum}=3'b101;

4'b11_00:{cout,sum}=3'b011; 4'b11_01:{cout,sum}=3'b100;

4'b11_10:{cout,sum}=3'b101; 4'b11_11:{cout,sum}=3'b110;

default:{cout,sum}=3'bzzz;

endcase

end

我们看生成的RTL图如下:

可见编译器知道我们的用意,使用了ROM作为查找的存储,加数为取址信号。

通过观察.ngc文件可知,这样的描述仍然使用了一级的3个LUT,输出使用寄存器同步输出。(4)卡诺图法

我们写出他的真值表,通过卡诺图进行简化,得出各输出的逻辑表达式:

assign sum[0] = (~a[0]&b[0])|(a[0]&~b[0]);

assign sum[1] =

(~a[1]&~a[0]&b[1])|(~a[1]&a[0]&~b[1]&b[0])|(a[1]&a[0]&b[1]&b[0])|(~a[1]&b[1]&~b[0])|(a[1]& ~b[1]&~b[0])|(a[1]&~a[0]&~b[1]);

assign cout = (a[0]&b[1]&b[0])|(a[1]&a[0]&b[0])|(a[1]&b[1]);

这种方法是用门电路数目较多,延时参次不齐,而且使用不方便,但速度相对会快些。

要注意,有时候适当的加上括号,除了有助于阅读,还可以减少逻辑门的级数,下面再举个例子:

assign out = (da + db) + (dc + dd);和assign out = da + db + dc + dd;

da + db + dc + dd生成的模块内部图

(da + db) + (dc + dd)所生成的模块内部图

尽管使用的加法器个数一样,但级数变少了,这样的编码风格,提高了模块运行的速度,但由于FPGA内部使用LUT实现,所以最终对提高速度影响不大,但对于ASIC(专用集成芯片)的模块设计,这样的考虑是很有必要的。

(5)超前加法器

assign sum[0] = a[0] ^ b[0] ^ cin;

assign sum[1] = a[1] ^ b[1] ^ ( (a[0] & b[0]) | (a[0] ^ b[0]) & cin );

assign cout = ( a[1] & b[1] ) | ( (a[1]^b[1]) & (a[0]&b[0]) ) | ( (a[0]^b[0]) & (a[1]^b[1]) & cin ); 根据数电书上的解释,人为地观察进位与输入的关系,由输入直接导出进位是这种方法的核心思想。但我们仍然可以看出,当位数增加的时候,电路的设计变得非常复杂,下面我们通过调用模块来简化多位加法器的设计。

(6)调用模块

module one_bit_adder(cout,sum,cin,ina,inb);

input ina,inb,cin;

output cout,sum;

assign {cout,sum} = ina + inb + cin;

endmodule

//two bit adder (by using one bit adder)

//This is a top module

module use_adder(cout,sum,c,x,y);

input [1:0] x,y;

input c;

output [1:0] sum;

output cout;

wire c_temp;

one_bit_adder u1(.cout(c_temp),.sum(sum[0]),.cin(c),.ina(x[0]),.inb(y[0]));

one_bit_adder u2(.cout(cout),.sum(sum[1]),.cin(c_temp),.ina(x[1]),.inb(y[1]));

endmodule

这里先设计一位计数器(当然,计数器的设计可以使用上面的任何一个例子),然后通过对模块端口的连线,而模块的调用有以下两种方法:

○1模块端口的对齐:即按照模块原型声明的端口顺序

○2模块端口对应连接:使用.端口名(线名),.端口名(线名)……这样的方式进行模块调用,当某一端口需要悬空,必须加上“,”但可以不填写任何东西。

(7)流水线

input[3:0] a,b; input clk,cin;

output[3:0]sum; output cout;

reg[3:0] tempa,tempb; reg tempci;reg cout; reg firstco;

reg[1:0] firstsum; reg[2:0] firsta,firstb;

reg[3:0] sum;

always@(posedge clk)

begin

tempa=a; tempb=b; tempci=cin;

end

always@(posedge clk)

begin

{firstco,firstsum}=tempa[1:0]+tempb[1:0]+tempci;

firsta=tempa[3:2]; firstb=tempb[3:2];

end

always@(posedge clk)

begin

{cout,sum}={firsta[2:0]+firstb[2:0]+firstco,firstsum};

end

endmodule

使用流水线的方法,最重要的是将未用到的数据进行存储,这样做使得流水线不同级之间相互独立,这样做大大提高了速度(除了第一次运算需要额外的两个时钟周期),但是这样的设计使用大量资源,这需要在性能和资源中进行折衷。

使用的资源:

我们从图中可以看出,流水线极大提高了触发器的使用量,是典型的以面积换取速度的例子。

小结:通过对加法器的各种设计以及编码风格,我们可以看出Verilog HDL——硬件描述语言的优势,不同的编码风格所产生的电路在速度与面积上都将产生不同的变化,要学好HDL,则需要经验的积累和对电路结构的了解,必须明白语言与电路之间的对应关系,这样,Verilog 语言才能用得得心应手。

反思:Verilog的编码与FPGA内部结构、内部器件特性有着很大关系,要编写一个好的代码,学习FPGA内部结构成为必不可少的一个阶段。

4.有限状态机

时序电路由组合电路和存储电路组成,时序电路是状态依赖的,所以称为状态机。

其中Melay状态机,其状态与当前状态,输入,输出均有关系,而Moore状态机则只跟当前状态有关,一下用两个实例对其进行探讨。

(1)Melay状态机

module serial_checkout(same,din,clk,rst);

input din; input clk,rst; output same;

reg [2:0] status; reg same_temp;

//Write down your serial which you want to check out

parameter serial_number = 8'h11010011; //check the lowest bit first

parameter bit1 = 1'b1; parameter bit2 = 1'b1; parameter bit3 = 1'b0;

parameter bit4 = 1'b0; parameter bit5 = 1'b1; parameter bit6 = 1'b0;

parameter bit7 = 1'b1; parameter bit8 = 1'b1;

assign same = same_temp;

always @ (posedge clk or negedge rst)

if(rst == 0)

begin

status <= 3'b000; same_temp <= 1'b0;

end

else

case(status)

3'b000:begin

if(din==bit1)

status <= 3'b001;

else

status <= 3'b000;

end

3'b001:begin

if(din==bit2)

status <= 3'b010;

else

status <= 3'b000;

end

3'b010:begin

if(din==bit3)

status <= 3'b011;

else

status <= 3'b000;

end

3'b011:begin

if(din==bit4)

status <= 3'b100;

else

status <= 3'b000;

end

3'b100:begin

if(din==bit5)

status <= 3'b101;

else

status <= 3'b000;

end

3'b101:begin

if(din==bit6)

status <= 3'b110;

else

status <= 3'b000;

end

3'b110:begin

if(din==bit7)

status <= 3'b111;

else

status <= 3'b000;

end

3'b111:begin

if(din==bit8)

same_temp <= 1;

else

status <= 3'b000;

end

endcase

endmodule

上述是使用Melay状态机实现的序列检测模块的完整代码,每一个状态都与输入有关,当所有状态均通过时,same_temp输出1以表示检测到特定序列。

(2)Moore状态机:实现LCD1602的初始化,显示和移位输出

module LCD1602_ctrl_8data(clk,rst,lcd_data,lcd_rs,lcd_rw,lcd_en);

input clk,rst; //系统时钟与系统复位信号

output lcd_rs,lcd_rw,lcd_en; //rs命令/数据选择信号,rw读/写数据选择信号,en操作使能

output [7:0] lcd_data; //8位数据总线//如果要求lcd_data为inout型引脚,这时候只能为wire型,需要使用reg变量驱动他

//暂时没有输入,只作演示说明

reg lcd_rs,lcd_rw,lcd_en;

reg [7:0] lcd_data;

reg [3:0] stage;

reg [7:0] ddram_address;

reg [4:0] shift_count;

reg [7:0] shift_freq;

reg flag,shift_flag;

//命令参数

parameter START =4'b0000;

// RS RW D7 D6 D5 D4 D3 D2 D1 D0

//指令1:清? 0 0 0 0 0 0 0 0 0 1

parameter CLEAR_SCREEN =4'b0001;

//指令2:光标复位0 0 0 0 0 0 0 0 1 0

//光标回到00h地址

parameter CURSOR_BACK =4'b0010;

//指令3:置输入模式0 0 0 0 0 0 0 1 I/D S

//光标和显示模式设置-> I/D:光标移动方向,I/D=1时右移(当读写一个字符后,地址指针加1),I/D=0时左移(当读写一个字符后,地址指针减1)S:当写一个字符屏幕上所有文字是否左移(I/D=1)或者右移(I/D=0)。S=1时表示有效,S=0时则无效parameter SETMODE =4'b0011;

parameter CURSOR_MOVE_RIGHT =1;

parameter CURSOR_MOVE_LEFT =0;

parameter WORD_SHIFT =1;

parameter WORD_NOSHIFT =0;

// RS RW D7 D6 D5 D4 D3 D2 D1 D0

//指令4:显示开关控制0 0 0 0 0 0 1 D C B

//D:控制整体显示的开与关,D=1表示开显示,D=0表示关显示

//C:控制光标的开与关,C=1表示有光标,C=0表示无光标

//B:控制光标是否闪烁,B=1闪烁,B=0不闪烁;闪烁只对于当前地址指针指向的字符位有效。

parameter DISPLAY_CTRL_OFF =4'b0100;

parameter DISPLAY_ON =1;

parameter DISPLAY_OFF =0;

parameter CURSOR_ON =1;

parameter CURSOR_OFF =0;

parameter CURSOR_FLASH_ON =1;

parameter CURSOR_FLASH_OFF =0;

// RS RW D7 D6 D5 D4 D3 D2 D1 D0

//指令5:光标或字符移动0 0 0 0 0 1 S/C R/L 0 0

//S/C:滚动对象选择:S/C=1时移动显示的文字,S/C=0时移动光标

//R/L:滚动方向选择:R/L=1时向右滚动,R/L=0 向左滚动

parameter SHIFT =4'b0101;

parameter SEL_WORD =1;

parameter SEL_CURSOR =0;

parameter RIGHT_SHIFT =1;

parameter LEFT_SHIFT =0;

// RS RW D7 D6 D5 D4 D3 D2 D1 D0

//指令6:功能设置命令0 0 0 0 1 D/L N F 0 0

//D/L:DL=1时为8位总线(DB7-DB0有效),D/L=0?位(DB7-DB4行В?

//N:N=0时为单行显示,N=1时双行显示

//F: F=0时?x7的阏字符,F=1时显示5x10的阏笾?

parameter SETFUNCTION =4'b0110;

parameter DATAWIDTH8 =1;

parameter DATAWIDTH4 =0;

parameter TWOLINE_DISPLAY =1;

parameter ONELINE_DISPLAY =0;

parameter FONT5x10 =1;

parameter FONT5x7 =0;

// RS RW D7 D6 D5 D4 D3 D2 D1 D0 //指令7:置字符发生器贮存地址0 0 0 1 ( AGG )

//AGG:设置CGRAM地址,AGG高三位为自定义字符代码,低三位为字模数据地址(5X8),可最多定义8个字符调用自定义字符时,调?~7这8个址 爰? parameter SETCGRAM =4'b0111;

// RS RW D7 D6 D5 D4 D3 D2 D1 D0 //指令8:置数据存贮器地址0 0 1 ( ADD )

//ADD:DDRAM地址

parameter SETDDRAM =4'b1000;

//指令9:读忙信号(不用)

parameter RESERVE =4'b1001;

// RS RW D7 D6 D5 D4 D3 D2 D1 D0 //指令10:写RAM数据 1 0 ( data

)

parameter WRITE_RAM =4'b1010;

// RS RW D7 D6 D5 D4 D3 D2 D1 D0 //指令11:读RAM数据 1 1 ( data

)

parameter READ_RAM =4'b1011;

parameter STOP =4'b1100;

//parameter DELAY =4'b1101;

parameter DISPLAY_CTRL_ON =4'b1110;

parameter SETFUNCTION2 =4'b1111;

//时钟信号

reg [15:0] clkcnt;

//分频函数

always @ (posedge clk)

begin

if(!rst)

clkcnt<=16'b0000_0000_0000_0000;

else

begin

if(clkcnt==16'b1111_1111_0101_0000)

//if(clkcnt==16'b1001_1100_0100_0000)

//if(clkcnt==16'b1001_1000_0100_0000)

clkcnt<=16'b0000_0000_0000_0000;

else

clkcnt<=clkcnt+1;

end

end

wire tc_clkcnt;

assign tc_clkcnt=(clkcnt==16'b1111_1111_0101_0000)?1:0; //100000? //assign

tc_clkcnt=(clkcnt==16'b1001_1100_0100_0000)?1:0; //80000分频

//assign tc_clkcnt=(clkcnt==16'b1001_1000_0100_0000)?1:0;

//对tc_clkcnt二分频

reg clkdiv;

always @ (posedge tc_clkcnt)

if(!rst)

clkdiv<=0;

else

clkdiv<=~clkdiv;

//对clkdiv二分频

reg clk_int;

always @ (posedge clkdiv)

if(rst==0)

clk_int<=0;

else

clk_int<=~clk_int;

always @ (negedge clkdiv)

if(rst==0)

lcd_en<=0;

else

lcd_en<=~lcd_en;

//为满足总线时序而进行的两次二分频,在rs,rw,io数葑急负煤螅 鼓躤n,所以这里孟跳沿触?

//有限状态机 //reg [15:0] myclkcnt;

//reg myclk;

always @ (posedge clk_int or negedge rst)

if(!rst)

begin

stage<=START;

ddram_address<=8'h80;

shift_flag<=1;

shift_freq<=8'h00;

//ddram_address<=8'b1001_0000; //写DDRAM缓冲区

shift_count<=5'b0_0000;

//myclkcnt<=16'h0000;

flag<=0;

//flag1<=1;

end

else

begin

case(stage)

START :begin

lcd_data<=8'bzzzz_zzzz;

stage<=SETFUNCTION;

end

STOP :begin

stage<=STOP;

end

CLEAR_SCREEN :begin //0000_0001 01H

lcd_rs<=0;

lcd_rw<=0;

lcd_data<=8'b0000_0001;

stage<=SETMODE;

end

SETMODE :begin //0000_0110 06H

lcd_rs<=0;

lcd_rw<=0;

lcd_data[7:2]<=6'b000001;

lcd_data[1]<=CURSOR_MOVE_RIGHT;

lcd_data[0]<=WORD_NOSHIFT;

stage<=DISPLAY_CTRL_ON;

end

CURSOR_BACK :begin //0000_0010 02H

lcd_rs<=0;

lcd_rw<=0;

lcd_data<=8'b00000010;

stage<=SETDDRAM;

end

DISPLAY_CTRL_OFF:begin //0000_1010 08H

lcd_rs<=0;

lcd_rw<=0;

lcd_data[7:3]<=5'b00001;

lcd_data[2]<=DISPLAY_OFF;

lcd_data[1]<=CURSOR_OFF;

lcd_data[0]<=CURSOR_FLASH_OFF;

stage<=CLEAR_SCREEN;

end

DISPLAY_CTRL_ON:begin //0000_1100 0CH

lcd_rs<=0;

lcd_rw<=0;

lcd_data[7:3]<=5'b00001;

lcd_data[2]<=DISPLAY_ON;

lcd_data[1]<=CURSOR_ON;

lcd_data[0]<=CURSOR_FLASH_ON;

stage<=SETDDRAM;

end

SETFUNCTION :begin //0011_1000 38H

lcd_rs<=0;

lcd_rw<=0;

lcd_data[7:5]<=3'b001;

lcd_data[4]<=DATAWIDTH8;

lcd_data[3]<=TWOLINE_DISPLAY;

lcd_data[2]<=FONT5x7;

lcd_data[1:0]<=2'b00;

stage<=SETFUNCTION2;

end

SETFUNCTION2 :begin //0011_1000 38H

lcd_rs<=0;

lcd_rw<=0;

lcd_data[7:5]<=3'b001;

lcd_data[4]<=DATAWIDTH8;

lcd_data[3]<=TWOLINE_DISPLAY;

lcd_data[2]<=FONT5x7;

lcd_data[1:0]<=2'b00;

stage<=DISPLAY_CTRL_OFF;

end

// SETCGRAM :begin

lcd_rs<=0;lcd_rw<=0;data<=8'b01000000;state<=START;end

SETDDRAM :begin //1XXX_XXXX

lcd_rs<=0;

lcd_rw<=0;

lcd_data[7:0]<=ddram_address;

stage<=WRITE_RAM;

end

// SETDDRAM1 :begin

lcd_rs<=0;lcd_rw<=0;data<=8'b11000000;state<=WRITERAM;end //设置第二行首地址

WRITE_RAM :begin //XXXX_XXXX

if(ddram_address<=8'h8F)

//if(ddram_address<=8'h9F)

begin

lcd_rs<=1; //写数据

lcd_rw<=0;

//data<=ddram(address);

case(ddram_address)

8'h80:lcd_data<=8'h43; //C

8'h81:lcd_data<=8'h68; //h

8'h82:lcd_data<=8'h61; //a

8'h83:lcd_data<=8'h6e; //n

8'h84:lcd_data<=8'h67; //g

8'h85:lcd_data<=8'h73; //s

8'h86:lcd_data<=8'h68; //h

8'h87:lcd_data<=8'h61; //a

8'h88:lcd_data<=8'h4d;

//M

8'h89:lcd_data<=8'h69; //i

8'h8A:lcd_data<=8'h6e; //n

8'h8B:lcd_data<=8'h67; //g

8'h8C:lcd_data<=8'h77; //w

8'h8D:lcd_data<=8'h65; //e

8'h8E:lcd_data<=8'h69; //i

8'h8F:lcd_data<=8'h21; //!

default:lcd_data<=8'h20;

endcase

ddram_address<=ddram_address+1;

//stage<=WRITE_RAM;

end

else

begin

if (flag==0)

begin

ddram_address<=8'hC0;

flag<=1; //flga指明当前操作的行号,0为第一行,1为第二行

//lcd_data<=8'h20;

lcd_rs<=1;

lcd_rw<=1; //屏蔽下次输入

stage<=SETDDRAM;

end

else

begin

if(ddram_address<=8'hCF)

//if (ddram_address<=8'hDF)

begin

lcd_rs<=1;

lcd_rw<=0;

case(ddram_address)

8'hC0:lcd_data<=8'h44; //D

8'hC1:lcd_data<=8'h65; //e

8'hC2:lcd_data<=8'h73; //s

8'hC3:lcd_data<=8'h69; //i

8'hC4:lcd_data<=8'h67; //g

8'hC5:lcd_data<=8'h6e; //n

8'hC6:lcd_data<=8'h62; //b

8'hC7:lcd_data<=8'h79; //y

8'hC8:lcd_data<=8'h3a; //:

8'hC9:lcd_data<=8'h53; //S

8'hCA:lcd_data<=8'h68; //h

8'hCB:lcd_data<=8'h75; //u

8'hCC:lcd_data<=8'h77; //w

8'hCD:lcd_data<=8'h61; //a

8'hCE:lcd_data<=8'h6e; //n

8'hCF:lcd_data<=8'h67; //g

default:lcd_data<=8'h20;

endcase

ddram_address<=ddram_address+1;

//stage<=WRITE_RAM;

end

else

begin

stage<=SHIFT;

//stage<=STOP;

lcd_rs<=1;

lcd_rw<=1;

//shift_flag<=0;

//lcd_data<=8'h00;

end

end

可综合的Verilog语法子集总汇

常用的RTL语法结构如下: ☆模块声明:module……endmodule ☆端口声明:input,output,inout(inout的用法比较特殊,需要注意) ☆信号类型:wire,reg,tri等,integer常用语for语句中(reg,wire时最常用的,一般tri和integer 不用) ☆参数定义:parameter ☆运算操作符:各种逻辑操作符、移位操作符、算术操作符大多时可综合的(注:===与!==是不可综合的) ☆比较判断:if……else,case(casex,casez)……default endcase ☆连续赋值:assign,问号表达式(?:) ☆always模块:(敏感表可以为电平、沿信号posedge/negedge;通常和@连用) ☆begin……end(通俗的说,它就是C语言里的“{ }”) ☆任务定义:task……endtask ☆循环语句:for(用的也比较少,但是在一些特定的设计中使用它会起到事半功倍的效果) ☆赋值符号:= 和<= (阻塞和非阻塞赋值,在具体设计中时很有讲究的) 可综合的语法时verilog可用语法里很小的一个子集,用最精简的语句描述最复杂的硬件,这也正是硬件描述语言的本质。对于做RTL级设计来说,掌握好上面这些基本语法是很重要。 相信大家在看了这么多了verilog语法书籍以后一定有点烦了,那么现在我告诉大家一个好消息,对于一个RTL级的设计来说,掌握了上面的语法就已经足够了,无论多么牛逼的工程师,在他的代码

里无非也就是上面一些语法而已。当然了,对于一个能够进行很好的仿真验证的代码,一般还需要在RTL级的设计代码中添加一些延时之类的语句,比如大家一定知道#10的作用,就是延时10个单位时间,这个语句虽然在仿真的时候是实实在在的延时,但是这个语句在综合后是会被忽略的,也就是说在我们综合并且布局布线最后烧进FPGA里,这个#10的延时是不会在硬件上实现的。所以说,上面给出的这些语法才是可以最后在硬件上实现的,其它的语法大多会在综合后被忽略。这么一来大家就要问了,为什么语法书里又要给出这么多的语法呢?呵呵,它们大都是为仿真验证是写testbench 准备的,先点到为止,下集继续! 对于模型(module)的建立,要保证可综合性应该注意: (1)不使用initial。(被忽略) (2)不使用#10。(被忽略) (3)不使用循环次数不确定的循环语句,如forever、while等。 (4)不使用用户自定义原语(UDP元件)。 (5)尽量使用同步方式设计电路。 (6)除非是关键路径的设计,一般不采用调用门级元件来描述设计的方法,建议采用行为语句来完成设计。 (7)用always过程块描述组合逻辑,应在敏感信号列表中列出所有的输入信号。 (8)所有的内部寄存器都应该能够被复位,在使用FPGA实现设计时,应尽量使用器件的全局复位端作为系统总的复位。 (9)对时序逻辑描述和建模,应尽量使用非阻塞赋值方式。对组合逻辑描述和建模,既可以用阻塞赋值,也可以用非阻塞赋值。但在同一个过程块中,最好不要同时用阻塞赋值和非阻塞赋值。(10)不能在一个以上的always过程块中对同一个变量赋值。而对同一个赋值对象不能既使用阻塞式赋值,又使用非阻塞式赋值。 (11)如果不打算把变量推导成锁存器,那么必须在if语句或case语句的所有条件分支中都对变量明确地赋值。 (12)避免混合使用上升沿和下降沿触发的触发器。

数字系统设计与verilog HDL课程设计

数字系统设计与verilog HDL课程设计 设计题目:实用多功能数字钟 专业:电子信息科学与技术 班级:0313410 学号:031341025 姓名:杨存智 指导老师:黄双林

摘要 本课程设计利用QuartusII软件Verilog VHDL语言的基本运用设计一个多功能数字钟,经分析采用模块化设计方法,分别是顶层模块、alarm、alarm_time、counter_time、clk50mto1、led、switch、bitel、adder、sound_ddd、sound_ddd_du模块,再进行试验设计和软件仿真调试,分别实现时分秒计时、闹钟闹铃、时分秒手动校时、时分秒清零,时间保持和整点报时等多种基本功能。 单个模块调试达到预期目标,再将整体模块进行试验设计和软件仿真调试,已完全达到分块模式设计功能,并达到设计目标要求。 关键字:多功能数字钟、Verilog、模块、调试、仿真、功能

目录 1.课程设计的目的及任务............................................................. 错误!未定义书签。 1.1 课程设计的目的 (3) 1.2 课程设计的任务与要求 (4) 2.课程设计思路及其原理 (4) 3.QuartusII软件的应用 (5) 3.1工程建立及存盘 (5) 3.2工程项目的编译 (5) 3.3时序仿真 (6) 4.分模块设计、调试、仿真与结果分析 (7) 4.1 clk50mto1时钟分频模块 (7) 4.2 adder加法器模块 (7) 4.3 hexcounter16 进制计数器模块 (7) 4.4 counter_time 计时模块 (8) 4.5 alarm闹铃模块 (8) 4.6 sound_ddd嘀嘀嘀闹铃声模块 (9) 4.7 sound_ddd_du嘀嘀嘀—嘟声音模块 (9) 4.8 alarm_time闹钟时间设定模块 (10) 4.9 bitsel将输出解码成时分秒选择模块 (10) 4.10 switch去抖模块 (11) 4.11 led译码显示模块 (11) 4.12 clock顶层模块 (12) 5.实验总结 (13) 5.1调试中遇到的问题及解决的方法 (13) 5.2实验中积累的经验 (14) 5.3心得体会 (14) 6.参考文献 (14) 1.1 课程设计的目的 通过课程设计的锻炼,要求学生掌握V erilog HDL语言的一般设计方法,掌握VerilogHDL语言的基本运用,具备初步的独立设计能力,提高综合运用所学的理论知识独立分析和解决问题的能力,基于实践、源于实践,实践出真知,实践检验真理,培养学生的

verilog基本语法

Verilog基本语法 【逻辑值】 逻辑0 表示低电平,GND 逻辑1 表示高电平,VCC 逻辑X 表示未知电平,可能是高电平,也可能是低电平 逻辑Z 表示高阻态,外部没有激励信号,是一个悬空状态 注:高阻态的实质:电路分析时高阻态可做开路理解。 可以把它看作输出(输入)电阻非常大,对下级电路无任何影响。 若为0、x、z则按照假处理;若为1,按真处理。 【进制】 二进制4'b0101 —4位二进制数0101 十进制数4’d2 —4位十进制数2 十六进制数4’ha —4位十六进制数a Verilog中若不指定位宽,默认32位;若不指定位宽不指定进制,默认32位宽的十进制数。 【标识符】 标识符可以是字母、数字、$和_(下划线)的组合,且开头必须是字母或下划线,区分大小写。不建议大小写混合使用。 【数据类型】 寄存器关键字reg,默认初始值位不定值X; reg[31:0] delay_cnt; //[31:0],指定寄存器位宽32位, reg key_reg; // 默认位宽为1. reg类型数据只能在always和initial语句中被赋值。 线网表示结构实体的物理连线,包括wire和tri类型 参数常量,用parameter定义。 parameter H_SYNC = 11'd41; 【运算符】 [条件操作符] ?: 例,a?b:c //如果a为真就选b,否则选择c。 result=(a>=b)?a:b; [逻辑运算符] !&& || [位运算符] ~ & | ^(按位异或) a&b; //自动将位宽小的数高位补零至较大数的位宽,然后按位与操作。[移位运算符] << >> 用0填补移出的空位。左移时位宽增加,右移位宽不变。 [位拼接运算符] {} 例,{a,b} //将a和b拼接起来,作为一个新信号,a为高位。 c={a,b[3:0]}; //a、b位宽均为8位,c为8+4=12位。

verilog课程设计—交通灯

课程论文 论文题目基于DE2的交通灯设计完成时间 课程名称Verilog语言设计 任课老师 专业 年级

1.交通信号控制器设计要求与思路 1.1设计背景 FPGA是一种用户根据各自需要而自行构造逻辑功能的数字集成电路,其种类很多,内部结构也不同,但共同的特点是体积小、使用方便。本文介绍了用VerilogHDL语言设计交通灯控制器的方法,并在QuartusII系统对FPGA芯片进行编译下载,由于生成的是集成化的数字电路,没有传统设计中的接线问题,所以故障率低、可靠性高,而且体积非常小。本文通过EDA设计,利用VerilogHDL语言模拟仿真交通灯控制电路。 1.2设计要求 根据交通灯控制器要实现的功能,考虑用两个并行执行的always语句来分别控制A方向和B方向的3盏灯。这两个always语句使用同一个时钟信号,以进行同步,也就是说,两个进程的敏感信号是同一个。每个always语句控制一个方向的3种灯按如下顺序点亮,并往复循环:绿灯----黄灯----红灯,每种灯亮的时间采用一个减法计数器进行计数,计数器用同步预置数法设计,这样只需改变预置数据,就能改变计数器的模,因此每个方向只要一个计数器进行预置数就可以。为便于显示灯亮的时间,计数器的输出均采用BCD码,显示由4个数码管来完成,A方向和B方向各用两个数码管。设定A方向红灯、黄灯、绿灯亮的时间分别为:35s、5s、35s,B方向的红灯、黄灯、绿灯亮的时间分别为:35s、5s、35s。假如要改变这些时间,只需要改变计数器的预置数即可。 1.3设计思路 两个方向各种灯亮的时间能够进行设置和修改,此外,假设B方向是主干道,车流量大,因此B方向通行的时间应该比A方向长。交通灯控制器的状态转换表见下表。表中,1表示灯亮,0表示灯不亮。A方向和B方向的红黄绿分别用R1、Y1、G1、R2、Y2、G2来表示。

FPGA夏宇闻Verilog学习笔记1

V erilog 数字系统设计教程 学习笔记 1 FPGA 学习 由于工作上的需要,现在又开始学习新的芯片,估计以后会在FPGA 和DSP 这两个方向有发展,以前学的ARM 现在可以待业休息了等待新的起点。虽然大学的时候学习过《EDA 技术与VHDL 》这门课程,但是我至今才知道VHDL 语言是FPGA 的设计语言之一。有一个好的指导老师是非常重要的,进入公司后由于实行的是导师制,指导我的导师就让我看《V erilog 数字系统设计教程》,学习一样东西有一本好书是非常重要的,就如同学习C 语言看谭浩强老师的教程,同样学习FPGA 看夏宇闻老师的书一样,确实学到了很多东西,而且会一直研读。 不管学习单片机,ARM ,DSP 还是FPGA 上机练习是非常重要的,所以在学习夏宇闻老师的教程时我就把书中的上机练习题自己练习一遍,并做简要的记录。 设计平台:Quartus II 11.1sp2 Web Edition 仿真平台:ModelSin10.0c Starter Editon 上机练习一 简单的组合逻辑设计 由于是第一个练习,我会将具体的软件使用过程都列出来,方便同我一样的学习者学习。 1、建立一个新的工程 弹出对话框,直接 Next

设置工程目录F:/FPGA V erilog test/lesson1,工程名compare,顶层设计模块名compare 如果你已经有一些要加入工程的文件,可以再该步将文件加入到工程中,没有则直接Next 这一步是选择你需要的设计芯片,由于我们只学习V erilog语言,所以芯片选择随意

V erilog 数字系统设计教程 学习笔记 3 选择仿真语言和综合工具 最后显示我们选择的信息,确认填写是否正确

基于VerilogHDL语言的可综合性设计

基于Verilog HDL语言的可综合性设计 1 引言 逻辑综合带来了数字设计行业的革命,有效地提高了生产率,减少了设计周期时间。在手动转换设计的年代,设计过程受到诸多限制,结更容易带来人为的错误。而一个小小的错误就导致整个模块需进行重新设计,设计转换工作占去了整个设计周期的大部分时间,验证工作进行困难,设计技术无法重用等等。而自动逻辑综合工具的出现,突破了上述种种限制,使得设计者从繁琐的转换工作中解脱出来,将更多的时间用于验证和优化,不仅保证了功能的实现,而且有利于提高性能。可见,综合在逻辑设计中具有举足轻重的作用。 2 综合的概念及其过程 2.1 逻辑综合概述 综合就是在给定标准元件库和一定的设计约束条件下,把用语言描述的电路模型转换成门级网表的过程。要完成一次综合过程,必须包含三要素:RTL级描述、约束条件和工艺库。 2.2 RTL级描述 RTL级描述是以规定设计中采用各种寄存器形式为特征,然后在寄存器之间插入组合逻辑,其可以用如图1所示的“寄存器和云图”方式来表示。 图1 RTL级描述 2.3 约束条件 为了控制优化输出和映射工艺要用约束,它为优化和映射试图满足的工艺约束提供了目标,并且它们控制设计的结构实现方式。目前综合工具中可用的约束包括面积、速度、功耗和可测性约束,未来我们或许会看到对封装的约束和对布图的约束等,但是,目前的最普遍的约束是按面积和按时间的约束。 时钟限制条件规定时钟的工作频率,面积限制条件规定该设计将花的最大面积。综合工具将试图用各种可能的规则和算法尽可能地满足这些条件。 2.4 工艺库 按照所希望的逻辑行为功能和有关的约束建立设计的网表时,工艺库持有综合工具必须的全部信息。工艺库含有允许综合进程为建立设计做正确选择的全部信息,工艺库不仅含有ASIC单元的逻辑功能,而且还有该单元的面积、单元输入到输出的定时关系、有关单元扇出的某种限制和对单元所需的定时检查。

Verilog HDL数字时钟课程设计

课程设计报告 课程设计名称:EDA课程设计课程名称:数字时钟 二级学院:信息工程学院 专业:通信工程 班级:12通信1班 学号:1200304126 姓名:@#$% 成绩: 指导老师:方振汉 年月日

目录 第一部分 EDA技术的仿真 (3) 1奇偶校验器 (3) 1.1奇偶校验器的基本要求 (3) 1.2奇偶校验器的原理 (3) 1.3奇偶校验器的源代码及其仿真波形 (3) 28选1数据选择器 (4) 2.18选1数据选择器的基本要求 (4) 2.28选1数据选择器的原理 (4) 2.38选1数据选择器的源代码及其仿真波形 (5) 34位数值比较器 (6) 3.14位数值比较器的基本要求 (6) 3.24位数值比较器的原理 (6) 3.34位数值比较器的源代码及其仿真波形 (7) 第二部分 EDA技术的综合设计与仿真(数字时钟) (8) 1概述 (8) 2数字时钟的基本要求 (9) 3数字时钟的设计思路 (9) 3.1数字时钟的理论原理 (9) 3.2数字时钟的原理框图 (10) 4模块各功能的设计 (10) 4.1分频模块 (10) 4.2计数模块(分秒/小时) (11) 4.3数码管及显示模块 (13) 5系统仿真设计及波形图........................... 错误!未定义书签。5 5.1芯片引脚图.................................... 错误!未定义书签。5 5.2数字时钟仿真及验证结果 (16) 5.3数字时钟完整主程序 (17) 6课程设计小结 (23) 7心得与体会 (23) 参考文献 (24)

FPGA CPLD设计学习笔记(特权同学完整版)

1、FPGA\CPLD设计学习笔记(特权同学完整版) 题记:这个笔记不是特权同学自己整理的,特权同学只是对这个笔记做了一下完善,也忘了是从那DOWNLOAD 来的,首先对整理者表示感谢。这些知识点确实都很实用,这些设计思想或者也可以说是经验吧,是很值得每一个有志于FPGA/CPLD方面发展的工程师学习的。 1、硬件设计基本原则 (1)、速度与面积平衡和互换原则:一个设计如果时序余量较大,所能跑的频率远高于设计要求,能可以通过模块复用来减少整个设计消耗的芯片面积,这就是用速度优势换面积的节约;反之,如果一个设计的时序要求很高,普通方法达不到设计频率,那么可以通过数据流串并转换,并行复制多个操作模块,对整个设计采用“乒乓操作”和“串并转换”的思想进行处理,在芯片输出模块处再对数据进行“并串转换”。从而实现了用面积复制换取速度的提高。 (2)、硬件原则:理解HDL本质 (3)、系统原则:整体把握 (4)、同步设计原则:设计时序稳定的基本原则 2、Verilog作为一种HDL语言,对系统行为的建模方式是分层次的。比较重要的层次有系统级(system)、算法级(Algorithm)、寄存器传输级(RTL)、逻辑级(Logic)、门级(Gate)、电路开关级(Switch)。 3、实际工作中,除了描述仿真测试激励(Testbench)时使用for循环语句外,极少在RTL级编码中使用for循环,这是因为for循环会被综合器展开为所有变量情况的执行语句,每个变量独立占用寄存器资源,不能有效的复用硬件逻辑资源,造成巨大的浪费。一般常用case语句代替。 4、if…else…和case在嵌套描述时是有很大区别的,if…else…是有优先级的,一般来说,第一个if的优先级最高,最后一个else的优先级最低。而case语句是平行语句,它是没有优先级的,而建立优先级结构需要耗费大量的逻辑资源,所以能用case的地方就不要用if…else…语句。 补充:1.也可以用if…; if…; if…;描述不带优先级的“平行”语句。(但是这样容易引入锁存器) 5、FPGA一般触发器资源比较丰富,而CPLD组合逻辑资源更丰富。 6、FPGA和CPLD的组成: FPGA基本有可编程I/O单元、基本可编程逻辑单元、嵌入式块RAM、丰富的布线资源、底层嵌入功能单元和内嵌专用硬核等6部分组成。 CPLD的结构相对比较简单,主要由可编程I/O单元、基本逻辑单元、布线池和其他辅助功能模块组成。 7、Block RAM: 3种块RAM结构,M512 RAM(512bit)、M4K RAM(4Kbit)、M-RAM(64Kbit). M512 RAM:适合做一些小的Buffer、FIFO、DPRAM、SPRAM、ROM等; M4K RAM: 适用于一般的需求 M-RAM: 适合做大块数据的缓冲区。 Xlinx 和Lattice FPGA的LUT可以灵活配置成小的RAM、ROM、FIFO等存储结构,这种技术被称为分布式RAM。补充:但是在一般的设计中,不提倡用FPGA/CPLD的片内资源配置成大量的存储器,这是处于成本的考虑。所以尽量采用外接存储器。

Verilog课程设计

一.实验目的 (1)学习RISC_CPU的基本结构和原理; (2)了解Verilog HDL仿真和综合工具的潜力; (3)展示Verilog设计方法对软/硬件联合设计和验证的意义; (4)学习并掌握一些常用的Verilog语法和验证方法。 二.实验原理 CPU即中央处理单元的英文缩写,它是计算机的核心部件。计算机进行信息处理可分为两个步骤: (1)将数据和程序(即指令序列)输入计算机的存储器中。 (2)从第一条指令的地址起开始执行该程序,得到所需结果,结束运行。CPU的作用是协调并控制计算机的各个部件并执行程序的指令序列,使其有条不紊地进行。因此它必须具有以下基本功能。 ①取指令——当程序忆在存储器中时,首先根据程序入口地址取出一条程序,为此要发出指令地址及控制信号。 ②分析指令——即指令译码,这是对当前取得的指令进行分析,指出它要求什么操作,并产生相应的操作控制命令。 ③执行指令——根据分析指令时产生的“操作命令”形成相应的操作控制信号序列,通过运算器、存储器及输入/输出设备的执行,实现每条指令的功能,其中包括对运算结果的处理以及下条指令地址的形成。 将CPU的功能进一步细化,可概括如下: (1)能对指令进行译码并执行规定的动作; (2)可以进行算术和逻辑运算; (3)能与存储器和外设交换数据; (4)提供整个系统所需要的控制。 尽管各种CPU的性能指标和结构细节各不相同,但它们所能完成的基本功能相同。由功能分析,可知任何一种CPU内部结构至少应包含下面这些部件:(1)算术逻辑运算部件(ALU); (2)累加器; (3)程序计数器;

(4)指令寄存器和译码器; (5)时序和控制部件。 三.实验内容 通过我们自己动手,设计出一个CPU的软核和固核。这个CPU是一个简化的专门为教学目的而设计的RISC_CPU。在设计中我们不但关心CPU总体设计的合理性,而且还使得构成这个RISC_CPU的每一个模块不仅是可仿真的也都可以综合成门级网表。因而从物理意义上说,这也是一个能真正通过具体电路结构而实现的CPU。为了能在这个虚拟的CPU上运行较为复杂的程序并进行仿真,把寻址空间规定为8K(即13们地址线)字节。 四.实验代码 1.源代码 //----------------------------------clk_gen.v------------------------------ `timescale 1ns/1ns //时间单位1ns,时间单位1ns module clk_gen(clk,reset,fetch,alu_ena); //模块名clk_gen,参数列表(clk,reset,fetch,alu_ena)input clk,reset; //输入clk,reset output fetch,alu_ena; //输出fetch,alu_ena wire clk,reset; //wire型变量clk,reset reg fetch,alu_ena; //reg寄存器型变量fetch,alu_ena reg[7:0]state; //reg寄存器型变量8位的state parameter S1=8'b00000001,S2=8'b00000010,S3=8'b00000100,S4=8'b00001000,S5=8'b00010000,S6=8'b001 00000,S7=8'b01000000,S8=8'b10000000,idle=8'b00000000; //参数型定义8位二进制常量s1,s2,s3,s4,s5,s6,s7,s8,idle always@(posedge clk) //always块时钟触发 if(reset) //如果reset为真 begin //执行begin,and顺序块 fetch<=0; //fetch非阻塞赋值赋为0 alu_ena<=0; //alu_ena非阻塞赋值赋为0 state<=idle; //idle非阻塞赋值给state end else //reset为假执行下面begin语句 begin case(state) //case表达式(state) S1:begin alu_ena<=1; //alu_ena非阻塞赋值赋为1 state<=S2; //state非阻塞赋值赋为S2 end S2:begin alu_ena<=0; //alu_ena非阻塞赋值赋为0 state<=S3; //state非阻塞赋值赋为S3 end

verilog综合心得

综合:不可综合的运算符:= = = ,!= =,/(除法),%(取余数)。 1、不使用初始化语句。 2、不使用带有延时的描述。 3、不使用循环次数不确定的循环语句,如:forever、while等。 4、尽量采用同步方式设计电路。 5、除非是关键路径的设计,一般不调用门级元件来描述设计的方法,建议采用行为语句来完成设计。 6、用always过程块描述组合逻辑,应在信号敏感列表中列出所有的输入信号。 7、所有的内部寄存器都应该能够被复位,在使用FPGA实现设计时,应尽量使用器件的全局复位端作为系统总的复位。 8、在verilog模块中,任务(task)通常被综合成组合逻辑的形式,每个函数(function)在调用时通常也被综合为一个独立的组合电路模块。 9、用户自定义原语(UDP)是不可综合的,它只能用来建立门级元件的仿真模型。 一般综合工具支持的V erilog HDL结构

移位运算符:V erilog HDL提供向右(>>)及向左(<<)两种运算符,运算符高位或地位一旦移出即予丢弃,其空缺的位则予以补零。 连续赋值语句(assign)、case语句、if…else语句都是可以综合的 initial 语句内若包含有多个语句时,必须以begin end 作聚合;单一的初值赋值,因此并不需以begin end做聚合。 循环(Loops)并不能单独地在程序中存在,而必须在initial和always块中才能使用。initial过程块中的语句仅执行一次,而always块中的语句是不断重复执行的。 编写顶层模块的注意事项 每个端口除了要声明是输入、输出还是双向外,还要声明其数据类型,是连线型(wire)还是寄存器型(reg),如果没有声明则综合器默认为wire型。 1、输入和双向端口不能声明为寄存器型。 2、在测试模块中不需要定义端口。 编写testbentch所归纳的心得

基于Verilog的课程设计

基于Verilog的课程设计 直流电机的PWM控制 指导老师:翁嘉民 班级:1031电气自动化技术成员:李高峰9112 王俊才9186 孟令朋9143

目录 1.绪论 (3) 直流电机介绍 (3) 1.1.1直流电机的特点 (3) 1.1.2直流电机的应用 (3) 介绍 (4) 介绍 (4) V ERILOG HDL硬件描述语言 (5) 1.4.1V ERILOG HDL硬件描述语言介绍 (5) 1.4.2V ERILOG HDL功能 (5) PWM脉冲宽度调制介绍 (6) 直流电机的PWM控制 (7) 2.设计原理 (8) 设计原理框图 (8) 原理图 (9) 模块设计 (9) 2.3.1 MOTO_TEST模块 (9) 2.3.4计数器模块 (12) 7实训心得 (13) 参考文献 (13)

直流电机的PWM控制器的设计 1.绪论 直流电机介绍 直流电机是实现直流电能与机械能之间相互转换的一种电力机械,按照直流电机的用途分为直流电动机和直流发电机两类。能够将机械能转换成直流电能的电机称为直流发电机;能够将直流电能转换成机械能的电机称为直流电动机。 1.1.1直流电机的特点 从直流电机与交流电机相比中可以看出,直流电机具有优良的调速性能和启动性能。直流电机具有宽广的调速范围,平滑的无级调速特性,可实现频繁的无级快速启动、制动和反转;过载能力大,能承受频繁的冲击负载;能满足自动化生产系统中各种特殊运行的要求。而直流发电机则能提供无脉动的大功率直流电源,且输出电压可以精确地调节和控制。 1.1.2直流电机的应用 直流电机是交通、工矿、建筑等行业中的常见动力机械,是机电行业人员的重要工作对象和工具。在某些要求调速范围广、速度快、精密度高、控制性能优异的场合,直流电机的应用目前仍占有较大的比重,如大型可逆式轧钢机、内燃机车、矿井卷扬机、造纸和印刷机械、宾馆高速电梯、城市电车、电动自行车、龙门刨床、电力机车、地铁列车、船舶机械、大型精密机床和大型起重机等生产机械中。

verilog语句可综合vs不可综合

1)所有综合工具都支持的结构: always,assign,begin,end,case,wire,tri,supply0,supply1,reg,integer,default,for,function,and,nand,or,nor,xor,xnor,buf,not,bufif0,bufif1,notif0,notif1,if,inout,input,instantitation,module,negedge,posedge,operators,output,parameter。 2)所有综合工具都不支持的结构: time,defparam,$finish,fork,join,initial,delays,UDP,wait。 3)有些工具支持有些工具不支持的结构: casex,casez,wand,triand,wor,trior,real,disable,forever,arrays,memories,repeat,task,while。 建立可综合模型的原则 要保证Verilog HDL赋值语句的可综合性,在建模时应注意以下要点: 1)不使用initial。 2)不使用#10。 3)不使用循环次数不确定的循环语句,如forever、while等。 4)不使用用户自定义原语(UDP元件)。 5)尽量使用同步方式设计电路。 6)除非是关键路径的设计,一般不采用调用门级元件来描述设计的方法,建议采用行为语句来完成设计。 7)用always过程块描述组合逻辑,应在敏感信号列表中列出所有的输入信号。8)所有的内部寄存器都应该能够被复位,在使用FPGA实现设计时,应尽量使用器件的全局复位端作为系统总的复位。 9)对时序逻辑描述和建模,应尽量使用非阻塞赋值方式。对组合逻辑描述和建模,既可以用阻塞赋值,也可以用非阻塞赋值。但在同一个过程块中,最好不要同时用阻塞赋值和非阻塞赋值。 10)不能在一个以上的always过程块中对同一个变量赋值。而对同一个赋值对

Verilog HDL课程设计

人民武装学院Verilog HDL课程设计洗衣机控制器的设计 学生姓名: 周云 学号: PB102027115 专业: 电子信息科学与技术 年级: 2010 级 指导老师: 周骅老师 时间: 2011年12月22日

目录 引言...................................................................................................................... - 3 - 一、设计内容...................................................................................................... - 4 - 1.设计内容.................................................................................................... - 4 - 2.功能............................................................................................................ - 4 - 二、洗衣机控制器的工作原理.......................................................................... - 6 - 1. 洗衣机的工作状态.................................................................................. - 6 - 2. 全自动洗衣过程...................................................................................... - 7 - 3.单独执行某个洗衣程序............................................................................ - 8 - 三、洗衣机的状态转换图.................................................................................. - 9 - 1.洗衣机的状态转换图................................................................................ - 9 - 2. 设计思路.................................................................................................. - 9 - 四、设计程序.................................................................................................... - 11 - 1.全自动洗衣机主程序.............................................................................. - 11 - 2.全自动洗衣机测试程序.......................................................................... - 15 - 五、步骤及仿真图............................................................................................ - 17 - 1.在代码提示框架中完成核心子模块wash_ctrl.v的设计 ................... - 17 - 2.对核心子模块wash_ctrl.v 进行时序仿真 ........................................... - 17 - 六、功能图........................................................................................................ - 20 - 1.设计顶层图形文件,编译.................................................................... - 20 - 2.功能引脚锁定.......................................................................................... - 20 - 心得体会............................................................................................................ - 22 -

capture学习笔记

Capture Allegro学习笔记 Allegro中常见的文件格式 .brd 工具:PCB Design Expert PCB布线 .ddb 工具:Protel .art 工具:CAM350 Allegro PCB Design file/impot ARTwork .d 工具:pads2005 .drl 工具:Protel .opj 设计项目工程 .olb 创建新的元件库 allegro/APD.jrl :记录开启Allegro/APD 期间每一个执行动作的command . 产生在每一次新开启Allegro/APD 的现行工作目录下 .env :存在pcbenv 下,无扩展名,环境设定档. allegro/APD.ini :存在pcbenv 下,记录menu 的设定. allegro/APD.geo :存在pcbenv 下,记录窗口的位置. master.tag :开启Allegro/APD 期间产生的文字文件,记录最后一次存盘的database文件名称,下次开启Allegro/APD 会将档案load 进来. 从Allegro/APD.ini搜寻directory = 即可知道Master.tag 存在的位置 . lallegro.col :存在pcbenv 下,从设定颜色的调色盘Read Local 所写出的档案.只会影响到调色盘的24 色而不会影响class/subclass 的设定. .brd :board file (Allegro). .mcm :multi-chip module (APD) ,design file. .log :记录数据处理过程及结果. .art :artwork 檔. .txt :文字文件,如参数数据,device 文件 .. 等. .tap :NC drill 的文字文件. .dat :资料文件. .scr :script 或macro 记录文件. .pad :padstack 檔. .dra :drawing 档, create symbol 前先建drawing ,之后再compiled 成

verilog语言的综合与不可综合

Verilog的综合与不可综合 综合说明编的代码可以对应出具体的电路,不可综合说明没有对应的电路结构。不可综合的代码编译通过,只能看到输出,不能实现电路,就是不能用来制作具体的芯片。 一、基本 Verilog中的变量有线网类型和寄存器类型。线网型变量综合成wire,而寄存器可能综合成WIRE,锁存器和触发器。 二:verilog语句结构到门级的映射 1、连续性赋值:assign 连续性赋值语句逻辑结构上就是将等式右边的驱动左边的结点。因些连续性赋值的目标结点总是综合成由组合逻辑驱动的结点。Assign语句中的延时综合时都将忽视。 2、过程性赋值: 过程性赋值只出现在always语句中。 阻塞赋值和非阻塞赋值就该赋值本身是没有区别的,只是对后面的语句有不同的影响。 建议设计组合逻辑电路时用阻塞赋值,设计时序电路时用非阻塞赋值。 过程性赋值的赋值对象有可能综合成wire,latch,和flip-flop,取决于具体状况。如,时钟控制下的非阻塞赋值综合成flip-flop。 过程性赋值语句中的任何延时在综合时都将忽略。 建议同一个变量单一地使用阻塞或者非阻塞赋值。 3、逻辑操作符: 逻辑操作符对应于硬件中已有的逻辑门 4、算术操作符: Verilog中将reg视为无符号数,而integer视为有符号数。因此,进行有符号操作时使用integer,使用无符号操作时使用reg。 5、进位: 通常会将进行运算操作的结果比原操作数扩展一位,用来存放进位或者借位。如: Wire [3:0] A,B; Wire [4:0] C; Assign C=A+B; C的最高位用来存放进位。 6、关系运算符: 关系运算符:<,>,<=,>= 和算术操作符一样,可以进行有符号和无符号运算,取决于数据类型是reg,net还是integer。

verilog课程设计—交通灯1

课程设计 课程名称__EDA技术综合设计与实践__ 题目名称交通灯控制系统 学生学院信息工程学院 专业班级通信工程08(4) 学号 3108002925 学生姓名高高 指导教师李学易 2011 年12 月26 日

基于FPGA 的交通灯控制器的设计 摘要:Verilog 是广泛应用的硬件描述语言,可以用在硬件设计流程的建模、综合和模拟等多个阶段。随着硬件设计规模的不断扩大,应用硬件描述语言进行描述的CPLD 结构,成为设计专用集成电路和其他集成电路的主流。现代城市在日常运行控制中,越来越多的使用红绿灯对交通进行指挥和管理。而一套完整的交通灯控制系统通常要实现自动控制和手动控制去实现其红绿灯的转换。 基于FPGA 设计的交通灯控制系统电路简单、可靠性好。本设计利用Verilog HDL 语言、采用层次化混合输入方式,可控制4个路口的红、黄、绿、左转四盏信号灯,让其按特定的规律进行变化。在QUARTUSⅡ下对系统进行了综合与仿真。仿真结果表明系统可实现十字路口红绿灯及左转弯控制和倒计时显示,并能够自动控制交通灯转变。通过应用Verilog HDL 对交通灯控制器的设计,达到对Verilog HDL 的理解 关键词:FPGA;交通灯自动控制;V erilog HDL;Quartus Ⅱ 1.交通信号控制器设计要求与思路 1.1设计要求 在交通灯系统中(图1),路口1、2、3、4均需要红、黄、绿、左转四盏灯(用RYGL分别表示) ,并且每个路口都需要一个倒数的计时器,假设绿灯每次维持的时间是40 s ,黄灯为5 s ,左转灯10s,红灯60s,黄灯亮时以一定的频率闪动。交通灯系统大多是自动控制来指挥交通的,但有时需要由交警手动控制红绿灯,所以要求设 计的该交通信号系统需要具有该功能。 实现设计目标如下: (1)设计一个十字路口的交通灯控制电路,每条路配有红、黄、绿交通信号灯,通过电路对十字路口的两组交通灯的状态实现自动循环控制; (2)实现东西车道和南北车道上的车辆交替运行,绿灯每次维持的时间是40 s ,黄灯为5 s ,左转灯10s,红灯60s; (3)要求黄灯亮5 秒后,红灯才能转为绿灯,黄灯亮时以一定的频率闪动; (4)东西车道和南北车道每次通行的时间不同且可调; 图1 交通灯系统示意图

16位乘法器学习笔记(Verilog语言源程序+仿真程序)

LCD1602显示源程序如下: module lcd1602(input clk, //60M input rst_n, output lcd_p, //Backlight Source + lcd屏幕背光 output lcd_n, //Backlight Source - output reg lcd_rs, //0:write order; 1:write data output lcd_rw, //0:write data; 1:read data output reg lcd_en, //negedge 在lcd_en下降沿需保证数据有效 output reg [7:0] lcd_data); mux16 mul(.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 address wire start,done; assign data_r0 = 8'h30 + data0[7:0] ; // 8'h30在LCD1602上显示值为0。 assign data_r1 = 8'h30 + data1[7:0] ; assign data_r2 = 8'h30 + data2[7:0]; //-------------------address------------------ assign addr = 8'h80; /****************************LCD1602 Driver****************************/ //-----------------------lcd1602 clk_en--------------------- reg [31:0] cnt; reg lcd_clk_en; always @(posedge clk or negedge rst_n) begin if(!rst_n) begin cnt <= 1'b0; lcd_clk_en <= 1'b0;

相关文档