Verilog实现加减乘除运算

用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 
 

你可能感兴趣的:(FPGA技术)