FPGA verliog语言学习日志

1.什么是verilog语言

Verilog HDL(Hardware Description Language)是一种用于电子系统设计和建模的硬件描述语言。它广泛应用于数字电路的设计和验证,特别是在FPGA(现场可编程门阵列)和ASIC(应用特定集成电路)的开发中。Verilog HDL允许设计师通过编写代码来描述电路的行为和结构,这些代码可以被合成工具转换成实际的硬件电路。

以下是Verilog HDL的一些关键特性和概念:

1. **模块(Module)**:Verilog中的模块是设计的基本构建块。每个模块可以包含逻辑电路的描述,并且可以被实例化多次以形成更复杂的系统。

2. **数据类型**:Verilog提供了多种数据类型,包括线网(wire)、寄存器(reg)、整数(integer)、实数(real)和时间(time)等。

3. **运算符**:Verilog支持多种运算符,包括算术运算符(+、-、*、/)、逻辑运算符(&&、||、!、&、|、~)、关系运算符(==、!=、>、<、>=、<=)和位运算符(&、|、^、~、>>、<<)。

4. **并发语句**:Verilog中的并发语句(如`assign`和`always`块)用于描述电路的并发行为。`assign`语句用于描述连续赋值,而`always`块用于描述过程赋值,可以是组合逻辑或时序逻辑。

5. **时序控制**:Verilog通过`always`块和时钟信号来描述时序逻辑。`always @(posedge clk)`表示在时钟信号的正边沿触发。

6. **条件语句**:`if`、`case`和`if-else`语句用于描述设计中的条件逻辑。

7. **循环语句**:`for`、`while`和`repeat`语句用于描述设计中的循环行为。

8. **任务(Task)和函数(Function)**:任务是用于描述在模块内部执行的过程,而函数用于执行计算并返回一个值。

9. **参数化模块**:Verilog允许使用参数化模块,这使得模块可以在不同的实例中具有不同的行为。

10. **测试台(Testbench)**:Verilog提供了编写测试台的能力,用于模拟和验证设计在不同条件下的行为。

Verilog HDL的一个简单示例代码如下:

在这个例子中,定义了一个名为`and_gate`的模块,它实现了一个逻辑与门的功能。然后,定义了一个名为`testbench`的测试台模块来验证`and_gate`模块的功能。在测试台中,使用`initial`块来初始化输入信号并模拟不同的输入组合,同时使用`$monitor`系统任务来监控信号的变化。
 

二、Verilog HDL 基础知识

1、Verilog HDL 语言要素

1.1、命名规则

标识符被用来命名信号、模块、参数等,它可以是任意一组字母、数字、$符号和_(下划线)符号的组合。(标识符中字母区分大小写,且第一个字必须是字母或下划线)

1.2关键字(均小写)

Verilog HDL 内部已经使用的词成为关键字或保留字,是事先定义好的确认符,用来组织语言结构。总结关键字大概有以下这么多:

always, and, assign, begin, buf, bufif0, bufif1, case, casex, casez, cmos, deassign, default, defparam, disable, edge, else, end, endcase, endfunction, endmodule, endprimitive, endspecify, endtable, endtask, event, for, force, forever, fork, function, highz0, highz1, if, ifnone, initial, inout, input, integer, join, large, macromodule, medium, module, nand, negedge, nmos, nor, not, notif0, notif1, or, output, parameter, pmos, posedge, primitive, pull0, pull1, pulldown, pullup, rcmos, real, realtime, reg, release, repeat, rnmos, rpmos, rtran, rtranif0, rtranif1, scalared, small, specify, specparam, strength, strong0, strong1, supply0, supply1, table, task, time, tran, tranif0, tranif1, tri, tri0, tri1, triand, trior, trireg, vectored, wait, wand, weak0, weak1, while, wire, wor, xnor, xor

                                                        Verilog常用的一些关键字

1. always:用于创建一个时序块,其中的代码会按照时序规则执行,产生reg信号语句的关键字。

2. assign:用于创建一个组合块,其中的代码会按照组合逻辑规则执行,产生wire信号语句的关键字。

3. begin/end:用于创建一个代码块,其中的代码会按照顺序执行,语句的起始和结束标志。

4. module:模块开始的定义,用于创建一个模块,其中包含了数字电路的结构和行为。

5. input/output:用于定义模块的输入和输出端口定义。

6. wire/reg:用于定义信号的类型(wire信号定义和reg信号定义),wire表示连续信号,reg表示时序信号。

7. always_comb/always_ff:用于创建一个组合逻辑块或时序逻辑块。

8. inout 双向端口定义。

9. parameter 信号的参数定义。

10. posedge/negedge 时序电路的标志。

11. case:case语句起始标记。

12. default:ase语句的默认分支标志。

13. endcase:case语句结束标记。

14. if:if/else语句标记。

15. else:if/else语句标记。

16. for:for语句标记。

17. endmodule:模块结束定义。

                                                可综合和不可综合的关键字

可综合(Synthesizable)是指可以被综合器(Synthesizer)转换为硬件电路的代码。在FPGA设计中,可综合的代码可以被综合器转换为硬件电路,从而实现所需的功能。可综合代码应该具有以下特点:

1. 代码应该是结构化的,不能使用goto语句或其他不可综合的语言结构。

2. 代码应该是可重用的,可以在不同的设计中使用。

3. 代码应该是可读的,易于维护和修改。

可综合关键字是指在FPGA设计中可以被综合器识别和转换为硬件电路的关键字。常见的可综合关键字包括:

1. always:用于定义时序逻辑的关键字。

2. case:用于实现多路选择器的关键字。

3. assign:用于赋值操作的关键字。

4. wire:用于定义信号的关键字。

不可综合关键字是指在FPGA设计中不能被综合器识别和转换为硬件电路的关键字。常见的不可综合关键字包括:

1. $display:用于调试输出的关键字。

2. $monitor:用于监视信号的关键字。

3. $finish:用于结束仿真的关键字。

在FPGA设计中,应该尽量避免使用不可综合关键字,以免影响设计的可综合性和性能。

                                                 Verilog所有关键字的作用和用法

1.     always

always是Verilog中的一个关键字,用于创建一个时序块。在Verilog中,时序块是一种用于描述数字电路中的时序逻辑的结构,always关键字可以用于创建一个时序块,其中的代码会按照时序逻辑规则执行。always块可以根据时钟触发或者条件触发进行执行。

示例代码:

2.     and

and是Verilog中的一个关键字,用于创建一个与门。在Verilog中,与门是一种用于实现布尔逻辑的结构,and关键字可以用于创建一个与门,其中的输入信号经过与运算后,输出信号为1或0。

示例代码:

```

wire a, b, c;

and gate (c, a, b);

```

3.     assign

assign是Verilog中的一个关键字,用于创建一个组合块。在Verilog中,组合块是一种用于描述数字电路中的组合逻辑的结构,assign关键字可以用于创建一个组合块,其中的代码会按照组合逻辑规则执行。

示例代码:

```

assign out = (a & b) | (c & d);

```

4.     begin

begin是Verilog中的一个关键字,用于创建一个代码块。在Verilog中,代码块是一种用于组织代码的结构,begin关键字可以用于创建一个代码块,其中的代码会按照顺序执行。

示例代码:

5.     buf

buf是Verilog中的一个关键字,用于创建一个缓冲器。在Verilog中,缓冲器是一种用于放大电路信号的结构,buf关键字可以用于创建一个缓冲器,其中的输入信号经过放大后,输出信号与输入信号相同。

示例代码:

```

wire a, b;

buf gate (b, a);

```

6.     bufif0

bufif0是Verilog中的一个关键字,用于创建一个带有使能信号的缓冲器。在Verilog中,带有使能信号的缓冲器是一种用于放大电路信号的结构,bufif0关键字可以用于创建一个带有使能信号的缓冲器,其中的输入信号经过放大后,输出信号与输入信号相同,当使能信号为0时,输出信号为高阻态。

示例代码:

```

wire a, b, enable;

bufif0 gate (b, a, enable);

```

7.     bufif1

bufif1是Verilog中的一个关键字,用于创建一个带有反向使能信号的缓冲器。在Verilog中,带有反向使能信号的缓冲器是一种用于放大电路信号的结构,bufif1关键字可以用于创建一个带有反向使能信号的缓冲器,其中的输入信号经过放大后,输出信号与输入信号相同,当使能信号为1时,输出信号为高阻态。

示例代码:

```

wire a, b, enable;

bufif1 gate (b, a, enable);

```

8.     case

case关键字用于描述多路选择器,它可以根据输入信号的值选择相应的输出信号。以下是一个简单的case语句示例:

在这个示例中,我们使用case语句根据sel的值选择相应的输出信号。当sel为2'b00时,out等于a;当sel为2'b01时,out等于b;以此类推。

9.     casex

casex关键字也用于描述多路选择器,但它可以处理不确定的输入信号值。以下是一个简单的casex语句示例:

在这个示例中,我们使用casex语句根据sel的值选择相应的输出信号。当sel的最高位为0,次高位为0时,out等于a;当sel的最高位为0,次高位为1时,out等于b;以此类推。如果sel的后两位是不确定的,也可以使用xx表示。

10.  casez

casez关键字也用于描述多路选择器,但它可以处理不确定的输入信号值,并且可以将输入信号的未知值(Z)视为0。以下是一个简单的casez语句示例:

在这个示例中,我们使用casez语句根据sel的值选择相应的输出信号。当sel的最高位为0,次高位为0时,out等于a;当sel的最高位为0,次高位为1时,out等于b;以此类推。如果sel的后两位是不确定的或者是Z,也可以使用zz表示。

11.  cmos

cmos关键字用于描述CMOS逻辑门,包括CMOS反相器、CMOS与门、CMOS或门等。以下是一个简单的CMOS逻辑门示例:

在这个示例中,我们定义了一个CMOS反相器模块,它有一个输入端口a和一个输出端口y。在模块中,我们使用cmos语句描述了CMOS反相器的逻辑。

12. deassign

deassign关键字用于取消信号的赋值。以下是一个简单的deassign语句示例:

```

deassign a;

```

在这个示例中,我们使用deassign语句取消了信号a的赋值。这意味着信号a现在没有值,可以重新赋值。

13.  default

default关键字用于描述case语句中的默认情况。当输入信号的值与case语句中的所有情况都不匹配时,将执行default语句。以下是一个简单的default语句示例:

在这个示例中,我们使用default语句定义了输入信号sel的默认情况。当sel不是2'b00、2'b01或2'b10时,out等于d。

14. defparam

defparam关键字用于为模块的参数赋值。以下是一个简单的defparam语句示例:

```

defparam adder.width = 8;

```

在这个示例中,我们使用defparam语句为模块adder的宽度参数赋值为8。这意味着adder将使用8位宽度进行运算。

15.  disable

disable关键字用于禁用任务或函数。在Verilog中,任务和函数是用来执行特定功能的代码块。如果需要在执行任务或函数的过程中停止它们的执行,就可以使用disable语句。以下是一个简单的disable语句示例:

在这个示例中,我们定义了一个名为my_task的任务,并在initial块中执行它。然后,我们使用disable语句停止my_task的执行。

16. edge

edge关键字用于描述时钟信号的边沿类型。在数字电路中,时钟信号通常用于同步电路中,用于控制电路的行为。时钟信号的边沿类型可以是上升沿、下降沿或两者都有。以下是一个简单的edge语句示例:

```

always @(posedge clk)

// 时钟上升沿触发的代码块

```

在这个示例中,我们使用edge关键字描述时钟信号的上升沿类型,并在always块中编写了时钟上升沿触发的代码块。

17.  else

else关键字用于描述if语句中的默认情况。当if语句中的条件不成立时,将执行else语句。以下是一个简单的else语句示例:

```

if (a == b)

// 条件成立的代码块

else

// 默认情况的代码块

```

在这个示例中,我们使用else语句定义了if语句中的默认情况。当a等于b时,将执行条件成立的代码块;否则,将执行默认情况的代码块。

18. end

end关键字用于结束模块、任务或函数的定义。在Verilog中,每个模块、任务或函数都必须以end关键字结束。以下是一个简单的end语句示例:

```

module my_module(input a, output b);

// 模块代码块

endmodule

```

在这个示例中,我们使用endmodule语句结束了模块my_module的定义。

19.  endcase

endcase关键字用于结束case语句的定义。在Verilog中,case语句用于根据输入信号的值选择相应的输出信号。以下是一个简单的endcase语句示例:

在这个示例中,我们使用endcase语句结束了case语句的定义。

20. endfunction

endfunction关键字用于结束函数的定义。在Verilog中,函数是用来执行特定功能并返回结果的代码块。以下是一个简单的endfunction语句示例:

```

function [7:0] my_function;

// 函数代码块

endfunction

```

在这个示例中,我们使用endfunction语句结束了函数my_function的定义。

21. endmodule

endmodule关键字用于结束模块的定义。在Verilog中,模块是用来描述数字电路的基本组件。以下是一个简单的endmodule语句示例:

在这个示例中,我们使用endmodule语句结束了模块my_module的定义。

22.  endprimitive

endprimitive关键字用于结束primitive的定义。在Verilog中,primitive是一种基本的数字电路元素,用于描述数字电路的物理实现。以下是一个简单的endprimitive语句示例:

```

primitive and_gate (input a, input b, output c);

// primitive代码块

endprimitive

```

在这个示例中,我们使用endprimitive语句结束了primitive and_gate的定义。

23.  endspecify

endspecify关键字用于结束specify块的定义。在Verilog中,specify块用于描述数字电路的时序和延迟。以下是一个简单的endspecify语句示例:

```

specify

// specify代码块

endspecify

```

在这个示例中,我们使用endspecify语句结束了specify块的定义。

24.  endtable

endtable关键字用于结束table块的定义。在Verilog中,table块用于描述数字电路的真值表。以下是一个简单的endtable语句示例:

```

table my_table (input a, input b, output c);

// table代码块

endtable

```

在这个示例中,我们使用endtable语句结束了table my_table的定义。

25.  endtask

endtask关键字用于结束task的定义。在Verilog中,task是一种用于执行特定功能的代码块。以下是一个简单的endtask语句示例:

```

task my_task;

// 任务代码块

endtask

```

在这个示例中,我们使用endtask语句结束了task my_task的定义。

26.  event

event关键字用于描述事件,即数字电路中的信号变化。在Verilog中,event通常与wait语句一起使用,用于等待某个事件的发生。以下是一个简单的event语句示例:

```

always @(event clk)

// 事件触发的代码块

```

在这个示例中,我们使用event关键字描述了时钟信号的边沿类型,并在always块中编写了事件触发的代码块。

27.  for

for关键字用于描述循环语句。在Verilog中,for语句通常用于重复执行一段代码块。以下是一个简单的for语句示例:

```

for (i = 0; i < 10; i = i + 1)

// 循环执行的代码块

```

在这个示例中,我们使用for语句描述了一个循环,i从0开始,每次增加1,直到i小于10为止,重复执行循环执行的代码块。

28.  force

force关键字用于强制改变数字电路中的信号值。在Verilog中,force通常与initial语句一起使用,用于初始化数字电路的状态。以下是一个简单的force语句示例:

```

initial begin

force a = 1;

#10 release a;

end

```

在这个示例中,我们使用force语句将信号a的值强制设为1,然后使用release语句在10个时间单位后释放a的值。

29.  forever

forever关键字用于创建一个无限循环。在Verilog中,forever通常与always语句一起使用,用于重复执行一段代码块。以下是一个简单的forever语句示例:

```

always @(posedge clk)

forever begin

// 重复执行的代码块

end

```

在这个示例中,我们使用forever关键字描述了一个无限循环,在时钟上升沿触发时重复执行代码块。

30.  fork

fork关键字用于创建一个并发执行的代码块。在Verilog中,fork通常与join语句一起使用,用于并发执行多个代码块。以下是一个简单的fork语句示例:

在这个示例中,我们使用fork关键字创建了两个并发执行的代码块,并使用join语句等待两个代码块的执行完成。

31.  function

function关键字用于创建一个函数。在Verilog中,function通常用于执行特定的计算或操作。以下是一个简单的function语句示例:

```

function int add(int a, int b);

add = a + b;

endfunction

```

在这个示例中,我们使用function关键字创建了一个add函数,用于计算两个整数的和。

32.  highz0

highz0关键字用于描述数字电路中的高阻态。在Verilog中,highz0通常用于描述三态门的输出。以下是一个简单的highz0语句示例:

```

assign out = (enable) ? data : highz0;

```

在这个示例中,我们使用highz0关键字描述了三态门的输出,在enable信号为1时输出data信号,在enable信号为0时输出高阻态。

33.  highz1

highz1关键字用于描述数字电路中的高阻态。在Verilog中,highz1通常用于描述三态门的输出。以下是一个简单的highz1语句示例:

```

assign out = (enable) ? data : highz1;

```

在这个示例中,我们使用highz1关键字描述了三态门的输出,在enable信号为1时输出data信号,在enable信号为0时输出高阻态。

34.  if

if关键字用于描述条件语句。在Verilog中,if语句通常用于根据某个条件执行特定的代码块。以下是一个简单的if语句示例:

在这个示例中,我们使用if语句判断a是否大于b,如果成立,执行条件成立时的代码块,否则执行条件不成立时的代码块。

35.  ifnone

ifnone关键字用于描述默认值。在Verilog中,ifnone通常用于描述信号的默认值。以下是一个简单的ifnone语句示例:

```

assign out = ifnone(in, 0);

```

在这个示例中,我们使用ifnone关键字描述了信号in的默认值为0,如果in信号没有被赋值,out信号将被赋值为0。

36.  initial

initial关键字用于描述初始化代码块。在Verilog中,initial语句通常用于初始化数字电路的状态。以下是一个简单的initial语句示例:

```

initial begin

// 初始化代码块

end

```

在这个示例中,我们使用initial关键字描述了一个初始化代码块,用于初始化数字电路的状态。

37.  inout

inout关键字用于描述双向信号。在Verilog中,inout通常用于描述三态门的输入和输出。以下是一个简单的inout语句示例:

```

module tri_gate(inout out, input enable, input data);

assign out = (enable) ? data : 1'bz;

endmodule

```

在这个示例中,我们使用inout关键字描述了三态门的输入和输出信号out,当enable信号为1时,输出data信号,否则输出高阻态。

38.  input

input关键字用于描述输入信号。在Verilog中,input通常用于描述数字电路的输入端口。以下是一个简单的input语句示例:

```

module adder(input [7:0] a, input [7:0] b, output [7:0] sum);

assign sum = a + b;

endmodule

```

在这个示例中,我们使用input关键字描述了两个8位输入信号a和b,用于加法运算。

39.  integer

integer关键字用于描述整数类型。在Verilog中,integer通常用于描述计数器和状态机等数字电路。以下是一个简单的integer语句示例:

在这个示例中,我们使用integer关键字定义了一个计数器变量i,用于计数,每当i等于255时,将计数器count加1。

40.  join

join关键字用于等待并发执行的代码块完成。在Verilog中,join通常与fork语句一起使用,用于等待多个并发执行的代码块的完成。以下是一个简单的join语句示例:

在这个示例中,我们使用fork关键字创建了两个并发执行的代码块,并使用join语句等待两个代码块的执行完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值