This commit is contained in:
2025-08-18 07:18:32 +03:00
commit 12dcc9d232
27 changed files with 1910 additions and 0 deletions

21
chapter4/cpu.txt Normal file
View File

@@ -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, its 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.

73
chapter4/pc Executable file
View File

@@ -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";
"<interactive>";
"pcTB.v";
"pc.v";

19
chapter4/pc.v Normal file
View File

@@ -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

201
chapter4/pc.vcd Normal file
View File

@@ -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#

87
chapter4/pcIMem Executable file
View File

@@ -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";
"<interactive>";
"pcIMemTB.v";
"pcIMem.v";

34
chapter4/pcIMem.v Normal file
View File

@@ -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

145
chapter4/pcIMem.vcd Normal file
View File

@@ -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$

229
chapter4/pcIMemDec Executable file
View File

@@ -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";
"<interactive>";
"pcIMemDecTB.v";
"pcIMemDec.v";

72
chapter4/pcIMemDec.v Normal file
View File

@@ -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

257
chapter4/pcIMemDec.vcd Normal file
View File

@@ -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$

56
chapter4/pcIMemDecTB.v Normal file
View File

@@ -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

29
chapter4/pcIMemTB.v Normal file
View File

@@ -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

28
chapter4/pcTB.v Normal file
View File

@@ -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

7
chapter4/program.hex Normal file
View File

@@ -0,0 +1,7 @@
// 0x00000000
00001037
00100093
001081b3
0010a023
00108663
00c0006f