源码:
module functions(
a,
b,
clk,
rst,
error,
sel
);
input [15:0] a;
input [1:0] sel;
input clk,rst;
output [47:0] b;//只满足了立方,阶乘可能越界,设置一个错误位
output error;
parameter callsquare = 2'd0,callcube = 2'd1,callfactorial = 2'd2;
reg [47:0] b;
reg error;
reg [47:0] factorial0;
integer i;//reg和integer可以相乘,不过integer默认有符号,并且相乘之前不要忘了初始化
reg c;//进位位
always@(posedge clk or negedge rst)
begin
if(rst == 1'b0)
begin
b <= 47'b0;
error <= 1'b0;
factorial0 <= 48'h0000_0000_0000;
c <= 1'b0;
end
else
begin
case(sel)
callsquare: b <= square(a);
callcube: b <= cube(a);
callfactorial: b <= factorial(a);
default:begin b <= 47'b0;error <= 1'b1; end
endcase
end
end
function [47:0] square;
input [15:0] a0;
begin
error = 1'b0;
c = 1'b0;
square = a0*a0;
end
endfunction
function [47:0] cube;
input [15:0] a1;
begin
error = 1'b0;
c = 1'b0;
cube = a1*a1*a1;//函数里面必须阻塞赋值
end
endfunction
function [47:0] factorial;
input [15:0] a2;
begin
error = 1'b0;
c = 1'b0;
factorial = 48'h0000_0000_0000;
factorial[15:0] = a2;
//不过奇怪的是,这里一个clk边沿就就计算出来了,所以逻辑会超级复杂,这样写或许一点也不好
for(i = 2;i < a2;i = i + 32'b1)
begin
{c,factorial} = factorial * i;//不过目前必须得设置中间变量,否则无法初始化
if(c == 1'b1) error = 1'b1;
end
if(error == 1'b1)
factorial = 48'hffff_ffff_ffff;
end
endfunction
endmodule
测试代码:
`timescale 1ns/1ns
module functionstb;
reg [15:0] a;
reg [1:0] sel;
reg clk,rst;
wire [47:0] b;//只满足了立方,阶乘可能越界,设置一个错误位
wire error;
initial
begin
sel = 2'b0;
a = 16'd3;
clk = 1'b0;
rst = 1'b1;
#5
rst = 1'b0;
#5
rst = 1'b1;
repeat(16)
begin
#10
sel = sel + 2'b1;
a = a + 16'd1;
end
end
always #1 clk = ~clk;
functions functions0(
.a(a),
.b(b),
.clk(clk),
.rst(rst),
.error(error),
.sel(sel)
);
endmodule
现象:
可见情况1,阶乘结果没有越界,未输出error,情况2,阶乘越界,输出error且输出全置一,在选到没有对应的sel = 3的时候,也是输出error,输出置零。