FMV.X.W命令とFMV.W.X命令
整数レジスタと浮動小数点レジスタ間で値の受け渡しを行う命令。
fmv.w.x (Floating-point move Word from Integer)
f[rd] = x[rs1]
fmv.x.w (Floating-point Move Word to Integer)
x[rd] = f[rs1]
https://gyazo.com/91a4945d95ef36519d8fa10acf16d762
実装した。
code:diff
diff --git a/rtl/cpu.sv b/rtl/cpu.sv
index 6b61886..c24e209 100644
--- a/rtl/cpu.sv
+++ b/rtl/cpu.sv
@@ -92,6 +92,7 @@ module cpu(
logic dc_mem_to_reg;
+ logic dc_reg_to_reg;
logic branch;
logic jump;
logic jump_reg;
@@ -109,6 +110,7 @@ module cpu(
.aluOp(alu_op),
.fpuOp(fpu_op),
.memToReg(dc_mem_to_reg),
+ .regToReg(dc_reg_to_reg),
.branch(branch),
.jump(jump),
.jumpReg(jump_reg),
@@ -207,6 +209,7 @@ module cpu(
assign rf_addr3 = instr_reg11:7; // rd assign rf_we3 = (stage_reg == WB_STAGE) && dc_reg_write;
assign rf_write_data3 = (dc_mem_to_reg) ? mem_rdata_reg : // lw の場合
+ (dc_reg_to_reg) ? rf_read_data1 : // fmv.x.w, fmv.w.x の場合
(jump) ? pc_reg + 4 : // jal, jalr の場合
(fpu === 1'b1) ? fpu_result_reg // FPU の演算結果
: alu_result;
@@ -332,6 +335,7 @@ module decoder(
output logic memToReg,
+ output logic regToReg,
output logic branch,
output logic jump,
output logic jumpReg,
@@ -390,6 +394,10 @@ module decoder(
(opCode == 7'b0000111) ? 1'b1 // flw
: 1'b0;
+ assign regToReg = (opCode == 7'b1010011 && funct7 == 7'b1110000) ? 1'b1 : // fmv.w.x
+ (opCode == 7'b1010011 && funct7 == 7'b1111000) ? 1'b1 // fmv.x.w
+ : 1'b0;
+
assign branch = (opCode === 7'b1100011) ? 1'b1 // B type
: 1'b0;
@@ -422,8 +430,13 @@ module decoder(
// readRegType1 は 1 で、writeRegType は 0 になる
// feq, flt, fle の場合(opCode = 1010011, funct7 = 1010000)
// writeRegType は 0 になる
+ // fmv.w.x (frd = xrs1) の場合(opCode = 1010011, funct7 = 1111000) + // readRegType1 は 0(整数レジスタ) で、writeRegType は 1(浮動小数点レジスタ) になる
+ // fmv.x.w (xrd = frs1) の場合(opCode = 1010011, funct7 = 1110000) + // readRegType1 は 1(浮動小数点レジスタ) で、writeRegType は 0(整数レジスタ) になる
assign readRegType1 = (opCode === 7'b1010011 && funct7 === 7'b1101000) ? 1'b0 : // 整数レジスタを参照 (fcvt.s.w = int to float)
+ (opCode === 7'b1010011 && funct7 === 7'b1111000) ? 1'b0 : // 整数レジスタを参照 (fmv.w.x = frd <- xrs1) (opCode === 7'b1010011) ? 1'b1 // 浮動小数点レジスタを参照 (fcvt.s.w 以外の RV32F の R-type 命令)
: 1'b0; // 整数レジスタを参照
@@ -434,6 +447,7 @@ module decoder(
assign writeRegType = (opCode === 7'b0000111) ? 1'b1 : // 浮動小数点レジスタへ書き込み (flw)
(opCode === 7'b1010011 && funct7 === 7'b1100000) ? 1'b0 : // 整数レジスタへ書き込み (fcvt.w.s = float to int)
(opCode === 7'b1010011 && funct7 === 7'b1010000) ? 1'b0 : // 整数レジスタへ書き込み (feq, flt, fle)
+ (opCode === 7'b1010011 && funct7 === 7'b1110000) ? 1'b0 : // 整数レジスタへ書き込み (fmv.x.w)
(opCode === 7'b1010011) ? 1'b1 // 浮動小数点レジスタを参照(RV32F の R type)
: 1'b0; // 整数レジスタへ書き込み
diff --git a/rtl/fpu_controller.sv b/rtl/fpu_controller.sv
index 61524a0..6111da0 100644
--- a/rtl/fpu_controller.sv
+++ b/rtl/fpu_controller.sv
@@ -88,7 +88,7 @@ module fpu_controller(
(op === 4'b1010) ? fle_out_stb :
(op === 4'b0010) ? multiplier_out_stb :
(op === 4'b0011) ? divider_out_stb
- : 1'bx;
+ : 1'b1; // 該当しない場合は、すぐにアサートしても良いかもしれない
assign out = (op === 4'b0000 || op === 4'b0001) ? adder_out :
(op === 4'b0100) ? int2float_out :
(op === 4'b0101) ? float2int_out :
diff --git a/rtl/test_program/fp.sv b/rtl/test_program/fp.sv
index b11f2ff..c04e51c 100644
--- a/rtl/test_program/fp.sv
+++ b/rtl/test_program/fp.sv
@@ -4,10 +4,10 @@
/* instruction0からinstruction63までの命令がメモリに書き込まれる */ -// FDIV.S のテスト
+// FMV 系のテスト
instructions0 = flw(5, 0, 32'h108); // f5 = 3.0 -instructions1 = flw(6, 0, 32'h104); // f6 = 2.0 -instructions2 = fdiv_s(7, 5, 6); // f7 = f5 / f6 +instructions1 = fmv_x_w(6, 5); // x6 = f5 +instructions2 = fmv_w_x(7, 6); // f7 = x6 instructions3 = fsw(0, 7, 32'h110); // M0x110 = f7 // FADD.S のテスト (1.0 + 2.0)
@@ -78,7 +78,13 @@ instructions43 = sw(0, 7, 32'h150); // M0x150 = x7 (== 0) instructions44 = fle_s(7, 5, 5); // x7 = (f5 <= f5) ? 1 : 0 instructions45 = sw(0, 7, 32'h154); // M0x154 = x7 (== 1) -instructions46 = jal(0, 0); // 無限ループ +// FDIV.S のテスト
+instructions46 = flw(5, 0, 32'h108); // f5 = 3.0 +instructions47 = flw(6, 0, 32'h104); // f6 = 2.0 +instructions48 = fdiv_s(7, 5, 6); // f7 = f5 / f6 +instructions49 = fsw(0, 7, 32'h158); // M0x158 = f7 +
+instructions50 = jal(0, 0); // 無限ループ // テスト用の浮動小数点数データ
instructions64 = 32'h3f800000; // M0x100 = 1.0 @@ -127,7 +133,7 @@ mem_monitor_wstrb_reg = 4'b0000;
wait(mem_ready);
assert(
- mem_rdata === 32'h3fc00000 // 1.5
+ mem_rdata === 32'h40400000 // 3.0
) $display("PASSED"); else $display("FAILED: %h", mem_rdata);
mem_monitor_valid_reg = 0;
@@ -253,7 +259,7 @@ mem_monitor_wstrb_reg = 4'b0000;
wait(mem_ready);
assert(
mem_rdata === 32'h0
-) $display("PASSED"); else $display("@FAILED: %h", mem_rdata);
+) $display("PASSED"); else $display("FAILED: %h", mem_rdata);
mem_monitor_valid_reg = 0;
@@ -331,3 +337,15 @@ assert(
) $display("PASSED"); else $display("FAILED: %h", mem_rdata);
mem_monitor_valid_reg = 0;
+
+mem_monitor_on = 1;
+mem_monitor_valid_reg = 1;
+mem_monitor_addr_reg = 32'h158;
+mem_monitor_wstrb_reg = 4'b0000;
+#10;
+wait(mem_ready);
+assert(
+ mem_rdata === 32'h3fc00000 // 1.5
+) $display("PASSED"); else $display("FAILED: %h", mem_rdata);
+mem_monitor_valid_reg = 0;
+#10;