模拟IEEE754的过程

#include <iostream>

using namespace std;

int carry; //CF

typedef struct FP{
	string S; //1
	string E; //8
	string M; //23
	string Guard, RoundUp, Safe;
} FPNumber;

int BitsZero(string a) {
	for (auto c: a)
		if (c == '1')
			return false;
	return true;
}

string BitsAdd(string a, string b);
int BitsToDecimal(string a);

void print(FPNumber a) {
	cout << "符号: " << a.S << endl;
	cout << "阶码: " << BitsToDecimal(a.E) - 127 << endl;
	cout << "数符: " << a.M << endl;
	cout << "G :" << ' ' << a.Guard << endl;
	cout << "R :" << ' ' << a.RoundUp << endl;
	cout << "S :" << ' ' << a.Safe << endl;
	return;
}

FPNumber lShift(FPNumber a) {
	string str = a.M + a.Guard + a.RoundUp + a.Safe;
	while (str[0] != '1') {
		a.E = BitsAdd(a.E, "11111111");
		if (!carry) {
			exit(1); //panic 溢出了
		}
		str = str.substr(1);
	}
	a.E = BitsAdd(a.E, "11111111");
	if (!carry) {
		exit(1); //panic 溢出了
	}
	str = str.substr(1);
	while(str.size() < 26)
		str += '0';
	int bits = str.size() - 23;
	if (bits > 0) {
		a.Guard = str[23];
	} else 
		a.Guard = "0";
	if (bits > 1) {
		a.RoundUp = str[23 + 1];
	} else
		a.RoundUp = "0";
	if (bits > 2) {
		int ok = 0;
		for (int i = 23; i < str.length(); i ++)
			if (str[i] == '1')
				ok = 1;
		a.Safe = ok + '0';
	}
	str = str.substr(0, 23);
	a.M = str;
	return a;
}

FPNumber rShift(FPNumber b, int bits) {
	//对阶、右移,符号位不变;隐藏位1参与运算。
	string r = "";
	for (int i = 0; i < bits; i ++)
		r += "0";
	r += b.M;
	cout << r << endl;
	if (bits > 0) {
		b.Guard = r[b.M.length()];
	}
	if (bits > 1) {
		b.RoundUp = r[b.M.length() + 1];
	}
	if (bits > 2) {
		int ok = 0;
		for (int i = b.M.length(); i < r.length(); i ++)
			if (r[i] == '1')
				ok = 1;
		b.Safe = ok + '0';
	}
	b.M = string(' ', 23);
	for (int i = 0; i < 23; i ++)
		b.M[i] = r[i];
	return b;
}

string BitsAdd(string a, string b) {
	carry = 0;
	for (int i = b.length() - 1; i >= 0; i --) {
		int A = a[i] - '0', B = b[i] - '0';
		a[i] = (A + B + carry) % 2 + '0';
		carry = (A + B + carry) / 2;
	}
	return a;
}

string BitsRev(string b) {
	for (int i = 0; i < b.length(); i ++) {
		if (b[i] == '0')
			b[i] = '1';
		else
			b[i] = '0';
	}
	string one = "";
	for (int i = 0; i < b.length() - 1; i ++)
		one += '0';
	one += '1';
	b = BitsAdd(b, one);
	return b;
}

string BitsSub(string a, string b) { //补码减法
	b = BitsRev(b);
	a = BitsAdd(b, a);
	return a;
}

int BitsToDecimal(string a) {
	reverse(a.begin(), a.end());
	int ans = 0, exp = 1;
	for (int i = 0; i < a.length(); i ++) {
		int A = a[i] - '0';
		ans = ans + exp * A;
		exp <<= 1;
	}
	return ans;
}

FPNumber add(FPNumber a, FPNumber b) {
	if (a.E > b.E) {
		swap(a, b);
	}
	// 1. 对阶
	FPNumber c = a; //小阶向大阶看齐; 只会右移.
	c = rShift(c, BitsToDecimal(BitsSub(b.E, c.E))); //数码右移;
	//对阶的时候不舍入!!
	c.E = b.E; //阶码看齐.
	print(c);


	// 2. 尾数加减
	// 尾数相加减的时候要把隐藏位加上. 也要带着GRS位.
	string A = "1" + a.M + a.Guard + a.RoundUp + a.Safe;
	string B = "1" + b.M + b.Guard + b.RoundUp + b.Safe;
	//原码加法。
	/*
		比较两个操作数的符号;
		对于加法,同和异差;
		减法相反。

		求和时,数值位相加,CF代表溢出;符号和被加数相同。
		求差时,加数求补,进行加法运算。CF=1说明结果为正;否则为负。
		最后要根据CF返回结果的真值(再次求补)。
	*/
	string C = "";
	if (a.S != b.S) {
		B = BitsRev(B);
		C = BitsAdd(A, B);
		if (carry) {
			c.S = "0";
		} else {
			c.S = "1";
			C = BitsRev(C);
		}
		carry = 0;
	} else {
		c.S = a.S;
		C = BitsAdd(A, B);
	}
	if (BitsZero(C)) {
		//带上隐藏位仍然是全0,机器零异常
		exit(1); //panic;
	}
	// 3. 结果规格化
	int ls = (C[0] == '0'); //如果隐藏位还是1的话,没必要左规了。
	C = C.substr(1); //把隐藏位去掉..
	c.M = C;
	if (carry) { //溢出,右归. 原码加法只有同号会溢出.
		c.E = BitsAdd(c.E, "00000001");
		if (carry) {
			exit(1); //panic
		}
		c = rShift(c, 1);
	}
	//左规。
	if (ls)
		c = lShift(c); //这个过程会溢出

	print(c);
	// 4. 尾数舍入
	string RD = c.Guard + c.RoundUp + c.Safe;
	if (RD >= "100") {
		//这里要给c.M + 0.000...1,还要左规右规。
	} else {
		//truncate.
	}
	c.Guard = "0";
	c.RoundUp = "0";
	c.Safe = "0";
	// 5. 判断溢出.
	return c;
}

int main() {
	FPNumber a = {"0", "01111111", "10000000000000000000000", "0", "0", "0"}; //1.5
	FPNumber b = {"1", "01111111", "01000000000000000000000", "0", "0", "0"}; //1.25
	add(a, b);
}
/*
 100000000000000000001111000
 100000000000000000000001000
1100000000000000000010000000
*/
下面是一个简单的 IEEE 754 浮点乘法运算的 Verilog 代码示例: ```verilog module float_multiplier( input [31:0] a, // IEEE 754 格式的浮点数 a input [31:0] b, // IEEE 754 格式的浮点数 b output reg [31:0] result // IEEE 754 格式的浮点数结果 ); reg [30:0] mantissa_a; reg [30:0] mantissa_b; reg [30:0] mantissa_result; reg [7:0] exponent_a; reg [7:0] exponent_b; reg [7:0] exponent_result; reg sign_a; reg sign_b; reg sign_result; // 解析输入浮点数 a 的符号、指数和尾数 assign sign_a = a[31]; assign exponent_a = a[30:23]; assign mantissa_a = {1'b1, a[22:0]}; // 解析输入浮点数 b 的符号、指数和尾数 assign sign_b = b[31]; assign exponent_b = b[30:23]; assign mantissa_b = {1'b1, b[22:0]}; // 计算结果的符号 assign sign_result = sign_a ^ sign_b; // 计算结果的指数 assign exponent_result = exponent_a + exponent_b - 127; // 计算结果的尾数 assign mantissa_result = mantissa_a * mantissa_b; // 处理尾数溢出 always @(*) begin if (mantissa_result[31:24] != 8'b00000000) begin exponent_result <= exponent_result + 1; mantissa_result <= mantissa_result >> 1; end end // 处理规格化和非规格化数 always @(*) begin if (mantissa_result[30] == 1'b1) begin mantissa_result <= mantissa_result[27:0]; end else begin mantissa_result <= {3'b0, mantissa_result[26:0]}; exponent_result <= exponent_result - 1; end end // 处理指数上溢和下溢 always @(*) begin if (exponent_result > 254) begin exponent_result <= 255; mantissa_result <= 0; end else if (exponent_result < 1) begin exponent_result <= 0; mantissa_result <= 0; end end // 组合结果 always @(*) begin result[31] = sign_result; result[30:23] = exponent_result; result[22:0] = mantissa_result[22:0]; end endmodule ``` 该代码将两个 IEEE 754 格式的浮点数相乘,并输出一个 IEEE 754 格式的浮点数结果。其中,使用了 Verilog 中的位运算和移位操作,以及一些条件分支语句,来实现浮点数的乘法运算。需要注意的是,该代码仅供参考,实际使用时应该根据具体的需求进行修改和优化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值