OpenCores
URL https://opencores.org/ocsvn/zipcpu/zipcpu/trunk

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [bench/] [formal/] [f_idecode.v] - Blame information for rev 209

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 209 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    f_idecode.v
4
//
5
// Project:     Zip CPU -- a small, lightweight, RISC CPU soft core
6
//
7
// Purpose:     This RTL file is meant to shadow the idecode.v file, but yet
8
//              to require no clocks for decoding at all.  The purpose is to
9
//      help to verify instructions as they go through the ZipCPU pipeline,
10
//      and so to know what instructions are supposed to do what when.
11
//
12
//
13
// Creator:     Dan Gisselquist, Ph.D.
14
//              Gisselquist Technology, LLC
15
//
16
////////////////////////////////////////////////////////////////////////////////
17
//
18
// Copyright (C) 2018-2019, Gisselquist Technology, LLC
19
//
20
// This program is free software (firmware): you can redistribute it and/or
21
// modify it under the terms of  the GNU General Public License as published
22
// by the Free Software Foundation, either version 3 of the License, or (at
23
// your option) any later version.
24
//
25
// This program is distributed in the hope that it will be useful, but WITHOUT
26
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
27
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
28
// for more details.
29
//
30
// You should have received a copy of the GNU General Public License along
31
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
32
// target there if the PDF file isn't present.)  If not, see
33
// <http://www.gnu.org/licenses/> for a copy.
34
//
35
// License:     GPL, v3, as defined and found on www.gnu.org,
36
//              http://www.gnu.org/licenses/gpl.html
37
//
38
//
39
////////////////////////////////////////////////////////////////////////////////
40
//
41
//
42
`default_nettype        none
43
//
44
`define CPU_SP_REG      4'hd
45
`define CPU_CC_REG      4'he
46
`define CPU_PC_REG      4'hf
47
//
48
`define CISBIT          31
49
`define CISIMMSEL       23
50
`define IMMSEL          18
51
//
52
//
53
//
54
module  f_idecode(i_instruction, i_phase, i_gie,
55
                o_illegal,
56
                o_dcdR, o_dcdA, o_dcdB, o_I, o_cond, o_wF,
57
                o_op, o_ALU, o_M, o_DV, o_FP, o_break, o_lock,
58
                o_wR, o_rA, o_rB, o_prepipe, o_sim, o_sim_immv
59
                );
60
        parameter               ADDRESS_WIDTH=24;
61
        parameter       [0:0]     OPT_MPY    = 1'b1;
62
        parameter       [0:0]     OPT_EARLY_BRANCHING = 1'b1;
63
        parameter       [0:0]     OPT_DIVIDE = 1'b1;
64
        parameter       [0:0]     OPT_FPU    = 1'b0;
65
        parameter       [0:0]     OPT_CIS    = 1'b1;
66
        parameter       [0:0]     OPT_LOCK   = 1'b1;
67
        parameter       [0:0]     OPT_OPIPE  = 1'b1;
68
        parameter       [0:0]     OPT_SIM    = 1'b0;
69
        localparam              AW = ADDRESS_WIDTH;
70
        //
71
        input   wire [31:0]      i_instruction;
72
        input   wire            i_phase, i_gie;
73
        output  reg             o_illegal;
74
        output  wire    [6:0]    o_dcdR, o_dcdA, o_dcdB;
75
        output  wire    [31:0]   o_I;
76
        output  wire    [3:0]    o_cond;
77
        output  wire            o_wF;
78
        output  wire    [3:0]    o_op;
79
        output  wire            o_ALU, o_M, o_DV, o_FP, o_break;
80
        output  wire            o_lock;
81
        output  wire            o_wR, o_rA, o_rB;
82
        output  wire            o_prepipe;
83
        output  wire            o_sim;
84
        output  wire    [22:0]   o_sim_immv;
85
 
86
 
87
        wire    [4:0]    w_op;
88
        wire            w_ldi, w_mov, w_cmptst, w_ldilo, w_ALU, w_brev,
89
                        w_noop, w_lock, w_sim, w_break, w_special, w_add,
90
                        w_mpy;
91
        wire    [4:0]    w_dcdR, w_dcdB, w_dcdA;
92
        wire            w_dcdR_pc, w_dcdR_cc;
93
        wire            w_dcdA_pc, w_dcdA_cc;
94
        wire            w_dcdB_pc, w_dcdB_cc;
95
        wire    [3:0]    w_cond;
96
        wire            w_wF, w_mem, w_sto, w_div, w_fpu;
97
        wire            w_wR, w_rA, w_rB, w_wR_n;
98
        wire            w_ljmp, w_ljmp_dly, w_cis_ljmp;
99
        wire    [31:0]   iword;
100
        wire            pf_valid;
101
 
102
 
103
        reg     [15:0]   r_nxt_half;
104
 
105
        generate if (OPT_CIS)
106
        begin : SET_IWORD
107
 
108
                assign  iword = ((!i_instruction[`CISBIT])||(i_phase))
109
                        ? i_instruction
110
                        : { 1'b1, i_instruction[14:0], i_instruction[15:0] };
111
 
112
        end else begin : CLR_IWORD
113
 
114
                assign  iword = { 1'b0, i_instruction[30:0] };
115
 
116
        end endgenerate
117
 
118
        generate
119
        if (OPT_EARLY_BRANCHING)
120
        begin
121
                if (OPT_CIS)
122
                begin : CIS_EARLY_BRANCHING
123
 
124
                        assign  w_cis_ljmp = (iword[31:16] == 16'hfcf8);
125
 
126
                end else begin : NOCIS_EARLY_BRANCH
127
 
128
                        assign  w_cis_ljmp = 1'b0;
129
 
130
                end
131
 
132
                assign  w_ljmp = (iword == 32'h7c87c000);
133
 
134
        end else begin : NO_EARLY_BRANCHING
135
 
136
                assign  w_cis_ljmp = 1'b0;
137
                assign  w_ljmp = 1'b0;
138
        end endgenerate
139
 
140
        reg     [4:0]    w_cis_op;
141
 
142
        generate if (OPT_CIS)
143
        begin : GEN_CIS_OP
144
 
145
                always @(*)
146
                if (!iword[`CISBIT])
147
                        w_cis_op = iword[26:22];
148
                else case(iword[26:24])
149
                3'h0: w_cis_op = 5'h00;
150
                3'h1: w_cis_op = 5'h01;
151
                3'h2: w_cis_op = 5'h02;
152
                3'h3: w_cis_op = 5'h10;
153
                3'h4: w_cis_op = 5'h12;
154
                3'h5: w_cis_op = 5'h13;
155
                3'h6: w_cis_op = 5'h18;
156
                3'h7: w_cis_op = 5'h0d;
157
                endcase
158
 
159
        end else begin : GEN_NOCIS_OP
160
 
161
                always @(*)
162
                        w_cis_op = w_op;
163
 
164
        end endgenerate
165
 
166
        // Decode instructions
167
        assign  w_op= iword[26:22];
168
        assign  w_mov    = (w_cis_op      == 5'h0d);
169
        assign  w_ldi    = (w_cis_op[4:1] == 4'hc);
170
        assign  w_brev   = (w_cis_op      == 5'h08);
171
        assign  w_mpy    = (w_cis_op[4:1] == 4'h5)||(w_cis_op[4:0]==5'h0c);
172
        assign  w_cmptst = (w_cis_op[4:1] == 4'h8);
173
        assign  w_ldilo  = (w_cis_op[4:0] == 5'h09);
174
        assign  w_ALU    = (!w_cis_op[4]) // anything with [4]==0, but ...
175
                                &&(w_cis_op[3:1] != 3'h7); // not the divide
176
        assign  w_add    = (w_cis_op[4:0] == 5'h02);
177
        assign  w_mem    = (w_cis_op[4:3] == 2'b10)&&(w_cis_op[2:1] !=2'b00);
178
        assign  w_sto    = (w_mem)&&( w_cis_op[0]);
179
        assign  w_div    = (!iword[`CISBIT])&&(w_op[4:1] == 4'h7);
180
        assign  w_fpu    = (!iword[`CISBIT])&&(w_op[4:3] == 2'b11)
181
                                &&(w_dcdR[3:1] != 3'h7)&&(w_op[2:1] != 2'b00);
182
        // If the result register is either CC or PC, and this would otherwise
183
        // be a floating point instruction with floating point opcode of 0,
184
        // then this is a NOOP.
185
        assign  w_special= (!iword[`CISBIT])&&((!OPT_FPU)||(w_dcdR[3:1]==3'h7))
186
                        &&(w_op[4:2] == 3'b111);
187
        assign  w_break = (w_special)&&(w_op[4:0]==5'h1c);
188
        assign  w_lock  = (w_special)&&(w_op[4:0]==5'h1d);
189
        assign  w_sim   = (w_special)&&(w_op[4:0]==5'h1e);
190
        assign  w_noop  = (w_special)&&(w_op[4:0]==5'h1f);
191
 
192
 
193
        // w_dcdR (4 LUTs)
194
        //
195
        // What register will we be placing results into (if at all)?
196
        //
197
        // Two parts to the result register: the register set, given for
198
        // moves in iword[18] but only for the supervisor, and the other
199
        // four bits encoded in the instruction.
200
        //
201
        assign  w_dcdR = { ((!iword[`CISBIT])&&(w_mov)&&(!i_gie))?iword[`IMMSEL]:i_gie,
202
                                iword[30:27] };
203
 
204
        // dcdB - What register is used in the opB?
205
        //
206
        assign w_dcdB[4] = ((!iword[`CISBIT])&&(w_mov)&&(!i_gie))?iword[13]:i_gie;
207
        assign w_dcdB[3:0]= (iword[`CISBIT])
208
                                ? (((!iword[`CISIMMSEL])&&(iword[26:25]==2'b10))
209
                                        ? `CPU_SP_REG : iword[22:19])
210
                                : iword[17:14];
211
 
212
        // 0 LUTs
213
        assign  w_dcdA = w_dcdR;        // on ZipCPU, A is always result reg
214
        // 2 LUTs, 1 delay each
215
        assign  w_dcdR_pc = (w_dcdR == {i_gie, `CPU_PC_REG});
216
        assign  w_dcdR_cc = (w_dcdR == {i_gie, `CPU_CC_REG});
217
        // 0 LUTs
218
        assign  w_dcdA_pc = w_dcdR_pc;
219
        assign  w_dcdA_cc = w_dcdR_cc;
220
        // 2 LUTs, 1 delays each
221
        assign  w_dcdB_pc = (w_rB)&&(w_dcdB[3:0] == `CPU_PC_REG);
222
        assign  w_dcdB_cc = (w_rB)&&(w_dcdB[3:0] == `CPU_CC_REG);
223
 
224
        //
225
        // Under what condition will we execute this instruction?  Only the
226
        // load immediate instruction and the CIS instructions are completely
227
        // unconditional.  Well ... not quite.  The BREAK, LOCK, and SIM/NOOP
228
        // instructions are also unconditional.
229
        //
230
        assign  w_cond = ((w_ldi)||(w_special)||(iword[`CISBIT])) ? 4'h8 :
231
                        { (iword[21:19]==3'h0), iword[21:19] };
232
 
233
        // rA - do we need to read register A?
234
        assign  w_rA = // Floating point reads reg A
235
                        ((w_fpu)&&(OPT_FPU))
236
                        // Divide's read A
237
                        ||(w_div)
238
                        // ALU ops read A,
239
                        //      except for MOV's and BREV's which don't
240
                        ||((w_ALU)&&(!w_brev)&&(!w_mov))
241
                        // STO's read A
242
                        ||(w_sto)
243
                        // Test/compares
244
                        ||(w_cmptst);
245
        // rB -- do we read a register for operand B?  Specifically, do we
246
        // add the registers value to the immediate to create opB?
247
        assign  w_rB     = (w_mov)
248
                                ||((!iword[`CISBIT])&&(iword[`IMMSEL])&&(!w_ldi)&&(!w_special))
249
                                ||(( iword[`CISBIT])&&(iword[`CISIMMSEL])&&(!w_ldi))
250
                                // If using compressed instruction sets,
251
                                // we *always* read on memory operands.
252
                                ||(( iword[`CISBIT])&&(w_mem));
253
 
254
        // wR -- will we be writing our result back?
255
        // wR_n = !wR
256
        // All but STO, NOOP/BREAK/LOCK, and CMP/TST write back to w_dcdR
257
        assign  w_wR_n   = (w_sto)
258
                                ||(w_special)
259
                                ||(w_cmptst);
260
        assign  w_wR     = !w_wR_n;
261
        //
262
        // wF -- do we write flags when we are done?
263
        //
264
        assign  w_wF     = (w_cmptst)
265
                        ||((w_cond[3])&&(((w_fpu)&&(OPT_FPU))||(w_div)
266
                                ||((w_ALU)&&(!w_mov)&&(!w_ldilo)&&(!w_brev)
267
                                        &&(w_dcdR[3:1] != 3'h7))));
268
 
269
        // Bottom 13 bits: no LUT's
270
        // w_dcd[12: 0] -- no LUTs
271
        // w_dcd[   13] -- 2 LUTs
272
        // w_dcd[17:14] -- (5+i0+i1) = 3 LUTs, 1 delay
273
        // w_dcd[22:18] : 5 LUTs, 1 delay (assuming high bit is o/w determined)
274
        wire    [22:0]   w_I, w_fullI;
275
        wire            w_Iz;
276
 
277
        assign  w_fullI = (w_ldi) ? { iword[22:0] } // LDI
278
                        // MOVE immediates have one less bit
279
                        :((w_mov) ?{ {(23-13){iword[12]}}, iword[12:0] }
280
                        // Normal Op-B immediate ... 18 or 14 bits
281
                        :((!iword[`IMMSEL]) ? { {(23-18){iword[17]}}, iword[17:0] }
282
                        : { {(23-14){iword[13]}}, iword[13:0] }
283
                        ));
284
 
285
        generate if (OPT_CIS)
286
        begin : GEN_CIS_IMMEDIATE
287
                wire    [7:0]    w_halfbits;
288
                assign  w_halfbits = iword[`CISIMMSEL:16];
289
 
290
                wire    [7:0]    w_halfI;
291
                assign  w_halfI = (iword[26:24]==3'h6) ? w_halfbits[7:0] // 8'b for LDI
292
                                :(w_halfbits[7])?
293
                                        { {(6){w_halfbits[2]}}, w_halfbits[1:0]}
294
                                        :{ w_halfbits[6], w_halfbits[6:0] };
295
                assign  w_I  = (iword[`CISBIT])
296
                                ? {{(23-8){w_halfI[7]}}, w_halfI }
297
                                : w_fullI;
298
 
299
        end else begin : GEN_NOCIS_IMMEDIATE
300
 
301
                assign  w_I  = w_fullI;
302
 
303
        end endgenerate
304
 
305
        assign  w_Iz = (w_I == 0);
306
 
307
 
308
        initial o_illegal = 1'b0;
309
        always @(*)
310
        begin
311
                o_illegal <= 1'b0;
312
                if ((!OPT_CIS)&&(i_instruction[`CISBIT]))
313
                        o_illegal <= 1'b1;
314
                if ((!OPT_MPY)&&(w_mpy))
315
                        o_illegal <= 1'b1;
316
 
317
                if ((!OPT_DIVIDE)&&(w_div))
318
                        o_illegal <= 1'b1;
319
                else if ((OPT_DIVIDE)&&(w_div)&&(w_dcdR[3:1]==3'h7))
320
                        o_illegal <= 1'b1;
321
 
322
 
323
                if ((!OPT_FPU)&&(w_fpu))
324
                        o_illegal <= 1'b1;
325
 
326
                if ((!OPT_SIM)&&(w_sim))
327
                        // Simulation instructions on real hardware should
328
                        // always cause an illegal instruction error
329
                        o_illegal <= 1'b1;
330
 
331
                // There are two (missing) special instructions
332
                // These should cause an illegal instruction error
333
                if ((w_dcdR[3:1]==3'h7)&&(w_cis_op[4:1]==4'b1101))
334
                        o_illegal <= 1'b1;
335
 
336
                // If the lock function isn't implemented, this should
337
                // also cause an illegal instruction error
338
                if ((!OPT_LOCK)&&(w_lock))
339
                        o_illegal <= 1'b1;
340
        end
341
 
342
        generate if (OPT_OPIPE)
343
        begin
344
                // o_prepipe is true if a pipelined memory instruction
345
                // might follow this one
346
                assign  o_prepipe =
347
                                ((OPT_CIS)||(!i_instruction[`CISBIT]))
348
                                &&(o_M)&&(o_rB)
349
                                &&(o_dcdB[3:1] != 3'h7)
350
                                &&(o_dcdR[3:1] != 3'h7)
351
                                &&((!o_wR)||(o_dcdR != o_dcdB));
352
        end else begin
353
                assign  o_prepipe = 1'b0;
354
        end endgenerate
355
 
356
        assign  o_dcdR = { w_dcdR_cc, w_dcdR_pc, w_dcdR};
357
        assign  o_dcdA = { w_dcdA_cc, w_dcdA_pc, w_dcdA};
358
        assign  o_dcdB = { w_dcdB_cc, w_dcdB_pc, w_dcdB};
359
        assign  o_I = { {(32-22){w_I[22]}}, w_I[21:0] };
360
        assign  o_cond = w_cond;
361
        assign  o_wF   = w_wF;
362
        assign  o_op   = ((w_ldi)||(w_noop))? 4'hd : w_cis_op[3:0];
363
        assign  o_ALU  =  (w_ALU)||(w_ldi)||(w_cmptst)||(w_noop);
364
        assign  o_M    = w_mem;
365
        assign  o_DV   = (OPT_DIVIDE)&&(w_div);
366
        assign  o_FP   = (OPT_FPU)&&(w_fpu);
367
        assign  o_break= w_break;
368
        assign  o_lock = (OPT_LOCK)&&(w_lock);
369
        assign  o_wR   = w_wR;
370
        assign  o_rA   = w_rA;
371
        assign  o_rB   = w_rB;
372
        assign  o_sim      = (OPT_SIM) ? ((w_sim)||(w_noop)) : 1'b0;
373
        assign  o_sim_immv = (OPT_SIM) ? iword[22:0] : 0;
374
 
375
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.