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

Subversion Repositories navre

[/] [navre/] [trunk/] [softusb_navre.v] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 lekernel
/*
2
 * Milkymist VJ SoC
3
 * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
4
 *
5
 * This program is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation, version 3 of the License.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
 */
17
 
18
module softusb_navre #(
19
        parameter pmem_width = 11, /* < in 16-bit instructions */
20
        parameter dmem_width = 13  /* < in bytes */
21
) (
22
        input clk,
23
        input rst,
24
 
25
        output reg pmem_ce,
26
        output [pmem_width-1:0] pmem_a,
27
        input [15:0] pmem_d,
28
 
29
        output reg dmem_we,
30
        output reg [dmem_width-1:0] dmem_a,
31
        input [7:0] dmem_di,
32
        output reg [7:0] dmem_do,
33
 
34
        output reg io_re,
35
        output reg io_we,
36
        output [5:0] io_a,
37
        output [7:0] io_do,
38
        input [7:0] io_di
39
);
40
 
41
/* Register file */
42
reg [pmem_width-1:0] PC;
43
reg [7:0] GPR[0:23];
44
reg [15:0] U;    /* < R24-R25 */
45
reg [15:0] pX;   /* < R26-R27 */
46
reg [15:0] pY;   /* < R28-R29 */
47
reg [15:0] pZ;   /* < R30-R31 */
48
reg T, H, S, V, N, Z, C;
49
 
50
/* Stack */
51
reg [7:0] io_sp;
52
reg [15:0] SP;
53
reg push;
54
reg pop;
55
always @(posedge clk) begin
56
        if(rst) begin
57
                io_sp <= 8'd0;
58
                SP <= 16'd0;
59
        end else begin
60
                io_sp <= io_a[0] ? SP[7:0] : SP[15:8];
61
                if((io_a == 6'b111101) | (io_a == 6'b111110)) begin
62
                        if(io_we) begin
63
                                if(io_a[0])
64
                                        SP[7:0] <= io_do;
65
                                else
66
                                        SP[15:8] <= io_do;
67
                        end
68
                end
69
                if(push)
70
                        SP <= SP - 16'd1;
71
                if(pop)
72
                        SP <= SP + 16'd1;
73
        end
74
end
75
 
76
/* I/O mapped registers */
77
 
78
parameter IO_SEL_EXT    = 2'd0;
79
parameter IO_SEL_STACK  = 2'd1;
80
parameter IO_SEL_SREG   = 2'd2;
81
 
82
reg [1:0] io_sel;
83
always @(posedge clk) begin
84
        if(rst)
85
                io_sel <= IO_SEL_EXT;
86
        else begin
87
                case(io_a)
88
                        6'b111101,
89
                        6'b111110: io_sel <= IO_SEL_STACK;
90
                        6'b111111: io_sel <= IO_SEL_SREG;
91
                        default: io_sel <= IO_SEL_EXT;
92
                endcase
93
        end
94
end
95
 
96
/* Register operations */
97
wire immediate = (pmem_d[14]
98
        | (pmem_d[15:12] == 4'b0011))           /* CPI */
99
        & (pmem_d[15:10] != 6'b111111);         /* SBRC - SBRS */
100
reg lpm_en;
101
wire [4:0] Rd = lpm_en ? 5'd0 : {immediate | pmem_d[8], pmem_d[7:4]};
102
wire [4:0] Rr = {pmem_d[9], pmem_d[3:0]};
103
wire [7:0] K = {pmem_d[11:8], pmem_d[3:0]};
104
wire [2:0] b = pmem_d[2:0];
105
wire [11:0] Kl = pmem_d[11:0];
106
wire [6:0] Ks = pmem_d[9:3];
107
wire [1:0] Rd16 = pmem_d[5:4];
108
wire [5:0] K16 = {pmem_d[7:6], pmem_d[3:0]};
109
wire [5:0] q = {pmem_d[13], pmem_d[11:10], pmem_d[2:0]};
110
 
111
wire [7:0] GPR_Rd8 = GPR[Rd];
112
wire [7:0] GPR_Rr8 = GPR[Rr];
113
reg [7:0] GPR_Rd;
114
always @(*) begin
115
        case(Rd)
116
                default: GPR_Rd = GPR_Rd8;
117
                5'd24: GPR_Rd = U[7:0];
118
                5'd25: GPR_Rd = U[15:8];
119
                5'd26: GPR_Rd = pX[7:0];
120
                5'd27: GPR_Rd = pX[15:8];
121
                5'd28: GPR_Rd = pY[7:0];
122
                5'd29: GPR_Rd = pY[15:8];
123
                5'd30: GPR_Rd = pZ[7:0];
124
                5'd31: GPR_Rd = pZ[15:8];
125
        endcase
126
end
127
reg [7:0] GPR_Rr;
128
always @(*) begin
129
        case(Rr)
130
                default: GPR_Rr = GPR_Rr8;
131
                5'd24: GPR_Rr = U[7:0];
132
                5'd25: GPR_Rr = U[15:8];
133
                5'd26: GPR_Rr = pX[7:0];
134
                5'd27: GPR_Rr = pX[15:8];
135
                5'd28: GPR_Rr = pY[7:0];
136
                5'd29: GPR_Rr = pY[15:8];
137
                5'd30: GPR_Rr = pZ[7:0];
138
                5'd31: GPR_Rr = pZ[15:8];
139
        endcase
140
end
141
wire GPR_Rd_b = GPR_Rd[b];
142
 
143
reg [15:0] GPR_Rd16;
144
always @(*) begin
145
        case(Rd16)
146
                2'd0: GPR_Rd16 = U;
147
                2'd1: GPR_Rd16 = pX;
148
                2'd2: GPR_Rd16 = pY;
149
                2'd3: GPR_Rd16 = pZ;
150
        endcase
151
end
152
 
153
/* Memorize values to support 16-bit instructions */
154
reg regmem_ce;
155
 
156
reg [4:0] Rd_r;
157
reg [7:0] GPR_Rd_r;
158
always @(posedge clk) begin
159
        if(regmem_ce)
160
                Rd_r <= Rd; /* < control with regmem_ce */
161
        GPR_Rd_r <= GPR_Rd; /* < always loaded */
162
end
163
 
164
/* PC */
165
 
166
reg [3:0] pc_sel;
167
 
168
parameter PC_SEL_NOP            = 4'd0;
169
parameter PC_SEL_INC            = 4'd1;
170
parameter PC_SEL_KL             = 4'd2;
171
parameter PC_SEL_KS             = 4'd3;
172
parameter PC_SEL_DMEML          = 4'd4;
173
parameter PC_SEL_DMEMH          = 4'd6;
174
parameter PC_SEL_DEC            = 4'd7;
175
parameter PC_SEL_Z              = 4'd7;
176
 
177
always @(posedge clk) begin
178
        if(rst) begin
179
                PC <= 0;
180
        end else begin
181
                case(pc_sel)
182
                        PC_SEL_NOP:;
183
                        PC_SEL_INC: PC <= PC + 1;
184
                        // !!! WARNING !!! replace with PC <= PC + {{pmem_width-12{Kl[11]}}, Kl}; if pmem_width>12
185
                        PC_SEL_KL: PC <= PC + Kl;
186
                        PC_SEL_KS: PC <= PC + {{pmem_width-7{Ks[6]}}, Ks};
187
                        PC_SEL_DMEML: PC[7:0] <= dmem_di;
188
                        PC_SEL_DMEMH: PC[pmem_width-1:8] <= dmem_di;
189
                        PC_SEL_DEC: PC <= PC - 1;
190
                        PC_SEL_Z: PC <= pZ - 1;
191
                endcase
192
        end
193
end
194
reg pmem_selz;
195
assign pmem_a = rst ? 0 : (pmem_selz ? pZ[15:1] : PC + 1);
196
 
197
/* Load/store operations */
198
reg [3:0] dmem_sel;
199
 
200
parameter DMEM_SEL_UNDEFINED    = 3'bxxx;
201
parameter DMEM_SEL_X            = 4'd0;
202
parameter DMEM_SEL_XPLUS        = 4'd1;
203
parameter DMEM_SEL_XMINUS       = 4'd2;
204
parameter DMEM_SEL_YPLUS        = 4'd3;
205
parameter DMEM_SEL_YMINUS       = 4'd4;
206
parameter DMEM_SEL_YQ           = 4'd5;
207
parameter DMEM_SEL_ZPLUS        = 4'd6;
208
parameter DMEM_SEL_ZMINUS       = 4'd7;
209
parameter DMEM_SEL_ZQ           = 4'd8;
210
parameter DMEM_SEL_SP_R         = 4'd9;
211
parameter DMEM_SEL_SP_PCL       = 4'd10;
212
parameter DMEM_SEL_SP_PCH       = 4'd11;
213
parameter DMEM_SEL_PMEM         = 4'd12;
214
 
215
/* ALU */
216
 
217
reg normal_en;
218
reg lds_writeback;
219
 
220
wire [4:0] write_dest = lds_writeback ? Rd_r : Rd;
221
 
222
// synthesis translate_off
223
integer i_rst_regf;
224
// synthesis translate_on
225
reg [7:0] R;
226
reg writeback;
227
reg update_nsz;
228
reg [15:0] R16;
229
reg mode16;
230
always @(posedge clk) begin
231
        R = 8'hxx;
232
        writeback = 1'b0;
233
        update_nsz = 1'b0;
234
        R16 = 16'hxxxx;
235
        mode16 = 1'b0;
236
        if(rst) begin
237
                /*
238
                 * Not resetting the register file enables the use of more efficient
239
                 * distributed block RAM.
240
                 */
241
                // synthesis translate_off
242
                for(i_rst_regf=0;i_rst_regf<24;i_rst_regf=i_rst_regf+1)
243
                        GPR[i_rst_regf] = 8'd0;
244
                U = 16'd0;
245
                pX = 16'd0;
246
                pY = 16'd0;
247
                pZ = 16'd0;
248
                // synthesis translate_on
249
                T = 1'b0;
250
                H = 1'b0;
251
                S = 1'b0;
252
                V = 1'b0;
253
                N = 1'b0;
254
                Z = 1'b0;
255
                C = 1'b0;
256
        end else begin
257
                if(normal_en) begin
258
                        writeback = 1'b1;
259
                        update_nsz = 1'b1;
260
                        casex(pmem_d)
261
                                16'b000x_11xx_xxxx_xxxx: begin
262
                                        /* ADD - ADC */
263
                                        {C, R} = GPR_Rd + GPR_Rr + (pmem_d[12] & C);
264
                                        H = (GPR_Rd[3] & GPR_Rr[3])|(GPR_Rr[3] & ~R[3])|(~R[3] & GPR_Rd[3]);
265
                                        V = (GPR_Rd[7] & GPR_Rr[7] & ~R[7])|(~GPR_Rd[7] & ~GPR_Rr[7] & R[7]);
266
                                end
267
                                16'b000x_10xx_xxxx_xxxx, /* subtract */
268
                                16'b000x_01xx_xxxx_xxxx: /* compare  */ begin
269
                                        /* SUB - SBC / CP - CPC */
270
                                        {C, R} = GPR_Rd - GPR_Rr - (~pmem_d[12] & C);
271
                                        H = (~GPR_Rd[3] & GPR_Rr[3])|(GPR_Rr[3] & R[3])|(R[3] & ~GPR_Rd[3]);
272
                                        V = (GPR_Rd[7] & ~GPR_Rr[7] & ~R[7])|(~GPR_Rd[7] & GPR_Rr[7] & R[7]);
273
                                        writeback = pmem_d[11];
274
                                end
275
                                16'b010x_xxxx_xxxx_xxxx, /* subtract */
276
                                16'b0011_xxxx_xxxx_xxxx: /* compare  */ begin
277
                                        /* SUBI - SBCI / CPI */
278
                                        {C, R} = GPR_Rd - K - (~pmem_d[12] & C);
279
                                        H = (~GPR_Rd[3] & K[3])|(K[3] & R[3])|(R[3] & ~GPR_Rd[3]);
280
                                        V = (GPR_Rd[7] & ~K[7] & ~R[7])|(~GPR_Rd[7] & K[7] & R[7]);
281
                                        writeback = pmem_d[14];
282
                                end
283
                                16'b0010_00xx_xxxx_xxxx: begin
284
                                        /* AND */
285
                                        R = GPR_Rd & GPR_Rr;
286
                                        V = 1'b0;
287
                                end
288
                                16'b0111_xxxx_xxxx_xxxx: begin
289
                                        /* ANDI */
290
                                        R = GPR_Rd & K;
291
                                        V = 1'b0;
292
                                end
293
                                16'b0010_10xx_xxxx_xxxx: begin
294
                                        /* OR */
295
                                        R = GPR_Rd | GPR_Rr;
296
                                        V = 1'b0;
297
                                end
298
                                16'b0110_xxxx_xxxx_xxxx: begin
299
                                        /* ORI */
300
                                        R = GPR_Rd | K;
301
                                        V = 1'b0;
302
                                end
303
                                16'b0010_01xx_xxxx_xxxx: begin
304
                                        /* EOR */
305
                                        R = GPR_Rd ^ GPR_Rr;
306
                                        V = 1'b0;
307
                                end
308
                                16'b1001_010x_xxxx_0000: begin
309
                                        /* COM */
310
                                        R = ~GPR_Rd;
311
                                        V = 1'b0;
312
                                        C = 1'b1;
313
                                end
314
                                16'b1001_010x_xxxx_0001: begin
315
                                        /* NEG */
316
                                        {C, R} = 8'h00 - GPR_Rd;
317
                                        H = R[3] | GPR_Rd[3];
318
                                        V = R == 8'h80;
319
                                end
320
                                16'b1001_010x_xxxx_0011: begin
321
                                        /* INC */
322
                                        R = GPR_Rd + 8'd1;
323
                                        V = R == 8'h80;
324
                                end
325
                                16'b1001_010x_xxxx_1010: begin
326
                                        /* DEC */
327
                                        R = GPR_Rd - 8'd1;
328
                                        V = R == 8'h7f;
329
                                end
330
                                16'b1001_010x_xxxx_011x: begin
331
                                        /* LSR - ROR */
332
                                        R = {pmem_d[0] & C, GPR_Rd[7:1]};
333
                                        C = GPR_Rd[0];
334
                                        V = R[7] ^ GPR_Rd[0];
335
                                end
336
                                16'b1001_010x_xxxx_0101: begin
337
                                        /* ASR */
338
                                        R = {GPR_Rd[7], GPR_Rd[7:1]};
339
                                        C = GPR_Rd[0];
340
                                        V = R[7] ^ GPR_Rd[0];
341
                                end
342
                                16'b1001_010x_xxxx_0010: begin
343
                                        /* SWAP */
344
                                        R = {GPR_Rd[3:0], GPR_Rd[7:4]};
345
                                        update_nsz = 1'b0;
346
                                end
347
                                16'b1001_010x_xxxx_1000: begin
348
                                        /* BSET - BCLR */
349
                                        case(pmem_d[7:4])
350
                                                4'b0000: C = 1'b1;
351
                                                4'b0001: Z = 1'b1;
352
                                                4'b0010: N = 1'b1;
353
                                                4'b0011: V = 1'b1;
354
                                                4'b0100: S = 1'b1;
355
                                                4'b0101: H = 1'b1;
356
                                                4'b0110: T = 1'b1;
357
                                                4'b1000: C = 1'b0;
358
                                                4'b1001: Z = 1'b0;
359
                                                4'b1010: N = 1'b0;
360
                                                4'b1011: V = 1'b0;
361
                                                4'b1100: S = 1'b0;
362
                                                4'b1101: H = 1'b0;
363
                                                4'b1110: T = 1'b0;
364
                                        endcase
365
                                        update_nsz = 1'b0;
366
                                        writeback = 1'b0;
367
                                end
368
                                16'b1001_011x_xxxx_xxxx: begin
369
                                        mode16 = 1'b1;
370
                                        if(pmem_d[8]) begin
371
                                                /* SBIW */
372
                                                {C, R16} = GPR_Rd16 - K16;
373
                                                V = GPR_Rd16[15] & ~R16[15];
374
                                        end else begin
375
                                                /* ADIW */
376
                                                {C, R16} = GPR_Rd16 + K16;
377
                                                V = ~GPR_Rd16[15] & R16[15];
378
                                        end
379
                                end
380
                                /* SBR and CBR are replaced with ORI and ANDI */
381
                                /* TST is replaced with AND */
382
                                /* CLR and SER are replaced with EOR and LDI */
383
                                16'b0010_11xx_xxxx_xxxx: begin
384
                                        /* MOV */
385
                                        R = GPR_Rr;
386
                                        update_nsz = 1'b0;
387
                                end
388
                                16'b1110_xxxx_xxxx_xxxx: begin
389
                                        /* LDI */
390
                                        R = K;
391
                                        update_nsz = 1'b0;
392
                                end
393
                                /* LSL is replaced with ADD */
394
                                /* ROL is replaced with ADC */
395
                                16'b1111_10xx_xxxx_xxxx: begin
396
                                        if(pmem_d[9]) begin
397
                                                /* BST */
398
                                                T = GPR_Rd_b;
399
                                                writeback = 1'b0;
400
                                        end else begin
401
                                                /* BLD */
402
                                                case(b)
403
                                                        3'd0: R = {GPR_Rd[7:1], T};
404
                                                        3'd1: R = {GPR_Rd[7:2], T, GPR_Rd[0]};
405
                                                        3'd2: R = {GPR_Rd[7:3], T, GPR_Rd[1:0]};
406
                                                        3'd3: R = {GPR_Rd[7:4], T, GPR_Rd[2:0]};
407
                                                        3'd4: R = {GPR_Rd[7:5], T, GPR_Rd[3:0]};
408
                                                        3'd5: R = {GPR_Rd[7:6], T, GPR_Rd[4:0]};
409
                                                        3'd6: R = {GPR_Rd[7], T, GPR_Rd[5:0]};
410
                                                        3'd7: R = {T, GPR_Rd[6:0]};
411
                                                endcase
412
                                        end
413
                                        update_nsz = 1'b0;
414
                                end
415
                                /* SEC, CLC, SEN, CLN, SEZ, CLZ, SEI, CLI, SES, CLS, SEV, CLV, SET, CLT, SEH, CLH
416
                                 * are replaced with BSET and BCLR */
417
                                16'b0000_0000_0000_0000: begin
418
                                        /* NOP */
419
                                        update_nsz = 1'b0;
420
                                        writeback = 1'b0;
421
                                end
422
                                /* SLEEP is not implemented */
423
                                /* WDR is not implemented */
424
                                16'b1001_00xx_xxxx_1111, /* PUSH/POP */
425
                                16'b1001_00xx_xxxx_1100, /*  X   */
426
                                16'b1001_00xx_xxxx_1101, /*  X+  */
427
                                16'b1001_00xx_xxxx_1110, /* -X   */
428
                                16'b1001_00xx_xxxx_1001, /*  Y+  */
429
                                16'b1001_00xx_xxxx_1010, /* -Y   */
430
                                16'b10x0_xxxx_xxxx_1xxx, /*  Y+q */
431
                                16'b1001_00xx_xxxx_0001, /*  Z+  */
432
                                16'b1001_00xx_xxxx_0010, /* -Z   */
433
                                16'b10x0_xxxx_xxxx_0xxx: /*  Z+q */
434
                                begin
435
                                        /* LD - POP (run from state WRITEBACK) */
436
                                        R = dmem_di;
437
                                        update_nsz = 1'b0;
438
                                end
439
                                16'b1011_0xxx_xxxx_xxxx: begin
440
                                        /* IN (run from state WRITEBACK) */
441
                                        case(io_sel)
442
                                                IO_SEL_EXT: R = io_di;
443
                                                IO_SEL_STACK: R = io_sp;
444
                                                IO_SEL_SREG: R = {1'b0, T, H, S, V, N, Z, C};
445
                                                default: R = 8'hxx;
446
                                        endcase
447
                                        update_nsz = 1'b0;
448
                                end
449
                        endcase
450
                end /* if(normal_en) */
451
                if(lds_writeback) begin
452
                        R = dmem_di;
453
                        writeback = 1'b1;
454
                end
455
                if(lpm_en) begin
456
                        R = pZ[0] ? pmem_d[15:8] : pmem_d[7:0];
457
                        writeback = 1'b1;
458
                end
459
                if(update_nsz) begin
460
                        N = mode16 ? R16[15] : R[7];
461
                        S = N ^ V;
462
                        Z = mode16 ? R16 == 16'h0000 : R == 8'h00;
463
                end
464
                if(io_we & (io_a == 6'b111111))
465
                        {T, H, S, V, N, Z, C} = io_do[6:0];
466
                if(writeback) begin
467
                        if(mode16) begin
468
                                // synthesis translate_off
469
                                //$display("REG WRITE(16): %d < %d", Rd16, R16);
470
                                // synthesis translate_on
471
                                case(Rd16)
472
                                        2'd0: U = R16;
473
                                        2'd1: pX = R16;
474
                                        2'd2: pY = R16;
475
                                        2'd3: pZ = R16;
476
                                endcase
477
                        end else begin
478
                                // synthesis translate_off
479
                                //$display("REG WRITE: %d < %d", Rd, R);
480
                                // synthesis translate_on
481
                                case(write_dest)
482
                                        default: GPR[write_dest] = R;
483
                                        5'd24: U[7:0] = R;
484
                                        5'd25: U[15:8] = R;
485
                                        5'd26: pX[7:0] = R;
486
                                        5'd27: pX[15:8] = R;
487
                                        5'd28: pY[7:0] = R;
488
                                        5'd29: pY[15:8] = R;
489
                                        5'd30: pZ[7:0] = R;
490
                                        5'd31: pZ[15:8] = R;
491
                                endcase
492
                        end
493
                end else begin /* if(writeback) */
494
                        case(dmem_sel)
495
                                DMEM_SEL_XPLUS:         pX = pX + 16'd1;
496
                                DMEM_SEL_XMINUS:        pX = pX - 16'd1;
497
                                DMEM_SEL_YPLUS:         pY = pY + 16'd1;
498
                                DMEM_SEL_YMINUS:        pY = pY - 16'd1;
499
                                DMEM_SEL_ZPLUS:         pZ = pZ + 16'd1;
500
                                DMEM_SEL_ZMINUS:        pZ = pZ - 16'd1;
501
                                default:;
502
                        endcase
503
                end
504
        end /* if(sys_rst) ... else */
505
end
506
 
507
/* I/O port */
508
assign io_a = {pmem_d[10:9], pmem_d[3:0]};
509
assign io_do = GPR_Rd;
510
 
511
/* Data memory */
512
always @(*) begin
513
        case(dmem_sel)
514
                DMEM_SEL_X,
515
                DMEM_SEL_XPLUS:         dmem_a = pX;
516
                DMEM_SEL_XMINUS:        dmem_a = pX - 16'd1;
517
                DMEM_SEL_YPLUS:         dmem_a = pY;
518
                DMEM_SEL_YMINUS:        dmem_a = pY - 16'd1;
519
                DMEM_SEL_YQ:            dmem_a = pY + q;
520
                DMEM_SEL_ZPLUS:         dmem_a = pZ;
521
                DMEM_SEL_ZMINUS:        dmem_a = pZ - 16'd1;
522
                DMEM_SEL_ZQ:            dmem_a = pZ + q;
523
                DMEM_SEL_SP_R,
524
                DMEM_SEL_SP_PCL,
525
                DMEM_SEL_SP_PCH:        dmem_a = SP + pop;
526
                DMEM_SEL_PMEM:          dmem_a = pmem_d;
527
                default:                dmem_a = {dmem_width{1'bx}};
528
        endcase
529
end
530
 
531
wire [pmem_width-1:0] PC_inc = PC + 1;
532
always @(*) begin
533
        case(dmem_sel)
534
                DMEM_SEL_X,
535
                DMEM_SEL_XMINUS,
536
                DMEM_SEL_YMINUS,
537
                DMEM_SEL_YQ,
538
                DMEM_SEL_ZMINUS,
539
                DMEM_SEL_ZQ,
540
                DMEM_SEL_SP_R:          dmem_do = GPR_Rd;
541
                DMEM_SEL_SP_PCL:        dmem_do = PC_inc[7:0];
542
                DMEM_SEL_SP_PCH:        dmem_do = PC_inc[pmem_width-1:8];
543
                DMEM_SEL_PMEM:          dmem_do = GPR_Rd_r;
544
                default:                dmem_do = 8'hxx;
545
        endcase
546
end
547
 
548
/* Multi-cycle operation sequencer */
549
 
550
wire reg_equal = GPR_Rd == GPR_Rr;
551
 
552
reg sreg_read;
553
always @(*) begin
554
        case(b)
555
                3'd0: sreg_read = C;
556
                3'd1: sreg_read = Z;
557
                3'd2: sreg_read = N;
558
                3'd3: sreg_read = V;
559
                3'd4: sreg_read = S;
560
                3'd5: sreg_read = H;
561
                3'd6: sreg_read = T;
562
                3'd7: sreg_read = 1'b0;
563
        endcase
564
end
565
 
566
reg [3:0] state;
567
reg [3:0] next_state;
568
 
569
parameter NORMAL        = 4'd0;
570
parameter RCALL         = 4'd1;
571
parameter ICALL         = 4'd2;
572
parameter STALL         = 4'd3;
573
parameter RET1          = 4'd4;
574
parameter RET2          = 4'd5;
575
parameter RET3          = 4'd6;
576
parameter LPM           = 4'd7;
577
parameter STS           = 4'd8;
578
parameter LDS1          = 4'd9;
579
parameter LDS2          = 4'd10;
580
parameter SKIP          = 4'd11;
581
parameter WRITEBACK     = 4'd12;
582
 
583
always @(posedge clk) begin
584
        if(rst)
585
                state <= NORMAL;
586
        else
587
                state <= next_state;
588
end
589
 
590
always @(*) begin
591
        next_state = state;
592
 
593
        pmem_ce = rst;
594
 
595
        pc_sel = PC_SEL_NOP;
596
        normal_en = 1'b0;
597
        lpm_en = 1'b0;
598
 
599
        io_re = 1'b0;
600
        io_we = 1'b0;
601
 
602
        dmem_we = 1'b0;
603
        dmem_sel = DMEM_SEL_UNDEFINED;
604
 
605
        push = 1'b0;
606
        pop = 1'b0;
607
 
608
        pmem_selz = 1'b0;
609
 
610
        regmem_ce = 1'b1;
611
        lds_writeback = 1'b0;
612
 
613
        case(state)
614
                NORMAL: begin
615
                        casex(pmem_d)
616
                                16'b1100_xxxx_xxxx_xxxx: begin
617
                                        /* RJMP */
618
                                        pc_sel = PC_SEL_KL;
619
                                        next_state = STALL;
620
                                end
621
                                16'b1101_xxxx_xxxx_xxxx: begin
622
                                        /* RCALL */
623
                                        /* TODO: in which order should we push the bytes? */
624
                                        dmem_sel = DMEM_SEL_SP_PCL;
625
                                        dmem_we = 1'b1;
626
                                        push = 1'b1;
627
                                        next_state = RCALL;
628
                                end
629
                                16'b0001_00xx_xxxx_xxxx: begin
630
                                        /* CPSE */
631
                                        pc_sel = PC_SEL_INC;
632
                                        pmem_ce = 1'b1;
633
                                        if(reg_equal)
634
                                                next_state = SKIP;
635
                                end
636
                                16'b1111_11xx_xxxx_xxxx: begin
637
                                        /* SBRC - SBRS */
638
                                        pc_sel = PC_SEL_INC;
639
                                        pmem_ce = 1'b1;
640
                                        if(GPR_Rd_b == pmem_d[9])
641
                                                next_state = SKIP;
642
                                end
643
                                /* SBIC, SBIS, SBI, CBI are not implemented */
644
                                16'b1111_0xxx_xxxx_xxxx: begin
645
                                        /* BRBS - BRBC */
646
                                        pmem_ce = 1'b1;
647
                                        if(sreg_read ^ pmem_d[10]) begin
648
                                                pc_sel = PC_SEL_KS;
649
                                                next_state = STALL;
650
                                        end else
651
                                                pc_sel = PC_SEL_INC;
652
                                end
653
                                /* BREQ, BRNE, BRCS, BRCC, BRSH, BRLO, BRMI, BRPL, BRGE, BRLT,
654
                                 * BRHS, BRHC, BRTS, BRTC, BRVS, BRVC, BRIE, BRID are replaced
655
                                 * with BRBS/BRBC */
656
                                16'b1001_00xx_xxxx_1100, /*  X   */
657
                                16'b1001_00xx_xxxx_1101, /*  X+  */
658
                                16'b1001_00xx_xxxx_1110, /* -X   */
659
                                16'b1001_00xx_xxxx_1001, /*  Y+  */
660
                                16'b1001_00xx_xxxx_1010, /* -Y   */
661
                                16'b10x0_xxxx_xxxx_1xxx, /*  Y+q */
662
                                16'b1001_00xx_xxxx_0001, /*  Z+  */
663
                                16'b1001_00xx_xxxx_0010, /* -Z   */
664
                                16'b10x0_xxxx_xxxx_0xxx: /*  Z+q */
665
                                begin
666
                                        casex({pmem_d[12], pmem_d[3:0]})
667
                                                5'b1_1100: dmem_sel = DMEM_SEL_X;
668
                                                5'b1_1101: dmem_sel = DMEM_SEL_XPLUS;
669
                                                5'b1_1110: dmem_sel = DMEM_SEL_XMINUS;
670
                                                5'b1_1001: dmem_sel = DMEM_SEL_YPLUS;
671
                                                5'b1_1010: dmem_sel = DMEM_SEL_YMINUS;
672
                                                5'b0_1xxx: dmem_sel = DMEM_SEL_YQ;
673
                                                5'b1_0001: dmem_sel = DMEM_SEL_ZPLUS;
674
                                                5'b1_0010: dmem_sel = DMEM_SEL_ZMINUS;
675
                                                5'b0_0xxx: dmem_sel = DMEM_SEL_ZQ;
676
                                        endcase
677
                                        if(pmem_d[9]) begin
678
                                                /* ST */
679
                                                pc_sel = PC_SEL_INC;
680
                                                pmem_ce = 1'b1;
681
                                                dmem_we = 1'b1;
682
                                        end else begin
683
                                                /* LD */
684
                                                next_state = WRITEBACK;
685
                                        end
686
                                end
687
                                16'b1011_0xxx_xxxx_xxxx: begin
688
                                        /* IN */
689
                                        io_re = 1'b1;
690
                                        next_state = WRITEBACK;
691
                                end
692
                                16'b1011_1xxx_xxxx_xxxx: begin
693
                                        /* OUT */
694
                                        io_we = 1'b1;
695
                                        pc_sel = PC_SEL_INC;
696
                                        pmem_ce = 1'b1;
697
                                end
698
                                16'b1001_00xx_xxxx_xxxx: begin
699
                                        if(pmem_d[3:0] == 4'hf) begin
700
                                                if(pmem_d[9]) begin
701
                                                        /* PUSH */
702
                                                        push = 1'b1;
703
                                                        dmem_sel = DMEM_SEL_SP_R;
704
                                                        dmem_we = 1'b1;
705
                                                        pc_sel = PC_SEL_INC;
706
                                                        pmem_ce = 1'b1;
707
                                                end else begin
708
                                                        /* POP */
709
                                                        pop = 1'b1;
710
                                                        dmem_sel = DMEM_SEL_SP_R;
711
                                                        next_state = WRITEBACK;
712
                                                end
713
                                        end else if(pmem_d[3:0] == 4'h0) begin
714
                                                pc_sel = PC_SEL_INC;
715
                                                pmem_ce = 1'b1;
716
                                                if(pmem_d[9])
717
                                                        /* STS */
718
                                                        next_state = STS;
719
                                                else
720
                                                        /* LDS */
721
                                                        next_state = LDS1;
722
                                        end
723
                                end
724
                                16'b1001_0101_000x_1000: begin
725
                                        /* RET - RETI (treated as RET) */
726
                                        /* TODO: in which order should we pop the bytes? */
727
                                        dmem_sel = DMEM_SEL_SP_PCH;
728
                                        pop = 1'b1;
729
                                        next_state = RET1;
730
                                end
731
                                16'b1001_0101_1100_1000: begin
732
                                        /* LPM */
733
                                        pmem_selz = 1'b1;
734
                                        pmem_ce = 1'b1;
735
                                        next_state = LPM;
736
                                end
737
                                16'b1001_0100_0000_1001: begin
738
                                        /* IJMP */
739
                                        pc_sel = PC_SEL_Z;
740
                                        next_state = STALL;
741
                                end
742
                                16'b1001_0101_0000_1001: begin
743
                                        /* ICALL */
744
                                        /* TODO: in which order should we push the bytes? */
745
                                        dmem_sel = DMEM_SEL_SP_PCL;
746
                                        dmem_we = 1'b1;
747
                                        push = 1'b1;
748
                                        next_state = ICALL;
749
                                end
750
                                default: begin
751
                                        pc_sel = PC_SEL_INC;
752
                                        normal_en = 1'b1;
753
                                        pmem_ce = 1'b1;
754
                                end
755
                        endcase
756
                end
757
                RCALL: begin
758
                        dmem_sel = DMEM_SEL_SP_PCH;
759
                        dmem_we = 1'b1;
760
                        push = 1'b1;
761
                        pc_sel = PC_SEL_KL;
762
                        next_state = STALL;
763
                end
764
                ICALL: begin
765
                        dmem_sel = DMEM_SEL_SP_PCH;
766
                        dmem_we = 1'b1;
767
                        push = 1'b1;
768
                        pc_sel = PC_SEL_Z;
769
                        next_state = STALL;
770
                end
771
                RET1: begin
772
                        pc_sel = PC_SEL_DMEMH;
773
                        dmem_sel = DMEM_SEL_SP_PCL;
774
                        pop = 1'b1;
775
                        next_state = RET2;
776
                end
777
                RET2: begin
778
                        pc_sel = PC_SEL_DMEML;
779
                        next_state = RET3;
780
                end
781
                RET3: begin
782
                        pc_sel = PC_SEL_DEC;
783
                        next_state = STALL;
784
                end
785
                LPM: begin
786
                        lpm_en = 1'b1;
787
                        pc_sel = PC_SEL_INC;
788
                        pmem_ce = 1'b1;
789
                        next_state = NORMAL;
790
                end
791
                STS: begin
792
                        pc_sel = PC_SEL_INC;
793
                        pmem_ce = 1'b1;
794
                        dmem_sel = DMEM_SEL_PMEM;
795
                        dmem_we = 1'b1;
796
                        next_state = NORMAL;
797
                end
798
                LDS1: begin
799
                        dmem_sel = DMEM_SEL_PMEM;
800
                        regmem_ce = 1'b0;
801
                        next_state = LDS2;
802
                end
803
                LDS2: begin
804
                        pc_sel = PC_SEL_INC;
805
                        pmem_ce = 1'b1;
806
                        normal_en = 1'b1;
807
                        lds_writeback = 1'b1;
808
                        next_state = NORMAL;
809
                end
810
                SKIP: begin
811
                        pc_sel = PC_SEL_INC;
812
                        pmem_ce = 1'b1;
813
                        /* test for STS and LDS */
814
                        if((pmem_d[15:10] == 6'b100100) & (pmem_d[3:0] == 4'h0))
815
                                next_state = STALL; /* 2-word instruction, skip the second word as well */
816
                        else
817
                                next_state = NORMAL; /* 1-word instruction */
818
                end
819
                STALL: begin
820
                        pc_sel = PC_SEL_INC;
821
                        pmem_ce = 1'b1;
822
                        next_state = NORMAL;
823
                end
824
                WRITEBACK: begin
825
                        pmem_ce = 1'b1;
826
                        pc_sel = PC_SEL_INC;
827
                        normal_en = 1'b1;
828
                        next_state = NORMAL;
829
                end
830
        endcase
831
end
832
 
833
endmodule

powered by: WebSVN 2.1.0

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