Files
BlogPosts/文章/学习之路/vivado_ip.md
2025-10-31 15:07:39 +08:00

4.3 KiB
Raw Blame History

Vivado使用乘法器、除法器IP核实现乘除取余仿真

环境

Vivado 20.2

添加并配置IP核

  1. 打开vivado找到对应IP核如下图
  2. 先双击除法器IP核进入配置页面如下图
    除法器配置默认即可点击OK后弹出界面点击Generate
    如下图即配置完成
  3. 配置乘法器IP核
    上图使用十六位有符号数与十六位无符号数进行运算
    上图输出32位间隔一个周期得到结果电脑性能不佳可适当增加
  4. 如下图即配置完成

添加并编写仿真代码文件

  1. 选择一个文件夹创建例如ipcore_test.v文件
  2. 添加文件到vivado
    找到自己创建的.v文件路径并添加
  3. 完成如下图
  4. 复制示例代码
    双击打开.veo 示例代码文件
    复制上图红框中的代码到自己的仿真文件,如下图我这是外部编辑器vivado自带编辑器同理
    上图的module与endmodule需要自己添加
    如下图可以看到除法器IP核在你自己的代码文件之下表示被正确调用
    乘法器同理,打开.veo文件复制代码
    示例代码复制完成后如下图这里我更改了实例名称u_ 开头,不改没影响)
  5. 最后自己补全仿真代码,我这里这样写
`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
  1. 结果分析
    选中除B之外的所有变量调整为有符号的十进制B调整为无符号的十进制数
    下图可以看到,乘法器得到数据(一开始),在第一个周期得到结果,除法器得到数据,在第二十个周期得到结果