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

Subversion Repositories xulalx25soc

[/] [xulalx25soc/] [trunk/] [rtl/] [cpu/] [idecode.v] - Blame information for rev 118

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 21 dgisselq
///////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    idecode.v
4
//
5
// Project:     Zip CPU -- a small, lightweight, RISC CPU soft core
6
//
7
// Purpose:     This RTL file specifies how instructions are to be decoded
8 118 dgisselq
//              into their underlying meanings. 
9 21 dgisselq
//
10
//
11
// Creator:     Dan Gisselquist, Ph.D.
12
//              Gisselquist Technology, LLC
13
//
14
///////////////////////////////////////////////////////////////////////////////
15
//
16 98 dgisselq
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
17 21 dgisselq
//
18
// This program is free software (firmware): you can redistribute it and/or
19
// modify it under the terms of  the GNU General Public License as published
20
// by the Free Software Foundation, either version 3 of the License, or (at
21
// your option) any later version.
22
//
23
// This program is distributed in the hope that it will be useful, but WITHOUT
24
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
25
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
26
// for more details.
27
//
28
// License:     GPL, v3, as defined and found on www.gnu.org,
29
//              http://www.gnu.org/licenses/gpl.html
30
//
31
//
32
///////////////////////////////////////////////////////////////////////////////
33
//
34
//
35
//
36
`define CPU_CC_REG      4'he
37
`define CPU_PC_REG      4'hf
38
//
39
`include "cpudefs.v"
40
//
41
//
42
//
43
module  idecode(i_clk, i_rst, i_ce, i_stalled,
44
                i_instruction, i_gie, i_pc, i_pf_valid,
45
                        i_illegal,
46
                o_phase, o_illegal,
47
                o_pc, o_gie,
48
                o_dcdR, o_dcdA, o_dcdB, o_I, o_zI,
49
                o_cond, o_wF,
50
                o_op, o_ALU, o_M, o_DV, o_FP, o_break, o_lock,
51
                o_wR, o_rA, o_rB,
52 26 dgisselq
                o_early_branch, o_branch_pc, o_ljmp,
53 21 dgisselq
                o_pipe
54
                );
55
        parameter       ADDRESS_WIDTH=24, IMPLEMENT_MPY=1, EARLY_BRANCHING=1,
56
                        IMPLEMENT_DIVIDE=1, IMPLEMENT_FPU=0, AW = ADDRESS_WIDTH;
57
        input                   i_clk, i_rst, i_ce, i_stalled;
58
        input   [31:0]           i_instruction;
59
        input                   i_gie;
60
        input   [(AW-1):0]       i_pc;
61
        input                   i_pf_valid, i_illegal;
62
        output  wire            o_phase;
63
        output  reg             o_illegal;
64
        output  reg     [(AW-1):0]       o_pc;
65
        output  reg             o_gie;
66
        output  reg     [6:0]    o_dcdR, o_dcdA, o_dcdB;
67
        output  wire    [31:0]   o_I;
68
        output  reg             o_zI;
69
        output  reg     [3:0]    o_cond;
70
        output  reg             o_wF;
71
        output  reg     [3:0]    o_op;
72 52 dgisselq
        output  reg             o_ALU, o_M, o_DV, o_FP, o_break;
73
        output  wire            o_lock;
74 21 dgisselq
        output  reg             o_wR, o_rA, o_rB;
75
        output  wire            o_early_branch;
76
        output  wire    [(AW-1):0]       o_branch_pc;
77 26 dgisselq
        output  wire            o_ljmp;
78 62 dgisselq
        output  wire            o_pipe;
79 21 dgisselq
 
80
        wire    dcdA_stall, dcdB_stall, dcdF_stall;
81
        wire                    o_dcd_early_branch;
82
        wire    [(AW-1):0]       o_dcd_branch_pc;
83
        reg     o_dcdI, o_dcdIz;
84 52 dgisselq
`ifdef  OPT_PIPELINED
85 86 dgisselq
        reg     r_lock;
86 52 dgisselq
`endif
87 86 dgisselq
`ifdef  OPT_PIPELINED_BUS_ACCESS
88
        reg     r_pipe;
89
`endif
90 21 dgisselq
 
91
 
92
        wire    [4:0]    w_op;
93 62 dgisselq
        wire            w_ldi, w_mov, w_cmptst, w_ldilo, w_ALU, w_brev, w_noop;
94 21 dgisselq
        wire    [4:0]    w_dcdR, w_dcdB, w_dcdA;
95
        wire            w_dcdR_pc, w_dcdR_cc;
96
        wire            w_dcdA_pc, w_dcdA_cc;
97
        wire            w_dcdB_pc, w_dcdB_cc;
98
        wire    [3:0]    w_cond;
99
        wire            w_wF, w_dcdM, w_dcdDV, w_dcdFP;
100
        wire            w_wR, w_rA, w_rB, w_wR_n;
101 113 dgisselq
        wire            w_ljmp, w_ljmp_dly;
102 50 dgisselq
        wire    [31:0]   iword;
103 21 dgisselq
 
104
 
105
`ifdef  OPT_VLIW
106
        reg     [16:0]   r_nxt_half;
107
        assign  iword = (o_phase)
108
                                // set second half as a NOOP ... but really 
109
                                // shouldn't matter
110
                        ? { r_nxt_half[16:7], 1'b0, r_nxt_half[6:0], 5'b11000, 3'h7, 6'h00 }
111
                        : i_instruction;
112
`else
113
        assign  iword = { 1'b0, i_instruction[30:0] };
114
`endif
115
 
116 50 dgisselq
        generate
117
        if (EARLY_BRANCHING != 0)
118
                assign  w_ljmp = (iword == 32'h7c87c000);
119
        else
120
                assign  w_ljmp = 1'b0;
121
        endgenerate
122
 
123
 
124 21 dgisselq
        assign  w_op= iword[26:22];
125
        assign  w_mov    = (w_op      == 5'h0f);
126
        assign  w_ldi    = (w_op[4:1] == 4'hb);
127 51 dgisselq
        assign  w_brev   = (w_op      == 5'hc);
128 21 dgisselq
        assign  w_cmptst = (w_op[4:1] == 4'h8);
129 52 dgisselq
        assign  w_ldilo  = (w_op[4:0] == 5'h9);
130 21 dgisselq
        assign  w_ALU    = (~w_op[4]);
131
 
132
        // 4 LUTs
133 62 dgisselq
        //
134
        // Two parts to the result register: the register set, given for
135
        // moves in i_word[18] but only for the supervisor, and the other
136
        // four bits encoded in the instruction.
137
        //
138 21 dgisselq
        assign  w_dcdR = { ((~iword[31])&&(w_mov)&&(~i_gie))?iword[18]:i_gie,
139
                                iword[30:27] };
140 62 dgisselq
        // 2 LUTs
141
        //
142
        // If the result register is either CC or PC, and this would otherwise
143
        // be a floating point instruction with floating point opcode of 0,
144
        // then this is a NOOP.
145 113 dgisselq
        assign  w_noop   = (w_op[4:0] == 5'h18)&&(
146
                        ((IMPLEMENT_FPU>0)&&(w_dcdR[3:1] == 3'h7))
147
                        ||(IMPLEMENT_FPU==0));
148 62 dgisselq
 
149 21 dgisselq
        // 4 LUTs
150
        assign  w_dcdB = { ((~iword[31])&&(w_mov)&&(~i_gie))?iword[13]:i_gie,
151
                                iword[17:14] };
152
 
153
        // 0 LUTs
154
        assign  w_dcdA = w_dcdR;
155
        // 2 LUTs, 1 delay each
156
        assign  w_dcdR_pc = (w_dcdR == {i_gie, `CPU_PC_REG});
157
        assign  w_dcdR_cc = (w_dcdR == {i_gie, `CPU_CC_REG});
158
        // 0 LUTs
159
        assign  w_dcdA_pc = w_dcdR_pc;
160
        assign  w_dcdA_cc = w_dcdR_cc;
161
        // 2 LUTs, 1 delays each
162
        assign  w_dcdB_pc = (w_dcdB[3:0] == `CPU_PC_REG);
163
        assign  w_dcdB_cc = (w_dcdB[3:0] == `CPU_CC_REG);
164
 
165
        // Under what condition will we execute this
166
        // instruction?  Only the load immediate instruction
167
        // is completely unconditional.
168
        //
169
        // 3+4 LUTs
170
        assign  w_cond = (w_ldi) ? 4'h8 :
171
                        (iword[31])?{(iword[20:19]==2'b00),
172
                                        1'b0,iword[20:19]}
173
                        : { (iword[21:19]==3'h0), iword[21:19] };
174
 
175
        // 1 LUT
176
        assign  w_dcdM    = (w_op[4:1] == 4'h9);
177
        // 1 LUT
178
        assign  w_dcdDV   = (w_op[4:1] == 4'ha);
179
        // 1 LUT
180
        assign  w_dcdFP   = (w_op[4:3] == 2'b11)&&(w_dcdR[3:1] != 3'h7);
181
        // 4 LUT's--since it depends upon FP/NOOP condition (vs 1 before)
182
        //      Everything reads A but ... NOOP/BREAK/LOCK, LDI, LOD, MOV
183
        assign  w_rA     = (w_dcdFP)
184
                                // Divide's read A
185
                                ||(w_dcdDV)
186
                                // ALU read's A, unless it's a MOV to A
187
                                // This includes LDIHI/LDILO
188
                                ||((~w_op[4])&&(w_op[3:0]!=4'hf))
189
                                // STO's read A
190
                                ||((w_dcdM)&&(w_op[0]))
191
                                // Test/compares
192
                                ||(w_op[4:1]== 4'h8);
193
        // 1 LUTs -- do we read a register for operand B?  Specifically, do
194
        // we need to stall if the register is not (yet) ready?
195 52 dgisselq
        assign  w_rB     = (w_mov)||((iword[18])&&(~w_ldi));
196 21 dgisselq
        // 1 LUT: All but STO, NOOP/BREAK/LOCK, and CMP/TST write back to w_dcdR
197
        assign  w_wR_n   = ((w_dcdM)&&(w_op[0]))
198
                                ||((w_op[4:3]==2'b11)&&(w_dcdR[3:1]==3'h7))
199
                                ||(w_cmptst);
200
        assign  w_wR     = ~w_wR_n;
201 23 dgisselq
        //
202
        // 1-output bit (5 Opcode bits, 4 out-reg bits, 3 condition bits)
203 21 dgisselq
        //      
204
        //      This'd be 4 LUTs, save that we have the carve out for NOOPs
205 23 dgisselq
        //      and writes to the PC/CC register(s).
206 21 dgisselq
        assign  w_wF     = (w_cmptst)
207
                        ||((w_cond[3])&&((w_dcdFP)||(w_dcdDV)
208 52 dgisselq
                                ||((w_ALU)&&(~w_mov)&&(~w_ldilo)&&(~w_brev)
209 23 dgisselq
                                        &&(iword[30:28] != 3'h7))));
210 21 dgisselq
 
211
        // Bottom 13 bits: no LUT's
212
        // w_dcd[12: 0] -- no LUTs
213
        // w_dcd[   13] -- 2 LUTs
214
        // w_dcd[17:14] -- (5+i0+i1) = 3 LUTs, 1 delay
215
        // w_dcd[22:18] : 5 LUTs, 1 delay (assuming high bit is o/w determined)
216
        reg     [22:0]   r_I;
217
        wire    [22:0]   w_I, w_fullI;
218
        wire            w_Iz;
219
 
220
        assign  w_fullI = (w_ldi) ? { iword[22:0] } // LDI
221
                        :((w_mov) ?{ {(23-13){iword[12]}}, iword[12:0] } // Move
222
                        :((~iword[18]) ? { {(23-18){iword[17]}}, iword[17:0] }
223
                        : { {(23-14){iword[13]}}, iword[13:0] }
224
                        ));
225
 
226
`ifdef  OPT_VLIW
227
        wire    [5:0]    w_halfI;
228
        assign  w_halfI = (w_ldi) ? iword[5:0]
229
                                :((iword[5]) ? 6'h00 : {iword[4],iword[4:0]});
230
        assign  w_I  = (iword[31])? {{(23-6){w_halfI[5]}}, w_halfI }:w_fullI;
231
`else
232
        assign  w_I  = w_fullI;
233
`endif
234
        assign  w_Iz = (w_I == 0);
235
 
236
 
237
`ifdef  OPT_VLIW
238
        //
239
        // The o_phase parameter is special.  It needs to let the software
240
        // following know that it cannot break/interrupt on an o_phase asserted
241
        // instruction, lest the break take place between the first and second
242
        // half of a VLIW instruction.  To do this, o_phase must be asserted
243
        // when the first instruction half is valid, but not asserted on either
244
        // a 32-bit instruction or the second half of a 2x16-bit instruction.
245
        reg     r_phase;
246
        initial r_phase = 1'b0;
247
        always @(posedge i_clk)
248 113 dgisselq
                if ((i_rst) // When no instruction is in the pipe, phase is zero
249
                        ||(o_early_branch)||(w_ljmp_dly))
250 21 dgisselq
                        r_phase <= 1'b0;
251 113 dgisselq
                else if ((i_ce)&&(i_pf_valid))
252 21 dgisselq
                        r_phase <= (o_phase)? 1'b0:(i_instruction[31]);
253
        // Phase is '1' on the first instruction of a two-part set
254
        // But, due to the delay in processing, it's '1' when our output is
255
        // valid for that first part, but that'll be the same time we
256
        // are processing the second part ... so it may look to us like a '1'
257
        // on the second half of processing.
258
 
259
        assign  o_phase = r_phase;
260
`else
261
        assign  o_phase = 1'b0;
262
`endif
263
 
264
 
265
        initial o_illegal = 1'b0;
266
        always @(posedge i_clk)
267
                if (i_rst)
268
                        o_illegal <= 1'b0;
269
                else if (i_ce)
270
                begin
271
`ifdef  OPT_VLIW
272
                        o_illegal <= (i_illegal);
273
`else
274
                        o_illegal <= ((i_illegal) || (i_instruction[31]));
275
`endif
276 113 dgisselq
                        if ((IMPLEMENT_MPY==0)&&((w_op[4:1]==4'h5)||(w_op[4:0]==5'h08)))
277 21 dgisselq
                                o_illegal <= 1'b1;
278
 
279
                        if ((IMPLEMENT_DIVIDE==0)&&(w_dcdDV))
280
                                o_illegal <= 1'b1;
281
                        else if ((IMPLEMENT_DIVIDE!=0)&&(w_dcdDV)&&(w_dcdR[3:1]==3'h7))
282
                                o_illegal <= 1'b1;
283
 
284
 
285
                        if ((IMPLEMENT_FPU!=0)&&(w_dcdFP)&&(w_dcdR[3:1]==3'h7))
286
                                o_illegal <= 1'b1;
287
                        else if ((IMPLEMENT_FPU==0)&&(w_dcdFP))
288
                                o_illegal <= 1'b1;
289
 
290
                        if ((w_op[4:3]==2'b11)&&(w_dcdR[3:1]==3'h7)
291
                                &&(
292 52 dgisselq
                                        (w_op[2:0] != 3'h1)      // BREAK
293
`ifdef  OPT_PIPELINED
294
                                        &&(w_op[2:0] != 3'h2)    // LOCK
295
`endif
296 21 dgisselq
                                        &&(w_op[2:0] != 3'h0)))  // NOOP
297
                                o_illegal <= 1'b1;
298
                end
299
 
300
 
301
        always @(posedge i_clk)
302
                if (i_ce)
303
                begin
304
`ifdef  OPT_VLIW
305
                        if (~o_phase)
306
                        begin
307
                                o_gie<= i_gie;
308
                                // i.e. dcd_pc+1
309
                                o_pc <= i_pc+{{(AW-1){1'b0}},1'b1};
310
                        end
311
`else
312
                        o_gie<= i_gie;
313
                        o_pc <= i_pc+{{(AW-1){1'b0}},1'b1};
314
`endif
315
 
316
                        // Under what condition will we execute this
317
                        // instruction?  Only the load immediate instruction
318
                        // is completely unconditional.
319
                        o_cond <= w_cond;
320
                        // Don't change the flags on conditional instructions,
321
                        // UNLESS: the conditional instruction was a CMP
322
                        // or TST instruction.
323
                        o_wF <= w_wF;
324
 
325
                        // Record what operation/op-code (4-bits) we are doing
326
                        //      Note that LDI magically becomes a MOV
327
                        //      instruction here.  That way it's a pass through
328
                        //      the ALU.  Likewise, the two compare instructions
329
                        //      CMP and TST becomes SUB and AND here as well.
330
                        // We keep only the bottom four bits, since we've
331
                        // already done the rest of the decode necessary to 
332
                        // settle between the other instructions.  For example,
333
                        // o_FP plus these four bits uniquely defines the FP
334
                        // instruction, o_DV plus the bottom of these defines
335
                        // the divide, etc.
336 62 dgisselq
                        o_op <= (w_ldi)||(w_noop)? 4'hf:w_op[3:0];
337 21 dgisselq
 
338
                        // Default values
339
                        o_dcdR <= { w_dcdR_cc, w_dcdR_pc, w_dcdR};
340
                        o_dcdA <= { w_dcdA_cc, w_dcdA_pc, w_dcdA};
341
                        o_dcdB <= { w_dcdB_cc, w_dcdB_pc, w_dcdB};
342
                        o_wR  <= w_wR;
343
                        o_rA  <= w_rA;
344
                        o_rB  <= w_rB;
345
                        r_I    <= w_I;
346
                        o_zI   <= w_Iz;
347
 
348 62 dgisselq
                        // Turn a NOOP into an ALU operation--subtract in 
349
                        // particular, although it doesn't really matter as long
350
                        // as it doesn't take longer than one clock.  Note
351
                        // also that this depends upon not setting any registers
352
                        // or flags, which should already be true.
353
                        o_ALU  <=  (w_ALU)||(w_ldi)||(w_cmptst)||(w_noop); // 2 LUT
354 21 dgisselq
                        o_M    <=  w_dcdM;
355
                        o_DV   <=  w_dcdDV;
356
                        o_FP   <=  w_dcdFP;
357 113 dgisselq
 
358
                        o_break <= (w_op[4:0]==5'b11001)&&(
359
                                ((IMPLEMENT_FPU>0)&&(w_dcdR[3:1]==3'h7))
360
                                ||(IMPLEMENT_FPU==0));
361 52 dgisselq
`ifdef  OPT_PIPELINED
362 113 dgisselq
                        r_lock  <= (w_op[4:0]==5'b11010)&&(
363
                                ((IMPLEMENT_FPU>0)&&(w_dcdR[3:1]==3'h7))
364
                                ||(IMPLEMENT_FPU==0));
365 52 dgisselq
`endif
366 21 dgisselq
`ifdef  OPT_VLIW
367
                        r_nxt_half <= { iword[31], iword[13:5],
368
                                ((iword[21])? iword[20:19] : 2'h0),
369
                                iword[4:0] };
370
`endif
371
                end
372
 
373 52 dgisselq
`ifdef  OPT_PIPELINED
374
        assign  o_lock = r_lock;
375
`else
376
        assign  o_lock = 1'b0;
377
`endif
378
 
379 21 dgisselq
        generate
380
        if (EARLY_BRANCHING!=0)
381
        begin
382 26 dgisselq
                reg                     r_early_branch, r_ljmp;
383 21 dgisselq
                reg     [(AW-1):0]       r_branch_pc;
384 26 dgisselq
 
385
                initial r_ljmp = 1'b0;
386 21 dgisselq
                always @(posedge i_clk)
387 26 dgisselq
                        if (i_rst)
388
                                r_ljmp <= 1'b0;
389
                        else if ((i_ce)&&(i_pf_valid))
390
                                r_ljmp <= (w_ljmp);
391
                assign  o_ljmp = r_ljmp;
392
 
393
                always @(posedge i_clk)
394
                if (i_rst)
395
                        r_early_branch <= 1'b0;
396
                else if ((i_ce)&&(i_pf_valid))
397 23 dgisselq
                begin
398 26 dgisselq
                        if (r_ljmp)
399
                                // LOD (PC),PC
400
                                r_early_branch <= 1'b1;
401
                        else if ((~iword[31])&&(iword[30:27]==`CPU_PC_REG)&&(w_cond[3]))
402 21 dgisselq
                        begin
403 23 dgisselq
                                if (w_op[4:1] == 4'hb) // LDI to PC
404 26 dgisselq
                                        // LDI x,PC
405 21 dgisselq
                                        r_early_branch     <= 1'b1;
406 26 dgisselq
                                else if ((w_op[4:0]==5'h02)&&(~iword[18]))
407
                                        // Add x,PC
408 21 dgisselq
                                        r_early_branch     <= 1'b1;
409 26 dgisselq
                                else begin
410 21 dgisselq
                                        r_early_branch     <= 1'b0;
411
                                end
412 23 dgisselq
                        end else
413
                                r_early_branch <= 1'b0;
414 26 dgisselq
                end else if (i_ce)
415
                        r_early_branch <= 1'b0;
416
 
417 21 dgisselq
                always @(posedge i_clk)
418
                        if (i_ce)
419
                        begin
420 26 dgisselq
                                if (r_ljmp)
421
                                        r_branch_pc <= iword[(AW-1):0];
422
                                else if (w_op[4:1] == 4'hb) // LDI
423 23 dgisselq
                                        r_branch_pc <= {{(AW-23){iword[22]}},iword[22:0]};
424
                                else // Add x,PC
425
                                r_branch_pc <= i_pc
426 26 dgisselq
                                        + {{(AW-17){iword[17]}},iword[16:0]}
427 23 dgisselq
                                        + {{(AW-1){1'b0}},1'b1};
428 21 dgisselq
                        end
429
 
430 113 dgisselq
                assign  w_ljmp_dly         = r_ljmp;
431 21 dgisselq
                assign  o_early_branch     = r_early_branch;
432
                assign  o_branch_pc        = r_branch_pc;
433
        end else begin
434 113 dgisselq
                assign  w_ljmp_dly         = 1'b0;
435 21 dgisselq
                assign  o_early_branch = 1'b0;
436
                assign  o_branch_pc = {(AW){1'b0}};
437 26 dgisselq
                assign  o_ljmp = 1'b0;
438 21 dgisselq
        end endgenerate
439
 
440
 
441
        // To be a pipeable operation there must be ...
442
        //      1. Two valid adjacent instructions
443
        //      2. Both must be memory operations, of the same time (both lods
444
        //              or both stos)
445
        //      3. Both must use the same register base address
446
        //      4. Both must be to the same address, or the address incremented
447
        //              by one
448
        // Note that we're not using iword here ... there's a lot of logic
449
        // taking place, and it's only valid if the new word is not compressed.
450
        //
451
        reg     r_valid;
452 86 dgisselq
`ifdef  OPT_PIPELINED_BUS_ACCESS
453 62 dgisselq
        initial r_pipe = 1'b0;
454 21 dgisselq
        always @(posedge i_clk)
455
                if (i_ce)
456 62 dgisselq
                        r_pipe <= (r_valid)&&(i_pf_valid)&&(~i_instruction[31])
457 21 dgisselq
                                &&(w_dcdM)&&(o_M)&&(o_op[0] ==i_instruction[22])
458
                                &&(i_instruction[17:14] == o_dcdB[3:0])
459 51 dgisselq
                                &&(i_instruction[17:14] != o_dcdA[3:0])
460 21 dgisselq
                                &&(i_gie == o_gie)
461
                                &&((i_instruction[21:19]==o_cond[2:0])
462
                                        ||(o_cond[2:0] == 3'h0))
463
                                &&((i_instruction[13:0]==r_I[13:0])
464
                                        ||({1'b0, i_instruction[13:0]}==(r_I[13:0]+14'h1)));
465 62 dgisselq
        assign o_pipe = r_pipe;
466
`else
467
        assign o_pipe = 1'b0;
468
`endif
469
 
470 21 dgisselq
        always @(posedge i_clk)
471
                if (i_rst)
472
                        r_valid <= 1'b0;
473 26 dgisselq
                else if ((i_ce)&&(o_ljmp))
474
                        r_valid <= 1'b0;
475 21 dgisselq
                else if ((i_ce)&&(i_pf_valid))
476
                        r_valid <= 1'b1;
477
                else if (~i_stalled)
478
                        r_valid <= 1'b0;
479
 
480
 
481
        assign  o_I = { {(32-22){r_I[22]}}, r_I[21:0] };
482
 
483
endmodule

powered by: WebSVN 2.1.0

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