module complex;
wire [31:0] rw1,rw2,rw3,rw4,rw5,rw6,rw7,rw8,rw9,rw10,rw11,rw12,rw13,rw14,rw15,rw16,iw1,iw2,iw3,iw4,iw5,iw6,iw7,iw8,iw9,iw10,iw11,iw12,iw13,iw14,iw15,iw16;
reg [31:0] rw [1:2];
reg [31:0] iw [1:2];
integer j,bin,bin1;
initial begin
bin=$fopen("realout.txt","w");
bin1=$fopen("imout.txt","w");
end
complexmul c1(ra1,ia1,h1r,h1i,rw1,iw1);
complexmul c2(ra2,ia2,h2r,h2i,rw2,iw2);
complexmul c3(ra3,ia3,h3r,h3i,rw3,iw3);
complexmul c4(ra4,ia4,h4r,h4i,rw4,iw4);
complexmul c5(ra5,ia5,h5r,h5i,rw5,iw5);
complexmul c6(ra6,ia6,h6r,h6i,rw6,iw6);
complexmul c7(ra7,ia7,h7r,h7i,rw7,iw7);
complexmul c8(ra8,ia8,h8r,h8i,rw8,iw8);
complexmul c9(ra9,ia9,h9r,h9i,rw9,iw9);
complexmul c10(ra10,ia10,h10r,h10i,rw10,iw10);
complexmul c11(ra11,ia11,h11r,h11i,rw11,iw11);
complexmul c12(ra12,ia12,h12r,h12i,rw12,iw12);
complexmul c13(ra13,ia13,h13r,h13i,rw13,iw13);
complexmul c14(ra14,ia14,h14r,h14i,rw14,iw14);
complexmul c15(ra15,ia15,h15r,h15i,rw15,iw15);
complexmul c16(ra16,ia16,h16r,h16i,rw16,iw16);
always@(rw1 or iw1 or rw2 or iw2)
begin
rw[1]=rw1;
iw[1]=iw1;
rw[2]=rw2;
iw[2]=iw2;
for(j=1;j<3;j=j+1)
begin
$fwrite(bin,"%b\n",rw[j]);
$fwrite(bin1,"%b\n",iw[j]);
end
$fclose(bin);
$fclose(bin1);
end
endmodule
module complexmul(yr,yi,h11r,h11i,r,i);
input [31:0]h11r,h11i;
input [31:0]yr,yi;
output [31:0]r,i;
wire [31:0]x1,x2,x3;
wire [31:0]x,y,z;
fpadd a1(yr,yi,x1);
fpadd a2(h11r,{~h11i[31],h11i[30:0]},x2);
fpmul m3(x1,x2,x);
fpmul m4(yi,h11r,y);
fpmul m5(yr,h11i,z);
fpadd a3(x,z,x3);
fpadd a4(x3,{~y[31],y[30:0]},r);
fpadd a5(y,z,i);
endmodule
//floating point multiplier
module fpmul(a,b,out);
input[31:0]a,b;
output [31:0]out;
wire [7:0]exp;
wire [22:0]mant;
wire s;
fmul manipulate(a[30:23],b[30:23],a[31],b[31],{1'b1,a[22:0]},{1'b1,b[22:0]},exp,mant,s);
assign out={s,exp,mant}; //concatenation
endmodule
//submodule for multiplication
module fmul(aexp,bexp,as,bs,am,bm,exp,mant,s);
input [23:0]am,bm;
input[7:0]aexp,bexp;
input as,bs;
output reg [7:0]exp;
output reg[22:0]mant;
output reg s;
reg flag; //zero flag
reg [7:0]ex;
reg [8:0]e;
reg [47:0]man;
always@(*)
begin
if(((aexp==0)||(bexp==0))&&((am[22:0]==0)||(bm[22:0]==0))) //check for zero operand
begin
exp=0;
mant=0;
s=0;
flag=1;
end
else
begin
s=as^bs; //sign
e=aexp+bexp; //exponent
ex=e-127;
man=am*bm; //mantissa
flag=0;
if(man[47]==0) //normalise
begin
mant=man[45:23]; //truncate and have only 23 bits from MSB
exp=ex;
end
else
begin
mant=man[46:24];
exp=ex+1;
end
end
end
endmodule
module fpadd(a,b,out);
input [31:0]a,b;
output [31:0]out;
wire [7:0]e1,e2,ex,ey,exy;
wire s1,s2,s,s3,sr;
wire [23:0]m1,m2,mx,my,mxy;
wire [24:0]mxy1;
assign s1=a[31];
assign s2=b[31];
assign e1=a[30:23];
assign e2=b[30:23];
assign m1[23]=1'b1;
assign m2[23]=1'b1;
assign m1[22:0]=a[22:0];
assign m2[22:0]=b[22:0];
//submodule for compare and shfit
cmpshift as(e1[7:0],e2[7:0],m1[23:0],m2[23:0],ex,ey,mx,my,s);
//submodule for mantissa addition snd subtraction
faddsub as1(mx,my,s1,s2,mxy1,s3);
//sub module for normalization
normalized as2(mxy1,s,s1,s2,s3,sr,ex,exy,mxy);
assign out={sr,exy,mxy[22:0]};
endmodule
module normalized(mxy1,s,s1,s2,s3,sr,ex,exy,mxy);
input[24:0]mxy1;
input s,s1,s2,s3;
input[7:0]ex;
output reg sr;
output reg[7:0]exy;
output reg[23:0]mxy;
reg [24:0]mxy2;
always@(*)
begin
sr=s?s1^(mxy1[24]&s3):s2^(mxy1[24]&s3);
mxy2=(mxy1[24]&s3)?~mxy1+25'b1:mxy1;
mxy=mxy2[24:1];
exy=ex;
repeat(24)
begin
if(mxy[23]==1'b0)
begin
mxy=mxy<<1'b1;
exy=exy-8'b1;
end
end
end
endmodule
//submodule for addition or subtraction
module faddsub(a,b,s1,s2,out,s);
input [23:0]a,b;
input s1,s2;
output reg[24:0]out;
output reg s;
always@(*)
begin
s=s1^s2;
if(s)
begin
out=a-b;
end
else
begin
out=a+b;
end
end
endmodule
//module for copare &shift
module cmpshift(e1,e2,m1,m2,ex,ey,mx,my,s);
input [7:0]e1,e2;
input [23:0]m1,m2;
output reg[7:0]ex,ey;
output reg[23:0]mx,my;
output reg s;
reg [7:0]diff;
always@(*)
begin
if(e1==e2)
begin
ex=e1+8'b1;
ey=e2+8'b1;
mx=m1;
my=m2;
s=1'b1;
end
else if(e1>e2)
begin
diff=e1-e2;
ex=e1+8'b1;
ey=e1+8'b1;
mx=m1;
my=m2>>diff;
s=1'b1;
end
else
begin
diff=e2-e1;
ex=e2+8'b1;
ey=e2+8'b1;
mx=m2;
my=m1>>diff;
s=1'b0;
end
end
endmodule