Skip to content

Commit ebcc244

Browse files
Start loading instructions from memory
1 parent bd544da commit ebcc244

File tree

2 files changed

+25
-309
lines changed

2 files changed

+25
-309
lines changed

src/main/scala/RISCV/Main.scala

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@ import scala.math._
77
import os.read
88

99
class Main() extends Module {
10-
1110
val io = IO(new Bundle {
12-
val instruction = Input(UInt(32.W))
11+
val execute = Input(Bool());
12+
13+
val debug_write = Input(Bool());
14+
val debug_write_address = Input(UInt(32.W));
15+
val debug_write_data = Input(UInt(32.W));
1316

1417
// Debugging variables for tests
1518
val out_A = Output(UInt(32.W))
@@ -22,6 +25,10 @@ class Main() extends Module {
2225
val write_addr = Input(UInt(5.W))
2326
val in = Input(UInt(32.W))
2427
})
28+
29+
val program_pointer = RegInit(0.U(32.W));
30+
31+
val memory = SRAM(1024, UInt(32.W), 1, 1, 0);
2532

2633
// Set up register file
2734
val regFile = Module(new Registers())
@@ -53,16 +60,19 @@ class Main() extends Module {
5360
alu.io.a := 0.U(32.W)
5461
alu.io.b := 0.U(32.W)
5562

56-
// Decode instruction
5763
val decoder = Module(new Decoder())
58-
// Default connections for decoder inputs
59-
60-
decoder.io.instruction := io.instruction
64+
decoder.io.instruction := memory.readPorts(0).data;
65+
66+
memory.readPorts(0).enable := io.execute;
67+
memory.readPorts(0).address := program_pointer;
68+
69+
memory.writePorts(0).enable := io.debug_write;
70+
memory.writePorts(0).address := io.debug_write_address;
71+
memory.writePorts(0).data := io.debug_write_data;
6172

6273
val operation = decoder.io.operation
63-
64-
// Uncomment to print instructions
65-
//printf("Instruction: %b, Operation: %b\n", io.instruction, operation)
74+
75+
printf("Operation: %b\n", operation)
6676

6777
switch(operation) {
6878
// U-type instructions

src/test/scala/RISCV/MainSpec.scala

Lines changed: 6 additions & 300 deletions
Original file line numberDiff line numberDiff line change
@@ -8,312 +8,18 @@ import org.scalatest.matchers.must.Matchers
88
class MainSpec extends AnyFreeSpec with Matchers with ChiselSim {
99
"Main should execute LUI correctly" in {
1010
simulate(new Main()) { dut =>
11-
// LUI x1, 0x12345
12-
val instr = "b00010010001101000101_00001_0110111".U(32.W) // opcode=0110111
13-
dut.io.instruction.poke(instr)
14-
dut.clock.step(1)
15-
16-
// Expect register x1 to hold immediate shifted left 12 bits
17-
dut.io.read_addr_C.poke(1.U)
18-
dut.io.out_C.expect("h12345000".U)
19-
}
20-
}
21-
22-
"Main should execute AUIPC correctly" in {
23-
simulate(new Main()) { dut =>
24-
// AUIPC x2, 0x1
25-
val instr = "b00000000000000000001_00010_0010111".U(32.W) // opcode=0010111
26-
dut.io.instruction.poke(instr)
27-
dut.clock.step(1)
28-
29-
// PC is 0 in this design, so x2 = pc + imm << 12
30-
dut.io.read_addr_C.poke(2.U)
31-
dut.io.out_C.expect("b00000000000000000001000000000000".U)
32-
}
33-
}
34-
35-
"Main should execute ADDI correctly" in {
36-
simulate(new Main()) { dut =>
37-
// First, write x1 = 5
38-
dut.io.write_enable.poke(true.B)
39-
dut.io.write_addr.poke(1.U)
40-
dut.io.in.poke(5.U)
41-
dut.clock.step(1)
42-
43-
// ADDI x2, x1, 7
44-
val instr = "b000000000111_00001_000_00010_0010011".U(32.W)
45-
dut.io.instruction.poke(instr)
46-
dut.clock.step(1)
47-
48-
// x2 should be 5 + 7 = 12
49-
dut.io.read_addr_C.poke(2.U)
50-
dut.io.out_C.expect(12.U)
51-
}
52-
}
53-
54-
"Main should execute SLTI correctly" in {
55-
simulate(new Main()) { dut =>
56-
// x1 = 5
57-
dut.io.write_enable.poke(true.B)
58-
dut.io.write_addr.poke(1.U)
59-
dut.io.in.poke(5.U)
60-
dut.clock.step(1)
61-
dut.io.write_enable.poke(false.B)
11+
dut.io.debug_write.poke(true.B);
12+
dut.io.debug_write_data.poke("b00010010001101000101_00001_0110111".U(32.W));
13+
dut.io.debug_write_address.poke(0.U);
6214

63-
// SLTI x2, x1, 7 -> 5 < 7 ? 1 : 0
64-
val instr = "b00000000111_00001_010_00010_0010011".U(32.W)
65-
dut.io.instruction.poke(instr)
66-
dut.clock.step(1)
67-
68-
// x2 should be 1
69-
dut.io.read_addr_C.poke(2.U)
70-
dut.io.out_C.expect(1.U)
71-
}
72-
}
73-
74-
"Main should execute SLTIU correctly" in {
75-
simulate(new Main()) { dut =>
76-
// x1 = 5
77-
dut.io.write_enable.poke(true.B)
78-
dut.io.write_addr.poke(1.U)
79-
dut.io.in.poke(5.U)
8015
dut.clock.step(1)
81-
dut.io.write_enable.poke(false.B)
8216

83-
// SLTIU x2, x1, 7 -> 5 < 7 ? 1 : 0 (unsigned)
84-
val instr = "b00000000111_00001_011_00010_0010011".U(32.W)
85-
dut.io.instruction.poke(instr)
86-
dut.clock.step(1)
17+
dut.io.debug_write.poke(false.B);
18+
dut.io.execute.poke(true.B);
8719

88-
// x2 should be 1
89-
dut.io.read_addr_C.poke(2.U)
90-
dut.io.out_C.expect(1.U)
91-
}
92-
}
93-
94-
"Main should execute XORI correctly" in {
95-
simulate(new Main()) { dut =>
96-
// x1 = 0b1010
97-
dut.io.write_enable.poke(true.B)
98-
dut.io.write_addr.poke(1.U)
99-
dut.io.in.poke("b1010".U)
10020
dut.clock.step(1)
101-
dut.io.write_enable.poke(false.B)
102-
103-
// XORI x2, x1, 0b1100 -> 0b1010 ^ 0b1100 = 0b0110
104-
val instr = "b000000001100_00001_100_00010_00100_11".U(32.W)
105-
dut.io.instruction.poke(instr)
21+
10622
dut.clock.step(1)
107-
108-
dut.io.read_addr_C.poke(2.U)
109-
dut.io.out_C.expect("b0110".U)
110-
}
111-
}
112-
113-
"Main should execute ORI correctly" in {
114-
simulate(new Main()) { dut =>
115-
// x1 = 0b1010
116-
dut.io.write_enable.poke(true.B)
117-
dut.io.write_addr.poke(1.U)
118-
dut.io.in.poke("b1010".U)
119-
dut.clock.step(1)
120-
dut.io.write_enable.poke(false.B)
121-
122-
// ORI x2, x1, 0b1100 -> 0b1010 | 0b1100 = 0b1110
123-
val instr = "b00000001100_00001_110_00010_00100_11".U(32.W)
124-
dut.io.instruction.poke(instr)
125-
dut.clock.step(1)
126-
127-
dut.io.read_addr_C.poke(2.U)
128-
dut.io.out_C.expect("b1110".U)
129-
}
130-
}
131-
132-
"Main should execute ANDI correctly" in {
133-
simulate(new Main()) { dut =>
134-
// x1 = 0b1010
135-
dut.io.write_enable.poke(true.B)
136-
dut.io.write_addr.poke(1.U)
137-
dut.io.in.poke("b1010".U)
138-
dut.clock.step(1)
139-
dut.io.write_enable.poke(false.B)
140-
141-
// ANDI x2, x1, 0b1100 -> 0b1010 & 0b1100 = 0b1000
142-
val instr = "b00000001100_00001_111_00010_00100_11".U(32.W)
143-
dut.io.instruction.poke(instr)
144-
dut.clock.step(1)
145-
146-
dut.io.read_addr_C.poke(2.U)
147-
dut.io.out_C.expect("b1000".U)
148-
}
149-
}
150-
151-
"Main should execute SLLI correctly" in {
152-
simulate(new Main()) { dut =>
153-
// x1 = 0b0001
154-
dut.io.write_enable.poke(true.B)
155-
dut.io.write_addr.poke(1.U)
156-
dut.io.in.poke("b0001".U)
157-
dut.clock.step(1)
158-
dut.io.write_enable.poke(false.B)
159-
160-
// SLLI x2, x1, 2 -> 0b0001 << 2 = 0b0100
161-
val instr = "b00000_0_00010_00001_001_00010_00100_11".U(32.W)
162-
dut.io.instruction.poke(instr)
163-
dut.clock.step(1)
164-
165-
dut.io.read_addr_C.poke(2.U)
166-
dut.io.out_C.expect("b0100".U)
167-
}
168-
}
169-
170-
"Main should execute SRLI correctly" in {
171-
simulate(new Main()) { dut =>
172-
// x1 = 0b0100
173-
dut.io.write_enable.poke(true.B)
174-
dut.io.write_addr.poke(1.U)
175-
dut.io.in.poke("b0100".U)
176-
dut.clock.step(1)
177-
dut.io.write_enable.poke(false.B)
178-
179-
// SRLI x2, x1, 2 -> 0b0100 >> 2 = 0b0001
180-
val instr = "b00000000010_00001_101_00010_0010011".U(32.W)
181-
dut.io.instruction.poke(instr)
182-
dut.clock.step(1)
183-
184-
dut.io.read_addr_C.poke(2.U)
185-
dut.io.out_C.expect("b0001".U)
186-
}
187-
}
188-
189-
"Main should execute SRAI correctly" in {
190-
simulate(new Main()) { dut =>
191-
// x1 = -8
192-
dut.io.write_enable.poke(true.B)
193-
dut.io.write_addr.poke(1.U)
194-
dut.io.in.poke("b11111111111111111111111111111000".U)
195-
dut.clock.step(1)
196-
dut.io.write_enable.poke(false.B)
197-
198-
// SRAI x2, x1, 2 -> -8 >> 2 = -2
199-
val instr = "b01000_0_00010_00001_101_00010_00100_11".U(32.W)
200-
dut.io.instruction.poke(instr)
201-
dut.clock.step(1)
202-
203-
dut.io.read_addr_C.poke(2.U)
204-
dut.io.out_C.expect("b11111111111111111111111111111110".U)
205-
}
206-
}
207-
208-
"Main should execute ADD correctly" in {
209-
simulate(new Main()) { dut =>
210-
// x1 = 5, x2 = 7
211-
dut.io.write_enable.poke(true.B)
212-
dut.io.write_addr.poke(1.U)
213-
dut.io.in.poke(5.U)
214-
dut.clock.step(1)
215-
dut.io.write_addr.poke(2.U)
216-
dut.io.in.poke(7.U)
217-
dut.clock.step(1)
218-
dut.io.write_enable.poke(false.B)
219-
220-
// ADD x3, x1, x2 -> 5 + 7 = 12
221-
val instr = "b0000000_00010_00001_000_00011_0110011".U(32.W)
222-
dut.io.instruction.poke(instr)
223-
dut.clock.step(1)
224-
225-
dut.io.read_addr_C.poke(3.U)
226-
dut.io.out_C.expect(12.U)
227-
}
228-
}
229-
230-
"Main should execute SUB correctly" in {
231-
simulate(new Main()) { dut =>
232-
// x1 = 10, x2 = 3
233-
dut.io.write_enable.poke(true.B)
234-
dut.io.write_addr.poke(1.U)
235-
dut.io.in.poke(10.U)
236-
dut.clock.step(1)
237-
dut.io.write_addr.poke(2.U)
238-
dut.io.in.poke(3.U)
239-
dut.clock.step(1)
240-
dut.io.write_enable.poke(false.B)
241-
242-
// SUB x3, x1, x2 -> 10 - 3 = 7
243-
val instr = "b0100000_00010_00001_000_00011_01100_11".U(32.W)
244-
dut.io.instruction.poke(instr)
245-
dut.clock.step(1)
246-
247-
dut.io.read_addr_C.poke(3.U)
248-
dut.io.out_C.expect(7.U)
249-
}
250-
}
251-
252-
"Main should execute SLL correctly" in {
253-
simulate(new Main()) { dut =>
254-
// x1 = 3, x2 = 2
255-
dut.io.write_enable.poke(true.B)
256-
dut.io.write_addr.poke(1.U)
257-
dut.io.in.poke(3.U)
258-
dut.clock.step(1)
259-
dut.io.write_addr.poke(2.U)
260-
dut.io.in.poke(2.U)
261-
dut.clock.step(1)
262-
dut.io.write_enable.poke(false.B)
263-
264-
// SLL x3, x1, x2 -> 3 << (2 & 0x1F) = 12
265-
val instr = "b0000000_00010_00001_001_00011_01100_11".U(32.W)
266-
dut.io.instruction.poke(instr)
267-
dut.clock.step(1)
268-
269-
dut.io.read_addr_C.poke(3.U)
270-
dut.io.out_C.expect(12.U)
271-
}
272-
}
273-
274-
"Main should execute SLT (signed) correctly" in {
275-
simulate(new Main()) { dut =>
276-
// x1 = -1 (0xFFFFFFFF), x2 = 1
277-
dut.io.write_enable.poke(true.B)
278-
dut.io.write_addr.poke(1.U)
279-
dut.io.in.poke("hFFFFFFFF".U) // -1 as 32-bit two's complement
280-
dut.clock.step(1)
281-
dut.io.write_addr.poke(2.U)
282-
dut.io.in.poke(1.U)
283-
dut.clock.step(1)
284-
dut.io.write_enable.poke(false.B)
285-
286-
// SLT x3, x1, x2 -> (-1 < 1) ? 1 : 0 => 1
287-
val instr = "b0000000_00010_00001_010_00011_01100_11".U(32.W)
288-
dut.io.instruction.poke(instr)
289-
dut.clock.step(1)
290-
291-
dut.io.read_addr_C.poke(3.U)
292-
dut.io.out_C.expect(1.U)
293-
}
294-
}
295-
296-
"Main should execute SLTU (unsigned) correctly" in {
297-
simulate(new Main()) { dut =>
298-
// x1 = 0xFFFFFFFF (unsigned 4294967295), x2 = 1
299-
// unsigned: 0xFFFFFFFF > 1 -> result should be 0
300-
dut.io.write_enable.poke(true.B)
301-
dut.io.write_addr.poke(1.U)
302-
dut.io.in.poke("hFFFFFFFF".U) // large unsigned value
303-
dut.clock.step(1)
304-
dut.io.write_addr.poke(2.U)
305-
dut.io.in.poke(1.U)
306-
dut.clock.step(1)
307-
dut.io.write_enable.poke(false.B)
308-
309-
// SLTU x3, x1, x2 -> (0xFFFFFFFF < 1) ? 1 : 0 => 0 (unsigned comparison)
310-
val instr = "b0000000_00010_00001_011_00011_01100_11".U(32.W)
311-
dut.io.instruction.poke(instr)
312-
dut.clock.step(1)
313-
314-
dut.io.read_addr_C.poke(3.U)
315-
dut.io.out_C.expect(0.U)
31623
}
31724
}
318-
31925
}

0 commit comments

Comments
 (0)