在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 2742|回复: 0

[转贴] Verilog实现加减乘除运算

[复制链接]
发表于 2020-2-16 09:15:53 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
用Verilog实现,两个16位输入,一个32位输出的四则运算模块,这里我是使用的调用IP核的方式,毕竟人家官方推出的要比我们自个写的要稳定一点,这里调用了加法器,减法器,乘法器,触发器的IP核。

代码如下:

module jisuan(
    //input pin;
    Clk,
    Rst_n,
    data_A,
    data_B,
    mode, //+,-,*,/.
    start,
    //output pin;
    data_C

);
//input pin define;
input Clk;
input Rst_n;
input [1 : 0]mode;
input [15 : 0]data_A;
input [15 : 0]data_B;
input start;
//output pin define;
output reg[31 : 0]data_C;

localparam
    add = 2'b00,
    min = 2'b01,
    mul = 2'b10,
    did = 2'b11;

wire [15 : 0]result1;
wire [15 : 0]result2;
wire [31 : 0]result3;
reg add_sub;   
wire cout;
reg clken_subormin;
reg clken_chufa;
reg clken_chengfa;
reg aclr;

subormin subormin1(
    .aclr(aclr),
    .add_sub(add_sub),
    .clken(clken_subormin),
    .clock(Clk),
    .dataa(data_A),
    .datab(data_B),
    .result(result1)
);

chufa chufa1(
    .aclr(aclr),
    .clken(clken_chufa),
    .clock(Clk),
    .denom(data_B),
    .numer(data_A),
    .quotient(result2),
    .remain()
);

chengfa chengfa1(
    .aclr(aclr),
    .clken(clken_chengfa),
    .clock(Clk),
    .dataa(data_A),
    .datab(data_B),
    .result(result3)
);
        
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)begin
    clken_subormin <= 1'b0;
    clken_chengfa <= 1'b0;
    clken_chufa <= 1'b0;
    add_sub <= 1'b0;
    aclr <= 1'b1; //清零
end
else if(start) begin
    aclr <= 1'b0;
   
    case(mode)
    add : begin add_sub <= 1'b1; clken_subormin <= 1'b1; end
    min : begin add_sub <= 1'b0; clken_subormin <= 1'b1; end
    mul : clken_chengfa <= 1'b1;
    did : clken_chufa <= 1'b1;
    default: ;
    endcase
   
end
else  begin
    clken_subormin <= 1'b0;
    clken_chengfa <= 1'b0;
    clken_chufa <= 1'b0;
    aclr <= 1'b1;
end

always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
    data_C <= 32'd0;
else if(start)
    case(mode)
        add : data_C[15 : 0] <= result1;
        min : data_C[15 : 0] <= result1;
        did : data_C[15 : 0] <= result2;
        mul : data_C <= result3;
        default : data_C <= 32'd0;
        endcase
else
    data_C <= 32'd0;
   
endmodule

模块使用方法:输入data_A,data_B,确定mode(加,减,乘,除),然后Start=1,开始进行计算,四个时钟周期后,data_C上的值就是运算结果。至于为什么要等待四个时钟周期呢,这是因为做运算是需要时间的吗,不可能刚给个输入数据,就直接可以得到输出数据。这个时间是怎么来的呢?通过仿真得来的,经过时序仿真,发现第四个时钟沿的时候数据是稳定的。

仿真代码如下:

`timescale 1ns / 1ns
`define clk_period 20

module jisuan_tb();

//input pin define;
reg Clk;
reg Rst_n;
reg [1 : 0]mode;
reg [31 : 0]data_A;
reg [31 : 0]data_B;
reg start;
//output pin define;
wire [31 : 0]data_C;
wire done;

initial Clk = 1;
always #(`clk_period / 2) Clk = ~Clk;

jisuan u1(
    //input pin;
    .Clk(Clk),
    .Rst_n(Rst_n),
    .data_A(data_A),
    .data_B(data_B),
    .mode(mode), //+,-,*,/.
    .start(start),
    //output pin;
    .data_C(data_C)
);

initial begin
mode = 0;
Rst_n = 0;
start = 0;
#(20 * `clk_period);
Rst_n = 1;
#(20 * `clk_period);
repeat(10)begin
    data_A = {$random} % 100;
    data_B = {$random} % 100;
    mode = mode + 1;
    start = 1;
    #(20 * `clk_period);
    start = 0;
    #(20 * `clk_period);
end
$stop;
end


endmodule


这里还有个问题,就是这个IP核是怎么调用的呢?这个问题也困扰了我好久,有些IP核我们听都没听过,我们怎么知道什么时候可以用IP核,以及IP核的调用格式呢?这里我分享一个关于altera IP核的电子书:

链接:https://pan.baidu.com/s/1P7y-ZCWhs0Ay6bLFZF3t5A
提取码:k6js
————————————————
版权声明:本文为CSDN博主「漫步人生只为寻你」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_37926592/article/details/86130514
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条


小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-12-22 10:42 , Processed in 0.014457 second(s), 5 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表