summaryrefslogtreecommitdiff
path: root/riscvsingle.sv
diff options
context:
space:
mode:
Diffstat (limited to 'riscvsingle.sv')
-rw-r--r--riscvsingle.sv390
1 files changed, 390 insertions, 0 deletions
diff --git a/riscvsingle.sv b/riscvsingle.sv
new file mode 100644
index 0000000..f536718
--- /dev/null
+++ b/riscvsingle.sv
@@ -0,0 +1,390 @@
1// riscvsingle.sv
2
3// RISC-V single-cycle processor
4// From Section 7.6 of Digital Design & Computer Architecture
5// 27 April 2020
6// David_Harris@hmc.edu
7// Sarah.Harris@unlv.edu
8
9// run 210
10// Expect simulator to print "Simulation succeeded"
11// when the value 25 (0x19) is written to address 100 (0x64)
12
13// Single-cycle implementation of RISC-V (RV32I)
14// User-level Instruction Set Architecture V2.2 (May 7, 2017)
15// Implements a subset of the base integer instructions:
16// lw, sw
17// add, sub, and, or, slt,
18// addi, andi, ori, slti
19// beq
20// jal
21// Exceptions, traps, and interrupts not implemented
22// little-endian memory
23
24// 31 32-bit registers x1-x31, x0 hardwired to 0
25// R-Type instructions
26// add, sub, and, or, slt
27// INSTR rd, rs1, rs2
28// Instr[31:25] = funct7 (funct7b5 & opb5 = 1 for sub, 0 for others)
29// Instr[24:20] = rs2
30// Instr[19:15] = rs1
31// Instr[14:12] = funct3
32// Instr[11:7] = rd
33// Instr[6:0] = opcode
34// I-Type Instructions
35// lw, I-type ALU (addi, andi, ori, slti)
36// lw: INSTR rd, imm(rs1)
37// I-type ALU: INSTR rd, rs1, imm (12-bit signed)
38// Instr[31:20] = imm[11:0]
39// Instr[24:20] = rs2
40// Instr[19:15] = rs1
41// Instr[14:12] = funct3
42// Instr[11:7] = rd
43// Instr[6:0] = opcode
44// S-Type Instruction
45// sw rs2, imm(rs1) (store rs2 into address specified by rs1 + immm)
46// Instr[31:25] = imm[11:5] (offset[11:5])
47// Instr[24:20] = rs2 (src)
48// Instr[19:15] = rs1 (base)
49// Instr[14:12] = funct3
50// Instr[11:7] = imm[4:0] (offset[4:0])
51// Instr[6:0] = opcode
52// B-Type Instruction
53// beq rs1, rs2, imm (PCTarget = PC + (signed imm x 2))
54// Instr[31:25] = imm[12], imm[10:5]
55// Instr[24:20] = rs2
56// Instr[19:15] = rs1
57// Instr[14:12] = funct3
58// Instr[11:7] = imm[4:1], imm[11]
59// Instr[6:0] = opcode
60// J-Type Instruction
61// jal rd, imm (signed imm is multiplied by 2 and added to PC, rd = PC+4)
62// Instr[31:12] = imm[20], imm[10:1], imm[11], imm[19:12]
63// Instr[11:7] = rd
64// Instr[6:0] = opcode
65
66// Instruction opcode funct3 funct7
67// add 0110011 000 0000000
68// sub 0110011 000 0100000
69// and 0110011 111 0000000
70// or 0110011 110 0000000
71// slt 0110011 010 0000000
72// addi 0010011 000 immediate
73// andi 0010011 111 immediate
74// ori 0010011 110 immediate
75// slti 0010011 010 immediate
76// beq 1100011 000 immediate
77// lw 0000011 010 immediate
78// sw 0100011 010 immediate
79// jal 1101111 immediate immediate
80
81
82// This part is modified by Dr.Toker
83module my_computer(input logic clk, reset,
84 input logic[ 9:0] my_sw,
85 output logic[31:0] my_rd,
86 output logic[31:0] my_PC
87);
88
89 logic [31:0] PC, Instr, ReadData, WriteData, DataAddr;
90 logic MemWrite;
91
92 // instantiate processor
93 riscvsingle rvsingle(clk, reset, PC, Instr, MemWrite, DataAddr,
94 WriteData, ReadData);
95 // program memory - ROM
96 imem imem(PC, Instr);
97
98 // data memort - RAM
99 dmem dmem(clk, MemWrite, DataAddr, WriteData, ReadData, my_sw, my_rd);
100
101 assign my_PC = PC;
102
103endmodule
104
105// =======================================================================
106// NEW STUFF ABOUT MEMORIES - MUST REVIEW FIRST
107// =======================================================================
108
109module regfile(input logic clk,
110 input logic we3,
111 input logic [ 4:0] a1, a2, a3,
112 input logic [31:0] wd3,
113 output logic [31:0] rd1, rd2);
114
115 logic [31:0] rf[31:0];
116
117 // three ported register file
118 // read two ports combinationally (A1/RD1, A2/RD2)
119 // write third port on rising edge of clock (A3/WD3/WE3)
120 // register 0 hardwired to 0
121
122 always_ff @(posedge clk)
123 if (we3) rf[a3] <= wd3;
124
125 assign rd1 = (a1 != 0) ? rf[a1] : 0;
126 assign rd2 = (a2 != 0) ? rf[a2] : 0;
127endmodule
128
129module imem(input logic [31:0] a,
130 output logic [31:0] rd);
131
132 logic [31:0] ROM[63:0];
133
134 // Initialize the program memory
135 // Simulator : ok
136 // Hardware : For FPGA ok, non-FPGA we need a 3rd party solution to program the FLASH memory (ROM)
137 initial
138 $readmemh("C:\\Users\\onur\\Desktop\\CE_Lab2\\CEL_PROJECT\\riscvtest_rom_image.txt", ROM);
139
140 assign rd = ROM[a[31:2]]; // word aligned
141endmodule
142
143// This part is modified by Dr. Toker
144module dmem(input logic clk, we,
145 input logic [31:0] a, wd,
146 output logic [31:0] rd,
147 input logic [ 7:0] my_sw,
148 output logic [31:0] my_rd);
149
150 logic [31:0] RAM[127:0];
151
152 assign rd = RAM[a[31:2]]; // word aligned
153
154 always_ff @(posedge clk)
155 begin
156 if (we) RAM[a[31:2]] <= wd;
157
158 // Used only for simulation, does not correspond to ANY hardware
159 if (we)
160 $display("Write RAM[%08x]=%08x at %t", a[31:2], wd, $time);
161 else
162 $display("Read RAM[%08x]=%08x at %t", a[31:2], rd, $time);
163
164 end
165
166 assign my_rd = RAM[my_sw[7:2]];
167
168 // Initialize the program memory
169 // Simulator : ok
170 // Hardware : For FPGA ok, non-FPGA we need a 3rd party solution to program the DATA memory (RAM)
171 initial
172 $readmemh("C:\\Users\\onur\\Desktop\\CE_Lab2\\CEL_PROJECT\\riscvtest_ram_image.txt", RAM);
173
174endmodule
175
176module flopr #(parameter WIDTH = 8)
177 (input logic clk, reset,
178 input logic [WIDTH-1:0] d,
179 output logic [WIDTH-1:0] q);
180
181 always_ff @(posedge clk, posedge reset)
182 if (reset) q <= 0;
183 else q <= d;
184endmodule
185
186// =======================================================================
187// OLD STUFF - Component Instantiation or New Combinatorial Designs
188// =======================================================================
189
190module riscvsingle(input logic clk, reset,
191 output logic [31:0] PC,
192 input logic [31:0] Instr,
193 output logic MemWrite,
194 output logic [31:0] ALUResult, WriteData,
195 input logic [31:0] ReadData);
196
197 logic ALUSrc, RegWrite, Jump, Zero;
198 logic [1:0] ResultSrc, ImmSrc;
199 logic [2:0] ALUControl;
200
201 controller c(Instr[6:0], Instr[14:12], Instr[30], Zero,
202 ResultSrc, MemWrite, PCSrc,
203 ALUSrc, RegWrite, Jump,
204 ImmSrc, ALUControl);
205 datapath dp(clk, reset, ResultSrc, PCSrc,
206 ALUSrc, RegWrite,
207 ImmSrc, ALUControl,
208 Zero, PC, Instr,
209 ALUResult, WriteData, ReadData);
210endmodule
211
212module controller(input logic [6:0] op,
213 input logic [2:0] funct3,
214 input logic funct7b5,
215 input logic Zero,
216 output logic [1:0] ResultSrc,
217 output logic MemWrite,
218 output logic PCSrc, ALUSrc,
219 output logic RegWrite, Jump,
220 output logic [1:0] ImmSrc,
221 output logic [2:0] ALUControl);
222
223 logic [1:0] ALUOp;
224 logic Branch;
225
226 maindec md(op, ResultSrc, MemWrite, Branch,
227 ALUSrc, RegWrite, Jump, ImmSrc, ALUOp);
228 aludec ad(op[5], funct3, funct7b5, ALUOp, ALUControl);
229
230 assign PCSrc = Branch & Zero | Jump;
231endmodule
232
233module maindec(input logic [6:0] op,
234 output logic [1:0] ResultSrc,
235 output logic MemWrite,
236 output logic Branch, ALUSrc,
237 output logic RegWrite, Jump,
238 output logic [1:0] ImmSrc,
239 output logic [1:0] ALUOp);
240
241 logic [10:0] controls;
242
243 assign {RegWrite, ImmSrc, ALUSrc, MemWrite,
244 ResultSrc, Branch, ALUOp, Jump} = controls;
245
246 always_comb
247 case(op)
248 // RegWrite_ImmSrc_ALUSrc_MemWrite_ResultSrc_Branch_ALUOp_Jump
249 7'b0000011: controls = 11'b1_00_1_0_01_0_00_0; // lw
250 7'b0100011: controls = 11'b0_01_1_1_00_0_00_0; // sw
251 7'b0110011: controls = 11'b1_xx_0_0_00_0_10_0; // R-type
252 7'b1100011: controls = 11'b0_10_0_0_00_1_01_0; // beq
253 7'b0010011: controls = 11'b1_00_1_0_00_0_10_0; // I-type ALU
254 7'b1101111: controls = 11'b1_11_0_0_10_0_00_1; // jal
255 default: controls = 11'bx_xx_x_x_xx_x_xx_x; // non-implemented instruction
256 endcase
257endmodule
258
259module aludec(input logic opb5,
260 input logic [2:0] funct3,
261 input logic funct7b5,
262 input logic [1:0] ALUOp,
263 output logic [2:0] ALUControl);
264
265 logic RtypeSub;
266 assign RtypeSub = funct7b5 & opb5; // TRUE for R-type subtract instruction
267
268 always_comb
269 case(ALUOp)
270 2'b00: ALUControl = 3'b000; // addition
271 2'b01: ALUControl = 3'b001; // subtraction
272 default: case(funct3) // R-type or I-type ALU
273 3'b000: if (RtypeSub)
274 ALUControl = 3'b001; // sub
275 else
276 ALUControl = 3'b000; // add, addi
277 3'b010: ALUControl = 3'b101; // slt, slti
278 3'b110: ALUControl = 3'b011; // or, ori
279 3'b111: ALUControl = 3'b010; // and, andi
280 default: ALUControl = 3'bxxx; // ???
281 endcase
282 endcase
283endmodule
284
285module datapath(input logic clk, reset,
286 input logic [1:0] ResultSrc,
287 input logic PCSrc, ALUSrc,
288 input logic RegWrite,
289 input logic [1:0] ImmSrc,
290 input logic [2:0] ALUControl,
291 output logic Zero,
292 output logic [31:0] PC,
293 input logic [31:0] Instr,
294 output logic [31:0] ALUResult, WriteData,
295 input logic [31:0] ReadData);
296
297 logic [31:0] PCNext, PCPlus4, PCTarget;
298 logic [31:0] ImmExt;
299 logic [31:0] SrcA, SrcB;
300 logic [31:0] Result;
301
302 // next PC logic
303 flopr #(32) pcreg(clk, reset, PCNext, PC);
304 adder pcadd4(PC, 32'd4, PCPlus4);
305 adder pcaddbranch(PC, ImmExt, PCTarget);
306 mux2 #(32) pcmux(PCPlus4, PCTarget, PCSrc, PCNext);
307
308 // register file logic
309 regfile rf(clk, RegWrite, Instr[19:15], Instr[24:20],
310 Instr[11:7], Result, SrcA, WriteData);
311 extend ext(Instr[31:7], ImmSrc, ImmExt);
312
313 // ALU logic
314 mux2 #(32) srcbmux(WriteData, ImmExt, ALUSrc, SrcB);
315 alu alu(SrcA, SrcB, ALUControl, ALUResult, Zero);
316 mux3 #(32) resultmux(ALUResult, ReadData, PCPlus4, ResultSrc, Result);
317endmodule
318
319
320module adder(input [31:0] a, b,
321 output [31:0] y);
322
323 assign y = a + b;
324endmodule
325
326module extend(input logic [31:7] instr,
327 input logic [1:0] immsrc,
328 output logic [31:0] immext);
329
330 always_comb
331 case(immsrc)
332 // I-type
333 2'b00: immext = {{20{instr[31]}}, instr[31:20]};
334 // S-type (stores)
335 2'b01: immext = {{20{instr[31]}}, instr[31:25], instr[11:7]};
336 // B-type (branches)
337 2'b10: immext = {{20{instr[31]}}, instr[7], instr[30:25], instr[11:8], 1'b0};
338 // J-type (jal)
339 2'b11: immext = {{12{instr[31]}}, instr[19:12], instr[20], instr[30:21], 1'b0};
340 default: immext = 32'bx; // undefined
341 endcase
342endmodule
343
344module mux2 #(parameter WIDTH = 8)
345 (input logic [WIDTH-1:0] d0, d1,
346 input logic s,
347 output logic [WIDTH-1:0] y);
348
349 assign y = s ? d1 : d0;
350endmodule
351
352module mux3 #(parameter WIDTH = 8)
353 (input logic [WIDTH-1:0] d0, d1, d2,
354 input logic [1:0] s,
355 output logic [WIDTH-1:0] y);
356
357 assign y = s[1] ? d2 : (s[0] ? d1 : d0);
358endmodule
359
360module alu(input logic [31:0] a, b,
361 input logic [2:0] alucontrol,
362 output logic [31:0] result,
363 output logic zero);
364
365 logic [31:0] condinvb, sum;
366 logic v; // overflow
367 logic isAddSub; // true when is add or subtract operation
368
369 assign condinvb = alucontrol[0] ? ~b : b;
370 assign sum = a + condinvb + alucontrol[0];
371 assign isAddSub = ~alucontrol[2] & ~alucontrol[1] |
372 ~alucontrol[1] & alucontrol[0];
373
374 always_comb
375 case (alucontrol)
376 3'b000: result = sum; // add
377 3'b001: result = sum; // subtract
378 3'b010: result = a & b; // and
379 3'b011: result = a | b; // or
380 3'b100: result = a ^ b; // xor
381 3'b101: result = sum[31] ^ v; // slt
382 3'b110: result = a << b[4:0]; // sll
383 3'b111: result = a >> b[4:0]; // srl
384 default: result = 32'bx;
385 endcase
386
387 assign zero = (result == 32'b0);
388 assign v = ~(alucontrol[0] ^ a[31] ^ b[31]) & (a[31] ^ sum[31]) & isAddSub;
389
390endmodule