30那个地方改仿真的时长,默认是10us(但实际上好像是1us) 这里改成30us


//加载被乘数,运算时每次左移一位  (这里把被乘数位拓展了)
    reg  [63:0] multiplicand

//加载乘数,运算时每次右移一位,相当于y
    reg  [31:0] multiplier;

// 部分积:乘数末位为1,由被乘数左移得到;乘数末位为0,部分积为0
    wire [63:0] partial_product;

//累加器
    reg [63:0] product_temp;    //临时结果   product_temp <= product_temp + partial_product;

这个部分积直接由被乘数得到,然后每一个时钟上跳沿直接加到temp上。

代码中always是并行的。这是理解乘法器的关键!然后每个always里仅对一个信号赋值!


mult_end 为1的时候     表示乘法运算结束 (故看仿真结果的时候得看end为1时候对应的结果)


mult_valid 为1 表示进行有效的运算

代码见Verilog编程之乘法器的实现_王森ouc的博客-CSDN博客_verilog乘法

人家总结:reg型变量必须通过过程赋值语句赋值!
不能通过assign语句赋值!
而wire型数据不能放在过程块内赋值。

multiply.v 与 testbench.v分别如下

`timescale 1ns / 1ps
module multiply(              // 乘法器input         clk,        // 时钟input         mult_begin, // 乘法开始信号input  [31:0] mult_op1,   // 乘法源操作数1input  [31:0] mult_op2,   // 乘法源操作数2output [63:0] product,    // 乘积output        mult_end   // 乘法结束信号
);//乘法正在运算信号和结束信号reg mult_valid;assign mult_end = mult_valid & ~(|multiplier); //乘法结束信号:乘数全0always @(posedge clk)   //①beginif (!mult_begin || mult_end)    //如果没有开始或者已经结束了beginmult_valid <= 1'b0;     //mult_valid 赋值成0,说明现在没有进行有效的乘法运算endelsebeginmult_valid <= 1'b1;endend//两个源操作取绝对值,正数的绝对值为其本身,负数的绝对值为取反加1wire        op1_sign;      //操作数1的符号位wire        op2_sign;      //操作数2的符号位wire [31:0] op1_absolute;  //操作数1的绝对值wire [31:0] op2_absolute;  //操作数2的绝对值assign op1_sign = mult_op1[31];assign op2_sign = mult_op2[31];assign op1_absolute = op1_sign ? (~mult_op1+1) : mult_op1;assign op2_absolute = op2_sign ? (~mult_op2+1) : mult_op2;//加载被乘数,运算时每次左移一位reg  [63:0] multiplicand;always @ (posedge clk)  //②beginif (mult_valid)begin    // 如果正在进行乘法,则被乘数每时钟左移一位multiplicand <= {multiplicand[62:0],1'b0};  //被乘数x每次左移一位。endelse if (mult_begin) begin   // 乘法开始,加载被乘数,为乘数1的绝对值multiplicand <= {32'd0,op1_absolute};endend//加载乘数,运算时每次右移一位,相当于yreg  [31:0] multiplier;always @ (posedge clk)  //③beginif(mult_valid)begin       //如果正在进行乘法,则乘数每时钟右移一位multiplier <= {1'b0,multiplier[31:1]}; //相当于乘数y右移一位endelse if(mult_begin)begin   //乘法开始,加载乘数,为乘数2的绝对值multiplier <= op2_absolute;endend// 部分积:乘数末位为1,由被乘数左移得到;乘数末位为0,部分积为0wire [63:0] partial_product;assign partial_product = multiplier[0] ? multiplicand:64'd0;        //若此时y的最低位为1,则把x赋值给部分积partial_product,否则把0赋值给partial_product//累加器reg [63:0] product_temp;        //临时结果always @ (posedge clk)  //④//clk信号从0变为1时,激发此段语句的执行,但语句的执行需要时间beginif (mult_valid)beginproduct_temp <= product_temp + partial_product;end      else if (mult_begin)beginproduct_temp <= 64'd0;endend//乘法结果的符号位和乘法结果reg product_sign;  //乘积结果的符号always @ (posedge clk)  // 乘积⑤beginif (mult_valid)beginproduct_sign <= op1_sign ^ op2_sign;endend //若乘法结果为负数,则需要对结果取反+1assign product = product_sign ? (~product_temp+1) : product_temp;
endmodule
`timescale 1ns / 1psmodule tb;// Inputsreg clk;reg mult_begin;reg [31:0] mult_op1;reg [31:0] mult_op2;// Outputswire [63:0] product;wire mult_end;// Instantiate the Unit Under Test (UUT)multiply uut (.clk(clk), .mult_begin(mult_begin), .mult_op1(mult_op1), .mult_op2(mult_op2), .product(product), .mult_end(mult_end));initial begin// Initialize Inputsclk = 0;mult_begin = 0;mult_op1 = 0;mult_op2 = 0;// Wait 100 ns for global reset to finish#100;mult_begin = 1;mult_op1 = 32'H00001111;mult_op2 = 32'H00001111;#400;mult_begin = 0;#500;mult_begin = 1;mult_op1 = 32'H00001111;mult_op2 = 32'H00002222;#400;mult_begin = 0;#500;mult_begin = 1;mult_op1 = 32'H00000002;mult_op2 = 32'HFFFFFFFF;#400;mult_begin = 0;#500;mult_begin = 1;mult_op1 = 32'H00000002;mult_op2 = 32'H80000000;#400;mult_begin = 0;// Add stimulus hereendalways #5 clk = ~clk;
endmodule

尽量不要在一个always块里对多个信号赋值,不然可能造成多驱动的问题(在不同的always里若有对相同的赋值,那出大问题(听谁的呢))

wire只是一个线路,并不能把数存住,存住得放到寄存器里(reg)

multiplier multiplicand 为内部信号 可从仿真的左侧栏里Scope-uut模块里-objects-右键某个信号就可以加进去(新加进去的是空的,得刷新下Relaunch)

仿真技巧: shift +滚轮   在变量可以新建文件夹:把要看的变量扔进去

赋初值的时候,常用非阻塞赋值。阻塞赋值即串行,非阻塞是执行完了一起赋值。(p58)


`timescale 1ns/1ns

写在所有仿真文件(.v)的代码首行,时间尺度、精度单位定义,时间尺度预编译指令,用来定义模块仿真时的时间单位和时间精度,不可被综合,但在可综合代码中也可以写,只是会在仿真时表达效果,而综合时会自动被综合器优化掉。格式如下:

`timescale   时间尺度/时间精度         或          `timescale timeunit / timeprecision

注意:仿真时间单位和时间精度的数字只能是1、10、100,不能为其它的数字。而且,时间精度不能比时间单位还要大。最多两者一样大。比如:下面定义都是对的:

`timescale  1ns/1ns

`timescale  100ns/100ns

下面的定义是错的

`timescale  1ps/1ns

时间的进位关系如下: s ms us ns ps  毫秒 微秒 纳秒 皮秒 10的三次方

时间精度就是模块仿真时间和延时的精确程序,比如:定义时间精度为10ns,那么时序中所有的延时至多能精确到10ns,而8ns或者18ns是不可能做到的。


上板验证:

约束文件 与 display文件  变量名字对应上哦,可根据之前加法器的display和约束文件对着看。

set_property PACKAGE_PIN AC19 [get_ports clk]
set_property PACKAGE_PIN U26  [get_ports led_end]
set_property PACKAGE_PIN AB21 [get_ports resetn]
set_property PACKAGE_PIN AE17 [get_ports input_sel]
set_property PACKAGE_PIN AF17 [get_ports sw_begin]set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports led_end]
set_property IOSTANDARD LVCMOS33 [get_ports resetn]
set_property IOSTANDARD LVCMOS33 [get_ports input_sel]
set_property IOSTANDARD LVCMOS33 [get_ports sw_begin]#lcd
set_property PACKAGE_PIN E5  [get_ports lcd_rst]
set_property PACKAGE_PIN G7  [get_ports lcd_cs]
set_property PACKAGE_PIN H7  [get_ports lcd_rs]
set_property PACKAGE_PIN E6  [get_ports lcd_wr]
set_property PACKAGE_PIN D5  [get_ports lcd_rd]
set_property PACKAGE_PIN J5  [get_ports lcd_bl_ctr]
set_property PACKAGE_PIN C4  [get_ports {lcd_data_io[0]}]
set_property PACKAGE_PIN C3  [get_ports {lcd_data_io[1]}]
set_property PACKAGE_PIN D4  [get_ports {lcd_data_io[2]}]
set_property PACKAGE_PIN D3  [get_ports {lcd_data_io[3]}]
set_property PACKAGE_PIN F5  [get_ports {lcd_data_io[4]}]
set_property PACKAGE_PIN G6  [get_ports {lcd_data_io[5]}]
set_property PACKAGE_PIN F4  [get_ports {lcd_data_io[6]}]
set_property PACKAGE_PIN E3  [get_ports {lcd_data_io[7]}]
set_property PACKAGE_PIN G5  [get_ports {lcd_data_io[8]}]
set_property PACKAGE_PIN H6  [get_ports {lcd_data_io[9]}]
set_property PACKAGE_PIN F2  [get_ports {lcd_data_io[10]}]
set_property PACKAGE_PIN F3  [get_ports {lcd_data_io[11]}]
set_property PACKAGE_PIN G4  [get_ports {lcd_data_io[12]}]
set_property PACKAGE_PIN G2  [get_ports {lcd_data_io[13]}]
set_property PACKAGE_PIN H4  [get_ports {lcd_data_io[14]}]
set_property PACKAGE_PIN H3  [get_ports {lcd_data_io[15]}]
set_property PACKAGE_PIN K6  [get_ports ct_int]
set_property PACKAGE_PIN J6  [get_ports ct_sda]
set_property PACKAGE_PIN L8  [get_ports ct_scl]
set_property PACKAGE_PIN K7  [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]

module multiply_display(//时钟与复位信号input clk,input resetn,    //后缀"n"代表低电平有效//拨码开关,用于选择输入数input input_sel, //0:输入为乘数1;1:输入为乘数2input sw_begin,//乘法结束信号output led_end,//触摸屏相关接口,不需要更改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
);
//-----{调用乘法器模块}beginwire        mult_begin;reg  [31:0] mult_op1; reg  [31:0] mult_op2;  wire [63:0] product; wire        mult_end;  assign mult_begin = sw_begin;assign led_end = mult_end;multiply multiply_module (.clk       (clk       ),.mult_begin(mult_begin),.mult_op1  (mult_op1  ), .mult_op2  (mult_op2  ),.product   (product   ),.mult_end  (mult_end  ));reg [63:0] product_r;always @(posedge clk)beginif (!resetn)beginproduct_r <= 64'd0;endelse if (mult_end)beginproduct_r <= product;endend
//-----{调用乘法器模块}end//---------------------{调用触摸屏模块}begin--------------------//
//-----{实例化触摸屏}begin
//此小节不需要更改reg         display_valid;reg  [39:0] display_name;reg  [31:0] display_value;wire [5 :0] display_number;wire        input_valid;wire [31:0] input_value;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//-----{从触摸屏获取输入}begin
//根据实际需要输入的数修改此小节,
//建议对每一个数的输入,编写单独一个always块//当input_sel为0时,表示输入数为乘数1always @(posedge clk)beginif (!resetn)beginmult_op1 <= 32'd0;endelse if (input_valid && !input_sel)beginmult_op1 <= input_value;endend//当input_sel为1时,表示输入数为乘数2always @(posedge clk)beginif (!resetn)beginmult_op2 <= 32'd0;endelse if (input_valid && input_sel)beginmult_op2 <= input_value;endend
//-----{从触摸屏获取输入}end//-----{输出到触摸屏显示}begin
//根据需要显示的数修改此小节,
//触摸屏上共有44块显示区域,可显示44组32位数据
//44块显示区域从1开始编号,编号为1~44,always @(posedge clk)begincase(display_number)6'd1 :begindisplay_valid <= 1'b1;display_name  <= "M_OP1";display_value <= mult_op1;end6'd2 :begindisplay_valid <= 1'b1;display_name  <= "M_OP2";display_value <= mult_op2;end6'd3 :begindisplay_valid <= 1'b1;display_name  <= "PRO_H";display_value <= product_r[63:32];end6'd4 :begindisplay_valid <= 1'b1;display_name  <= "PRO_L";display_value <= product_r[31: 0];enddefault :begindisplay_valid <= 1'b0;display_name  <= 48'd0;display_value <= 32'd0;endendcaseend
//-----{输出到触摸屏显示}end
//----------------------{调用触摸屏模块}end---------------------//
endmodule

Verilog 乘法器相关推荐

  1. verilog乘法器以及booth编码改进

    第一章 整数乘法器 1.1 整数的概念 整数在IEEE 的规定上有,短整数short integer , 中整数integer 和 长整数long integer ,它们之间的关系如下: 整数 字节空 ...

  2. Verilog乘法器

    32位无符号乘法器 使用Verilog实现32位无符号乘法器: 求x+y,其中x与y都是32位 介绍三种方法: 循环迭代,但用这种方法综合出来的电路会出现32级电路,延时较大,不推荐 Wallace树 ...

  3. verilog乘法器——基于Booth算法和Wallace树

    加法器 半加器 半加器实现两个二进制数相加的功能,不考虑低位进位. 半加器真值表 半加器逻辑表达式 S = A ^ B Cout = AB 半加器逻辑图 全加器 全加器实现两个二进制数和一个进位信号相 ...

  4. 基于Basys2的Booth乘法器的设计

    目录 一.设计指标(老样子,鲲鲲定的,我直接贴上来) 二.Booth乘法原理 三.Verilog代码 1.Booth乘法器: 2.显示转换模块: 3.数值位译码器: 4.符号位译码器: 5.时钟分频模 ...

  5. FPGA学习之路—应用程序—原码二位乘法器及Verilog代码分析

    FPGA学习之路--原码二位乘法器及Verilog代码分析 原理 原码乘法可以分为原码一位乘和原码二位乘,两者在实现规则上大同小异.原码一位乘每次判断乘数的最低位,对被乘数和部分积进行相应操作.而原码 ...

  6. Verilog编程之乘法器的实现

    知识储备 首先来回顾一下乘法是如何在计算机中实现的. 假设现在有两个32位带符号定点整数x和y,我们现在要让x和y相乘,然后把乘积存放在z中,大家知道,两个32位数相乘,结果不会超过64位,因此z的长 ...

  7. 【Verilog】布斯算法(Booth Algorithm)乘法器的 Verilog 实现

    目录 布斯算法介绍 计算步骤 计算流程图 举个栗子 Verilog 实现 设计思想 Verilog 代码 TestBench 代码 仿真波形 布斯算法介绍 Booth 的算法检查有符号二的补码表示中 ...

  8. 基2-booth乘法器原理及verilog代码

    1.booth乘法器原理 对于一个n位的有符号二进制数B,首位是0则B可以表示为: 首位是1,B[n-2:0]是实际数字的补码,所以可以得到 . 可以得到合并的公式如下所示: 将公式展开: 除了n-1 ...

  9. Verilog实现---IEEE标准的单精度浮点乘法器

    目录 1.实现目标 2.原理说明 3.设计说明 4.Verilog代码 后言 1.实现目标 2.原理说明 首先要懂得浮点乘法器的工作原理与如何编码运算的过程,这里给出两个参考Blog. 浮点加法.减法 ...

最新文章

  1. python类介绍_python类介绍
  2. 使用python向Redis批量导入数据
  3. javascript访问ACCESS数据库
  4. HALCON示例程序vessel.hdev血管的分割与测量
  5. leetcode 538. 把二叉搜索树转换为累加树 思考分析
  6. Lucene Boost 精度表
  7. 软件测试与发布,软件测试与发布技术
  8. python爬虫实践
  9. PyInstaller:编译exe与反编译
  10. 关于 intptr_t
  11. 背景建模之codebook算法
  12. 一位大牛对于写技术博客的一些建议
  13. 2012, PPSN,Geometric Semantic Genetic Programming,GSGP
  14. 来看看未来最有前景的行业
  15. html5 canvas 图片移动端,支持移动端的HTML5 Canvas逼真黑板特效
  16. 虚拟内存、虚拟地址-页-页号、物理地址-页框-页框号
  17. Swift - 设置UILabel、UITextView的文字行间距
  18. Kafka概述-什么是Kafka?
  19. unity GetComponent使用
  20. 分布式游戏服务器通用架构的设计

热门文章

  1. 【androidx86 5.1.1】Android HttpClient请求过程解析(上)
  2. 清除U盘内所占的隐藏空间
  3. CAD图纸中CAD文字边界为锯齿形的原因及解决办法
  4. IntelliJ IDEA(2020.2)的下载、安装步骤(详细讲解)
  5. 红米k30 允许调用gpu调试层_老司机带带你:一张图看懂红米K30全系区别-红米K30,小米 ——快科技(驱动之家旗下媒体)-...
  6. 项目经理如何做好跨部门沟通?
  7. java实现 蓝桥杯 算法训练 安慰奶牛
  8. 面试官:MySQL事务的隔离性是如何实现的?
  9. 在RGUI中更新R 的版本
  10. unity给自己的模型加上镜面效果