# Vivado使用乘法器、除法器IP核实现乘除取余仿真 ### 环境 Vivado 20.2 ## 添加并配置IP核 1. 打开vivado,找到对应IP核,如下图 ![](./vivado_ip_img/IPCore01.png) 2. 先双击除法器IP核进入配置页面,如下图 ![](./vivado_ip_img/IPCore02.png) ![](./vivado_ip_img/IPCore03.png) 除法器配置默认即可,点击OK;后弹出界面,点击Generate 如下图即配置完成 ![](./vivado_ip_img/IPCore04.png) 3. 配置乘法器IP核 ![](./vivado_ip_img/IPCore05.png) 上图使用十六位有符号数与十六位无符号数进行运算 ![](./vivado_ip_img/IPCore06.png) 上图输出32位,间隔一个周期得到结果(电脑性能不佳可适当增加) 4. 如下图即配置完成 ![](./vivado_ip_img/IPCore07.png) ## 添加并编写仿真代码文件 1. 选择一个文件夹,创建例如ipcore_test.v文件 2. 添加文件到vivado ![](./vivado_ip_img/IPCore08.png) ![](./vivado_ip_img/IPCore09.png) 找到自己创建的.v文件路径并添加 3. 完成如下图 ![](./vivado_ip_img/IPCore10.png) 4. 复制示例代码 ![](./vivado_ip_img/IPCore11.png) 双击打开.veo 示例代码文件 ![](./vivado_ip_img/IPCore12.png) 复制上图红框中的代码到自己的仿真文件,如下图(我这是外部编辑器,vivado自带编辑器同理) ![](./vivado_ip_img/IPCore13.png) 上图的module与endmodule需要自己添加 如下图,可以看到,除法器IP核在你自己的代码文件之下,表示被正确调用 ![](./vivado_ip_img/IPCore14.png) 乘法器同理,打开.veo文件复制代码 ![](./vivado_ip_img/IPCore15.png) ![](./vivado_ip_img/IPCore16.png) 示例代码复制完成后如下图,这里我更改了实例名称(u_ 开头,不改没影响) ![](./vivado_ip_img/IPCore17.png) 5. 最后自己补全仿真代码,我这里这样写 ```verilog `timescale 1ns / 1ps module tb_ipcore_test(); reg clk; //时钟变量 reg signed [15:0] A; //有符号因数数据 reg unsigned [15:0] B; //无符号因数数据 wire signed [31:0] P; //乘法器结果 reg dividend_tvalid; //被除数有效使能,高为有效,低为无效 reg signed [15:0] dividend_tdata; //被除数数据 reg divisor_tvalid; //除数有效使能,高为有效,低为无效 reg signed [15:0] divisor_tdata; //除数数据 wire dout_tvalid; //输出电平,高为正确输出,低为错误输出 wire [31:0] dout_tdata; //除法器结果 wire signed [15:0] quotient; //商 wire signed [15:0] remainder; //余数 mult_gen_0 u_mult_gen_0 ( .CLK(clk), // input wire CLK .A(A), // input wire [15 : 0] A .B(B), // input wire [15 : 0] B .P(P) // output wire [31 : 0] P ); div_gen_0 u_div_gen_0 ( .aclk(clk), // input wire aclk .s_axis_divisor_tvalid(divisor_tvalid), // input wire s_axis_divisor_tvalid .s_axis_divisor_tdata(divisor_tdata), // input wire [15 : 0] s_axis_divisor_tdata .s_axis_dividend_tvalid(dividend_tvalid), // input wire s_axis_dividend_tvalid .s_axis_dividend_tdata(dividend_tdata), // input wire [15 : 0] s_axis_dividend_tdata .m_axis_dout_tvalid(dout_tvalid), // output wire m_axis_dout_tvalid .m_axis_dout_tdata(dout_tdata) // output wire [31 : 0] m_axis_dout_tdata ); assign quotient = dout_tdata[31:16]; //除法器16位余数模式,高16位是商,低十六位是余数 assign remainder = dout_tdata[15:0]; always #5 clk = ~clk; //10ns周期时钟 initial begin clk = 0; A = 16'h7FFF; B = 16'hFFFF; dividend_tvalid = 1; dividend_tdata = 16'h7FFF; divisor_tvalid = 1; divisor_tdata = 16'hFFFF; #300; A = 16'h8001; B = 16'h0001; dividend_tvalid = 1; dividend_tdata = 16'h8001; divisor_tvalid = 1; divisor_tdata = 16'hFFFF; #300; $finish; end endmodule ``` 6. 结果分析 选中除B之外的所有变量,调整为有符号的十进制,B调整为无符号的十进制数 ![](./vivado_ip_img/IPCore19.png) 下图可以看到,乘法器得到数据(一开始),在第一个周期得到结果,除法器得到数据,在第二十个周期得到结果 ![](./vivado_ip_img/IPCore18.png)