译码器74x138是数电组合逻辑的重要MSI,在完成设计并下载到电路板后,将工程转化为可以被其他工程调用的IP核。
小贴士: FPGA每次复位需要时间嗷!
注:在写这篇博客时是几天写成的,为了锻炼一下我还是新手,所以代码块和后面调用IP时候3-8译码器部分代码虽然一样,但是命名不一样,每次都是重新开始做一遍。
module v74x138(G1,G2A_L,G2B_L,a,Y_L);
input G1,G2A_L,G2B_L;
input [2:0] a;
output [7:0] Y_L;
reg [7:0] Y_L=0;
always@(G1 or G2A_L or G2B_L or a) //always块,有输入发生变化,执行
begin
if(G1 && ~G2A_L && ~G2B_L) //如果使能有效
case(a)
7: Y_L=8'b01111111; //根据输入端的值进行译码
6: Y_L=8'b10111111;
5: Y_L=8'b11011111;
4: Y_L=8'b11101111;
3: Y_L=8'b11110111;
2: Y_L=8'b11111011;
1: Y_L=8'b11111101;
0: Y_L=8'b11111110;
default Y_L=8'b11111111; //如果使能无效
endcase
else
Y_L=8'b11111111;
end
endmodule
module sim_74x138;
reg G1,G2A_L,G2B_L; //变量定义
reg [2:0] a;
wire [7:0] Y_L;
v74x138 u38(G1,G2A_L,G2B_L,a,Y_L); //调用被仿真模块
initial //初始化
begin
G1=0; G2A_L=0; G2B_L=0; a=0 ;
#100;
G1=1; G2A_L=0; G2B_L=0;
end
always #100 a=a+1; //开始always
endmodule
这里提供一种非代码生成约束文件的方法。
在RYL分析的设计视图下,点击上方工具栏Layout,有I/O Planning选项,点击之后下面出现页框I/O ports,对Package Pin进行管脚的选择即可,完成之后crtl+S进行保存,弹出XDC文件命名窗口,保存即可。
此时在源小窗口中打开,发现已存在约束文件,代码为:
set_property PACKAGE_PIN F3 [get_ports G1]
set_property PACKAGE_PIN H4 [get_ports G2A_L]
set_property PACKAGE_PIN N4 [get_ports G2B_L]
set_property PACKAGE_PIN R2 [get_ports {
a[2]}]
set_property PACKAGE_PIN R3 [get_ports {
a[1]}]
set_property PACKAGE_PIN P4 [get_ports {
a[0]}]
set_property PACKAGE_PIN T2 [get_ports {
Y_L[7]}]
set_property PACKAGE_PIN T3 [get_ports {
Y_L[6]}]
set_property PACKAGE_PIN T4 [get_ports {
Y_L[5]}]
set_property PACKAGE_PIN N6 [get_ports {
Y_L[4]}]
set_property PACKAGE_PIN T5 [get_ports {
Y_L[3]}]
set_property PACKAGE_PIN R7 [get_ports {
Y_L[2]}]
set_property PACKAGE_PIN R8 [get_ports {
Y_L[1]}]
set_property PACKAGE_PIN P9 [get_ports {
Y_L[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {
a[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {
a[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {
a[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {
Y_L[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {
Y_L[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {
Y_L[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {
Y_L[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {
Y_L[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {
Y_L[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {
Y_L[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {
Y_L[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports G1]
set_property IOSTANDARD LVCMOS33 [get_ports G2A_L]
set_property IOSTANDARD LVCMOS33 [get_ports G2B_L]
发现在综合实现之后,点击实现中的schematic生成的是门级电路。
1、输入通过拨码开关,输出通过LED确定即可。
2、以拨码开关为例,SW是名称,从SW0~SW11,下方的T9等代表管脚。
最后生成的IP和约束文件无关。
1、Tools->create and Package New IP
(在PROGECT MANAGER)下打开的tools中才会有。
2、把当前工程生成为IP
3、保存路径,并包含sci文件
4、next->finish。
5、对IP进行属性设置。
6、可以看到这里以图形的形式展示了该IP的输入输出接口。
7、改动之后需要重新生成IP。
实际上,在数字电路中,三输入的译码器可以实现任意三输入的逻辑函数,所以三变量的多数表决器也可以用译码器实现。
1、建立新工程p_dsbjq_useip_Verilog,并创建设计源文件。
2、点开左侧工程管理窗口的IP Catalog(IP目录),右侧页框显示vivado内置的IP。要添加已经构建好的IP,在工程管理中的Settings选项,在工程设置中,选择IP->Repository,点击“+”,选中3-8译码器工程的目录,点击Select,显示已经添加,点击OK。
3、可以看到我们自己定义的IP也已经加入到了IP目录中。
4、接下来就是将IP添加到现在的工程中。双击选中的IP,打开窗口。显示逻辑符号和组件名称,不必修改,点击OK,即创建了该目录。
5、之后出现Generate Output Prodects窗口,点击Generate即可。
6、点击该xcl文件,选择OK。
7、可以看到源代码,并且还有一个前缀为inst:的代码文件。可以分别打开观察代码。
在decoder38_0中,代码为:
(* X_CORE_INFO = "decoder38,Vivado 2017.4" *)
(* CHECK_LICENSE_TYPE = "decoder38_0,decoder38,{}" *)
(* CORE_GENERATION_INFO = "decoder38_0,decoder38,{x_ipProduct=Vivado 2017.4,x_ipVendor=xilinx.com,x_ipLibrary=user,x_ipName=decoder38,x_ipVersion=1.0,x_ipCoreRevision=1,x_ipLanguage=VERILOG,x_ipSimLanguage=MIXED}" *)
(* DowngradeIPIdentifiedWarnings = "yes" *)
module decoder38_0 (
G1,
G2A_L,
G2B_L,
a,
Y_L
);
input wire G1;
input wire G2A_L;
input wire G2B_L;
input wire [2 : 0] a;
output wire [7 : 0] Y_L;
decoder38 inst (
.G1(G1),
.G2A_L(G2A_L),
.G2B_L(G2B_L),
.a(a),
.Y_L(Y_L)
);
endmodule
而在inst:前缀的文件中,代码为:
module decoder38(G1,G2A_L,G2B_L,a,Y_L);
input G1,G2A_L,G2B_L;
input [2:0] a;
output [7:0] Y_L;
reg [7:0] Y_L=0;
always@(G1 or G2A_L or G2B_L or a) //always块,有输入发生变化,执行
begin
if(G1 && ~G2A_L && ~G2B_L) //如果使能有效
case(a)
7: Y_L=8'b01111111; //根据输入端的值进行译码
6: Y_L=8'b10111111;
5: Y_L=8'b11011111;
4: Y_L=8'b11101111;
3: Y_L=8'b11110111;
2: Y_L=8'b11111011;
1: Y_L=8'b11111101;
0: Y_L=8'b11111110;
default Y_L=8'b11111111; //如果使能无效
endcase
else
Y_L=8'b11111111;
end
endmodule
是之前的源代码。
但要注意!
我们实际调用的模块只能是decoder38_0
不是有inst前缀那个!
8、复制decoder38_0中的模块头部分,在顶层文件p_dsbjq_useip_Verilog中粘贴,实现调用。
9、对顶层模块进行编辑优化。
代码为:
module dsbjq_useip(input a,input b,input c,output f);
wire [7:0] Y_L;
assign f=~(Y_L[3]&Y_L[5]&Y_L[6]&Y_L[7]);
decoder38_0 u38(
.G1(1),
.G2A_L(0),
.G2B_L(0),
.a({
c,b,a}),
.Y_L(Y_L)
);
endmodule
decoder38_0 实现了IP核的调用,在复制粘贴过来之后,需要进行实例化命名,这里为u38,对内部变量也进行定义。由于Y_L在顶层模块中未定义,所以还需在模块中定义 wire [7:0] Y_L。
由组合逻辑函数在3-8译码器的功能实现可知,最终输出f是对四个端口的与非。
10、仿真代码放在这里,有兴趣可以做一下噻。
module sim_dsbjq_useip;
reg a,b,c;
wire f;
dsbjq_useip uds(a,b,c,f);
initial
begin
a=0;b=0;c=0;
end
always #10 {
a,b,c}={
a,b,c}+1;
endmodule
11、编写约束文件。
##switches
set_property PACKAGE_PIN F3 [get_ports a]
set_property IOSTANDARD LVCMOS33 [get_ports a]
set_property PACKAGE_PIN H4 [get_ports b]
set_property IOSTANDARD LVCMOS33 [get_ports b]
set_property PACKAGE_PIN N4 [get_ports c]
set_property IOSTANDARD LVCMOS33 [get_ports c]
##led
set_property PACKAGE_PIN E3 [get_ports f]
set_property IOSTANDARD LVCMOS33 [get_ports f]
12、综合实现。
具体过程参考vivado进阶:FPGA实现(一)
发现实现生成的Schematic似乎也是门级电路。
13、生成比特流文件,下载到实验板上运行即可。发现现在又实现了我们的第一个工程——多数表决器。
IP核实现了调用模块,其实就像在仿真文件里调用源文件实例化一样,只不过复杂了一些。