是相同的。图2.11最大项由对应最小项取反获得图2.12基于0输出的和项积设计BTx&(x图2.13基于和项积设计的异或函数的逻辑电路图Verilog 例程例1:2输入逻辑门图2.14所示电路包含6个不同的逻辑门,它可以用程序清单2.1所示的Verilog 语句来描述。程序清单2.1中的第一行是注释语句。在Verilog中,跟随在双斜线“”之后的语句是注释。所有的Verilog 程序都以module(模块)声明语句开始,其中包含模块名(此例中为gates2),紧随其后的是一个输入/输出信号程序清单,包含信号名、方向和类型。我们将一直采用小写字母来命名信号。输入/输出信号的方向通过 input,output及inout(双向信号)语句声明。信号类型可以是wire 或reg。在程序清单2.1中所有的信号都是wire类型。对于wire类型信号,我们可以将其想象成如图2.14所示的电路连线,在其上可以测得实际电压值。对于reg型变量,我们将在例5中介绍。图2.14所示电路中共有6个独立的输出信号,我们可以采用数组的形式来描述它们,比如z[1:6]。在程序清单2.1中,我们用以下语句来定义输出信号:tputwire[5:01z我们用assign语句来定义图2.14所示的每个逻辑门的输出。assign赋值
9 是相同的。 图 2.11 最大项由对应最小项取反获得 图 2.12 基于 0 输出的和项积设计 : 图 2.13 基于和项积设计的异或函数的逻辑电路图 Verilog 例程 例 1:2 输入逻辑门 图 2.14 所示电路包含 6 个不同的逻辑门,它可以用程序清单 2.1 所示的 Verilog 语句来描述。程序清单 2.1 中的第一行是注释语句。在 Verilog 中, 跟随在双斜线“//”之后的语句是注释。所有的 Verilog 程序都以 module(模 块)声明语句开始,其中包含模块名(此例中为 gates2),紧随其后的是一个输 入/输出信号程序清单,包含信号名、方向和类型。我们将一直采用小写字 母来命名信号。输入/输出信号的方向通过 input,output 及 inout(双向信号) 语句声明。信号类型可以是 wire 或 reg。在程序清单 2.1 中所有的信号都是 wire 类型。对于 wire 类型信号,我们可以将其想象成如图 2.14 所示的电路 连线,在其上可以测得实际电压值。对于 reg 型变量,我们将在例 5 中介绍。 图 2.14 所示电路中共有 6 个独立的输出信号,我们可以采用数组的形 式来描述它们,比如 z[1:6]。在程序清单 2.1 中,我们用以下语句来定义输 出信号: 我们用 assign 语句来定义图 2.14 所示的每个逻辑门的输出。assign 赋值
语句为并发语句,所以在程序中可以用任意的顺序来书写各输出赋值语句。仿真结果如图2.15所示。程序清单2.1qates2.v/Example1:2-input gatesmodule gates 2Cinput wire a.input wire b,output wire[5:0]2assignz[5]-a&bassign z/4--(a&b):asign 231-06:assign2/2]-(alb);signzll-ab:广业QD23DD图2.14程序清单2.1对图2.18程序清单2.1所示Verilog程序仿真结果应的逻辑电路在FPGA开发板上验证设计为了将程序清单2.1中的Verilog程序综合到BASYS2或NEXYS2开发板上的XilinxSpartan3E芯片中,需要为程序中的输入/输出信号指定引脚。本书中所有例程均使用8个拨位开关和4个按钮开关作为输入,8个LED和4个7段数码管作为输出。所有输入/输出信号所对应的引脚号都在basys2.ucf(BASYS2开发板)及nexys2.ucf(NEXYS2开发板)约束文件中定义。程序清单2.2列出了basys2.ucf文件中的引脚定义。两个.ucf文件都可以在译者序中提供的网站中找到。10
10 语句为并发语句,所以在程序中可以用任意的顺序来书写各输出赋值语句。 仿真结果如图 2.15 所示。 程序清单 2.1 qates2.v 图 2.14 程序清单 2.1 对 应的逻辑电路 图 2.18 程序清单 2.1 所示 Verilog 程序仿真结果 在 FPGA 开发板上验证设计 为了将程序清单 2.1 中的 Verilog 程序综合到 BASYS2 或 NEXYS2 开发 板上的 XilinxSpartan 3E 芯片中,需要为程序中的输入/输出信号指定引脚。 本书中所有例程均使用 8 个拨位开关和 4 个按钮开关作为输入,8 个 LED 和 4 个 7 段数码管作为输出。所有输入/输出信号所对应的引脚号都在 basys2.ucf ( BASYS2 开发板)及 nexys2.ucf (NEXYS2 开发板)约束文件中定 义。程序清单 2.2 列出了 basys2.ucf 文件中的引脚定义。两个.ucf 文件都可 以在译者序中提供的网站中找到
附录A展示了如何运用上述文件在XilinxFPGA上实现程序设计。为了使用程序清单2.2所示的约束文件,我们必须将拨位开关对应的信号命名为sw[7:0],将按钮开关对应的信号命名为btn[3:0],将 LED 输出命名为ld[7:0]。为了方便,我们可以写一个顶层模块来使用这些输入/输出信号名称。对于7段数码管我们将在例11~例13中予以讨论。mclk是BASYS2开发板上提供的时钟信号,默认频率为50MHz,可以通过JP4跳线将其设为100MHz或25MHz。而NEXYS2开发板所提供的时钟频率则恒为50MHz。在本书中,我们将始终采用50MHz的时钟频率。程序清单2.3展示了本设计的顶层模块。其中,以开发板中最右边的两个拨位开关sw[1:0]作为输入,以右侧6个LED灯ld[5:0]作为输出。为了将这些输入/输出和程序清单2.1中的输入a、b及输出z[5:0]相关联,我们使用如下Verilog例化语句:gates2 G2 (a(sw[1]).bsw[0],2(ld)Verilog例化语句以被实例化的模块名起始(本例中为gates2),紧随其后的是顶层模块的例化名(本例中为G2),接着在其后的圆括号内,我们将程序清单2.1和程序清单2.3中的输入/输出信号相关联。请注意:在本例中我们将程序清单2.1 中的输入a 连接到FPGA开发板中的 sw[1];将输入b 连接到sw[0];将输出z[5:0]连接到对应的 LED的输出1d[5:0],因为这两个数组拥有相同的长度,所以在程序语句中不必特别将长度[5:0]指出。按照附录A的说明在开发板上完成本设计的验证。注意:当你改变右边两个拔位开关的状态时,LED灯也将随之改变并指示当前的输出状态。11
11 附录 A 展示了如何运用上述文件在 Xilinx FPGA 上实现程序设计。为了 使用程序清单 2.2 所示的约束文件,我们必须将拨位开关对应的信号命名为 sw[7:0],将按钮开关对应的信号命名为 btn[3:0],将 LED 输出命名为 ld[7:0]。 为了方便,我们可以写一个顶层模块来使用这些输入/输出信号名称。对于 7 段数码管我们将在例 11~例 13 中予以讨论。mclk 是 BASYS2 开发板上提供 的时钟信号,默认频率为 50MHz,可以通过 JP4 跳线将其设为 100MHz 或 25MHz。而 NEXYS2 开发板所提供的时钟频率则恒为 50MHz 。在本书中, 我们将始终采用 50MHz 的时钟频率。 程序清单 2.3 展示了本设计的顶层模块。其中,以开发板中最右边的两 个拨位开关 sw[1:0]作为输入,以右侧 6 个 LED 灯 ld[5:0]作为输出。为了 将这些输入/输出和程序清单 2.1 中的输入 a、b 及输出 z[5:0]相关联,我们 使用如下 Verilog 例化语句: Verilog 例化语句以被实例化的模块名起始(本例中为 gates2),紧随其后的 是顶层模块的例化名(本例中为 G2),接着在其后的圆括号内,我们将程序 清单 2.1 和程序清单 2.3 中的输入/输出信号相关联。请注意:在本例中我们将 程序清单 2.1 中的输入 a 连接到 FPGA 开发板中的 sw[1];将输入 b 连接到 sw[0];将输出 z[5:0]连接到对应的 LED 的输出 ld[5:0],因为这两个数组拥 有相同的长度,所以在程序语句中不必特别将长度[5 :0]指出。 按照附录 A 的说明在开发板上完成本设计的验证。注意:当你改变右 边两个拨位开关的状态时,LED 灯也将随之改变并指示当前的输出状态
程序清单2.2basys2.ucfPin assignmentforslide switchesNET"sw<>"LOC-"n3”NET"sW6>"LOC-"c2NET"W<S-LOC-"3"NET"sw>LOC-3”NET"sW"LOC-"b4"NET"sw2>"LOC-"k3"NET"SW<1>LOC-13NET"sw>"LOC-"PI1"Psignmentfor pushbutton switcheES5NET"btnk3>"LOCa7r;NET"bln<LOCm4"NET"bnLOC-e1NET"buD"LOC-812assignmar7-se9ent displayLOC-"114"NET"a_10.g<6NET"a_108LOC-"h12"LOC="n14"NETa_108Loc-"nlTETNET'atoLOC-"p12"NET"a_0gLOC-"13"NETAtg"LOC-"m12NETdp"LOC-"n13"NET"AnS3SLOC-"k4"#PinassigmentforLEDsNET l7"LOC-"g":NET"ld<6"LOC-"p4"NET"Id<5>"LOC-"n4"NET"Id<4>LOC-"n5"NET"LOC-"p"NET"d2"LOC-"p7NETI<I>"LOC-"m":NETld<0>"LOC-"ms"NET"an<1>"LOC-"12”NET"an<>"LOC-"12"#Pin assignment for clockNET"ck"LOC-"b8"12
12 程序清单 2.2 basys2.ucf
程序清单2.3gates2_top.v /Example lb:2-input gates module gates 2-top( input wire[1:0]sw, output wire [5:0] ld ) gates 2 G2(.a(sw[1]). b(sw[0]). z(ld) ) endmodule 例2:多输入逻辑门 在例1中所涉及的与、或、一与非、或非、异或及同或门都只有两个输入。 多输入逻辑门的基本原理和2输入逻辑门是一致的。图2.16所示为一个多 输入与门。只有当所有输入信号均为高电平时、与门的输出信号才为高电平。 在Verilog中有3种方法可以描述多输入与门。第一种方法是写出其逻辑表 达式: assign z=x[1]&x[2]&.&x[n]; (2.5) 其次,在Verilog中我们可以将“&”作为一元简约运算符使用: assign z=&x; (2.6) 式(2.6)同式(2.5)的结果是完全一致的,但是写法更简单。最后,我们也 可以采用门实例化语句来描述与门: and(z,x[1],x[2],..,x[n]); (2.7) 在式(2.7)所示语句中,圆括号中第一项为输出信号,后面为输入信号程 序清单。 图2.17所示为多输入或门。只有当所有输入信号均为低电平时,或门 的输出信号才为低电平口同与门的情形一样,在Verilog中同样有3种方式 可以描述多输入或门。逻辑表达式为 assign z=x[1]|x[2].|x[n]; (2.8) |”也可以作为一元简约运算符使用: assign z=|x; (2.9) 或者我们也可以用门例化语句来描述多输入或门: or(z,x[1],x[2],..,x[n]); (2.10) 13
13 程序清单 2.3 gates2 _top.v 例 2:多输入逻辑门 在例 1 中所涉及的与、或、一与非、或非、异或及同或门都只有两个输入。 多输入逻辑门的基本原理和 2 输入逻辑门是一致的。图 2.16 所示为一个多 输入与门。只有当所有输入信号均为高电平时、与门的输出信号才为高电平。 在 Verilog 中有 3 种方法可以描述多输入与门。第一种方法是写出其逻辑表 达式: assign z=x[1]&x[2]&.&x[n]; (2.5) 其次,在 Verilog 中我们可以将“&”作为一元简约运算符使用: assign z=&x; ( 2.6) 式(2.6)同式(2.5 )的结果是完全一致的,但是写法更简单。最后,我们也 可以采用门实例化语句来描述与门: and(z,x[1],x[2],., x[n]); (2.7) 在式(2.7)所示语句中,圆括号中第一项为输出信号,后面为输入信号程 序清单。 图 2.17 所示为多输入或门。只有当所有输入信号均为低电平时,或门 的输出信号才为低电平口同与门的情形一样,在 Verilog 中同样有 3 种方式 可以描述多输入或门。逻辑表达式为 assign z=x[1]|x[2].| x[n]; (2.8) |”也可以作为一元简约运算符使用: assign z=|x; (2.9) 或者我们也可以用门例化语句来描述多输入或门: or(z, x[1], x[2],.,x[n]); (2.10)