Skip to content

Commit 37854f4

Browse files
committed
RTL design complete. Testbench passed.
1 parent af866d2 commit 37854f4

15 files changed

+664
-1
lines changed

README.md

+29-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,30 @@
11
# mips_cpu
2-
A implementation of a 32-bit single cycle MIPS processor in Verilog.
2+
3+
A implementation of a 32-bit single cycle MIPS processor in Verilog. This version of the MIPS single-cycle processor can execute the following instructions: add, sub, and, or, slt, lw, sw, beq, addi, and j.
4+
5+
To tun the test bench:
6+
7+
$ iverilog *.v
8+
$ ./a.out; gtkwave dump.vcd test.gtkw
9+
10+
Each of the memories is a 64-word × 32-bit array. The instruction memory contains some initial values representing a test program.
11+
12+
## Test MIPS instructions.
13+
14+
main: addi $2, $0, 5 # 20020005
15+
addi $7, $0, 3 # 20070003
16+
addi $3, $0, 0xc # 2003000c
17+
or $4, $7, $2 # 00e22025
18+
and $5, $3, $4 # 00642824
19+
add $5, $5, $4 # 00a42820
20+
beq $5, $7, end # 10a70008
21+
slt $6, $3, $4 # 0064302a
22+
beq $6, $0, around # 10c00001
23+
addi $5, $0, 10 # 2005000a
24+
around: slt $6, $7, $2 # 00e2302a
25+
add $7, $6, $5 # 00c53820
26+
sub $7, $7, $2 # 00e23822
27+
j end # 0800000f
28+
lw $7, 0($0) # 8c070000
29+
end: sw $7, 71($2) # ac470047
30+

alu.v

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
module alu (
2+
input [31:0] a_in, b_in,
3+
input [ 2:0] f_in ,
4+
output zero,
5+
output c_out,
6+
output [31:0] y_out
7+
);
8+
9+
wire [31:0] not_b_in;
10+
assign not_b_in = ~ b_in;
11+
12+
wire [31:0] b_mux_not_b;
13+
assign b_mux_not_b = (1'b0 == f_in[2]) ? b_in : not_b_in;
14+
15+
wire [31:0] fx00;
16+
assign fx00 = a_in & b_mux_not_b;
17+
18+
wire [31:0] fx01;
19+
assign fx01 = a_in | b_mux_not_b;
20+
21+
wire [31:0] fx10;
22+
assign {c_out, fx10} = a_in + b_mux_not_b + f_in[2];
23+
24+
wire [31:0] fx11;
25+
assign fx11 = {{31{1'b0}}, ((a_in[31] == not_b_in[31]) && (fx10[31] != a_in[31])) ? ~(fx10[31]) : fx10[31]};
26+
27+
assign zero = ~| y_out;
28+
29+
assign y_out = 2'b00 == f_in[1:0] ? fx00 : (2'b01 == f_in[1:0] ? fx01 : (2'b10 == f_in[1:0] ? fx10 : fx11 ));
30+
31+
endmodule

aludec.v

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
module aludec (
2+
input [31:0] instr ,
3+
output [ 2:0] alucontrol
4+
);
5+
6+
reg [2:0] alucontrol;
7+
8+
always @(instr) begin
9+
casex ({instr[31:26], instr[5:0]})
10+
12'b000100xxxxxx : alucontrol = 3'b110;
11+
12'b001010xxxxxx : alucontrol = 3'b111;
12+
12'b001000xxxxxx : alucontrol = 3'b010;
13+
12'bxxxxxx100000 : alucontrol = 3'b010;
14+
12'bxxxxxx100010 : alucontrol = 3'b110;
15+
12'bxxxxxx100100 : alucontrol = 3'b000;
16+
12'bxxxxxx100101 : alucontrol = 3'b001;
17+
12'bxxxxxx101010 : alucontrol = 3'b111;
18+
default : alucontrol = 3'b010;
19+
endcase
20+
end
21+
22+
endmodule

controller.v

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
module controller (
2+
input [31:0] instr ,
3+
// other side
4+
output branch ,
5+
output jump ,
6+
output mem_to_reg,
7+
output mem_write ,
8+
output reg_dst ,
9+
output reg_write ,
10+
// alu side
11+
output [ 2:0] alucontrol,
12+
output alu_src
13+
);
14+
15+
maindec maindec_inst (
16+
.instr (instr ),
17+
.branch (branch ),
18+
.jump (jump ),
19+
.mem_to_reg(mem_to_reg),
20+
.mem_write (mem_write ),
21+
.reg_dst (reg_dst ),
22+
.reg_write (reg_write ),
23+
.alu_src (alu_src )
24+
);
25+
26+
aludec aludec_inst (
27+
.instr (instr ),
28+
.alucontrol(alucontrol)
29+
);
30+
31+
endmodule

datapath.v

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
module datapath (
2+
input clk ,
3+
input rst ,
4+
input [ 2:0] alucontrol,
5+
input alu_src ,
6+
input branch ,
7+
input jump ,
8+
input mem_to_reg,
9+
input mem_write ,
10+
input reg_dst ,
11+
input reg_write ,
12+
// imem side
13+
input [31:0] instr ,
14+
output [31:0] pc ,
15+
// dmem side
16+
input [31:0] read_data ,
17+
output [31:0] alu_result,
18+
output [31:0] write_data
19+
);
20+
21+
wire [31:0] pc_plus_4;
22+
assign pc_plus_4 = pc + 4;
23+
24+
wire [31:0] pc_jump;
25+
assign pc_jump = {pc_plus_4[31:28], instr[25:0], 2'b00};
26+
27+
wire pc_src;
28+
assign pc_src = branch & zero;
29+
30+
wire [31:0] pc_branch;
31+
assign pc_branch = pc_plus_4 + {imm_ext[29:0], 2'b00};
32+
33+
wire [31:0] pc_next;
34+
assign pc_next = jump ? pc_jump : (pc_src ? pc_branch : pc_plus_4);
35+
36+
reg [31:0] pc;
37+
always @(posedge clk) begin : proc_pc
38+
if(~rst) begin
39+
pc = pc_next;
40+
end else begin
41+
pc = 32'h00000000;
42+
end
43+
end
44+
45+
wire [5:0] rt;
46+
assign rt = instr[20:16];
47+
48+
wire [5:0] rd;
49+
assign rd = instr[15:11];
50+
51+
wire [4:0] write_reg;
52+
assign write_reg = reg_dst ? rd : rt;
53+
54+
wire [31:0] result;
55+
assign result = mem_to_reg ? read_data : alu_result ;
56+
57+
wire [31:0] reg_data1;
58+
wire [31:0] reg_data2;
59+
60+
regfile regfile_inst (
61+
.clk (clk ),
62+
.rw (reg_write ),
63+
.addr1(instr[25:21]),
64+
.addr2(instr[20:16]),
65+
.addr3(write_reg ),
66+
.wdata(result ),
67+
.data1(reg_data1 ),
68+
.data2(reg_data2 )
69+
);
70+
71+
wire [31:0] src_a;
72+
wire [31:0] src_b;
73+
wire c_out;
74+
75+
assign src_a = reg_data1;
76+
assign src_b = alu_src ? imm_ext : reg_data2;
77+
78+
alu alu_inst (
79+
.a_in (src_a ),
80+
.b_in (src_b ),
81+
.f_in (alucontrol),
82+
.zero (zero ),
83+
.c_out(c_out ),
84+
.y_out(alu_out )
85+
);
86+
wire [31:0] alu_out;
87+
assign alu_result = alu_out;
88+
89+
wire [31:0] imm_ext;
90+
sign_extend sign_extend_inst (
91+
.idata(instr[15:0]),
92+
.odata(imm_ext )
93+
);
94+
95+
assign write_data = reg_data2;
96+
97+
endmodule

dmem.v

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module dmem (
2+
input clk ,
3+
input we ,
4+
input [31:0] addr ,
5+
input [31:0] wdata,
6+
output [31:0] rdata
7+
);
8+
9+
reg [31:0] rdata;
10+
11+
reg [31:0] memdata[63:0];
12+
13+
always @(memdata[addr]) begin
14+
rdata = memdata[addr];
15+
end
16+
17+
always @(posedge clk) begin
18+
if(1'b1 == we) begin
19+
memdata[addr] = wdata;
20+
end
21+
end
22+
23+
endmodule

imem.v

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
module imem (
2+
input [ 5:0] addr,
3+
output [31:0] data
4+
);
5+
6+
reg [31:0] data;
7+
8+
// echo -e {00..63}": data = 32'h00000000;\n"
9+
// xx : data = {6'dx,5'dx,5'dx,5'dx,5'dx,6'dx};
10+
always @(addr) begin
11+
case(addr)
12+
00 : data = 32'h20020005;
13+
01 : data = 32'h20070003;
14+
02 : data = 32'h2003000c;
15+
03 : data = 32'h00e22025;
16+
04 : data = 32'h00642824;
17+
05 : data = 32'h00a42820;
18+
06 : data = 32'h10a70008;
19+
07 : data = 32'h0064302a;
20+
08 : data = 32'h10c00001;
21+
09 : data = 32'h2005000a;
22+
10 : data = 32'h00e2302a;
23+
11 : data = 32'h00c53820;
24+
12 : data = 32'h00e23822;
25+
13 : data = 32'h0800000f;
26+
14 : data = 32'h8c070000;
27+
15 : data = 32'hac470047;
28+
16 : data = 32'h00000000;
29+
17 : data = 32'h00000000;
30+
18 : data = 32'h00000000;
31+
19 : data = 32'h00000000;
32+
20 : data = 32'h00000000;
33+
21 : data = 32'h00000000;
34+
22 : data = 32'h00000000;
35+
23 : data = 32'h00000000;
36+
24 : data = 32'h00000000;
37+
25 : data = 32'h00000000;
38+
26 : data = 32'h00000000;
39+
27 : data = 32'h00000000;
40+
28 : data = 32'h00000000;
41+
29 : data = 32'h00000000;
42+
30 : data = 32'h00000000;
43+
31 : data = 32'h00000000;
44+
32 : data = 32'h00000000;
45+
33 : data = 32'h00000000;
46+
34 : data = 32'h00000000;
47+
35 : data = 32'h00000000;
48+
36 : data = 32'h00000000;
49+
37 : data = 32'h00000000;
50+
38 : data = 32'h00000000;
51+
39 : data = 32'h00000000;
52+
40 : data = 32'h00000000;
53+
41 : data = 32'h00000000;
54+
42 : data = 32'h00000000;
55+
43 : data = 32'h00000000;
56+
44 : data = 32'h00000000;
57+
45 : data = 32'h00000000;
58+
46 : data = 32'h00000000;
59+
47 : data = 32'h00000000;
60+
48 : data = 32'h00000000;
61+
49 : data = 32'h00000000;
62+
50 : data = 32'h00000000;
63+
51 : data = 32'h00000000;
64+
52 : data = 32'h00000000;
65+
53 : data = 32'h00000000;
66+
54 : data = 32'h00000000;
67+
55 : data = 32'h00000000;
68+
56 : data = 32'h00000000;
69+
57 : data = 32'h00000000;
70+
58 : data = 32'h00000000;
71+
59 : data = 32'h00000000;
72+
60 : data = 32'h00000000;
73+
61 : data = 32'h00000000;
74+
62 : data = 32'h00000000;
75+
63 : data = 32'h00000000;
76+
endcase
77+
end
78+
79+
endmodule

maindec.v

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
module maindec (
2+
input [31:0] instr ,
3+
//
4+
output branch ,
5+
output jump ,
6+
output mem_to_reg,
7+
output mem_write ,
8+
output reg_dst ,
9+
output reg_write ,
10+
output alu_src
11+
);
12+
13+
wire [5:0] opcode;
14+
assign opcode = instr[31:26];
15+
16+
wire [5:0] func;
17+
assign func = instr[5:0];
18+
19+
wire is_add = ((opcode == 6'h00) & (func == 6'h20));
20+
wire is_sub = ((opcode == 6'h00) & (func == 6'h22));
21+
wire is_and = ((opcode == 6'h00) & (func == 6'h24));
22+
wire is_or = ((opcode == 6'h00) & (func == 6'h25));
23+
wire is_slt = ((opcode == 6'h00) & (func == 6'h2A));
24+
25+
wire is_lw = (opcode == 6'h23);
26+
wire is_sw = (opcode == 6'h2B);
27+
28+
wire is_beq = (opcode == 6'h04);
29+
wire is_addi = (opcode == 6'h08);
30+
wire is_j = (opcode == 6'h02);
31+
32+
assign branch = is_beq;
33+
assign jump = is_j;
34+
assign mem_to_reg = is_lw;
35+
assign mem_write = is_sw;
36+
assign reg_dst = is_add | is_sub | is_and | is_or | is_slt;
37+
assign reg_write = is_add | is_sub | is_and | is_or | is_slt | is_addi | is_lw;
38+
assign alu_src = is_addi | is_lw | is_sw;
39+
40+
endmodule

0 commit comments

Comments
 (0)