Blob


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