Vivado的使用
以实验书中给出的加法器文件为例
1. Design Source 中添加 adder.v 文件
-
打开 Vivado,创建一个新项目。
-
在项目中,右键点击
Design Sources,选择Add Sources,然后选择Add or create design sources。 -
点击
Create File,输入文件名adder.v,点击OK。 -
在
adder.v文件中编写代码
添加好文件以后,文件会产生向导,输入输出向导。但是这部分代码最终的目的是在代码段中生成程序的输入输出端口,理论上来说代码处编写即可,在文件中添加下面的内容
module adder(
input [31:0] operand1, //定义端口32位的输入
input [31:0] operand2,
input cin, //来自低位的进位
output [31:0] result,
output cout //向高位的进位
);
assign {cout,result} = operand1 + operand2 + cin; //输出形式
endmodule
2. 综合(Synthesis)
综合是将高层次的设计描述(如 Verilog 或 VHDL 代码)转换为低层次的逻辑门级网表(Gate-level Netlist)的过程。主要任务:
-
逻辑优化:将代码转换为逻辑单元
-
语法和逻辑的检查
-
生成网表:生成中间文件(EDIF或NGC格式)
3. 实现(Implementation)
实现是将综合生成的逻辑网表映射到具体的 FPGA 硬件资源上,并生成最终的比特流文件(Bitstream)的过程。主要任务是:
-
布局布线:将逻辑网表中的逻辑单元映射到 FPGA 的物理资源上(如 CLB、DSP、BRAM 等),并完成信号的路由。
-
时序优化:确保设计的布局仍能满足时序要求
-
生成比特流:生成可以下载到FPGA的配置文件
4. 检验逻辑是否正确的方式:
(1)仿真 创建虚拟信号(Simulation Sources)
-
右键点击
Simulation Sources,选择Add Sources,然后选择Add or create simulation sources。 -
点击
Create File,输入文件名testbench.v,点击OK。 -
在
testbench.v文件中编写代码
添加仿真文件,默认文件名为testbench.v .仿真文件也是Verilog文件,仿真文件自己内部构造输入,不需要对外添加。刚刚创建好以后,adder.v 是顶部文件,在testbench.v 文件中添加下面的内容:
`timescale 1ns / 1ps //仿真单位时间为1ns,精度为1ps 董老师给出的代码中没有这一行
module testbench;
// Inputs 这里的reg定义的变量以及wire输出的变量是为了后续的 adder 模块的输入输出
reg [31:0] operand1;
reg [31:0] operand2;
reg cin;
// Outputs
wire [31:0] result;
wire cout;
// Instantiate the Unit Under Test (UUT) 给adder起了个别名 uut
//这里的顺序要和adder中的一样 作用是实例化adder。
//语法 .port_name1(external_signal1) 。实例化的时候,如果实例化了多个对象,就要起别名。
//也可以位置端口连接,但是连接顺序必须与模块定义中的端口顺序完全一致
adder uut (
//模块定义的端口名称(外部信号(可以是reg、wire等信号)) operand1是之前adder文件中的,而括号内的是这个文件中的
.operand1(operand1),
.operand2(operand2),
.cin(cin),
.result(result),
.cout(cout)
);
initial begin //寄存器中的一定要有值,因此要先初始化
// Initialize Inputs
operand1 = 0;
operand2 = 0;
cin = 0;
// Wait 100 ns for global reset to finish
#100;
// Add stimulus here
end
always #10 operand1 = $random; //$random为系统任务,产生一个随机的32位数
always #10 operand2 = $random; //#10 表示等待10个单位时间(10ns),即每过10ns,赋值一个随机的32位数
always #10 cin = {$random} % 2; //加了拼接符,{$random}产生一个非负数,除2取余得到0或1
endmodule
仿真文件编写完毕以后,Simulation Souces 变成了顶层模块,走仿真的时候一定要是顶层模块。
注意:每次写完一个文件都跑一遍综合和实现。运行完以后,点击Simulation 中的 Run Simulation 进行仿真,出现波形图。进行缩放,拖动滚轮,右键 Radix 选择展示的进制
(2)试验箱
根据曾经的描述,可以画出定点实验加法 顶层模块图

观察 lcd_module.v 文件
顶层模块文件
-
右键点击
Design Sources,选择Add Sources,然后选择Add or create design sources。 -
点击
Create File,输入文件名adder_display.v,点击OK。 -
在
adder_display.v文件中编写代码
在 Design Source 中添加顶层模块文件。顶层模块代码如下,adder_display.v 代码,需要注意的是输入输出定义好,以及始终和 reset 信号。
module adder_display(
//时钟与复位信号,
input clk,
input resetn, //后缀"n"表示低电平有效
//拨码开关,用于选择输入数和产生cin
input input_sel, //0:输入为加数1(add_operand1);1:为加数2(add_operand2)
input sw_cin,
//led灯,用于显示cout
output led_cout,
//触摸屏相关接口,不需要更改
output lcd_rst,
output lcd_cs,
output lcd_rs,
output lcd_wr,
output lcd_rd,
inout[15:0] lcd_data_io,
output lcd_bl_ctr,
inout ct_int,
inout ct_sda,
output ct_scl,
output ct_rstn
);
//上面的都是adder_display的对外端口,先买你的是内部的原理,这里是把加法器接好了
//-----{调用加法模块}begin
reg [31:0] adder_operand1;
reg [31:0] adder_operand2;
wire adder_cin;
wire [31:0] adder_result ;
wire adder_cout;
adder adder_module(
.operand1(adder_operand1),
.operand2(adder_operand2),
.cin (adder_cin ),
.result (adder_result ),
.cout (adder_cout )
);
//输入的端口接到加法器的输入的端口上,输出接到输出的端口上,assign是接线
assign adder_cin = sw_cin;
assign led_cout = adder_cout;
//-----{调用加法模块}end
//---------------------{调用触摸屏模块}begin--------------------//
//-----{实例化触摸屏}begin
//此小节不需要更改
reg display_valid;
reg [39:0] display_name;//五个字符,带上了五个ASCII码,一个8位,一共40
reg [31:0] display_value;//数字都是32位的
wire [5 :0] display_number;//刷新0~44,则一共需要5个
wire input_valid;
wire [31:0] input_value;
//实例化LCD屏
lcd_module lcd_module(
.clk (clk ), //10Mhz
.resetn (resetn ),
//调用触摸屏的接口
.display_valid (display_valid ),
.display_name (display_name ),
.display_value (display_value ),
.display_number (display_number),
.input_valid (input_valid ),
.input_value (input_value ),
//lcd触摸屏相关接口,不需要更改
.lcd_rst (lcd_rst ),
.lcd_cs (lcd_cs ),
.lcd_rs (lcd_rs ),
.lcd_wr (lcd_wr ),
.lcd_rd (lcd_rd ),
.lcd_data_io (lcd_data_io ),
.lcd_bl_ctr (lcd_bl_ctr ),
.ct_int (ct_int ),
.ct_sda (ct_sda ),
.ct_scl (ct_scl ),
.ct_rstn (ct_rstn )
);
//-----{实例化触摸屏}end
//LCD屏和加法器连线
//-----{从触摸屏获取输入}begin
//根据实际需要输入的数修改此小节,
//建议对每一个数的输入,编写单独一个always块
//当input_sel为0时,表示输入数为加数1,即operand1
always @(posedge clk) //时钟触发
begin
if (!resetn) //当前要不要清零
begin
adder_operand1 <= 32'd0;
end
else if (input_valid && !input_sel) //检查当前的输入是否点了OK,是不是要输入第一个数
begin
adder_operand1 <= input_value; //如果是,则传入到operand1中
end
end
//当input_sel为1时,表示输入数为加数2,即operand2
always @(posedge clk)
begin
if (!resetn)
begin
adder_operand2 <= 32'd0;
end
else if (input_valid && input_sel)
begin
adder_operand2 <= input_value;
end
end
//-----{从触摸屏获取输入}end
//输出到LCD屏上
//-----{输出到触摸屏显示}begin
//根据需要显示的数修改此小节,
//触摸屏上共有44块显示区域,可显示44组32位数据
//44块显示区域从1开始编号,编号为1~44,
always @(posedge clk)
begin
case(display_number) //所有的44个位置,但是这次只用3个
6'd1 : //6表示位宽,d为十进制,2为常量2
begin
display_valid <= 1'b1;
display_name <= "ADD_1"; //五个字符
display_value <= adder_operand1; //第一个数
end
6'd2 :
begin
display_valid <= 1'b1;
display_name <= "ADD_2";
display_value <= adder_operand2;
end
6'd3 :
begin
display_valid <= 1'b1;
display_name <= "RESUL";
display_value <= adder_result;
end
default :
begin
display_valid <= 1'b0; //1位宽的常量二进制数0
display_name <= 40'd0; //40位宽
display_value <= 32'd0; //32位宽
end
endcase
end
//-----{输出到触摸屏显示}end
//----------------------{调用触摸屏模块}end---------------------//
endmodule
使用源代码的时候一定要用写字板打开,记事本会乱码,直接导入的时候会对别的项目直接进行更改。添加完文件并且保存以后,会发现顶层模块变成了 adder_display ,
LCD模块
此时缺少 lcd_module 模块,需要我们直接导入出来,因为此时这个模块是打包好的,因此要手动导入,添加模块,点击 add design source 结尾文件为.dcp
excel 中为接口对应的控制信号编号。
导入 lcd_module 模块后,进行综合和实现,实现结束以后,点击 Implemented Design ,可以看到设备的预览图,右上角的 Default Layout 布局改为 IO Planing 会更加的直观。可以看到每一个信号的横纵坐标,即为接口编号,接下来要做的就是让顶层模块的端口接入到试验箱上。去写约束文件
约束文件
-
右键点击
Constraints,选择Add Sources,然后选择Add or create constraints。 -
点击
Create File,输入文件名adder.xdc,点击OK。 -
在
adder.xdc文件中编写以下代码,实现的时候,请将双斜杠注释删去
//对每个信号绑定实验向上的位置
set_property PACKAGE_PIN AC19 [get_ports clk] //将时钟信号,绑定到AC19信号当中
set_property PACKAGE_PIN H7 [get_ports led_cout]
set_property PACKAGE_PIN Y3 [get_ports resetn]
set_property PACKAGE_PIN AC21 [get_ports input_sel]
set_property PACKAGE_PIN AD24 [get_ports sw_cin]
//给每个信号定义标准电压为3.3伏
set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports led_cout]
set_property IOSTANDARD LVCMOS33 [get_ports resetn]
set_property IOSTANDARD LVCMOS33 [get_ports input_sel]
set_property IOSTANDARD LVCMOS33 [get_ports sw_cin]
//其他的内容直接复制过来
#lcd
set_property PACKAGE_PIN J25 [get_ports lcd_rst]
set_property PACKAGE_PIN H18 [get_ports lcd_cs]
set_property PACKAGE_PIN K16 [get_ports lcd_rs]
set_property PACKAGE_PIN L8 [get_ports lcd_wr]
set_property PACKAGE_PIN K8 [get_ports lcd_rd]
set_property PACKAGE_PIN J15 [get_ports lcd_bl_ctr]
set_property PACKAGE_PIN H9 [get_ports {lcd_data_io[0]}]
set_property PACKAGE_PIN K17 [get_ports {lcd_data_io[1]}]
set_property PACKAGE_PIN J20 [get_ports {lcd_data_io[2]}]
set_property PACKAGE_PIN M17 [get_ports {lcd_data_io[3]}]
set_property PACKAGE_PIN L17 [get_ports {lcd_data_io[4]}]
set_property PACKAGE_PIN L18 [get_ports {lcd_data_io[5]}]
set_property PACKAGE_PIN L15 [get_ports {lcd_data_io[6]}]
set_property PACKAGE_PIN M15 [get_ports {lcd_data_io[7]}]
set_property PACKAGE_PIN M16 [get_ports {lcd_data_io[8]}]
set_property PACKAGE_PIN L14 [get_ports {lcd_data_io[9]}]
set_property PACKAGE_PIN M14 [get_ports {lcd_data_io[10]}]
set_property PACKAGE_PIN F22 [get_ports {lcd_data_io[11]}]
set_property PACKAGE_PIN G22 [get_ports {lcd_data_io[12]}]
set_property PACKAGE_PIN G21 [get_ports {lcd_data_io[13]}]
set_property PACKAGE_PIN H24 [get_ports {lcd_data_io[14]}]
set_property PACKAGE_PIN J16 [get_ports {lcd_data_io[15]}]
set_property PACKAGE_PIN L19 [get_ports ct_int]
set_property PACKAGE_PIN J24 [get_ports ct_sda]
set_property PACKAGE_PIN H21 [get_ports ct_scl]
set_property PACKAGE_PIN G24 [get_ports ct_rstn]
set_property IOSTANDARD LVCMOS33 [get_ports lcd_rst]
set_property IOSTANDARD LVCMOS33 [get_ports lcd_cs]
set_property IOSTANDARD LVCMOS33 [get_ports lcd_rs]
set_property IOSTANDARD LVCMOS33 [get_ports lcd_wr]
set_property IOSTANDARD LVCMOS33 [get_ports lcd_rd]
set_property IOSTANDARD LVCMOS33 [get_ports lcd_bl_ctr]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[8]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[9]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[10]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[11]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[12]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[13]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[14]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[15]}]
set_property IOSTANDARD LVCMOS33 [get_ports ct_int]
set_property IOSTANDARD LVCMOS33 [get_ports ct_sda]
set_property IOSTANDARD LVCMOS33 [get_ports ct_scl]
set_property IOSTANDARD LVCMOS33 [get_ports ct_rstn]
约束文件,建立好后就可以进行上箱了
生成位流文件
控制栏拉到最下面,看到 Generate Bitstream 生成位流文件,此时需要重新跑综合和实现。
准备试验箱
一定要将箱子里的线通过小口拉出来再连到电脑上,防止线被夹断。旁边的红色功能为开关。
-
试验箱供上电
-
USB插口插在自己的电脑上
一切准备就绪以后,让试验箱找位流文件,generate stream 下面有一个,open Hardware manager(打开文件管理器) 随后右上角会出现绿色的条,点击 Open target 便会自动开始连接试验箱。找不到的话,一定要断开链接以后,再去链接。
8359

被折叠的 条评论
为什么被折叠?



