乗算と除算を追加したらタイミングエラーが発生した話
雑に乗算と除算を追加したら、タイミング制約を満たせなくてエラーが発生するようになった。恐ろしい...
FPUみたいに、待ち合わせが必要になりそう。
code:diff
diff --git a/rtl/cpu.sv b/rtl/cpu.sv
index 6b61886..c608578 100644
--- a/rtl/cpu.sv
+++ b/rtl/cpu.sv
@@ -500,6 +500,8 @@ module alu_controller(
default: case(funct)
10'b0000000000: aluOp = 4'b0000; // add
10'b0100000000: aluOp = 4'b0001; // sub
+ 10'b0000001100: aluOp = 4'b1011; // div
+ 10'b0000001000: aluOp = 4'b1010; // mul
10'b0000000111: aluOp = 4'b1001; // and
10'b0000000100: aluOp = 4'b0101; // xor
10'b0000000110: aluOp = 4'b1000; // or
@@ -578,6 +580,8 @@ endmodule
// 0111 | sra
// 1000 | or
// 1001 | and
+// 1010 | mul
+// 1011 | div
// ------------------
module alu(
input logic 31:0 in1, in2, @@ -593,8 +597,10 @@ module alu(
assign sltResult = ($signed(in1) < $signed(in2)) ? 32'b1 : 32'b0;
assign sltuResult = (in1 < in2) ? 32'b1 : 32'b0;
- assign result = (op === 4'b0000) ? (in1 + in2) : // plus
- (op === 4'b0001) ? (in1 - in2) : // minus
+ assign result = (op === 4'b0000) ? (in1 + in2) : // add
+ (op === 4'b0001) ? (in1 - in2) : // sub
+ (op === 4'b1010) ? (in1 * in2) : // mul
+ (op === 4'b1011) ? (in1 / in2) : // div
(op === 4'b1001) ? (in1 & in2) : // and
(op === 4'b1000) ? (in1 | in2) : // or
(op === 4'b0101) ? (in1 ^ in2) : // xor
diff --git a/rtl/cpu_test.sv b/rtl/cpu_test.sv
index 805a5cc..999f86f 100644
--- a/rtl/cpu_test.sv
+++ b/rtl/cpu_test.sv
@@ -71,8 +71,8 @@ module cpu_test;
$monitoroff; // プログラム書き込み中は $monitor を一時停止
- // `include "test_program/beq_and_auipc.sv"
- `include "test_program/fp.sv"
+ `include "test_program/beq_and_auipc.sv"
+ // `include "test_program/fp.sv"
$finish;
end
diff --git a/rtl/instructions.sv b/rtl/instructions.sv
index 5663438..f27c13b 100644
--- a/rtl/instructions.sv
+++ b/rtl/instructions.sv
@@ -83,6 +83,40 @@ function 31:0 sub( };
endfunction
+// div rd, rs1, rs2
+// rd = rs1 / rs2
+);
+ div = {
+ 7'b0000001, // funct7
+ rs2,
+ rs1,
+ 3'b100, // funct3
+ rd,
+ 7'b0110011 // opCode
+ };
+endfunction
+
+// mul rd, rs1, rs2
+// rd = rs1 * rs2
+);
+ mul = {
+ 7'b0000001, // funct7
+ rs2,
+ rs1,
+ 3'b000, // funct3
+ rd,
+ 7'b0110011 // opCode
+ };
+endfunction
+
// and rd, rs1, rs2
// rd = rs1 & rs2
diff --git a/rtl/test_program/beq_and_auipc.sv b/rtl/test_program/beq_and_auipc.sv
index 5a259ed..7bd00ff 100644
--- a/rtl/test_program/beq_and_auipc.sv
+++ b/rtl/test_program/beq_and_auipc.sv
@@ -18,7 +18,16 @@ instructions7 = addi(5, 0, 123); // x5 = 123 instructions8 = sw(0, 5, 12'h408); // M0x408 = x5 instructions9 = addi(5, 5, 123); // x5 = x5 + 123 instructions10 = sw(0, 5, 12'h40c); // M0x40c = x5 -instructions11 = jal(0, 0); // 無限ループ +
+// mul と div のテスト
+instructions11 = addi(5, 0, 10); // x5 = 10 +instructions12 = addi(6, 0, 20); // x6 = 20 +instructions13 = mul(7, 5, 6); // x7 = x5 * x6 (200) +instructions14 = div(8, 6, 5); // x8 = x6 / x5 (2) +instructions15 = add(9, 7, 8); // x9 = 200 + 2 +instructions16 = sw(0, 9, 12'h410); // M0x410 = x9 +instructions17 = jal(0, 0); // 無限ループ +
/**
* プログラムの書き込み
@@ -103,3 +112,16 @@ assert(
) $display("PASSED"); else $display("FAILED: %h", mem_rdata);
mem_monitor_valid_reg = 0;
+
+
+mem_monitor_valid_reg = 1;
+mem_monitor_addr_reg = 32'h00000410;
+mem_monitor_wstrb_reg = 4'b0000;
+#10;
+wait(mem_ready);
+#10;
+assert(
+ mem_rdata === 202
+) $display("PASSED"); else $display("FAILED: %h", mem_rdata);
+mem_monitor_valid_reg = 0;
+#10;