Blame


1 8515162d 2024-02-02 benni `define FMT_R 3'b000
2 8515162d 2024-02-02 benni `define FMT_I 3'b001
3 8515162d 2024-02-02 benni `define FMT_L 3'b010
4 8515162d 2024-02-02 benni `define FMT_S 3'b011
5 8515162d 2024-02-02 benni `define FMT_J 3'b100
6 8515162d 2024-02-02 benni `define FMT_UD 3'b111
7 8515162d 2024-02-02 benni
8 8515162d 2024-02-02 benni `define CWB_MEM_WR 0
9 8515162d 2024-02-02 benni `define CWB_MEM_EN 1
10 8515162d 2024-02-02 benni `define CWB_PC_WR 2
11 8515162d 2024-02-02 benni `define CWB_IR_WR 3
12 8515162d 2024-02-02 benni `define CWB_WB 4
13 8515162d 2024-02-02 benni
14 8515162d 2024-02-02 benni `define CW_MEM_WR (16'b1 << `CWB_MEM_WR)
15 8515162d 2024-02-02 benni `define CW_MEM_EN (16'b1 << `CWB_MEM_EN)
16 8515162d 2024-02-02 benni `define CW_PC_WR (16'b1 << `CWB_PC_WR)
17 8515162d 2024-02-02 benni `define CW_IR_WR (16'b1 << `CWB_IR_WR)
18 8515162d 2024-02-02 benni `define CW_WB (16'b1 << `CWB_WB)
19 8515162d 2024-02-02 benni
20 8515162d 2024-02-02 benni function [15:0] lshift(input [15:0] value, input [15:0] shamt);
21 8515162d 2024-02-02 benni if (shamt[15] == 1'b0)
22 8515162d 2024-02-02 benni lshift = value << shamt;
23 8515162d 2024-02-02 benni else
24 8515162d 2024-02-02 benni lshift = value >> -shamt;
25 8515162d 2024-02-02 benni endfunction
26 8515162d 2024-02-02 benni
27 8515162d 2024-02-02 benni module ALU(
28 8515162d 2024-02-02 benni input [15:0] in1,
29 8515162d 2024-02-02 benni input [15:0] in2,
30 8515162d 2024-02-02 benni input [2:0] op,
31 8515162d 2024-02-02 benni output reg [15:0] out
32 8515162d 2024-02-02 benni );
33 8515162d 2024-02-02 benni
34 8515162d 2024-02-02 benni wire signed [15:0] in1s = in1;
35 8515162d 2024-02-02 benni wire signed [15:0] in2s = in2;
36 8515162d 2024-02-02 benni
37 8515162d 2024-02-02 benni always@ (*) begin
38 8515162d 2024-02-02 benni case (op)
39 8515162d 2024-02-02 benni 3'b000: out = in1 + in2;
40 8515162d 2024-02-02 benni 3'b001: out = in1 - in2;
41 8515162d 2024-02-02 benni 3'b010: out = in1 & in2;
42 8515162d 2024-02-02 benni 3'b011: out = in1 | in2;
43 8515162d 2024-02-02 benni 3'b100: out = lshift(in1, in2);
44 8515162d 2024-02-02 benni 3'b101: out = in1 ^ in2;
45 8515162d 2024-02-02 benni 3'b110: out = { 15'b0, (in1 < in2) };
46 8515162d 2024-02-02 benni 3'b111: out = { 15'b0, (in1s < in2s) };
47 8515162d 2024-02-02 benni endcase
48 8515162d 2024-02-02 benni end
49 8515162d 2024-02-02 benni endmodule
50 8515162d 2024-02-02 benni
51 8515162d 2024-02-02 benni module Processor(
52 8515162d 2024-02-02 benni output [7:0] debug,
53 8515162d 2024-02-02 benni output reg [15:0] mem_addr,
54 8515162d 2024-02-02 benni inout [15:0] mem_data,
55 8515162d 2024-02-02 benni output mem_wr,
56 8515162d 2024-02-02 benni output mem_en,
57 8515162d 2024-02-02 benni input mem_busy,
58 8515162d 2024-02-02 benni input clk,
59 8515162d 2024-02-02 benni input rst
60 8515162d 2024-02-02 benni );
61 8515162d 2024-02-02 benni
62 8515162d 2024-02-02 benni wire [15:0] alu_in2, alu_out;
63 8515162d 2024-02-02 benni reg [15:0] regs [7:1];
64 8515162d 2024-02-02 benni reg [15:0] rd, pc, next_pc, instr;
65 8515162d 2024-02-02 benni reg [15:0] control_word;
66 8515162d 2024-02-02 benni reg [3:0] state = 0;
67 8515162d 2024-02-02 benni reg [2:0] ifmt;
68 8515162d 2024-02-02 benni reg [15:0] imm, imm2;
69 8515162d 2024-02-02 benni wire [2:0] rd_sel = instr[15:12] != 4'b1110 ? instr[10:8] : 3'h7;
70 8515162d 2024-02-02 benni wire [2:0] rs_sel = ifmt == `FMT_I ? instr[10:8] : instr[6:4];
71 8515162d 2024-02-02 benni wire [2:0] rt_sel = instr[2:0];
72 8515162d 2024-02-02 benni wire [2:0] alu_op = ifmt == `FMT_R ? { instr[11], instr[7], instr[3] } : { instr[11], 2'b00 };
73 8515162d 2024-02-02 benni wire [15:0] rs = regs[rs_sel];
74 8515162d 2024-02-02 benni wire [15:0] rt = regs[rt_sel];
75 8515162d 2024-02-02 benni wire [15:0] alu_in1 = rs;
76 8515162d 2024-02-02 benni
77 8515162d 2024-02-02 benni assign debug = control_word[7:0];
78 8515162d 2024-02-02 benni
79 8515162d 2024-02-02 benni ALU _alu(
80 8515162d 2024-02-02 benni .in1(alu_in1),
81 8515162d 2024-02-02 benni .in2(alu_in2),
82 8515162d 2024-02-02 benni .op(alu_op),
83 8515162d 2024-02-02 benni .out(alu_out)
84 8515162d 2024-02-02 benni );
85 8515162d 2024-02-02 benni
86 8515162d 2024-02-02 benni always@ (posedge clk or posedge rst) begin
87 8515162d 2024-02-02 benni if (rst)
88 8515162d 2024-02-02 benni pc <= 16'b0;
89 8515162d 2024-02-02 benni else if (control_word[`CWB_PC_WR] )
90 8515162d 2024-02-02 benni pc <= next_pc;
91 8515162d 2024-02-02 benni end
92 8515162d 2024-02-02 benni
93 8515162d 2024-02-02 benni always@ (posedge clk or posedge rst) begin
94 8515162d 2024-02-02 benni if (rst)
95 8515162d 2024-02-02 benni instr <= 0;
96 8515162d 2024-02-02 benni else if (control_word[`CWB_IR_WR])
97 8515162d 2024-02-02 benni instr <= mem_data;
98 8515162d 2024-02-02 benni end
99 8515162d 2024-02-02 benni
100 8515162d 2024-02-02 benni always@ (negedge clk or posedge rst) begin
101 8515162d 2024-02-02 benni if (rst)
102 8515162d 2024-02-02 benni state <= 0;
103 8515162d 2024-02-02 benni else begin
104 8515162d 2024-02-02 benni if (mem_busy)
105 8515162d 2024-02-02 benni control_word <= 0;
106 8515162d 2024-02-02 benni else begin
107 8515162d 2024-02-02 benni case (state)
108 8515162d 2024-02-02 benni // Fetch
109 8515162d 2024-02-02 benni 4'b0000: begin
110 8515162d 2024-02-02 benni mem_addr <= pc;
111 8515162d 2024-02-02 benni next_pc <= pc + 2;
112 8515162d 2024-02-02 benni control_word <= `CW_MEM_EN | `CW_IR_WR | `CW_PC_WR;
113 8515162d 2024-02-02 benni state <= state + 1;
114 8515162d 2024-02-02 benni end
115 8515162d 2024-02-02 benni // Execute
116 8515162d 2024-02-02 benni 4'b0001: begin
117 8515162d 2024-02-02 benni casez (instr[15:12])
118 8515162d 2024-02-02 benni // alu rd, rs, rt
119 8515162d 2024-02-02 benni 4'b0000: begin
120 8515162d 2024-02-02 benni rd <= alu_out;
121 8515162d 2024-02-02 benni control_word <= `CW_WB;
122 8515162d 2024-02-02 benni state <= 0;
123 8515162d 2024-02-02 benni end
124 8515162d 2024-02-02 benni // jalr rd, rt
125 8515162d 2024-02-02 benni 4'b0001: begin
126 8515162d 2024-02-02 benni next_pc <= rt;
127 8515162d 2024-02-02 benni rd <= pc;
128 8515162d 2024-02-02 benni control_word <= `CW_WB | `CW_PC_WR;
129 8515162d 2024-02-02 benni state <= 0;
130 8515162d 2024-02-02 benni end
131 8515162d 2024-02-02 benni // alui rd, imm
132 8515162d 2024-02-02 benni 4'b0010: begin
133 8515162d 2024-02-02 benni rd <= alu_out;
134 8515162d 2024-02-02 benni control_word <= `CW_WB;
135 8515162d 2024-02-02 benni state <= 0;
136 8515162d 2024-02-02 benni end
137 8515162d 2024-02-02 benni // lui/li rd, imm
138 8515162d 2024-02-02 benni 4'b0011: begin
139 8515162d 2024-02-02 benni rd <= instr[11] ? imm : (imm << 8);
140 8515162d 2024-02-02 benni control_word <= `CW_WB;
141 8515162d 2024-02-02 benni state <= 0;
142 8515162d 2024-02-02 benni end
143 8515162d 2024-02-02 benni // lw rd, [rt, imm]
144 8515162d 2024-02-02 benni 4'b0100: begin
145 8515162d 2024-02-02 benni mem_addr <= rt;
146 8515162d 2024-02-02 benni control_word <= `CW_MEM_EN;
147 8515162d 2024-02-02 benni state <= state + 1;
148 8515162d 2024-02-02 benni end
149 8515162d 2024-02-02 benni // TODO: lb, lbu
150 8515162d 2024-02-02 benni // sw rs, [rt, imm]
151 8515162d 2024-02-02 benni 4'b1000: begin
152 8515162d 2024-02-02 benni mem_addr <= rt;
153 8515162d 2024-02-02 benni control_word <= `CW_MEM_WR;
154 8515162d 2024-02-02 benni state <= 0;
155 8515162d 2024-02-02 benni end
156 8515162d 2024-02-02 benni // TODO: sb
157 8515162d 2024-02-02 benni // bcc rs, rt, imm
158 8515162d 2024-02-02 benni 4'b101?: begin
159 8515162d 2024-02-02 benni if ((rs == rt) ^ instr[12]) begin
160 8515162d 2024-02-02 benni next_pc <= pc + imm;
161 8515162d 2024-02-02 benni control_word <= `CW_PC_WR;
162 8515162d 2024-02-02 benni end
163 8515162d 2024-02-02 benni else control_word <= 0;
164 8515162d 2024-02-02 benni state <= 0;
165 8515162d 2024-02-02 benni end
166 8515162d 2024-02-02 benni // jal imm
167 8515162d 2024-02-02 benni 4'b1110: begin
168 8515162d 2024-02-02 benni rd <= pc;
169 8515162d 2024-02-02 benni next_pc <= pc + imm;
170 8515162d 2024-02-02 benni control_word <= `CW_WB | `CW_PC_WR;
171 8515162d 2024-02-02 benni state <= 0;
172 8515162d 2024-02-02 benni end
173 8515162d 2024-02-02 benni // j imm
174 8515162d 2024-02-02 benni 4'b1111: begin
175 8515162d 2024-02-02 benni next_pc <= pc + imm;
176 8515162d 2024-02-02 benni control_word <= `CW_PC_WR;
177 8515162d 2024-02-02 benni state <= 0;
178 8515162d 2024-02-02 benni end
179 8515162d 2024-02-02 benni endcase
180 8515162d 2024-02-02 benni end // case: 4'b0001
181 8515162d 2024-02-02 benni // WB Memory
182 8515162d 2024-02-02 benni 4'b0010: begin
183 8515162d 2024-02-02 benni case (instr[15:12])
184 8515162d 2024-02-02 benni 4'b0100: begin
185 8515162d 2024-02-02 benni rd <= mem_data;
186 8515162d 2024-02-02 benni control_word <= `CW_WB;
187 8515162d 2024-02-02 benni state <= 0;
188 8515162d 2024-02-02 benni end
189 8515162d 2024-02-02 benni default: state <= 0;
190 8515162d 2024-02-02 benni endcase
191 8515162d 2024-02-02 benni end
192 8515162d 2024-02-02 benni default: state <= 0;
193 8515162d 2024-02-02 benni endcase
194 8515162d 2024-02-02 benni end
195 8515162d 2024-02-02 benni end
196 8515162d 2024-02-02 benni end
197 8515162d 2024-02-02 benni
198 8515162d 2024-02-02 benni always@ (posedge clk) begin
199 8515162d 2024-02-02 benni if (control_word[`CWB_WB] && rd_sel != 0)
200 8515162d 2024-02-02 benni regs[rd_sel] <= rd;
201 8515162d 2024-02-02 benni end
202 8515162d 2024-02-02 benni
203 8515162d 2024-02-02 benni always@ (*) begin
204 8515162d 2024-02-02 benni casez (instr[15:12])
205 8515162d 2024-02-02 benni 4'b000?: ifmt = `FMT_R;
206 8515162d 2024-02-02 benni 4'b001?: ifmt = `FMT_I;
207 8515162d 2024-02-02 benni 4'b01??: ifmt = `FMT_L;
208 8515162d 2024-02-02 benni 4'b10??: ifmt = `FMT_S;
209 8515162d 2024-02-02 benni 4'b110?: ifmt = `FMT_UD;
210 8515162d 2024-02-02 benni 4'b111?: ifmt = `FMT_J;
211 8515162d 2024-02-02 benni endcase
212 8515162d 2024-02-02 benni end
213 8515162d 2024-02-02 benni
214 8515162d 2024-02-02 benni always@ (*) begin
215 8515162d 2024-02-02 benni case (ifmt)
216 8515162d 2024-02-02 benni `FMT_I: imm2 = { {8{instr[7]}}, instr[7:0] };
217 8515162d 2024-02-02 benni `FMT_L: imm2 = { {10{instr[11]}}, instr[11], instr[7:3] };
218 8515162d 2024-02-02 benni `FMT_S: imm2 = { {10{instr[11]}}, instr[11:7], instr[3] };
219 8515162d 2024-02-02 benni `FMT_J: imm2 = { {4{instr[11]}}, instr[11:0] };
220 8515162d 2024-02-02 benni default: imm2 = 0;
221 8515162d 2024-02-02 benni endcase
222 8515162d 2024-02-02 benni casez (instr[15:12])
223 8515162d 2024-02-02 benni 4'b1000: imm = imm2 << 1;
224 8515162d 2024-02-02 benni 4'b101?: imm = imm2 << 1;
225 8515162d 2024-02-02 benni 4'b111?: imm = imm2 << 1;
226 8515162d 2024-02-02 benni default: imm = imm2;
227 8515162d 2024-02-02 benni endcase
228 8515162d 2024-02-02 benni end
229 8515162d 2024-02-02 benni
230 8515162d 2024-02-02 benni assign alu_in2 = ifmt == `FMT_R ? rt : imm;
231 8515162d 2024-02-02 benni assign mem_wr = control_word[`CWB_MEM_WR];
232 8515162d 2024-02-02 benni assign mem_en = control_word[`CWB_MEM_EN];
233 8515162d 2024-02-02 benni assign mem_data = control_word[`CWB_MEM_WR] ? rs : 16'bz;
234 8515162d 2024-02-02 benni endmodule