Skip to content

Commit 299793f

Browse files
committed
Add IFU
1 parent df38492 commit 299793f

File tree

6 files changed

+410
-0
lines changed

6 files changed

+410
-0
lines changed

instr_mem.v

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
`timescale 1ns / 1ps
2+
//////////////////////////////////////////////////////////////////////////////////
3+
// Company:
4+
// Engineer:
5+
//
6+
// Create Date: 03/07/2023 07:29:27 AM
7+
// Design Name:
8+
// Module Name: instr_mem
9+
// Project Name:
10+
// Target Devices:
11+
// Tool Versions:
12+
// Description:
13+
//
14+
// Dependencies:
15+
//
16+
// Revision:
17+
// Revision 0.01 - File Created
18+
// Additional Comments:
19+
//
20+
//////////////////////////////////////////////////////////////////////////////////
21+
22+
23+
// Define the instruction memory module with three parameters:
24+
// - ADDRESS_WIDTH: the number of bits in the memory address
25+
// - INSTR_WIDTH: the number of bits in each instruction
26+
// - PROGRAM: the name of the file containing the program instructions
27+
module instr_mem
28+
#(
29+
parameter ADDRESS_WIDTH = 32,
30+
parameter INSTR_WIDTH = 32,
31+
parameter PROGRAM = "fibonacci.txt"
32+
)
33+
(
34+
input wire [ADDRESS_WIDTH-1:0] addr, // Input address wire
35+
output wire [INSTR_WIDTH-1:0] instr // Output instruction wire
36+
);
37+
38+
localparam DEPTH = 64; // Set the depth of the instruction memory
39+
40+
// Declare a register array to hold the instruction memory contents
41+
// The array is indexed by the address wire and holds instructions of width INSTR_WIDTH
42+
reg [INSTR_WIDTH-1:0] memory [DEPTH-1:0];
43+
44+
// Initialize the instruction memory contents from the file specified by PROGRAM
45+
initial begin
46+
$readmemh(PROGRAM, memory);
47+
end
48+
49+
// Assign the output instruction wire to the instruction memory contents at the input address
50+
assign instr = memory[addr[31:2]]; // word aligned
51+
52+
endmodule

instruction_fetch_unit.v

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
`timescale 1ns / 1ps
2+
//////////////////////////////////////////////////////////////////////////////////
3+
// Company:
4+
// Engineer:
5+
//
6+
// Create Date: 03/07/2023 11:19:25 AM
7+
// Design Name:
8+
// Module Name: instruction_fetch_unit
9+
// Project Name:
10+
// Target Devices:
11+
// Tool Versions:
12+
// Description:
13+
// This is a module for the Instruction Fetch Unit (IFU)
14+
// It retrieves the instruction from the memory and prepares it for execution
15+
// Dependencies:
16+
//
17+
// Revision:
18+
// Revision 0.01 - File Created
19+
// Additional Comments:
20+
//
21+
//////////////////////////////////////////////////////////////////////////////////
22+
23+
24+
module instruction_fetch_unit
25+
#(
26+
parameter ADDRESS_WIDTH = 32, // Defines the number of bits for the memory address
27+
parameter INSTR_WIDTH = 32, // Defines the number of bits for the instruction
28+
parameter PROGRAM = "fibonacci.txt", // The program file to be loaded into memory
29+
parameter N = 32 // Parameter defining the number of bits for the PC counter
30+
)(
31+
input wire clk, n_reset, // Clock and reset inputs
32+
input load, pc_src, // Load input for setting a new PC value
33+
input [1:0] imm_src, // immediate source
34+
output wire [INSTR_WIDTH-1:0] instr, // Output the fetched instruction
35+
output wire [INSTR_WIDTH-1:0] imm_ext
36+
);
37+
wire [N-1: 0] pc, pc_next, pc_plus_4, pc_target, imm_ext_internal;
38+
39+
// Instantiate the program counter module
40+
prg_cntr #(.N(N)) program_counter (
41+
.clk(clk), // Clock input
42+
.n_reset(n_reset), // Reset input
43+
.load(load), // Load input
44+
.pc_next(pc_next), // Next PC output
45+
.pc(pc) // Current PC output
46+
);
47+
48+
// Instantiate the instruction memory module
49+
instr_mem #(
50+
.ADDRESS_WIDTH(ADDRESS_WIDTH), // Set the address width to 32 bits
51+
.INSTR_WIDTH(INSTR_WIDTH), // Set the instruction width to 32 bits
52+
.PROGRAM(PROGRAM) // Set the program file to PROGRAM
53+
) instruction_memory (
54+
.addr(pc), // Address input wire
55+
.instr(instr) // Fetched instruction output wire
56+
);
57+
58+
// Calculate the PC+4 value
59+
addr #(.N(32)) pc_plus_4_addr (
60+
.X(pc),
61+
.Y(4),
62+
.Z(pc_plus_4)
63+
);
64+
65+
// Sign-extend the immediate value for arithmetic operations
66+
sign_extend extended (
67+
.instr_part(instr[31:7]), // Immediate value extracted from the instruction
68+
.imm_src(imm_src), // Source of the immediate value
69+
.data_out_signed(imm_ext_internal) // Sign-extended immediate value output
70+
);
71+
72+
// Calculate the target PC for a branch or jump instruction
73+
addr #(.N(32)) pc_target_addr (
74+
.X(pc),
75+
.Y(imm_ext_internal),
76+
.Z(pc_target)
77+
);
78+
79+
// Select the next PC value based on the instruction type
80+
mux pc_next_mux (
81+
.data_true(pc_target), // Target PC
82+
.data_false(pc_plus_4), // PC+4
83+
.sel(pc_src), // Source of the next PC value
84+
.data_out(pc_next) // Next PC output
85+
);
86+
87+
assign imm_ext = imm_ext_internal;
88+
89+
endmodule

modules_testbenches/instr_mem_tb.v

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
`timescale 1ns / 1ps
2+
//////////////////////////////////////////////////////////////////////////////////
3+
// Company:
4+
// Engineer:
5+
//
6+
// Create Date: 03/07/2023 09:08:49 AM
7+
// Design Name:
8+
// Module Name: instr_mem_tb
9+
// Project Name:
10+
// Target Devices:
11+
// Tool Versions:
12+
// Description:
13+
//
14+
// Dependencies:
15+
//
16+
// Revision:
17+
// Revision 0.01 - File Created
18+
// Additional Comments:
19+
//
20+
//////////////////////////////////////////////////////////////////////////////////
21+
22+
23+
module instr_mem_tb;
24+
25+
localparam ADDRESS_WIDTH = 32;
26+
localparam INSTR_WIDTH = 32;
27+
28+
reg [ADDRESS_WIDTH-1:0] addr;
29+
wire [INSTR_WIDTH-1:0] instr;
30+
31+
instr_mem dut (
32+
.addr(addr),
33+
.instr(instr)
34+
);
35+
36+
task disp_instr(
37+
input [ADDRESS_WIDTH-1:0] address
38+
);
39+
#10 $display("Instruction at address 0x%x is 0x%x", address, instr);
40+
endtask
41+
42+
initial begin
43+
// Load test program into memory
44+
$readmemh("fibbonachi.txt", dut.memory);
45+
46+
// Test instruction memory reads
47+
addr = 0;
48+
disp_instr(addr);
49+
addr = 4;
50+
disp_instr(addr);
51+
addr = 8;
52+
disp_instr(addr);
53+
addr = 12;
54+
disp_instr(addr);
55+
addr = 16;
56+
disp_instr(addr);
57+
addr = 18;
58+
disp_instr(addr);
59+
addr = 20;
60+
disp_instr(addr);
61+
addr = 24;
62+
disp_instr(addr);
63+
$stop;
64+
end
65+
66+
endmodule
67+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
`timescale 1ns / 1ps
2+
//////////////////////////////////////////////////////////////////////////////////
3+
// Company:
4+
// Engineer:
5+
//
6+
// Create Date: 03/07/2023 09:08:49 AM
7+
// Design Name:
8+
// Module Name: instruction_fetch_unit_tb
9+
// Project Name:
10+
// Target Devices:
11+
// Tool Versions:
12+
// Description:
13+
//
14+
// Dependencies:
15+
//
16+
// Revision:
17+
// Revision 0.01 - File Created
18+
// Additional Comments:
19+
//
20+
//////////////////////////////////////////////////////////////////////////////////
21+
22+
23+
`timescale 1ns / 1ps
24+
25+
module instruction_fetch_unit_tb;
26+
27+
// Parameters
28+
parameter ADDRESS_WIDTH = 32;
29+
parameter INSTR_WIDTH = 32;
30+
parameter PROGRAM = "fibonacci.txt";
31+
parameter N = 32;
32+
33+
// Inputs
34+
reg clk;
35+
reg n_reset;
36+
reg load;
37+
reg pc_src;
38+
reg [1:0] imm_src;
39+
40+
// Outputs
41+
wire [INSTR_WIDTH-1:0] instr;
42+
wire [INSTR_WIDTH-1:0] imm_ext;
43+
44+
// Instantiate the module
45+
instruction_fetch_unit #(
46+
.ADDRESS_WIDTH(ADDRESS_WIDTH),
47+
.INSTR_WIDTH(INSTR_WIDTH),
48+
.PROGRAM(PROGRAM),
49+
.N(N)
50+
) ifu (
51+
.clk(clk),
52+
.n_reset(n_reset),
53+
.load(load),
54+
.pc_src(pc_src),
55+
.imm_src(imm_src),
56+
.instr(instr),
57+
.imm_ext(imm_ext)
58+
);
59+
60+
// Clock generation
61+
always #5 clk = ~clk;
62+
63+
task initialize();
64+
begin
65+
n_reset = 0;
66+
clk = 0;
67+
load = 1;
68+
pc_src = 0;
69+
imm_src = 0;
70+
@(negedge clk);
71+
n_reset = 1;
72+
end
73+
endtask
74+
75+
task sequential_instruction();
76+
begin
77+
pc_src = 0;
78+
@(negedge clk);
79+
end
80+
endtask
81+
82+
// Test sequence
83+
initial begin
84+
initialize();
85+
sequential_instruction();
86+
sequential_instruction();
87+
sequential_instruction();
88+
sequential_instruction();
89+
90+
$stop;
91+
end
92+
93+
endmodule
94+

modules_testbenches/sign_extend_tb.v

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
`timescale 1ns / 1ps
2+
//////////////////////////////////////////////////////////////////////////////////
3+
// Company:
4+
// Engineer:
5+
//
6+
// Create Date: 03/07/2023 01:13:02 AM
7+
// Design Name:
8+
// Module Name: sign_extend_tb
9+
// Project Name:
10+
// Target Devices:
11+
// Tool Versions:
12+
// Description:
13+
//
14+
// Dependencies:
15+
//
16+
// Revision:
17+
// Revision 0.01 - File Created
18+
// Additional Comments:
19+
//
20+
//////////////////////////////////////////////////////////////////////////////////
21+
22+
23+
`timescale 1ns / 1ps
24+
25+
module sign_extend_tb;
26+
27+
// Parameters
28+
localparam INST_LEN = 32;
29+
30+
// Inputs
31+
reg [31:7] instr_part;
32+
reg [1:0] imm_src;
33+
reg clk;
34+
35+
// Outputs
36+
wire [INST_LEN-1:0] data_out_signed;
37+
38+
39+
// Instantiate the Unit Under Test (UUT)
40+
sign_extend uut (
41+
.instr_part(instr_part),
42+
.imm_src(imm_src),
43+
.data_out_signed(data_out_signed)
44+
);
45+
46+
// Initialize Inputs
47+
initial begin
48+
instr_part = 32'h12345678;
49+
imm_src = 2'b01; // s_type
50+
end
51+
52+
// Stimulus
53+
always #10 imm_src = (imm_src + 1) % 3;
54+
55+
// Print Output
56+
always @(posedge clk) $display("data_out_signed = %h", data_out_signed);
57+
58+
// Clock
59+
initial begin
60+
clk =0;
61+
forever #5 clk = ~clk;
62+
end
63+
64+
endmodule
65+

0 commit comments

Comments
 (0)