commit 12dcc9d2328e4d77c9d8b1f3c757da0ff6d71b86 Author: kaltinsoy Date: Mon Aug 18 07:18:32 2025 +0300 initial diff --git a/chapter2/a.out b/chapter2/a.out new file mode 100755 index 0000000..f0d70fd --- /dev/null +++ b/chapter2/a.out @@ -0,0 +1,99 @@ +#! /usr/bin/vvp +:ivl_version "12.0 (stable)"; +:ivl_delay_selection "TYPICAL"; +:vpi_time_precision + 0; +:vpi_module "/usr/lib64/ivl/system.vpi"; +:vpi_module "/usr/lib64/ivl/vhdl_sys.vpi"; +:vpi_module "/usr/lib64/ivl/vhdl_textio.vpi"; +:vpi_module "/usr/lib64/ivl/v2005_math.vpi"; +:vpi_module "/usr/lib64/ivl/va_math.vpi"; +S_0x56542d3760c0 .scope module, "fibonacciTB" "fibonacciTB" 2 1; + .timescale 0 0; +v0x56542d388680_0 .var "clk", 0 0; +v0x56542d388750_0 .net "num", 31 0, v0x56542d388390_0; 1 drivers +v0x56542d388820_0 .var "rst", 0 0; +S_0x56542d376250 .scope module, "uut" "fibonacci" 2 6, 3 1 0, S_0x56542d3760c0; + .timescale 0 0; + .port_info 0 /INPUT 1 "clk"; + .port_info 1 /INPUT 1 "rst"; + .port_info 2 /OUTPUT 32 "num"; +v0x56542d3764a0_0 .net "clk", 0 0, v0x56542d388680_0; 1 drivers +v0x56542d388390_0 .var "num", 31 0; +v0x56542d388470 .array "nums", 0 1, 31 0; +v0x56542d388540_0 .net "rst", 0 0, v0x56542d388820_0; 1 drivers +E_0x56542d373800 .event posedge, v0x56542d3764a0_0; + .scope S_0x56542d376250; +T_0 ; + %wait E_0x56542d373800; + %load/vec4 v0x56542d388540_0; + %flag_set/vec4 8; + %jmp/0xz T_0.0, 8; + %pushi/vec4 1, 0, 32; + %assign/vec4 v0x56542d388390_0, 0; + %pushi/vec4 0, 0, 32; + %ix/load 3, 0, 0; + %flag_set/imm 4, 0; + %ix/load 4, 0, 0; Constant delay + %assign/vec4/a/d v0x56542d388470, 0, 4; + %pushi/vec4 0, 0, 32; + %ix/load 3, 1, 0; + %flag_set/imm 4, 0; + %ix/load 4, 0, 0; Constant delay + %assign/vec4/a/d v0x56542d388470, 0, 4; + %jmp T_0.1; +T_0.0 ; + %ix/load 4, 0, 0; + %flag_set/imm 4, 0; + %load/vec4a v0x56542d388470, 4; + %ix/load 4, 1, 0; + %flag_set/imm 4, 0; + %load/vec4a v0x56542d388470, 4; + %add; + %assign/vec4 v0x56542d388390_0, 0; + %ix/load 4, 0, 0; + %flag_set/imm 4, 0; + %load/vec4a v0x56542d388470, 4; + %ix/load 3, 1, 0; + %flag_set/imm 4, 0; + %ix/load 4, 0, 0; Constant delay + %assign/vec4/a/d v0x56542d388470, 0, 4; + %load/vec4 v0x56542d388390_0; + %ix/load 3, 0, 0; + %flag_set/imm 4, 0; + %ix/load 4, 0, 0; Constant delay + %assign/vec4/a/d v0x56542d388470, 0, 4; +T_0.1 ; + %jmp T_0; + .thread T_0; + .scope S_0x56542d3760c0; +T_1 ; + %load/vec4 v0x56542d388680_0; + %inv; + %store/vec4 v0x56542d388680_0, 0, 1; + %delay 1, 0; + %jmp T_1; + .thread T_1; + .scope S_0x56542d3760c0; +T_2 ; + %vpi_call 2 17 "$dumpfile", "fibonacci.vcd" {0 0 0}; + %vpi_call 2 18 "$dumpvars" {0 0 0}; + %pushi/vec4 0, 0, 1; + %store/vec4 v0x56542d388680_0, 0, 1; + %pushi/vec4 0, 0, 1; + %store/vec4 v0x56542d388820_0, 0, 1; + %delay 1, 0; + %pushi/vec4 1, 0, 1; + %store/vec4 v0x56542d388820_0, 0, 1; + %delay 1, 0; + %pushi/vec4 0, 0, 1; + %store/vec4 v0x56542d388820_0, 0, 1; + %delay 10, 0; + %vpi_call 2 23 "$finish" {0 0 0}; + %end; + .thread T_2; +# The file index is used to find the file name in the following table. +:file_names 4; + "N/A"; + ""; + "fibonacciTB.v"; + "fibonacci.v"; diff --git a/chapter2/calculator b/chapter2/calculator new file mode 100755 index 0000000..01cb29e --- /dev/null +++ b/chapter2/calculator @@ -0,0 +1,83 @@ +#! /usr/bin/vvp +:ivl_version "12.0 (stable)"; +:ivl_delay_selection "TYPICAL"; +:vpi_time_precision + 0; +:vpi_module "/usr/lib64/ivl/system.vpi"; +:vpi_module "/usr/lib64/ivl/vhdl_sys.vpi"; +:vpi_module "/usr/lib64/ivl/vhdl_textio.vpi"; +:vpi_module "/usr/lib64/ivl/v2005_math.vpi"; +:vpi_module "/usr/lib64/ivl/va_math.vpi"; +S_0x55fa39636f10 .scope module, "calculator" "calculator" 2 1; + .timescale 0 0; + .port_info 0 /INPUT 32 "A"; + .port_info 1 /INPUT 32 "B"; + .port_info 2 /INPUT 2 "op"; + .port_info 3 /OUTPUT 32 "Y"; +L_0x7feabdea7018 .functor BUFT 1, C4<0000000000000000000000000000zzzz>, C4<0>, C4<0>, C4<0>; +v0x55fa39635140_0 .net "A", 31 0, L_0x7feabdea7018; 1 drivers +o0x7feabdef0048 .functor BUFZ 4, C4; HiZ drive +v0x55fa39610eb0_0 .net "A_rand", 3 0, o0x7feabdef0048; 0 drivers +L_0x7feabdea7060 .functor BUFT 1, C4<00000000000000000000000000zzzzzz>, C4<0>, C4<0>, C4<0>; +v0x55fa3965a2a0_0 .net "B", 31 0, L_0x7feabdea7060; 1 drivers +o0x7feabdef00a8 .functor BUFZ 6, C4; HiZ drive +v0x55fa3965a360_0 .net "B_rand", 5 0, o0x7feabdef00a8; 0 drivers +v0x55fa3965a440_0 .var "Y", 31 0; +o0x7feabdef0108 .functor BUFZ 2, C4; HiZ drive +v0x55fa3965a570_0 .net "op", 1 0, o0x7feabdef0108; 0 drivers +E_0x55fa39647e70 .event anyedge, v0x55fa3965a570_0, v0x55fa39635140_0, v0x55fa3965a2a0_0; + .scope S_0x55fa39636f10; +T_0 ; + %wait E_0x55fa39647e70; + %load/vec4 v0x55fa3965a570_0; + %dup/vec4; + %pushi/vec4 0, 0, 2; + %cmp/u; + %jmp/1 T_0.0, 6; + %dup/vec4; + %pushi/vec4 1, 0, 2; + %cmp/u; + %jmp/1 T_0.1, 6; + %dup/vec4; + %pushi/vec4 2, 0, 2; + %cmp/u; + %jmp/1 T_0.2, 6; + %dup/vec4; + %pushi/vec4 3, 0, 2; + %cmp/u; + %jmp/1 T_0.3, 6; + %pushi/vec4 0, 0, 32; + %store/vec4 v0x55fa3965a440_0, 0, 32; + %jmp T_0.5; +T_0.0 ; + %load/vec4 v0x55fa39635140_0; + %load/vec4 v0x55fa3965a2a0_0; + %add; + %store/vec4 v0x55fa3965a440_0, 0, 32; + %jmp T_0.5; +T_0.1 ; + %load/vec4 v0x55fa39635140_0; + %load/vec4 v0x55fa3965a2a0_0; + %sub; + %store/vec4 v0x55fa3965a440_0, 0, 32; + %jmp T_0.5; +T_0.2 ; + %load/vec4 v0x55fa39635140_0; + %load/vec4 v0x55fa3965a2a0_0; + %mul; + %store/vec4 v0x55fa3965a440_0, 0, 32; + %jmp T_0.5; +T_0.3 ; + %load/vec4 v0x55fa39635140_0; + %load/vec4 v0x55fa3965a2a0_0; + %div; + %store/vec4 v0x55fa3965a440_0, 0, 32; + %jmp T_0.5; +T_0.5 ; + %pop/vec4 1; + %jmp T_0; + .thread T_0, $push; +# The file index is used to find the file name in the following table. +:file_names 3; + "N/A"; + ""; + "calculator.v"; diff --git a/chapter2/calculator.v b/chapter2/calculator.v new file mode 100644 index 0000000..a95e0c1 --- /dev/null +++ b/chapter2/calculator.v @@ -0,0 +1,45 @@ +module calculator ( + input [1:0] op, + input clk, + input rst, + output reg [31:0] Y +); + +reg [31:0] A; +reg [31:0] B; + +wire [5:0] B_rand; +wire [3:0] A_rand; + +reg [31:0] Y_prev; + +assign A = {{28{1'b0}}, A_rand[5:0]}; +assign B = {{26{1'b0}}, B_rand[3:0]}; + +always @(*) begin + if(!rst) begin + case(op) + 2'b00 :Y = A + B; + 2'b01 :Y = A - B; + 2'b10 :Y = A * B; + 2'b11 :Y = A / B; + default: Y = 0; + endcase + end + else begin + Y = 0; + end +end + +always @(posedge clk) begin + if (rst) begin + Y_prev <= 32'd0; + A <= 32'd0; + B <= 32'd0; + end + else begin + Y_prev <= Y; + A <= Y_prev; + end +end +endmodule diff --git a/chapter2/fibonacci b/chapter2/fibonacci new file mode 100755 index 0000000..6f8f797 --- /dev/null +++ b/chapter2/fibonacci @@ -0,0 +1,96 @@ +#! /usr/bin/vvp +:ivl_version "12.0 (stable)"; +:ivl_delay_selection "TYPICAL"; +:vpi_time_precision + 0; +:vpi_module "/usr/lib64/ivl/system.vpi"; +:vpi_module "/usr/lib64/ivl/vhdl_sys.vpi"; +:vpi_module "/usr/lib64/ivl/vhdl_textio.vpi"; +:vpi_module "/usr/lib64/ivl/v2005_math.vpi"; +:vpi_module "/usr/lib64/ivl/va_math.vpi"; +S_0x562127b680c0 .scope module, "fibonacciTB" "fibonacciTB" 2 1; + .timescale 0 0; +v0x562127b7a290_0 .var "clk", 0 0; +v0x562127b7a360_0 .net "num", 31 0, v0x562127b79fa0_0; 1 drivers +v0x562127b7a430_0 .var "rst", 0 0; +S_0x562127b68250 .scope module, "uut" "fibonacci" 2 6, 3 1 0, S_0x562127b680c0; + .timescale 0 0; + .port_info 0 /INPUT 1 "clk"; + .port_info 1 /INPUT 1 "rst"; + .port_info 2 /OUTPUT 32 "num"; +v0x562127b68480_0 .net "clk", 0 0, v0x562127b7a290_0; 1 drivers +v0x562127b79fa0_0 .var "num", 31 0; +v0x562127b7a080 .array "nums", 0 1, 31 0; +v0x562127b7a150_0 .net "rst", 0 0, v0x562127b7a430_0; 1 drivers +E_0x562127b65800 .event posedge, v0x562127b68480_0; + .scope S_0x562127b68250; +T_0 ; + %wait E_0x562127b65800; + %load/vec4 v0x562127b7a150_0; + %flag_set/vec4 8; + %jmp/0xz T_0.0, 8; + %pushi/vec4 1, 0, 32; + %assign/vec4 v0x562127b79fa0_0, 0; + %pushi/vec4 0, 0, 32; + %ix/load 3, 0, 0; + %flag_set/imm 4, 0; + %ix/load 4, 0, 0; Constant delay + %assign/vec4/a/d v0x562127b7a080, 0, 4; + %pushi/vec4 0, 0, 32; + %ix/load 3, 1, 0; + %flag_set/imm 4, 0; + %ix/load 4, 0, 0; Constant delay + %assign/vec4/a/d v0x562127b7a080, 0, 4; + %jmp T_0.1; +T_0.0 ; + %ix/load 4, 0, 0; + %flag_set/imm 4, 0; + %load/vec4a v0x562127b7a080, 4; + %ix/load 3, 1, 0; + %flag_set/imm 4, 0; + %ix/load 4, 0, 0; Constant delay + %assign/vec4/a/d v0x562127b7a080, 0, 4; + %load/vec4 v0x562127b79fa0_0; + %ix/load 3, 0, 0; + %flag_set/imm 4, 0; + %ix/load 4, 0, 0; Constant delay + %assign/vec4/a/d v0x562127b7a080, 0, 4; + %ix/load 4, 0, 0; + %flag_set/imm 4, 0; + %load/vec4a v0x562127b7a080, 4; + %ix/load 4, 1, 0; + %flag_set/imm 4, 0; + %load/vec4a v0x562127b7a080, 4; + %add; + %assign/vec4 v0x562127b79fa0_0, 0; +T_0.1 ; + %jmp T_0; + .thread T_0; + .scope S_0x562127b680c0; +T_1 ; + %load/vec4 v0x562127b7a290_0; + %inv; + %store/vec4 v0x562127b7a290_0, 0, 1; + %delay 1, 0; + %jmp T_1; + .thread T_1; + .scope S_0x562127b680c0; +T_2 ; + %vpi_call 2 17 "$dumpfile", "fibonacci.vcd" {0 0 0}; + %vpi_call 2 18 "$dumpvars" {0 0 0}; + %pushi/vec4 0, 0, 1; + %store/vec4 v0x562127b7a290_0, 0, 1; + %pushi/vec4 1, 0, 1; + %store/vec4 v0x562127b7a430_0, 0, 1; + %delay 4, 0; + %pushi/vec4 0, 0, 1; + %store/vec4 v0x562127b7a430_0, 0, 1; + %delay 40, 0; + %vpi_call 2 21 "$finish" {0 0 0}; + %end; + .thread T_2; +# The file index is used to find the file name in the following table. +:file_names 4; + "N/A"; + ""; + "fibonacciTB.v"; + "fibonacci.v"; diff --git a/chapter2/fibonacci.v b/chapter2/fibonacci.v new file mode 100644 index 0000000..ce25640 --- /dev/null +++ b/chapter2/fibonacci.v @@ -0,0 +1,22 @@ +module fibonacci ( + input clk, + input rst, + output reg [31:0] num +); + +reg [31:0] nums [1:0]; + +always @(posedge clk) begin + if (rst) begin + num <= 32'd1; + nums[0] <= 32'd0; + nums[1] <= 32'd0; + end + else begin + nums[1] <= nums[0]; + nums[0] <= num; + num <= nums[0] + nums[1]; + end +end + +endmodule diff --git a/chapter2/fibonacci.vcd b/chapter2/fibonacci.vcd new file mode 100644 index 0000000..3fe9d83 --- /dev/null +++ b/chapter2/fibonacci.vcd @@ -0,0 +1,155 @@ +$date + Sun Aug 17 18:49:30 2025 +$end +$version + Icarus Verilog +$end +$timescale + 1s +$end +$scope module fibonacciTB $end +$var wire 32 ! num [31:0] $end +$var reg 1 " clk $end +$var reg 1 # rst $end +$scope module uut $end +$var wire 1 " clk $end +$var wire 1 # rst $end +$var reg 32 $ num [31:0] $end +$upscope $end +$upscope $end +$enddefinitions $end +$comment Show the parameter values. $end +$dumpall +$end +#0 +$dumpvars +bx $ +1# +0" +bx ! +$end +#1 +b1 ! +b1 $ +1" +#2 +0" +#3 +1" +#4 +0" +0# +#5 +b0 ! +b0 $ +1" +#6 +0" +#7 +b1 ! +b1 $ +1" +#8 +0" +#9 +1" +#10 +0" +#11 +1" +#12 +0" +#13 +b10 ! +b10 $ +1" +#14 +0" +#15 +1" +#16 +0" +#17 +b11 ! +b11 $ +1" +#18 +0" +#19 +b100 ! +b100 $ +1" +#20 +0" +#21 +b101 ! +b101 $ +1" +#22 +0" +#23 +b111 ! +b111 $ +1" +#24 +0" +#25 +b1001 ! +b1001 $ +1" +#26 +0" +#27 +b1100 ! +b1100 $ +1" +#28 +0" +#29 +b10000 ! +b10000 $ +1" +#30 +0" +#31 +b10101 ! +b10101 $ +1" +#32 +0" +#33 +b11100 ! +b11100 $ +1" +#34 +0" +#35 +b100101 ! +b100101 $ +1" +#36 +0" +#37 +b110001 ! +b110001 $ +1" +#38 +0" +#39 +b1000001 ! +b1000001 $ +1" +#40 +0" +#41 +b1010110 ! +b1010110 $ +1" +#42 +0" +#43 +b1110010 ! +b1110010 $ +1" +#44 +0" diff --git a/chapter2/fibonacciTB.v b/chapter2/fibonacciTB.v new file mode 100644 index 0000000..5c929b6 --- /dev/null +++ b/chapter2/fibonacciTB.v @@ -0,0 +1,23 @@ +module fibonacciTB(); + +reg clk, rst; +wire [31:0] num; + +fibonacci uut ( + .clk(clk), + .rst(rst), + .num(num) +); + +always begin + clk = ~clk; #1; +end + +initial begin + $dumpfile("fibonacci.vcd"); + $dumpvars; + clk = 1'b0; rst = 1'b1; #4; + rst = 1'b0; #40; + $finish; +end +endmodule diff --git a/chapter2/fullAdder.v b/chapter2/fullAdder.v new file mode 100644 index 0000000..6086db2 --- /dev/null +++ b/chapter2/fullAdder.v @@ -0,0 +1,19 @@ +module fulladder ( + input in1, + input in2, + input carryIn, + output sum, + output carryO +); + +wire xor1, and1, and2; + +xor x1 (xor1, in1, in2); +xor x2 (sum, xor1, carryIn); + +and a1 (and1, xor1, carryIn); +and a2 (and2, in1, in2); + +or o1 (carryO, and1, and2); + +endmodule diff --git a/chapter2/invGate b/chapter2/invGate new file mode 100755 index 0000000..ab3a9f9 --- /dev/null +++ b/chapter2/invGate @@ -0,0 +1,39 @@ +#! /usr/bin/vvp +:ivl_version "12.0 (stable)"; +:ivl_delay_selection "TYPICAL"; +:vpi_time_precision + 0; +:vpi_module "/usr/lib64/ivl/system.vpi"; +:vpi_module "/usr/lib64/ivl/vhdl_sys.vpi"; +:vpi_module "/usr/lib64/ivl/vhdl_textio.vpi"; +:vpi_module "/usr/lib64/ivl/v2005_math.vpi"; +:vpi_module "/usr/lib64/ivl/va_math.vpi"; +S_0x56122ac89ed0 .scope module, "invGateTB" "invGateTB" 2 1; + .timescale 0 0; +v0x56122ac99480_0 .var "A", 0 0; +v0x56122ac99520_0 .net "B", 0 0, L_0x56122ac995f0; 1 drivers +S_0x56122ac8a060 .scope module, "uut" "invGate" 2 6, 3 1 0, S_0x56122ac89ed0; + .timescale 0 0; + .port_info 0 /INPUT 1 "A"; + .port_info 1 /OUTPUT 1 "B"; +L_0x56122ac995f0 .functor NOT 1, v0x56122ac99480_0, C4<0>, C4<0>, C4<0>; +v0x56122ac77570_0 .net "A", 0 0, v0x56122ac99480_0; 1 drivers +v0x56122ac99360_0 .net "B", 0 0, L_0x56122ac995f0; alias, 1 drivers + .scope S_0x56122ac89ed0; +T_0 ; + %vpi_call 2 12 "$dumpfile", "invGate.vcd" {0 0 0}; + %vpi_call 2 13 "$dumpvars" {0 0 0}; + %pushi/vec4 1, 0, 1; + %store/vec4 v0x56122ac99480_0, 0, 1; + %delay 10, 0; + %pushi/vec4 0, 0, 1; + %store/vec4 v0x56122ac99480_0, 0, 1; + %delay 10, 0; + %vpi_call 2 16 "$finish" {0 0 0}; + %end; + .thread T_0; +# The file index is used to find the file name in the following table. +:file_names 4; + "N/A"; + ""; + "invGateTB.v"; + "invGate.v"; diff --git a/chapter2/invGate.v b/chapter2/invGate.v new file mode 100644 index 0000000..d32c12f --- /dev/null +++ b/chapter2/invGate.v @@ -0,0 +1,8 @@ +module invGate ( + input A, + output B +); + +not a1 (B, A); + +endmodule diff --git a/chapter2/invGate.vcd b/chapter2/invGate.vcd new file mode 100644 index 0000000..e8cb2ba --- /dev/null +++ b/chapter2/invGate.vcd @@ -0,0 +1,30 @@ +$date + Sun Aug 17 06:21:41 2025 +$end +$version + Icarus Verilog +$end +$timescale + 1s +$end +$scope module invGateTB $end +$var wire 1 ! B $end +$var reg 1 " A $end +$scope module uut $end +$var wire 1 " A $end +$var wire 1 ! B $end +$upscope $end +$upscope $end +$enddefinitions $end +$comment Show the parameter values. $end +$dumpall +$end +#0 +$dumpvars +1" +0! +$end +#10 +1! +0" +#20 diff --git a/chapter2/invGateTB.v b/chapter2/invGateTB.v new file mode 100644 index 0000000..a4d5f4a --- /dev/null +++ b/chapter2/invGateTB.v @@ -0,0 +1,19 @@ +module invGateTB(); + +reg A; +wire B; + +invGate uut ( + .A(A), + .B(B) +); + +initial begin + $dumpfile("invGate.vcd"); + $dumpvars; + A = 1'b1; #10; + A = 1'b0; #10; + $finish; + end + +endmodule diff --git a/chapter2/mux.v b/chapter2/mux.v new file mode 100644 index 0000000..166a922 --- /dev/null +++ b/chapter2/mux.v @@ -0,0 +1,14 @@ +module mux ( + input [1:0] A, + input S, + output Y +); + +wire and1, and2; + +and a1 (and1, A[0], S); +and a2 (and2, A[1], ~S); + +or o1 (Y, and1, and2); + +endmodule diff --git a/chapter4/cpu.txt b/chapter4/cpu.txt new file mode 100644 index 0000000..6a96282 --- /dev/null +++ b/chapter4/cpu.txt @@ -0,0 +1,21 @@ + +1. PC Logic + This logic is responsible for the program counter (PC). The PC identifies the instruction our CPU will execute next. Most instructions execute sequentially, meaning the default behavior of the PC is to increment to the following instruction each clock cycle. Branch and jump instructions, however, are non-sequential. They specify a target instruction to execute next, and the PC logic must update the PC accordingly. + +2. Fetch + The instruction memory (IMem) holds the instructions to execute. To read the IMem, or "fetch", we simply pull out the instruction pointed to by the PC. + Decode Logic + Now that we have an instruction to execute, we must interpret, or decode, it. We must break it into fields based on its type. These fields would tell us which registers to read, which operation to perform, etc. + +3. Register File Read + The register file is a small local storage of values the program is actively working with. We decoded the instruction to determine which registers we need to operate on. Now, we need to read those registers from the register file. + +4. Arithmetic Logic Unit (ALU) + Now that we have the register values, it’s time to operate on them. This is the job of the ALU. It will add, subtract, multiply, shift, etc, based on the operation specified in the instruction. + +5. Register File Write + Now the result value from the ALU can be written back to the destination register specified in the instruction. + +6. DMem + Our test program executes entirely out of the register file and does not require a data memory (DMem). But no CPU is complete without one. The DMem is written to by store instructions and read from by load instructions. + diff --git a/chapter4/pc b/chapter4/pc new file mode 100755 index 0000000..25f817c --- /dev/null +++ b/chapter4/pc @@ -0,0 +1,73 @@ +#! /usr/bin/vvp +:ivl_version "12.0 (stable)"; +:ivl_delay_selection "TYPICAL"; +:vpi_time_precision + 0; +:vpi_module "/usr/lib64/ivl/system.vpi"; +:vpi_module "/usr/lib64/ivl/vhdl_sys.vpi"; +:vpi_module "/usr/lib64/ivl/vhdl_textio.vpi"; +:vpi_module "/usr/lib64/ivl/v2005_math.vpi"; +:vpi_module "/usr/lib64/ivl/va_math.vpi"; +S_0x56486b9b1530 .scope module, "pcTB" "pcTB" 2 1; + .timescale 0 0; +v0x56486b9c2f90_0 .var "clk", 0 0; +v0x56486b9c3050_0 .net "next_pc", 31 0, v0x56486b9c2c50_0; 1 drivers +v0x56486b9c3120_0 .net "pc", 31 0, v0x56486b9c2d30_0; 1 drivers +v0x56486b9c3220_0 .var "rst", 0 0; +S_0x56486b9b16c0 .scope module, "uut" "pc" 2 8, 3 1 0, S_0x56486b9b1530; + .timescale 0 0; + .port_info 0 /INPUT 1 "rst"; + .port_info 1 /INPUT 1 "clk"; + .port_info 2 /OUTPUT 32 "pc"; + .port_info 3 /OUTPUT 32 "next_pc"; +v0x56486b99e730_0 .net "clk", 0 0, v0x56486b9c2f90_0; 1 drivers +v0x56486b9c2c50_0 .var "next_pc", 31 0; +v0x56486b9c2d30_0 .var "pc", 31 0; +v0x56486b9c2e20_0 .net "rst", 0 0, v0x56486b9c3220_0; 1 drivers +E_0x56486b9afa90 .event posedge, v0x56486b99e730_0; + .scope S_0x56486b9b16c0; +T_0 ; + %wait E_0x56486b9afa90; + %load/vec4 v0x56486b9c2e20_0; + %flag_set/vec4 8; + %jmp/0xz T_0.0, 8; + %pushi/vec4 0, 0, 32; + %assign/vec4 v0x56486b9c2d30_0, 0; + %jmp T_0.1; +T_0.0 ; + %load/vec4 v0x56486b9c2d30_0; + %assign/vec4 v0x56486b9c2c50_0, 0; + %load/vec4 v0x56486b9c2d30_0; + %addi 1, 0, 32; + %assign/vec4 v0x56486b9c2d30_0, 0; +T_0.1 ; + %jmp T_0; + .thread T_0; + .scope S_0x56486b9b1530; +T_1 ; + %load/vec4 v0x56486b9c2f90_0; + %inv; + %store/vec4 v0x56486b9c2f90_0, 0, 1; + %delay 2, 0; + %jmp T_1; + .thread T_1; + .scope S_0x56486b9b1530; +T_2 ; + %vpi_call 2 20 "$dumpfile", "pc.vcd" {0 0 0}; + %vpi_call 2 21 "$dumpvars" {0 0 0}; + %pushi/vec4 0, 0, 1; + %store/vec4 v0x56486b9c2f90_0, 0, 1; + %pushi/vec4 1, 0, 1; + %store/vec4 v0x56486b9c3220_0, 0, 1; + %delay 4, 0; + %pushi/vec4 0, 0, 1; + %store/vec4 v0x56486b9c3220_0, 0, 1; + %delay 80, 0; + %vpi_call 2 25 "$finish" {0 0 0}; + %end; + .thread T_2; +# The file index is used to find the file name in the following table. +:file_names 4; + "N/A"; + ""; + "pcTB.v"; + "pc.v"; diff --git a/chapter4/pc.v b/chapter4/pc.v new file mode 100644 index 0000000..8916582 --- /dev/null +++ b/chapter4/pc.v @@ -0,0 +1,19 @@ +module pc ( + input rst, + input clk, + output reg [31:0] pc, + output reg [31:0] next_pc +); + + +always @(posedge clk) begin + if(rst) begin + pc <= 0; + end + else begin + next_pc <= pc; + pc <= pc + 1; + end +end + +endmodule diff --git a/chapter4/pc.vcd b/chapter4/pc.vcd new file mode 100644 index 0000000..5907fa5 --- /dev/null +++ b/chapter4/pc.vcd @@ -0,0 +1,201 @@ +$date + Mon Aug 18 02:30:00 2025 +$end +$version + Icarus Verilog +$end +$timescale + 1s +$end +$scope module pcTB $end +$var wire 32 ! pc [31:0] $end +$var wire 32 " next_pc [31:0] $end +$var reg 1 # clk $end +$var reg 1 $ rst $end +$scope module uut $end +$var wire 1 # clk $end +$var wire 1 $ rst $end +$var reg 32 % next_pc [31:0] $end +$var reg 32 & pc [31:0] $end +$upscope $end +$upscope $end +$enddefinitions $end +$comment Show the parameter values. $end +$dumpall +$end +#0 +$dumpvars +bx & +bx % +1$ +0# +bx " +bx ! +$end +#2 +b0 ! +b0 & +1# +#4 +0# +0$ +#6 +b1 ! +b1 & +b0 " +b0 % +1# +#8 +0# +#10 +b10 ! +b10 & +b1 " +b1 % +1# +#12 +0# +#14 +b11 ! +b11 & +b10 " +b10 % +1# +#16 +0# +#18 +b100 ! +b100 & +b11 " +b11 % +1# +#20 +0# +#22 +b101 ! +b101 & +b100 " +b100 % +1# +#24 +0# +#26 +b110 ! +b110 & +b101 " +b101 % +1# +#28 +0# +#30 +b111 ! +b111 & +b110 " +b110 % +1# +#32 +0# +#34 +b1000 ! +b1000 & +b111 " +b111 % +1# +#36 +0# +#38 +b1001 ! +b1001 & +b1000 " +b1000 % +1# +#40 +0# +#42 +b1010 ! +b1010 & +b1001 " +b1001 % +1# +#44 +0# +#46 +b1011 ! +b1011 & +b1010 " +b1010 % +1# +#48 +0# +#50 +b1100 ! +b1100 & +b1011 " +b1011 % +1# +#52 +0# +#54 +b1101 ! +b1101 & +b1100 " +b1100 % +1# +#56 +0# +#58 +b1110 ! +b1110 & +b1101 " +b1101 % +1# +#60 +0# +#62 +b1111 ! +b1111 & +b1110 " +b1110 % +1# +#64 +0# +#66 +b10000 ! +b10000 & +b1111 " +b1111 % +1# +#68 +0# +#70 +b10001 ! +b10001 & +b10000 " +b10000 % +1# +#72 +0# +#74 +b10010 ! +b10010 & +b10001 " +b10001 % +1# +#76 +0# +#78 +b10011 ! +b10011 & +b10010 " +b10010 % +1# +#80 +0# +#82 +b10100 ! +b10100 & +b10011 " +b10011 % +1# +#84 +0# diff --git a/chapter4/pcIMem b/chapter4/pcIMem new file mode 100755 index 0000000..97b3c09 --- /dev/null +++ b/chapter4/pcIMem @@ -0,0 +1,87 @@ +#! /usr/bin/vvp +:ivl_version "12.0 (stable)"; +:ivl_delay_selection "TYPICAL"; +:vpi_time_precision + 0; +:vpi_module "/usr/lib64/ivl/system.vpi"; +:vpi_module "/usr/lib64/ivl/vhdl_sys.vpi"; +:vpi_module "/usr/lib64/ivl/vhdl_textio.vpi"; +:vpi_module "/usr/lib64/ivl/v2005_math.vpi"; +:vpi_module "/usr/lib64/ivl/va_math.vpi"; +S_0x562710cf28c0 .scope module, "pcIMemTB" "pcIMemTB" 2 1; + .timescale 0 0; +v0x562710d063a0_0 .var "clk", 0 0; +v0x562710d06460_0 .net "instr", 31 0, L_0x562710d06a00; 1 drivers +v0x562710d06500_0 .net "next_pc", 31 0, v0x562710d06080_0; 1 drivers +v0x562710d06600_0 .net "pc", 31 0, v0x562710d06160_0; 1 drivers +v0x562710d066d0_0 .var "rst", 0 0; +S_0x562710cf2a50 .scope module, "dut" "pcIMem" 2 9, 3 1 0, S_0x562710cf28c0; + .timescale 0 0; + .port_info 0 /INPUT 1 "rst"; + .port_info 1 /INPUT 1 "clk"; + .port_info 2 /OUTPUT 32 "pc"; + .port_info 3 /OUTPUT 32 "next_pc"; + .port_info 4 /OUTPUT 32 "instr"; +L_0x562710d06a00 .functor BUFZ 32, L_0x562710d067c0, C4<00000000000000000000000000000000>, C4<00000000000000000000000000000000>, C4<00000000000000000000000000000000>; +v0x562710cdff80_0 .net *"_ivl_0", 31 0, L_0x562710d067c0; 1 drivers +v0x562710d05d10_0 .net *"_ivl_3", 29 0, L_0x562710d068c0; 1 drivers +v0x562710d05df0_0 .net "clk", 0 0, v0x562710d063a0_0; 1 drivers +v0x562710d05e90 .array "imem", 255 0, 31 0; +v0x562710d05f50_0 .net "instr", 31 0, L_0x562710d06a00; alias, 1 drivers +v0x562710d06080_0 .var "next_pc", 31 0; +v0x562710d06160_0 .var "pc", 31 0; +v0x562710d06240_0 .net "rst", 0 0, v0x562710d066d0_0; 1 drivers +E_0x562710cf0790 .event posedge, v0x562710d05df0_0; +L_0x562710d067c0 .array/port v0x562710d05e90, L_0x562710d068c0; +L_0x562710d068c0 .part v0x562710d06160_0, 2, 30; + .scope S_0x562710cf2a50; +T_0 ; + %wait E_0x562710cf0790; + %load/vec4 v0x562710d06240_0; + %flag_set/vec4 8; + %jmp/0xz T_0.0, 8; + %pushi/vec4 0, 0, 32; + %assign/vec4 v0x562710d06160_0, 0; + %jmp T_0.1; +T_0.0 ; + %load/vec4 v0x562710d06160_0; + %assign/vec4 v0x562710d06080_0, 0; + %load/vec4 v0x562710d06160_0; + %addi 4, 0, 32; + %assign/vec4 v0x562710d06160_0, 0; +T_0.1 ; + %jmp T_0; + .thread T_0; + .scope S_0x562710cf2a50; +T_1 ; + %vpi_call 3 25 "$readmemh", "program.hex", v0x562710d05e90 {0 0 0}; + %end; + .thread T_1; + .scope S_0x562710cf28c0; +T_2 ; + %load/vec4 v0x562710d063a0_0; + %inv; + %store/vec4 v0x562710d063a0_0, 0, 1; + %delay 2, 0; + %jmp T_2; + .thread T_2; + .scope S_0x562710cf28c0; +T_3 ; + %vpi_call 2 22 "$dumpfile", "pcIMem.vcd" {0 0 0}; + %vpi_call 2 23 "$dumpvars" {0 0 0}; + %pushi/vec4 0, 0, 1; + %store/vec4 v0x562710d063a0_0, 0, 1; + %pushi/vec4 1, 0, 1; + %store/vec4 v0x562710d066d0_0, 0, 1; + %delay 4, 0; + %pushi/vec4 0, 0, 1; + %store/vec4 v0x562710d066d0_0, 0, 1; + %delay 38, 0; + %vpi_call 2 27 "$finish" {0 0 0}; + %end; + .thread T_3; +# The file index is used to find the file name in the following table. +:file_names 4; + "N/A"; + ""; + "pcIMemTB.v"; + "pcIMem.v"; diff --git a/chapter4/pcIMem.v b/chapter4/pcIMem.v new file mode 100644 index 0000000..585a19d --- /dev/null +++ b/chapter4/pcIMem.v @@ -0,0 +1,34 @@ +module pcIMem ( + input rst, + input clk, + output reg [31:0] pc, + output reg [31:0] next_pc, + output wire [31:0] instr +); + + +//PC +always @(posedge clk) begin + if(rst) begin + pc <= 32'h0; + end + else begin + next_pc <= pc; + pc <= pc + 32'h4; + end +end + +//IMem +reg [31:0] imem [0:255]; + +initial begin + $readmemh("program.hex", imem); +end + +assign instr = imem[pc[31:2]]; + +//Decoder +r + + +endmodule diff --git a/chapter4/pcIMem.vcd b/chapter4/pcIMem.vcd new file mode 100644 index 0000000..2adb9a4 --- /dev/null +++ b/chapter4/pcIMem.vcd @@ -0,0 +1,145 @@ +$date + Mon Aug 18 06:14:05 2025 +$end +$version + Icarus Verilog +$end +$timescale + 1s +$end +$scope module pcIMemTB $end +$var wire 32 ! pc [31:0] $end +$var wire 32 " next_pc [31:0] $end +$var wire 32 # instr [31:0] $end +$var reg 1 $ clk $end +$var reg 1 % rst $end +$scope module dut $end +$var wire 1 $ clk $end +$var wire 32 & instr [31:0] $end +$var wire 1 % rst $end +$var reg 32 ' next_pc [31:0] $end +$var reg 32 ( pc [31:0] $end +$upscope $end +$upscope $end +$enddefinitions $end +$comment Show the parameter values. $end +$dumpall +$end +#0 +$dumpvars +bx ( +bx ' +bx & +1% +0$ +bx # +bx " +bx ! +$end +#2 +b10011 # +b10011 & +b0 ! +b0 ( +1$ +#4 +0$ +0% +#6 +b100000000000010010011 # +b100000000000010010011 & +b100 ! +b100 ( +b0 " +b0 ' +1$ +#8 +0$ +#10 +b1000000000000100010011 # +b1000000000000100010011 & +b1000 ! +b1000 ( +b100 " +b100 ' +1$ +#12 +0$ +#14 +b1100001000000110010011 # +b1100001000000110010011 & +b1100 ! +b1100 ( +b1000 " +b1000 ' +1$ +#16 +0$ +#18 +b10000001000001000010011 # +b10000001000001000010011 & +b10000 ! +b10000 ( +b1100 " +b1100 ' +1$ +#20 +0$ +#22 +b10100010000001010010011 # +b10100010000001010010011 & +b10100 ! +b10100 ( +b10000 " +b10000 ' +1$ +#24 +0$ +#26 +b11000010000001100010011 # +b11000010000001100010011 & +b11000 ! +b11000 ( +b10100 " +b10100 ' +1$ +#28 +0$ +#30 +b110000011000001110010011 # +b110000011000001110010011 & +b11100 ! +b11100 ( +b11000 " +b11000 ' +1$ +#32 +0$ +#34 +b110100101000010000010011 # +b110100101000010000010011 & +b100000 ! +b100000 ( +b11100 " +b11100 ' +1$ +#36 +0$ +#38 +b11111111111111111111011100110111 # +b11111111111111111111011100110111 & +b100100 ! +b100100 ( +b100000 " +b100000 ' +1$ +#40 +0$ +#42 +bx # +bx & +b101000 ! +b101000 ( +b100100 " +b100100 ' +1$ diff --git a/chapter4/pcIMemDec b/chapter4/pcIMemDec new file mode 100755 index 0000000..b7c9392 --- /dev/null +++ b/chapter4/pcIMemDec @@ -0,0 +1,229 @@ +#! /usr/bin/vvp +:ivl_version "12.0 (stable)"; +:ivl_delay_selection "TYPICAL"; +:vpi_time_precision - 12; +:vpi_module "/usr/lib64/ivl/system.vpi"; +:vpi_module "/usr/lib64/ivl/vhdl_sys.vpi"; +:vpi_module "/usr/lib64/ivl/vhdl_textio.vpi"; +:vpi_module "/usr/lib64/ivl/v2005_math.vpi"; +:vpi_module "/usr/lib64/ivl/va_math.vpi"; +S_0x5615a9568800 .scope module, "pcIMemDecTB" "pcIMemDecTB" 2 3; + .timescale -9 -12; +v0x5615a9591ae0_0 .var "clk", 0 0; +v0x5615a9591ba0_0 .net "instr", 31 0, L_0x5615a95920d0; 1 drivers +v0x5615a9591c40_0 .net "next_pc", 31 0, v0x5615a95917c0_0; 1 drivers +v0x5615a9591ce0_0 .net "pc", 31 0, v0x5615a95918a0_0; 1 drivers +v0x5615a9591d80_0 .var "rst", 0 0; +v0x5615a9591e20 .array "test_mem", 5 0, 31 0; +S_0x5615a9568990 .scope module, "dut" "pcIMemDec" 2 28, 3 1 0, S_0x5615a9568800; + .timescale 0 0; + .port_info 0 /INPUT 1 "rst"; + .port_info 1 /INPUT 1 "clk"; + .port_info 2 /OUTPUT 32 "pc"; + .port_info 3 /OUTPUT 32 "next_pc"; + .port_info 4 /OUTPUT 32 "instr"; +L_0x5615a95920d0 .functor BUFZ 32, L_0x5615a9591ec0, C4<00000000000000000000000000000000>, C4<00000000000000000000000000000000>, C4<00000000000000000000000000000000>; +L_0x5615a95925c0 .functor OR 1, L_0x5615a9592280, L_0x5615a9592490, C4<0>, C4<0>; +L_0x5615a9592b70 .functor OR 1, L_0x5615a9592770, L_0x5615a95929a0, C4<0>, C4<0>; +L_0x5615a9592ed0 .functor OR 1, L_0x5615a9592b70, L_0x5615a9592d20, C4<0>, C4<0>; +L_0x5615a9592e60 .functor OR 1, L_0x5615a9592ed0, L_0x5615a95930b0, C4<0>, C4<0>; +L_0x5615a9593580 .functor OR 1, L_0x5615a9592e60, L_0x5615a95933b0, C4<0>, C4<0>; +L_0x5615a9593b90 .functor OR 1, L_0x5615a9593770, L_0x5615a95939f0, C4<0>, C4<0>; +L_0x5615a9593ea0 .functor OR 1, L_0x5615a9593b90, L_0x5615a9593ca0, C4<0>, C4<0>; +L_0x5615a95942b0 .functor OR 1, L_0x5615a9593ea0, L_0x5615a95940a0, C4<0>, C4<0>; +L_0x5615a9594950 .functor OR 1, L_0x5615a9594460, L_0x5615a9594720, C4<0>, C4<0>; +v0x5615a9563ea0_0 .net *"_ivl_0", 31 0, L_0x5615a9591ec0; 1 drivers +v0x5615a958e600_0 .net *"_ivl_10", 0 0, L_0x5615a9592280; 1 drivers +v0x5615a958e6c0_0 .net *"_ivl_103", 6 0, L_0x5615a9594ac0; 1 drivers +L_0x7f12ec2a43c0 .functor BUFT 1, C4<1100011>, C4<0>, C4<0>, C4<0>; +v0x5615a958e780_0 .net/2u *"_ivl_104", 6 0, L_0x7f12ec2a43c0; 1 drivers +v0x5615a958e860_0 .net *"_ivl_109", 6 0, L_0x5615a9594f60; 1 drivers +L_0x7f12ec2a4408 .functor BUFT 1, C4<1101111>, C4<0>, C4<0>, C4<0>; +v0x5615a958e990_0 .net/2u *"_ivl_110", 6 0, L_0x7f12ec2a4408; 1 drivers +v0x5615a958ea70_0 .net *"_ivl_13", 6 0, L_0x5615a95923f0; 1 drivers +L_0x7f12ec2a4060 .functor BUFT 1, C4<0010111>, C4<0>, C4<0>, C4<0>; +v0x5615a958eb50_0 .net/2u *"_ivl_14", 6 0, L_0x7f12ec2a4060; 1 drivers +v0x5615a958ec30_0 .net *"_ivl_16", 0 0, L_0x5615a9592490; 1 drivers +v0x5615a958ecf0_0 .net *"_ivl_21", 6 0, L_0x5615a95926d0; 1 drivers +L_0x7f12ec2a40a8 .functor BUFT 1, C4<0000011>, C4<0>, C4<0>, C4<0>; +v0x5615a958edd0_0 .net/2u *"_ivl_22", 6 0, L_0x7f12ec2a40a8; 1 drivers +v0x5615a958eeb0_0 .net *"_ivl_24", 0 0, L_0x5615a9592770; 1 drivers +v0x5615a958ef70_0 .net *"_ivl_27", 6 0, L_0x5615a9592900; 1 drivers +L_0x7f12ec2a40f0 .functor BUFT 1, C4<0000111>, C4<0>, C4<0>, C4<0>; +v0x5615a958f050_0 .net/2u *"_ivl_28", 6 0, L_0x7f12ec2a40f0; 1 drivers +v0x5615a958f130_0 .net *"_ivl_3", 29 0, L_0x5615a9591f90; 1 drivers +v0x5615a958f210_0 .net *"_ivl_30", 0 0, L_0x5615a95929a0; 1 drivers +v0x5615a958f2d0_0 .net *"_ivl_33", 0 0, L_0x5615a9592b70; 1 drivers +v0x5615a958f390_0 .net *"_ivl_35", 6 0, L_0x5615a9592c30; 1 drivers +L_0x7f12ec2a4138 .functor BUFT 1, C4<0010011>, C4<0>, C4<0>, C4<0>; +v0x5615a958f470_0 .net/2u *"_ivl_36", 6 0, L_0x7f12ec2a4138; 1 drivers +v0x5615a958f550_0 .net *"_ivl_38", 0 0, L_0x5615a9592d20; 1 drivers +v0x5615a958f610_0 .net *"_ivl_41", 0 0, L_0x5615a9592ed0; 1 drivers +v0x5615a958f6d0_0 .net *"_ivl_43", 6 0, L_0x5615a9593010; 1 drivers +L_0x7f12ec2a4180 .functor BUFT 1, C4<0011011>, C4<0>, C4<0>, C4<0>; +v0x5615a958f7b0_0 .net/2u *"_ivl_44", 6 0, L_0x7f12ec2a4180; 1 drivers +v0x5615a958f890_0 .net *"_ivl_46", 0 0, L_0x5615a95930b0; 1 drivers +v0x5615a958f950_0 .net *"_ivl_49", 0 0, L_0x5615a9592e60; 1 drivers +v0x5615a958fa10_0 .net *"_ivl_51", 6 0, L_0x5615a9593310; 1 drivers +L_0x7f12ec2a41c8 .functor BUFT 1, C4<1100111>, C4<0>, C4<0>, C4<0>; +v0x5615a958faf0_0 .net/2u *"_ivl_52", 6 0, L_0x7f12ec2a41c8; 1 drivers +v0x5615a958fbd0_0 .net *"_ivl_54", 0 0, L_0x5615a95933b0; 1 drivers +v0x5615a958fc90_0 .net *"_ivl_59", 6 0, L_0x5615a95936d0; 1 drivers +L_0x7f12ec2a4210 .functor BUFT 1, C4<0101111>, C4<0>, C4<0>, C4<0>; +v0x5615a958fd70_0 .net/2u *"_ivl_60", 6 0, L_0x7f12ec2a4210; 1 drivers +v0x5615a958fe50_0 .net *"_ivl_62", 0 0, L_0x5615a9593770; 1 drivers +v0x5615a958ff10_0 .net *"_ivl_65", 6 0, L_0x5615a9593950; 1 drivers +L_0x7f12ec2a4258 .functor BUFT 1, C4<0110011>, C4<0>, C4<0>, C4<0>; +v0x5615a958fff0_0 .net/2u *"_ivl_66", 6 0, L_0x7f12ec2a4258; 1 drivers +v0x5615a95902e0_0 .net *"_ivl_68", 0 0, L_0x5615a95939f0; 1 drivers +v0x5615a95903a0_0 .net *"_ivl_7", 6 0, L_0x5615a95921e0; 1 drivers +v0x5615a9590480_0 .net *"_ivl_71", 0 0, L_0x5615a9593b90; 1 drivers +v0x5615a9590540_0 .net *"_ivl_73", 6 0, L_0x5615a95938b0; 1 drivers +L_0x7f12ec2a42a0 .functor BUFT 1, C4<0111011>, C4<0>, C4<0>, C4<0>; +v0x5615a9590620_0 .net/2u *"_ivl_74", 6 0, L_0x7f12ec2a42a0; 1 drivers +v0x5615a9590700_0 .net *"_ivl_76", 0 0, L_0x5615a9593ca0; 1 drivers +v0x5615a95907c0_0 .net *"_ivl_79", 0 0, L_0x5615a9593ea0; 1 drivers +L_0x7f12ec2a4018 .functor BUFT 1, C4<0110111>, C4<0>, C4<0>, C4<0>; +v0x5615a9590880_0 .net/2u *"_ivl_8", 6 0, L_0x7f12ec2a4018; 1 drivers +v0x5615a9590960_0 .net *"_ivl_81", 6 0, L_0x5615a9594000; 1 drivers +L_0x7f12ec2a42e8 .functor BUFT 1, C4<0110011>, C4<0>, C4<0>, C4<0>; +v0x5615a9590a40_0 .net/2u *"_ivl_82", 6 0, L_0x7f12ec2a42e8; 1 drivers +v0x5615a9590b20_0 .net *"_ivl_84", 0 0, L_0x5615a95940a0; 1 drivers +v0x5615a9590be0_0 .net *"_ivl_89", 6 0, L_0x5615a95943c0; 1 drivers +L_0x7f12ec2a4330 .functor BUFT 1, C4<0100011>, C4<0>, C4<0>, C4<0>; +v0x5615a9590cc0_0 .net/2u *"_ivl_90", 6 0, L_0x7f12ec2a4330; 1 drivers +v0x5615a9590da0_0 .net *"_ivl_92", 0 0, L_0x5615a9594460; 1 drivers +v0x5615a9590e60_0 .net *"_ivl_95", 6 0, L_0x5615a9594680; 1 drivers +L_0x7f12ec2a4378 .functor BUFT 1, C4<0100111>, C4<0>, C4<0>, C4<0>; +v0x5615a9590f40_0 .net/2u *"_ivl_96", 6 0, L_0x7f12ec2a4378; 1 drivers +v0x5615a9591020_0 .net *"_ivl_98", 0 0, L_0x5615a9594720; 1 drivers +v0x5615a95910e0_0 .net "clk", 0 0, v0x5615a9591ae0_0; 1 drivers +v0x5615a95911a0 .array "imem", 255 0, 31 0; +v0x5615a9591260_0 .net "instr", 31 0, L_0x5615a95920d0; alias, 1 drivers +v0x5615a9591340_0 .net "isBType", 0 0, L_0x5615a9594d70; 1 drivers +v0x5615a9591400_0 .net "isIType", 0 0, L_0x5615a9593580; 1 drivers +v0x5615a95914c0_0 .net "isJType", 0 0, L_0x5615a9595000; 1 drivers +v0x5615a9591580_0 .net "isRType", 0 0, L_0x5615a95942b0; 1 drivers +v0x5615a9591640_0 .net "isSType", 0 0, L_0x5615a9594950; 1 drivers +v0x5615a9591700_0 .net "isUType", 0 0, L_0x5615a95925c0; 1 drivers +v0x5615a95917c0_0 .var "next_pc", 31 0; +v0x5615a95918a0_0 .var "pc", 31 0; +v0x5615a9591980_0 .net "rst", 0 0, v0x5615a9591d80_0; 1 drivers +E_0x5615a9561800 .event posedge, v0x5615a95910e0_0; +L_0x5615a9591ec0 .array/port v0x5615a95911a0, L_0x5615a9591f90; +L_0x5615a9591f90 .part v0x5615a95918a0_0, 2, 30; +L_0x5615a95921e0 .part L_0x5615a95920d0, 0, 7; +L_0x5615a9592280 .cmp/eq 7, L_0x5615a95921e0, L_0x7f12ec2a4018; +L_0x5615a95923f0 .part L_0x5615a95920d0, 0, 7; +L_0x5615a9592490 .cmp/eq 7, L_0x5615a95923f0, L_0x7f12ec2a4060; +L_0x5615a95926d0 .part L_0x5615a95920d0, 0, 7; +L_0x5615a9592770 .cmp/eq 7, L_0x5615a95926d0, L_0x7f12ec2a40a8; +L_0x5615a9592900 .part L_0x5615a95920d0, 0, 7; +L_0x5615a95929a0 .cmp/eq 7, L_0x5615a9592900, L_0x7f12ec2a40f0; +L_0x5615a9592c30 .part L_0x5615a95920d0, 0, 7; +L_0x5615a9592d20 .cmp/eq 7, L_0x5615a9592c30, L_0x7f12ec2a4138; +L_0x5615a9593010 .part L_0x5615a95920d0, 0, 7; +L_0x5615a95930b0 .cmp/eq 7, L_0x5615a9593010, L_0x7f12ec2a4180; +L_0x5615a9593310 .part L_0x5615a95920d0, 0, 7; +L_0x5615a95933b0 .cmp/eq 7, L_0x5615a9593310, L_0x7f12ec2a41c8; +L_0x5615a95936d0 .part L_0x5615a95920d0, 0, 7; +L_0x5615a9593770 .cmp/eq 7, L_0x5615a95936d0, L_0x7f12ec2a4210; +L_0x5615a9593950 .part L_0x5615a95920d0, 0, 7; +L_0x5615a95939f0 .cmp/eq 7, L_0x5615a9593950, L_0x7f12ec2a4258; +L_0x5615a95938b0 .part L_0x5615a95920d0, 0, 7; +L_0x5615a9593ca0 .cmp/eq 7, L_0x5615a95938b0, L_0x7f12ec2a42a0; +L_0x5615a9594000 .part L_0x5615a95920d0, 0, 7; +L_0x5615a95940a0 .cmp/eq 7, L_0x5615a9594000, L_0x7f12ec2a42e8; +L_0x5615a95943c0 .part L_0x5615a95920d0, 0, 7; +L_0x5615a9594460 .cmp/eq 7, L_0x5615a95943c0, L_0x7f12ec2a4330; +L_0x5615a9594680 .part L_0x5615a95920d0, 0, 7; +L_0x5615a9594720 .cmp/eq 7, L_0x5615a9594680, L_0x7f12ec2a4378; +L_0x5615a9594ac0 .part L_0x5615a95920d0, 0, 7; +L_0x5615a9594d70 .cmp/eq 7, L_0x5615a9594ac0, L_0x7f12ec2a43c0; +L_0x5615a9594f60 .part L_0x5615a95920d0, 0, 7; +L_0x5615a9595000 .cmp/eq 7, L_0x5615a9594f60, L_0x7f12ec2a4408; + .scope S_0x5615a9568990; +T_0 ; + %wait E_0x5615a9561800; + %load/vec4 v0x5615a9591980_0; + %flag_set/vec4 8; + %jmp/0xz T_0.0, 8; + %pushi/vec4 0, 0, 32; + %assign/vec4 v0x5615a95918a0_0, 0; + %jmp T_0.1; +T_0.0 ; + %load/vec4 v0x5615a95918a0_0; + %assign/vec4 v0x5615a95917c0_0, 0; + %load/vec4 v0x5615a95918a0_0; + %addi 4, 0, 32; + %assign/vec4 v0x5615a95918a0_0, 0; +T_0.1 ; + %jmp T_0; + .thread T_0; + .scope S_0x5615a9568990; +T_1 ; + %vpi_call 3 25 "$readmemh", "program.hex", v0x5615a95911a0 {0 0 0}; + %end; + .thread T_1; + .scope S_0x5615a9568800; +T_2 ; + %pushi/vec4 4151, 0, 32; + %ix/load 4, 0, 0; + %flag_set/imm 4, 0; + %store/vec4a v0x5615a9591e20, 4, 0; + %pushi/vec4 1048723, 0, 32; + %ix/load 4, 1, 0; + %flag_set/imm 4, 0; + %store/vec4a v0x5615a9591e20, 4, 0; + %pushi/vec4 1081779, 0, 32; + %ix/load 4, 2, 0; + %flag_set/imm 4, 0; + %store/vec4a v0x5615a9591e20, 4, 0; + %pushi/vec4 1089571, 0, 32; + %ix/load 4, 3, 0; + %flag_set/imm 4, 0; + %store/vec4a v0x5615a9591e20, 4, 0; + %pushi/vec4 1082979, 0, 32; + %ix/load 4, 4, 0; + %flag_set/imm 4, 0; + %store/vec4a v0x5615a9591e20, 4, 0; + %pushi/vec4 12583023, 0, 32; + %ix/load 4, 5, 0; + %flag_set/imm 4, 0; + %store/vec4a v0x5615a9591e20, 4, 0; + %vpi_call 2 23 "$writememh", "program.hex", v0x5615a9591e20 {0 0 0}; + %delay 1000, 0; + %end; + .thread T_2; + .scope S_0x5615a9568800; +T_3 ; + %pushi/vec4 0, 0, 1; + %store/vec4 v0x5615a9591ae0_0, 0, 1; +T_3.0 ; + %delay 5000, 0; + %load/vec4 v0x5615a9591ae0_0; + %inv; + %store/vec4 v0x5615a9591ae0_0, 0, 1; + %jmp T_3.0; + %end; + .thread T_3; + .scope S_0x5615a9568800; +T_4 ; + %vpi_call 2 44 "$dumpfile", "pcIMemDec.vcd" {0 0 0}; + %vpi_call 2 45 "$dumpvars", 32'sb00000000000000000000000000000000, S_0x5615a9568800 {0 0 0}; + %pushi/vec4 1, 0, 1; + %store/vec4 v0x5615a9591d80_0, 0, 1; + %delay 20000, 0; + %pushi/vec4 0, 0, 1; + %store/vec4 v0x5615a9591d80_0, 0, 1; + %vpi_call 2 50 "$monitor", "Time=%0t PC=%h Instr=%h Types: U=%b I=%b R=%b S=%b B=%b J=%b", $time, v0x5615a9591ce0_0, v0x5615a9591ba0_0, v0x5615a9591700_0, v0x5615a9591400_0, v0x5615a9591580_0, v0x5615a9591640_0, v0x5615a9591340_0, v0x5615a95914c0_0 {0 0 0}; + %delay 200000, 0; + %vpi_call 2 54 "$finish" {0 0 0}; + %end; + .thread T_4; +# The file index is used to find the file name in the following table. +:file_names 4; + "N/A"; + ""; + "pcIMemDecTB.v"; + "pcIMemDec.v"; diff --git a/chapter4/pcIMemDec.v b/chapter4/pcIMemDec.v new file mode 100644 index 0000000..49d9d94 --- /dev/null +++ b/chapter4/pcIMemDec.v @@ -0,0 +1,72 @@ +module pcIMemDec ( + input rst, + input clk, + output reg [31:0] pc, + output reg [31:0] next_pc, + output wire [31:0] instr +); + + +//PC +always @(posedge clk) begin + if(rst) begin + pc <= 32'h0; + end + else begin + next_pc <= pc; + pc <= pc + 32'h4; + end +end + +//IMem +reg [31:0] imem [0:255]; + +initial begin + $readmemh("program.hex", imem); +end + +assign instr = imem[pc[31:2]]; + +//Decoder + +wire isUType = ((instr[6:0] == 7'b0110111) || (instr[6:0] == 7'b0010111)); +wire isIType = ((instr[6:0] == 7'b0000011) || (instr[6:0] == 7'b0000111) || (instr[6:0] == 7'b0010011) || (instr[6:0] == 7'b0011011) || (instr [6:0] == 7'b1100111)); +wire isRType = ((instr[6:0] == 7'b0101111) || (instr[6:0] == 7'b0110011) || (instr[6:0] == 7'b0111011) || (instr[6:0] == 7'b0110011)); +wire isSType = ((instr[6:0] == 7'b0100011) || (instr[6:0] == 7'b0100111)); +wire isBType = (instr[6:0] == 7'b1100011); +wire isJType = (instr[6:0] == 7'b1101111); + +wire [4:0] rs1 = instr[19:15]; +wire [4:0] rs2 = instr[24:20]; +wire [4:0] rd = instr[11:7]; + +wire rs2Valid = (isRType || isSType || isBType); +wire rs1Valid = (~isUType && ~isJType); +wire rdValid = (~isSType && ~isBType); + +wire [3:0] funct3 = instr[14:12]; +wire [6:0] funct7 = instr[31:25]; + +wire funct3Valid = rs1Valid; +wire funct7Valid = isRType; + +wire [31:0] Iimm = {{21{instr[31]}}, {instr[30:25]}, {instr[24:20]}}; +wire [31:0] Simm = {{21{instr[31]}}, {instr[30:25]}, {instr[11:7]}}; +wire [31:0] Bimm = {{20{instr[31]}}, {instr[7]}, {instr[30:25]}, {instr[11:8]}, 1'b0}; +wire [31:0] Uimm = {{instr[31]}, {instr[30:20]}, {instr[19:12]}, {12{1'b0}}; +wire [31:0] Jimm = {{12{instr[31]}}, {instr[19:12]}, {instr[20]}, {instr[30:25]}, {instr[24:21]}, 1'b0}; + +//Instructions + +isBEQ = (funct3 == 000 && isBType); +isBNE = (funct3 == 001 && isBType); +isBLT = (funct3 == 100 && isBType); +isBGE = (funct3 == 101 && isBType); +isBLTU = (funct3 == 110 && isBType); +isBGEU = (funct3 == 111 && isBType); + +isADDI = (funct3 == 000 && isIType); + +isADD = (funct7[5] == 0 && isRType); + +endmodule diff --git a/chapter4/pcIMemDec.vcd b/chapter4/pcIMemDec.vcd new file mode 100644 index 0000000..1e61bf9 --- /dev/null +++ b/chapter4/pcIMemDec.vcd @@ -0,0 +1,257 @@ +$date + Mon Aug 18 06:47:55 2025 +$end +$version + Icarus Verilog +$end +$timescale + 1ps +$end +$scope module pcIMemDecTB $end +$var wire 32 ! pc [31:0] $end +$var wire 32 " next_pc [31:0] $end +$var wire 32 # instr [31:0] $end +$var reg 1 $ clk $end +$var reg 1 % rst $end +$scope module dut $end +$var wire 1 $ clk $end +$var wire 32 & instr [31:0] $end +$var wire 1 ' isIType $end +$var wire 1 ( isRType $end +$var wire 1 ) isSType $end +$var wire 1 * isUType $end +$var wire 1 % rst $end +$var wire 1 + isJType $end +$var wire 1 , isBType $end +$var reg 32 - next_pc [31:0] $end +$var reg 32 . pc [31:0] $end +$upscope $end +$upscope $end +$enddefinitions $end +$comment Show the parameter values. $end +$dumpall +$end +#0 +$dumpvars +bx . +bx - +x, +x+ +x* +x) +x( +x' +bx & +1% +0$ +bx # +bx " +bx ! +$end +#5000 +0' +0( +1* +0) +0, +0+ +b1000000110111 # +b1000000110111 & +b0 ! +b0 . +1$ +#10000 +0$ +#15000 +1$ +#20000 +0$ +0% +#25000 +1' +0* +b100000000000010010011 # +b100000000000010010011 & +b100 ! +b100 . +b0 " +b0 - +1$ +#30000 +0$ +#35000 +0' +1( +b100001000000110110011 # +b100001000000110110011 & +b1000 ! +b1000 . +b100 " +b100 - +1$ +#40000 +0$ +#45000 +0( +1) +b100001010000000100011 # +b100001010000000100011 & +b1100 ! +b1100 . +b1000 " +b1000 - +1$ +#50000 +0$ +#55000 +0) +1, +b100001000011001100011 # +b100001000011001100011 & +b10000 ! +b10000 . +b1100 " +b1100 - +1$ +#60000 +0$ +#65000 +0, +1+ +b110000000000000001101111 # +b110000000000000001101111 & +b10100 ! +b10100 . +b10000 " +b10000 - +1$ +#70000 +0$ +#75000 +x* +x' +x( +x) +x, +x+ +bx # +bx & +b11000 ! +b11000 . +b10100 " +b10100 - +1$ +#80000 +0$ +#85000 +b11100 ! +b11100 . +b11000 " +b11000 - +1$ +#90000 +0$ +#95000 +b100000 ! +b100000 . +b11100 " +b11100 - +1$ +#100000 +0$ +#105000 +b100100 ! +b100100 . +b100000 " +b100000 - +1$ +#110000 +0$ +#115000 +b101000 ! +b101000 . +b100100 " +b100100 - +1$ +#120000 +0$ +#125000 +b101100 ! +b101100 . +b101000 " +b101000 - +1$ +#130000 +0$ +#135000 +b110000 ! +b110000 . +b101100 " +b101100 - +1$ +#140000 +0$ +#145000 +b110100 ! +b110100 . +b110000 " +b110000 - +1$ +#150000 +0$ +#155000 +b111000 ! +b111000 . +b110100 " +b110100 - +1$ +#160000 +0$ +#165000 +b111100 ! +b111100 . +b111000 " +b111000 - +1$ +#170000 +0$ +#175000 +b1000000 ! +b1000000 . +b111100 " +b111100 - +1$ +#180000 +0$ +#185000 +b1000100 ! +b1000100 . +b1000000 " +b1000000 - +1$ +#190000 +0$ +#195000 +b1001000 ! +b1001000 . +b1000100 " +b1000100 - +1$ +#200000 +0$ +#205000 +b1001100 ! +b1001100 . +b1001000 " +b1001000 - +1$ +#210000 +0$ +#215000 +b1010000 ! +b1010000 . +b1001100 " +b1001100 - +1$ +#220000 +0$ diff --git a/chapter4/pcIMemDecTB.v b/chapter4/pcIMemDecTB.v new file mode 100644 index 0000000..860be90 --- /dev/null +++ b/chapter4/pcIMemDecTB.v @@ -0,0 +1,56 @@ +`timescale 1ns/1ps + +module pcIMemDecTB(); + // Inputs + reg clk; + reg rst; + + // Outputs + wire [31:0] pc; + wire [31:0] next_pc; + wire [31:0] instr; + + // Create test memory and program.hex FIRST + reg [31:0] test_mem [0:5]; + initial begin + test_mem[0] = 32'h00001037; // lui x0, 1 + test_mem[1] = 32'h00100093; // addi x1, x0, 1 + test_mem[2] = 32'h001081b3; // add x3, x1, x1 + test_mem[3] = 32'h0010a023; // sw x1, 0(x1) + test_mem[4] = 32'h00108663; // beq x1, x1, 12 + test_mem[5] = 32'h00c0006f; // jal x0, 12 + + $writememh("program.hex", test_mem); + #1; // Small delay to ensure file creation + end + + // Instantiate DUT AFTER file creation + pcIMemDec dut ( + .clk(clk), + .rst(rst), + .pc(pc), + .next_pc(next_pc), + .instr(instr) + ); + + // Clock generation (100MHz) + initial begin + clk = 0; + forever #5 clk = ~clk; + end + + // Test sequence + initial begin + $dumpfile("pcIMemDec.vcd"); + $dumpvars(0, pcIMemDecTB); + + rst = 1; + #20 rst = 0; + + $monitor("Time=%0t PC=%h Instr=%h Types: U=%b I=%b R=%b S=%b B=%b J=%b", + $time, pc, instr, + dut.isUType, dut.isIType, dut.isRType, dut.isSType, dut.isBType, dut.isJType); + + #200 $finish; + end +endmodule diff --git a/chapter4/pcIMemTB.v b/chapter4/pcIMemTB.v new file mode 100644 index 0000000..acb9a22 --- /dev/null +++ b/chapter4/pcIMemTB.v @@ -0,0 +1,29 @@ +module pcIMemTB(); + + reg rst; + reg clk; + wire [31:0] pc; + wire [31:0] next_pc; + wire [31:0] instr; + +pcIMem dut ( + .clk(clk), + .rst(rst), + .pc(pc), + .instr(instr), + .next_pc(next_pc) +); + +always begin + clk = ~clk; #2; +end + +initial begin + $dumpfile("pcIMem.vcd"); + $dumpvars; + clk = 1'b0; + rst = 1'b1; #4; + rst = 1'b0; #38; + $finish; +end +endmodule diff --git a/chapter4/pcTB.v b/chapter4/pcTB.v new file mode 100644 index 0000000..bf1e359 --- /dev/null +++ b/chapter4/pcTB.v @@ -0,0 +1,28 @@ +module pcTB(); + +reg clk; +reg rst; +wire [31:0] pc; +wire [31:0] next_pc; + +pc uut ( + .clk(clk), + .rst(rst), + .pc(pc), + .next_pc(next_pc) +); + +always begin + clk = ~clk; #2; +end + +initial begin + $dumpfile("pc.vcd"); + $dumpvars; + clk = 0; + rst = 1; #4; + rst = 0; #80; + $finish; +end + +endmodule diff --git a/chapter4/program.hex b/chapter4/program.hex new file mode 100644 index 0000000..1ba4faf --- /dev/null +++ b/chapter4/program.hex @@ -0,0 +1,7 @@ +// 0x00000000 +00001037 +00100093 +001081b3 +0010a023 +00108663 +00c0006f