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

Subversion Repositories softavrcore

[/] [softavrcore/] [trunk/] [core/] [avr_core.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 apal
/*****************************************************************************/
2
/* avr_core.v                                                                */
3
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4
/* (c) 2019-2020; Andras Pal <apal@szofi.net>                                */
5
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
6
/* Portions of the code got inspiration from the Navre project               */
7
/* (https://opencores.org/projects/navre)                                    */
8
/*****************************************************************************/
9
 
10
`define AVR_200
11
//`define AVR_250
12
//`define AVR_310
13
//`define AVR_350
14
//`define AVR_400
15
//`define AVR_500
16
//`define AVR_510
17
 
18
`define AVR_INITIAL
19
 
20
/*****************************************************************************/
21
 
22
module avr_core
23
#(      parameter pmem_width = 9, /* PMEM address bus width (16-bit instr)   */
24
        parameter dmem_width = 9, /* RAM address bus width (bytes)           */
25
        parameter interrupt  = 1,
26
        parameter intr_width = 2  /* number of interrupt vector bits         */
27
 )
28
 (      input   clk,
29
        input   rst,
30
 
31
        output  pmem_ce,
32
        output  [pmem_width-1:0] pmem_a,
33
        input   [15:0] pmem_d,
34
 
35
        output  dmem_re,
36
        output  dmem_we,
37
        output  [dmem_width-1:0] dmem_a,
38
        input   [7:0] dmem_di,
39
        output  [7:0] dmem_do,
40
 
41
        output  io_re,
42
        output  io_we,
43
        output  [5:0] io_a,
44
        input   [7:0] io_di,
45
        output  [7:0] io_do,
46
 
47
        input   in_iflag,
48
        input   [intr_width-1:0] in_ivect
49
 );
50
 
51
/*****************************************************************************/
52
 
53
/******************************************************************************
54
             |  avr2    avr25   avr31   avr35   avr4    avr5    avr51
55
-------------+-----------------------------------------------------------------
56
MOVW         |            X        X      X       X       X       X
57
LPM  Rd,Z(+) |            X        X      X       X       X       X
58
ELPM         |                     X                              X
59
ELPM Rd,Z(+) |                                                    X
60
JMP/CALL     |                     X      X               X       X
61
SPM          |            X               X       X       X       X
62
MUL          |                                    X       X       X
63
******************************************************************************/
64
 
65
`ifdef AVR_250
66
`define AVR_HAVE_MOVW
67
`define AVR_HAVE_LPMZ
68
`define AVR_HAVE_SPM
69
`endif
70
 
71
`ifdef AVR_310
72
`define AVR_HAVE_MOVW
73
`define AVR_HAVE_LPMZ
74
`define AVR_HAVE_ELPM
75
`define AVR_HAVE_22BITPC
76
`endif
77
 
78
`ifdef AVR_350
79
`define AVR_HAVE_MOVW
80
`define AVR_HAVE_LPMZ
81
`define AVR_HAVE_22BITPC
82
`define AVR_HAVE_SPM
83
`endif
84
 
85
`ifdef AVR_400
86
`define AVR_HAVE_MOVW
87
`define AVR_HAVE_LPMZ
88
`define AVR_HAVE_SPM
89
`define AVR_HAVE_MUL
90
`endif
91
 
92
`ifdef AVR_500
93
`define AVR_HAVE_MOVW
94
`define AVR_HAVE_LPMZ
95
`define AVR_HAVE_22BITPC
96
`define AVR_HAVE_SPM
97
`define AVR_HAVE_MUL
98
`endif
99
 
100
`ifdef AVR_510
101
`define AVR_HAVE_MOVW
102
`define AVR_HAVE_LPMZ
103
`define AVR_HAVE_ELPM
104
`define AVR_HAVE_ELPMZ
105
`define AVR_HAVE_22BITPC
106
`define AVR_HAVE_SPM
107
`define AVR_HAVE_MUL
108
`endif
109
 
110
/*****************************************************************************/
111
 
112
localparam MEM_OFFSET = 96;
113
 
114
/*****************************************************************************/
115
 
116
`ifdef AVR_INITIAL
117
localparam      STATE_INITIAL   = 4'd0;
118
localparam      STATE_STALL     = 4'd1;
119
`else
120
localparam      STATE_STALL     = 4'd0;
121
`endif
122
localparam      STATE_NORMAL    = 4'd2;
123
localparam      STATE_TWOWORD   = 4'd3;
124
localparam      STATE_SKIP      = 4'd4;
125
localparam      STATE_LD        = 4'd5;
126
localparam      STATE_CALL      = 4'd6;
127
localparam      STATE_RET       = 4'd7;
128
localparam      STATE_RET2      = 4'd8;
129
localparam      STATE_LPM       = 4'd9;
130
localparam      STATE_LPM2      = 4'd10;
131
localparam      STATE_ADIW      = 4'd11;
132
localparam      STATE_IO_BIT    = 4'd12;
133
localparam      STATE_MUL       = 4'd13;
134
localparam      STATE_IN        = 4'd14;
135
 
136
/*****************************************************************************/
137
 
138
/* CPU core state registers: */
139
reg [pmem_width-1:0] PC; /* <= 0 */
140
reg [3:0] state;         /* <= 0: hence, STALL state should be zero! */
141
 
142
wire [15:0] INSTR;
143
reg [15:0] PREVI;
144
 
145
reg [7:0] GPR[0:31];
146
 
147
`ifdef AVR_INITIAL
148
`ifdef SIMULATOR
149
localparam      init_depth = 3;
150
`else
151
localparam      init_depth = 8;
152
`endif
153
reg [init_depth-1:0] init_count;
154
`endif
155
 
156
`ifdef SIMULATOR
157
integer i;
158
initial begin
159
        for ( i=0;i<32;i=i+1)
160
                GPR[i] <= 8'hA0 + i;
161
end
162
`endif
163
 
164
wire [15:0] RX = { GPR[27], GPR[26] };
165
wire [15:0] RY = { GPR[29], GPR[28] };
166
wire [15:0] RZ = { GPR[31], GPR[30] };
167
 
168
reg I, T, H, S, V, N, Z, C;     /* initialized as <= 0  */
169
 
170
wire [7:0] SREG = { I, T, H, S, V, N, Z, C };
171
 
172
reg [15:0] SP;                   /* initialized as <= 0  */
173
 
174
 
175
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
176
 
177
reg nI, nT, nH, nS, nV, nN, nZ, nC;
178
wire [7:0] nSREG = { nI, nT, nH, nS, nV, nN, nZ, nC };
179
 
180
reg [7:0] R;                     /* generic result for writeback         */
181
reg [7:0] R_high;                /* result for 1-word writeback - high byte */
182
 
183
wire [15:0] RX_inc_dec = (INSTR[0] ? RX + 1 : RX - 1);
184
wire [15:0] RY_inc_dec = (INSTR[0] ? RY + 1 : RY - 1);
185
wire [15:0] RZ_inc_dec = (INSTR[0] ? RZ + 1 : RZ - 1);
186
wire [15:0] RZ_inc     = (INSTR[0] ? RZ + 1 :   RZ  );
187
 
188
/* arithmetic and logic operators, followed by an 8-bit immediate operand: */
189
/* only these instruction imply destination registers r16 ... r31 */
190
wire immediate = (INSTR[15:14] == 2'b01  ) |    /* ANDI, ORI, SBCI, SUBI */
191
                 (INSTR[15:12] == 4'b0011) |    /* CPI                   */
192
                 (INSTR[15:12] == 4'b1110);     /* LDI                   */
193
 
194
wire [4:0] Rd_normal = { immediate | INSTR[8], INSTR[7:4] };
195
 
196
wire [4:0] Rd = Rd_normal;
197
 
198
wire [4:0] Rd_prev = PREVI[8:4];
199
wire [4:0] Rr = { INSTR[9], INSTR[3:0] };
200
wire [1:0] Rd16 = INSTR[5:4];
201
wire [1:0] Rp16 = PREVI[5:4];
202
wire [7:0] GPR_Rd = GPR[Rd];
203
wire [2:0] b = INSTR[2:0];
204
wire GPR_Rd_b = GPR_Rd[b];
205
wire [7:0] GPR_Rr = GPR[Rr];
206
wire [3:0] RD16 = INSTR[7:4];
207
wire [3:0] RR16 = INSTR[3:0];
208
 
209
/* used by: ANDI, ORI, SBCI, SUBI, CPI, LDI (i.e. where immediate == 1'b1): */
210
wire [7:0] K = { INSTR[11:8], INSTR[3:0] };
211
/* used by: LDD Rd, Y+q; LDD RD, Z+q; STD Y+q, Rd; STD Z+q, Rd: */
212
wire [5:0] q = { INSTR[13], INSTR[11:10], INSTR[2:0] };
213
/* used by: ADIW, SBIW: */
214
wire [5:0] K16 = { INSTR[7:6], INSTR[3:0] };
215
 
216
wire two_word_lds_sts = ((INSTR[15:10]==6'b100100) & (INSTR[3:0]==4'b0000));
217
 
218
`ifdef AVR_HAVE_22BITPC
219
/* this is for avr3 (avr31, avr35) and avr5 (avr51): */
220
wire two_word_jmp_call = ((INSTR[15:9]==7'b1001010) & (INSTR[3:2]==2'b11));
221
wire two_word_instr = two_word_lds_sts | two_word_jmp_call;
222
`else
223
/* otherwise (avr2, avr25 and avr4): */
224
wire two_word_instr = two_word_lds_sts;
225
`endif
226
 
227
`ifdef AVR_HAVE_MUL
228
wire [4:0] Rd_mul = INSTR[15] ? INSTR[8:4] : ~INSTR[8] ? { 1'b1, INSTR[7:4] } : { 2'b10, INSTR[6:4] };
229
wire [4:0] Rr_mul = INSTR[15] ? Rr         : ~INSTR[8] ? { 1'b1, INSTR[3:0] } : { 2'b10, INSTR[2:0] };
230
wire [7:0] GPR_Rd_mul = GPR[Rd_mul];
231
wire [7:0] GPR_Rr_mul = GPR[Rr_mul];
232
reg [7:0] mul_rd;
233
reg [7:0] mul_rr;
234
reg [15:0] product;
235
/* FMUL, FMULS, FMULSU: */
236
wire fmulxx = ~INSTR[15] & (INSTR[3]  | INSTR[7]);
237
/* MULS, FMULS: */
238
wire xmulsx = ~INSTR[15] & (~INSTR[8] | ({INSTR[7],INSTR[3]} == 2'b10));
239
/* MULS, MULSU, FMULS, FMULSU: */
240
wire xmulsu = ~INSTR[15] & (~INSTR[8] | ({INSTR[7],INSTR[3]} != 2'b01));
241
reg [2:0] mul_type; /* = { fmulxx, xmulsx, xmulsu }; */
242
`endif
243
 
244
/* stage2 temporary registers: */
245
 
246
reg [2:0] writeback;
247
reg change_z;
248
reg update_nsz;
249
reg [pmem_width-1:0] pc_next;
250
reg [15:0] sp_next;
251
reg sp_update;
252
 
253
reg [4:0] Rd_ld_save;
254
reg lpm_z_low;
255
 
256
localparam      WRITEBACK_NONE   = 3'd0;
257
localparam      WRITEBACK_GPR    = 3'd1;
258
localparam      WRITEBACK_ZINC   = 3'd4;
259
localparam      WRITEBACK_ZY     = 3'd5;
260
localparam      WRITEBACK_X      = 3'd6;
261
 
262
reg [3:0] next_state;
263
 
264
reg  [15:0] pc_call_next;
265
reg  [15:0] pc_call;
266
 
267
wire [15:0] pc_full = { {(16-pmem_width){1'b0}}, PC };
268
wire [15:0] pc_full_dec = { {(16-pmem_width){1'b0}}, PC - 1'b1 };
269
 
270
/* data memory interface: */
271
reg [15:0] d_addr;
272
reg d_read;
273
reg d_write;
274
reg [7:0] d_out;
275
 
276
/* interrupts: */
277
wire is_tail_reti;
278
wire is_interrupt;
279
 
280
reg iflag;
281
reg [intr_width-1:0] ivect;
282
 
283
generate
284
        if ( interrupt ) begin
285
                assign is_tail_reti = INSTR[4] & iflag;
286
                assign is_interrupt = I & iflag & (state==STATE_NORMAL);
287
        end else begin
288
                assign is_tail_reti = 0;
289
                assign is_interrupt = 0;
290
        end
291
endgenerate
292
 
293
/* Instructions performing memory I/O via the dmem_* bus: */
294
 
295
// 16'b10q0_qq0d_dddd_0qqq              LD Rd, Z+q
296
// 16'b10q0_qq0d_dddd_1qqq              LD Rd, Y+q
297
// 16'b10q0_qq1d_dddd_0qqq              ST Z+q, Rd
298
// 16'b10q0_qq1d_dddd_1qqq              ST Y+q, Rd
299
// 16'b1001_000d_dddd_0001              LD Rd, Z++
300
// 16'b1001_000d_dddd_1001              LD Rd, Y++
301
// 16'b1001_001d_dddd_0001              ST Z++, Rd
302
// 16'b1001_001d_dddd_1001              ST Y++, Rd      
303
// 16'b1001_000d_dddd_0010              LD Rd, --Z
304
// 16'b1001_000d_dddd_1010              LD Rd, --Y
305
// 16'b1001_001d_dddd_0010              ST --Z, Rd
306
// 16'b1001_001d_dddd_1010              ST --Y, Rd
307
// 16'b1001_000d_dddd_1100              LD Rd, X
308
// 16'b1001_000d_dddd_1101              LD Rd, X++
309
// 16'b1001_000d_dddd_1110              LD Rd, --X
310
// 16'b1001_001d_dddd_1100              ST X, Rd
311
// 16'b1001_001d_dddd_1101              ST X++, Rd
312
// 16'b1001_001d_dddd_1110              ST --X, Rd
313
// 16'b1001_000d_dddd_1111              POP Rd  == LD Rd, ++SP
314
// 16'b1001_001d_dddd_1111              PUSH Rd == ST SP--, Rd
315
 
316
// 16'b1001_000d_dddd_1101              LD Rd, X++
317
// 16'b1001_000d_dddd_1110              LD Rd, --X
318
// 16'b1001_001d_dddd_1101              ST X++, Rd
319
// 16'b1001_001d_dddd_1110              ST --X, Rd
320
 
321
// 16'b1001_000d_dddd_1001              LD Rd, Y++
322
// 16'b1001_000d_dddd_1010              LD Rd, --Y
323
// 16'b1001_001d_dddd_1001              ST Y++, Rd      
324
// 16'b1001_001d_dddd_1010              ST --Y, Rd
325
 
326
// 16'b1001_000d_dddd_0001              LD Rd, Z++
327
// 16'b1001_000d_dddd_0010              LD Rd, --Z
328
// 16'b1001_001d_dddd_0001              ST Z++, Rd
329
// 16'b1001_001d_dddd_0010              ST --Z, Rd
330
 
331
// 16'b1001_000d_dddd_01x1              LPM Rd, Z++
332
 
333
// INSTR[15:10] == 6'b100100
334
// X increased/decreased: INSTR[3:2] == 2'b11   
335
// Y increased/decreased: INSTR[3:2] == 2'b10
336
// Z increased/decreased: INSTR[3:2] == 2'b00
337
// Z increased            INSTR[3:2] == 2'b01   
338
 
339
/* setting up memory interface lines (d_addr, d_out, d_read and d_write): */
340
 
341
always @(*) begin
342
 
343
        d_out = 0;
344
        d_addr = 0;
345
        d_read = 0;
346
        d_write = 0;
347
 
348
        case (state)
349
 
350
            STATE_NORMAL: begin
351
 
352
                casex (INSTR)
353
 
354
                    16'b10x0_xx0x_xxxx_xxxx: begin
355
                        /* LD Rd, Z+q */
356
                        /* LD Rd, Y+q */
357
                        d_addr = (~INSTR[3]?RZ:RY) + q;
358
                        d_read = 1;
359
                        end
360
 
361
                    16'b10x0_xx1x_xxxx_xxxx: begin
362
                        /* ST Z+q, Rd */
363
                        /* ST Y+q, Rd */
364
                        d_addr = (~INSTR[3]?RZ:RY) + q;
365
                        d_out = GPR_Rd;
366
                        d_write = 1;
367
                        end
368
 
369
                    16'b1001_000x_xxxx_x001: begin
370
                        /* LD Rd, Z++ */
371
                        /* LD Rd, Y++ */
372
                        d_addr = (~INSTR[3]?RZ:RY);
373
                        d_read = 1;
374
                        end
375
 
376
                    16'b1001_001x_xxxx_x001: begin
377
                        /* ST Z++, Rd */
378
                        /* ST Y++, Rd */
379
                        d_addr = (~INSTR[3]?RZ:RY);
380
                        d_out = GPR_Rd;
381
                        d_write = 1;
382
                        end
383
 
384
                    16'b1001_000x_xxxx_x010: begin
385
                        /* LD Rd, --Z */
386
                        /* LD Rd, --Y */
387
                        d_addr = (~INSTR[3]?RZ:RY) - 1;
388
                        d_read = 1;
389
                        end
390
 
391
                    16'b1001_001x_xxxx_x010: begin
392
                        /* ST --Z, Rd */
393
                        /* ST --Y, Rd */
394
                        d_addr = (~INSTR[3]?RZ:RY) - 1;
395
                        d_out = GPR_Rd;
396
                        d_write = 1;
397
                        end
398
 
399
                    16'b1001_000x_xxxx_110x: begin
400
                        /* LD Rd, X */
401
                        /* LD Rd, X++ */
402
                        d_addr = RX;
403
                        d_read = 1;
404
                        end
405
                    16'b1001_000x_xxxx_1110: begin
406
                        /* LD Rd, --X */
407
                        d_addr = RX - 1;
408
                        d_read = 1;
409
                        end
410
 
411
                    16'b1001_001x_xxxx_110x: begin
412
                        /* ST X, Rd */
413
                        /* ST X++, Rd */
414
                        d_addr = RX;
415
                        d_out = GPR_Rd;
416
                        d_write = 1;
417
                        end
418
 
419
                    16'b1001_001x_xxxx_1110: begin
420
                        /* ST --X, Rd */
421
                        d_addr = RX - 1;
422
                        d_out = GPR_Rd;
423
                        d_write = 1;
424
                        end
425
 
426
                    16'b1001_000x_xxxx_1111: begin
427
                        /* POP Rd -- LD Rd, ++SP */
428
                        d_addr = SP + 1;
429
                        d_read = 1;
430
                        end
431
 
432
                    16'b1001_001x_xxxx_1111: begin
433
                        /* PUSH Rd -- ST SP--, Rd */
434
                        d_addr = SP;
435
                        d_out = GPR_Rd;
436
                        d_write = 1;
437
                        end
438
 
439
                    16'b1101_xxxx_xxxx_xxxx,
440
                    16'b1001_0101_0000_1001: begin
441
                        /* RCALL */
442
                        /* ICALL */
443
                        d_addr = SP;
444
                        d_out = pc_full[15:8];
445
                        d_write = 1;
446
                        end
447
 
448
                    16'b1001_0101_000x_1000: begin
449
                        /* RET, RETI */
450
                        d_addr = SP + 1;
451
                        d_read = 1;
452
                        end
453
 
454
                endcase
455
 
456
                if (is_interrupt) begin
457
                        d_addr = SP;
458
                        d_out = pc_full_dec[15:8];
459
                        d_write = 1;
460
                end
461
 
462
                end
463
 
464
            STATE_TWOWORD: begin
465
                casex(PREVI)
466
 
467
                    16'b1001_000x_xxxx_0000: begin
468
                        /* LDS Rd, 0xXXXX */
469
                        d_addr = INSTR;
470
                        d_read = 1;
471
                        end
472
 
473
                    16'b1001_001x_xxxx_0000: begin
474
                        /* STS 0xXXXX, Rd */
475
                        d_addr = INSTR;
476
                        d_out = GPR[Rd_prev];
477
                        d_write = 1;
478
                        end
479
 
480
                `ifdef AVR_HAVE_22BITPC
481
                    16'b1001_010x_xxxx_111x: begin
482
                        /* CALL k */
483
                        d_addr = SP;
484
                        d_out = pc_full[15:8];
485
                        d_write = 1;
486
                        end
487
                `endif
488
 
489
                endcase
490
 
491
                end
492
 
493
            STATE_CALL: begin
494
                /* RCALL */
495
                /* ICALL */
496
                d_addr = SP;
497
                d_out = pc_full[7:0];
498
                d_write = 1;
499
                end
500
 
501
            STATE_RET: begin
502
                d_addr = SP + 1;
503
                d_read = 1;
504
                end
505
 
506
        endcase
507
end
508
 
509
assign  dmem_a  = d_addr[dmem_width-1:0] - MEM_OFFSET;
510
assign  dmem_re = d_read;
511
assign  dmem_we = d_write;
512
assign  dmem_do = d_out;
513
 
514
/* IN/OUT assignments: */
515
 
516
/* used by: IN, OUT, SBIC, SBIS, CBI, SBI: */
517
// 16'b1011_0aad_dddd_aaaa:     /* IN   */
518
// 16'b1011_1aad_dddd_aaaa:     /* OUT  */
519
// 16'b1001_1000_aaaa_abbb:     /* CBI  */
520
// 16'b1001_1010_aaaa_abbb:     /* SBI  */
521
// 16'b1001_1001_aaaa_abbb:     /* SBIC */
522
// 16'b1001_1011_aaaa_abbb:     /* SBIS */
523
 
524
reg [7:0] Rio;
525
 
526
wire    [5:0] a = INSTR[13] ? {INSTR[10:9], INSTR[3:0]} : {1'b0, INSTR[7:3]};
527
wire    io_act = (INSTR[15:12]==4'b1011) & (state == STATE_NORMAL);
528
assign  io_a = (state == STATE_IO_BIT ? {1'b0, PREVI[7:3]} : a);
529
assign  io_do = (state == STATE_IO_BIT ? Rio : GPR_Rd);
530
assign  io_re = (io_act & (INSTR[11]==1'b0)) | ((state == STATE_NORMAL) & (INSTR[15:10]==6'b100110));
531
assign  io_we = (io_act & (INSTR[11]==1'b1)) | (state == STATE_IO_BIT);
532
 
533
 
534
wire [7:0] Rin = (a==61?(SP[7:0]):(a==62?(SP[15:8]):(a==63?SREG:io_di)));
535
 
536
/*
537
reg [7:0] Rin;
538
always @(*) begin
539
        if (a==6'b111101) begin
540
                Rin = SP[7:0];
541
        end else if (a==6'b111110) begin
542
                Rin = SP[15:8];
543
        end else if (a==6'b111111) begin
544
                Rin = SREG;
545
        end else begin
546
                Rin = io_di;
547
        end
548
end
549
*/
550
 
551
/* CPU instruction pipeline, stage 1: */
552
 
553
assign pmem_ce = 1'b1;
554
assign pmem_a = PC;
555
/* always @(posedge clk) pmem_d <= FLASH[pmem_a]; */
556
assign INSTR = pmem_d;
557
 
558
always @(posedge clk) begin
559
 
560
        PREVI <= INSTR;
561
 
562
        iflag <= in_iflag;
563
        ivect <= in_ivect;
564
 
565
end /* always @(posedge clk) */
566
 
567
/* CPU instruction pipeline, stage 2: */
568
 
569
always @(*) begin
570
 
571
        R = 0;
572
        R_high = 0;
573
 
574
        writeback = WRITEBACK_NONE ;
575
        change_z = 1;
576
        update_nsz = 0;
577
 
578
        next_state = STATE_NORMAL;
579
        pc_next = PC;
580
        sp_next = SP;
581
        sp_update = 0;
582
 
583
        pc_call_next = 0;
584
 
585
        { nI, nT, nH, nS, nV, nN, nZ, nC } = SREG;
586
 
587
        case(state)
588
 
589
            STATE_NORMAL: begin
590
 
591
                casex(INSTR)
592
 
593
                `ifdef AVR_HAVE_MOVW
594
                    16'b0000_0001_xxxx_xxxx: begin
595
                        R = GPR[2*RR16+0];
596
                        R_high = GPR[2*RR16+1];
597
                        pc_next = PC + 1;
598
                        end
599
                `endif
600
 
601
                `ifdef AVR_HAVE_MUL
602
                    16'b1001_11xx_xxxx_xxxx,
603
                    16'b0000_001x_xxxx_xxxx: begin
604
                        /* MUL */
605
                        /* MULS */
606
                        /* MULSU */
607
                        /* FMUL */
608
                        /* FMULS */
609
                        /* FMULSU */
610
                        next_state = STATE_MUL;
611
                        end
612
                `endif
613
 
614
                    16'b000x_10xx_xxxx_xxxx, /* subtract */
615
                    16'b000x_01xx_xxxx_xxxx: /* compare  */ begin
616
                        /* SUB - SBC / CP - CPC */
617
                        {nC, R} = GPR_Rd - GPR_Rr - (~INSTR[12] & C);
618
                        nH = (~GPR_Rd[3] & GPR_Rr[3])|(GPR_Rr[3] & R[3])|(R[3] & ~GPR_Rd[3]);
619
                        nV = (GPR_Rd[7] & ~GPR_Rr[7] & ~R[7])|(~GPR_Rd[7] & GPR_Rr[7] & R[7]);
620
                        update_nsz = 1;
621
                        if (~INSTR[12])
622
                                change_z = 1'b0;
623
                        if (INSTR[11])
624
                                writeback = WRITEBACK_GPR;
625
                        pc_next = PC + 1;
626
                        end
627
                    16'b000x_11xx_xxxx_xxxx: begin
628
                        /* ADD - ADC */
629
                        {nC, R} = GPR_Rd + GPR_Rr + (INSTR[12] & C);
630
                        nH = (GPR_Rd[3] & GPR_Rr[3])|(GPR_Rr[3] & ~R[3])|(~R[3] & GPR_Rd[3]);
631
                        nV = (GPR_Rd[7] & GPR_Rr[7] & ~R[7])|(~GPR_Rd[7] & ~GPR_Rr[7] & R[7]);
632
                        update_nsz = 1;
633
                        writeback = WRITEBACK_GPR;
634
                        pc_next = PC + 1;
635
                        end
636
                    16'b010x_xxxx_xxxx_xxxx, /* subtract */
637
                    16'b0011_xxxx_xxxx_xxxx: /* compare  */ begin
638
                        /* SUBI - SBCI / CPI */
639
                        {nC, R} = GPR_Rd - K - (~INSTR[12] & C);
640
                        nH = (~GPR_Rd[3] & K[3])|(K[3] & R[3])|(R[3] & ~GPR_Rd[3]);
641
                        nV = (GPR_Rd[7] & ~K[7] & ~R[7])|(~GPR_Rd[7] & K[7] & R[7]);
642
                        update_nsz = 1;
643
                        if (~INSTR[12])
644
                                change_z = 1'b0;
645
                        if (INSTR[14])
646
                                writeback = WRITEBACK_GPR;
647
                        pc_next = PC + 1;
648
                        end
649
 
650
                    16'b0111_xxxx_xxxx_xxxx: begin
651
                        /* ANDI Rd, K; */
652
                        R = GPR_Rd & K;
653
                        nV = 1'b0;
654
                        update_nsz = 1;
655
                        writeback = WRITEBACK_GPR;
656
                        pc_next = PC + 1;
657
                        end
658
 
659
                    16'b0110_xxxx_xxxx_xxxx: begin
660
                        /* ORI Rd, K; */
661
                        R = GPR_Rd | K;
662
                        nV = 1'b0;
663
                        update_nsz = 1;
664
                        writeback = WRITEBACK_GPR;
665
                        pc_next = PC + 1;
666
                        end
667
 
668
                    16'b0010_00xx_xxxx_xxxx: begin
669
                        /* AND */
670
                        R = GPR_Rd & GPR_Rr;
671
                        nV = 1'b0;
672
                        update_nsz = 1;
673
                        writeback = WRITEBACK_GPR;
674
                        pc_next = PC + 1;
675
                        end
676
                    16'b0010_01xx_xxxx_xxxx: begin
677
                        /* EOR */
678
                        R = GPR_Rd ^ GPR_Rr;
679
                        nV = 1'b0;
680
                        update_nsz = 1;
681
                        writeback = WRITEBACK_GPR;
682
                        pc_next = PC + 1;
683
                        end
684
                    16'b0010_10xx_xxxx_xxxx: begin
685
                        /* OR */
686
                        R = GPR_Rd | GPR_Rr;
687
                        nV = 1'b0;
688
                        update_nsz = 1;
689
                        writeback = WRITEBACK_GPR;
690
                        pc_next = PC + 1;
691
                        end
692
                    16'b0010_11xx_xxxx_xxxx: begin
693
                        /* MOV */
694
                        R = GPR_Rr;
695
                        writeback = WRITEBACK_GPR;
696
                        pc_next = PC + 1;
697
                        end
698
                    16'b1001_010x_xxxx_0000: begin
699
                        /* COM */
700
                        R = ~GPR_Rd;
701
                        nV = 1'b0;
702
                        nC = 1'b1;
703
                        update_nsz = 1;
704
                        writeback = WRITEBACK_GPR;
705
                        pc_next = PC + 1;
706
                        end
707
                    16'b1001_010x_xxxx_0001: begin
708
                        /* NEG */
709
                        {nC, R} = 8'h00 - GPR_Rd;
710
                        nH = R[3] | GPR_Rd[3];
711
                        nV = (R == 8'h80);
712
                        update_nsz = 1;
713
                        writeback = WRITEBACK_GPR;
714
                        pc_next = PC + 1;
715
                        end
716
                    16'b1001_010x_xxxx_0011: begin
717
                        /* INC */
718
                        R = GPR_Rd + 8'd1;
719
                        nV = (R == 8'h80);
720
                        update_nsz = 1;
721
                        writeback = WRITEBACK_GPR;
722
                        pc_next = PC + 1;
723
                        end
724
                    16'b1001_010x_xxxx_1010: begin
725
                        /* DEC */
726
                        R = GPR_Rd - 8'd1;
727
                        nV = (R == 8'h7f);
728
                        update_nsz = 1;
729
                        writeback = WRITEBACK_GPR;
730
                        pc_next = PC + 1;
731
                        end
732
                    16'b1001_010x_xxxx_011x: begin
733
                        /* LSR - ROR */
734
                        R = {INSTR[0] & C, GPR_Rd[7:1]};
735
                        nC = GPR_Rd[0];
736
                        nV = R[7] ^ GPR_Rd[0];
737
                        update_nsz = 1;
738
                        writeback = WRITEBACK_GPR;
739
                        pc_next = PC + 1;
740
                        end
741
                    16'b1001_010x_xxxx_0101: begin
742
                        /* ASR */
743
                        R = {GPR_Rd[7], GPR_Rd[7:1]};
744
                        nC = GPR_Rd[0];
745
                        nV = R[7] ^ GPR_Rd[0];
746
                        update_nsz = 1;
747
                        writeback = WRITEBACK_GPR;
748
                        pc_next = PC + 1;
749
                        end
750
                    16'b1001_010x_xxxx_0010: begin
751
                        /* SWAP */
752
                        R = {GPR_Rd[3:0], GPR_Rd[7:4]};
753
                        writeback = WRITEBACK_GPR;
754
                        pc_next = PC + 1;
755
                        end
756
                    16'b1001_0100_xxxx_1000: begin
757
                        /* BSET - BCLR */
758
                        case(INSTR[7:4])
759
                                4'b0000: nC = 1'b1;
760
                                4'b0001: nZ = 1'b1;
761
                                4'b0010: nN = 1'b1;
762
                                4'b0011: nV = 1'b1;
763
                                4'b0100: nS = 1'b1;
764
                                4'b0101: nH = 1'b1;
765
                                4'b0110: nT = 1'b1;
766
                                4'b0111: nI = 1'b1;
767
                                4'b1000: nC = 1'b0;
768
                                4'b1001: nZ = 1'b0;
769
                                4'b1010: nN = 1'b0;
770
                                4'b1011: nV = 1'b0;
771
                                4'b1100: nS = 1'b0;
772
                                4'b1101: nH = 1'b0;
773
                                4'b1110: nT = 1'b0;
774
                                4'b1111: nI = 1'b0;
775
                        endcase
776
                        pc_next = PC + 1;
777
                        end
778
 
779
                    16'b1001_011x_xxxx_xxxx: begin
780
                        /* SBIW */
781
                        /* ADIW */
782
                        if(INSTR[8]) begin      /* SBIW */
783
                                {nC, R} = GPR[24+2*Rd16] - K16;
784
                        end else begin          /* ADIW */
785
                                {nC, R} = GPR[24+2*Rd16] + K16;
786
                        end
787
                        nZ = (R==0);
788
                        next_state = STATE_ADIW;
789
                        end
790
 
791
                    16'b1001_00xx_xxxx_0000: begin
792
                        /* LDS Rd, 0xXXXX */
793
                        /* STS 0xXXXX, Rd */
794
                        pc_next = PC + 1;
795
                        next_state = STATE_TWOWORD;
796
                        end
797
 
798
                `ifdef AVR_HAVE_22BITPC
799
                    16'b1001_010x_xxxx_11xx: begin
800
                        /* JMP k */
801
                        /* CALL k */
802
                        pc_next = PC + 1;
803
                        next_state = STATE_TWOWORD;
804
                        end
805
                `endif
806
 
807
                    16'b10x0_xx0x_xxxx_xxxx: begin
808
                        /* LD Rd, Z+q; */
809
                        /* LD Rd, Y+q; */
810
                        next_state = STATE_LD;
811
                        end
812
 
813
                    16'b10x0_xx1x_xxxx_xxxx: begin
814
                        /* ST Z+q, Rd */
815
                        /* ST Y+q, Rd */
816
                        pc_next = PC + 1;
817
                        end
818
 
819
                    16'b1001_000x_xxxx_x001: begin
820
                        /* LD Rd, Z++ */
821
                        /* LD Rd, Y++ */
822
                        next_state = STATE_LD;
823
                        /* save dest register for the next cycle: */
824
                        writeback = WRITEBACK_ZY;
825
                        end
826
 
827
                    16'b1001_001x_xxxx_x001: begin
828
                        /* ST Z++, Rd */
829
                        /* ST Y++, Rd */
830
                        pc_next = PC + 1;
831
                        writeback = WRITEBACK_ZY;
832
                        end
833
 
834
                    16'b1001_000x_xxxx_x010: begin
835
                        /* LD Rd, --Z */
836
                        /* LD Rd, --Y */
837
                        next_state = STATE_LD;
838
                        /* save dest register for the next cycle: */
839
                        writeback = WRITEBACK_ZY;
840
                        end
841
 
842
                    16'b1001_001x_xxxx_x010: begin
843
                        /* ST --Z, Rd */
844
                        /* ST --Y, Rd */
845
                        pc_next = PC + 1;
846
                        writeback = WRITEBACK_ZY;
847
                        end
848
 
849
                    16'b1001_000x_xxxx_1100: begin
850
                        /* LD Rd, X */
851
                        next_state = STATE_LD;
852
                        end
853
 
854
                    16'b1001_001x_xxxx_1100: begin
855
                        /* ST X, Rd */
856
                        pc_next = PC + 1;
857
                        end
858
 
859
                    16'b1001_000x_xxxx_1101: begin
860
                        /* LD Rd, X++ */
861
                        writeback = WRITEBACK_X;
862
                        next_state = STATE_LD;
863
                        end
864
 
865
                    16'b1001_001x_xxxx_1101: begin
866
                        /* ST X++, Rd */
867
                        writeback = WRITEBACK_X;
868
                        pc_next = PC + 1;
869
                        end
870
 
871
                    16'b1001_000x_xxxx_1110: begin
872
                        /* LD Rd, --X */
873
                        writeback = WRITEBACK_X;
874
                        next_state = STATE_LD;
875
                        end
876
 
877
                    16'b1001_001x_xxxx_1110: begin
878
                        /* ST --X, Rd */
879
                        writeback = WRITEBACK_X;
880
                        pc_next = PC + 1;
881
                        end
882
 
883
                    16'b1001_000x_xxxx_1111: begin
884
                        /* POP Rd */    /* LD Rd, ++SP */
885
                        sp_next = SP + 1;
886
                        sp_update = 1;
887
                        next_state = STATE_LD;
888
                        end
889
 
890
                    16'b1001_001x_xxxx_1111: begin
891
                        /* PUSH Rd */   /* ST SP--, Rd */
892
                        sp_next = SP - 1;
893
                        sp_update = 1;
894
                        next_state = STATE_STALL;
895
                        end
896
 
897
                    16'b1100_xxxx_xxxx_xxxx: begin
898
                        /* RJMP */
899
                        next_state = STATE_STALL;
900
                        pc_next = PC + { {4{INSTR[11]}}, INSTR[11:0] };
901
                        end
902
                    16'b1001_0100_0000_1001: begin
903
                        /* IJMP */
904
                        next_state = STATE_STALL;
905
                        pc_next = RZ;
906
                        end
907
 
908
                    16'b1101_xxxx_xxxx_xxxx: begin
909
                        /* RCALL */
910
                        pc_call_next = pc_full + { {4{INSTR[11]}}, INSTR[11:0] };
911
                        sp_next = SP - 1;
912
                        sp_update = 1;
913
                        next_state = STATE_CALL;
914
                        end
915
                    16'b1001_0101_0000_1001: begin
916
                        /* ICALL */
917
                        pc_call_next = RZ;
918
                        sp_next = SP - 1;
919
                        sp_update = 1;
920
                        next_state = STATE_CALL;
921
                        end
922
 
923
                    16'b1001_0101_0000_1000,            /* INSTR: 0x9508 */
924
                    16'b1001_0101_0001_1000: begin      /* INSTR: 0x9518 */
925
                        /* RET */
926
                        /* RETI */
927
 
928
                        if ( is_tail_reti ) begin
929
                                // `RETI` is equivalent to `JMP ivect` if
930
                                // there is a pending interrupt:
931
                                next_state = STATE_STALL;
932
                                pc_next = ivect;
933
                        end else begin
934
                                // Otherwise, RETI and RET is the same...
935
                                next_state = STATE_RET;
936
                                sp_next = SP + 1;
937
                                sp_update = 1;
938
                                // ... besides that RETI sets the I flag: 
939
                                if (INSTR[4])
940
                                        nI = 1'b1;
941
 
942
                        end
943
 
944
                        end
945
 
946
                    16'b1001_0101_110x_1000: begin
947
                        /* LPM */
948
                        /* ELPM */
949
                        pc_call_next = PC;
950
                        pc_next = RZ[pmem_width:1];
951
                        next_state = STATE_LPM;
952
                        end
953
 
954
//              `ifdef AVR_HAVE_SPM
955
//                  16'b1001_0101_111x_1000: begin
956
//                      /* SPM Z */
957
//                      /* SPM Z+ */
958
//                      pc_call_next = PC;
959
//                      pc_next = RZ[pmem_width:1];
960
//                      next_state = STATE_LPM;
961
//                      end
962
//              `endif
963
 
964
                `ifdef AVR_HAVE_LPMZ
965
                    16'b1001_000x_xxxx_01xx: begin
966
                        /* LPM Rd, Z */
967
                        /* LPM Rd, Z++ */
968
                        /* ELPM Rd, Z */
969
                        /* ELPM Rd, Z++ */
970
                        pc_call_next = PC;
971
                        pc_next = RZ[pmem_width:1];
972
                        next_state = STATE_LPM;
973
                        writeback = WRITEBACK_ZINC;
974
                        end
975
                `endif
976
 
977
                    16'b1111_0xxx_xxxx_xxxx: begin
978
                        /* BRxS - BRxC */
979
                        if (SREG[b] ^ INSTR[10]) begin
980
                                next_state = STATE_STALL;
981
                                pc_next = PC + { {9{INSTR[9]}}, INSTR[9:3] };
982
                        end else begin
983
                                pc_next = PC + 1;
984
                        end
985
                        end
986
                    16'b1111_11xx_xxxx_0xxx: begin
987
                        /* SBRC */
988
                        /* SBRS */
989
                        if (GPR_Rd_b == INSTR[9]) begin
990
                                next_state = STATE_SKIP;
991
                        end
992
                        pc_next = PC + 1;
993
                        end
994
                    16'b1001_10x0_xxxx_xxxx: begin
995
                        /* CBI */
996
                        /* SBI */
997
                        next_state = STATE_IO_BIT;
998
                        end
999
                    16'b1001_10x1_xxxx_xxxx: begin
1000
                        /* SBIC */
1001
                        /* SBIS */
1002
                        if (Rin[b]==INSTR[9]) begin
1003
                                next_state = STATE_SKIP;
1004
                        end
1005
                        pc_next = PC + 1;
1006
                        end
1007
                    16'b0001_00xx_xxxx_xxxx: begin
1008
                        /* CPSE */
1009
                        if (GPR_Rd == GPR_Rr) begin
1010
                                next_state = STATE_SKIP;
1011
                        end
1012
                        pc_next = PC + 1;
1013
                        end
1014
                    16'b1110_xxxx_xxxx_xxxx: begin
1015
                        /* LDI */
1016
                        R = K;
1017
                        writeback = WRITEBACK_GPR;
1018
                        pc_next = PC + 1;
1019
                        end
1020
                    16'b1111_10xx_xxxx_0xxx: begin
1021
                        /* BST */
1022
                        /* BLD */
1023
                        if (INSTR[9]) begin     /* BST */
1024
                                nT = GPR_Rd_b;
1025
                        end else begin          /* BLD */
1026
                                case (b)
1027
                                        3'd0: R = { GPR_Rd[7:1], T };
1028
                                        3'd1: R = { GPR_Rd[7:2], T, GPR_Rd[0] };
1029
                                        3'd2: R = { GPR_Rd[7:3], T, GPR_Rd[1:0] };
1030
                                        3'd3: R = { GPR_Rd[7:4], T, GPR_Rd[2:0] };
1031
                                        3'd4: R = { GPR_Rd[7:5], T, GPR_Rd[3:0] };
1032
                                        3'd5: R = { GPR_Rd[7:6], T, GPR_Rd[4:0] };
1033
                                        3'd6: R = { GPR_Rd[7], T, GPR_Rd[5:0] };
1034
                                        3'd7: R = { T, GPR_Rd[6:0] };
1035
                                endcase
1036
                                writeback = WRITEBACK_GPR;
1037
                        end
1038
                        pc_next = PC + 1;
1039
                        end
1040
                    16'b1011_0xxx_xxxx_xxxx: begin
1041
                        /* IN */
1042
                        R = Rin;
1043
                        writeback = WRITEBACK_GPR;
1044
                        pc_next = PC + 1;
1045
                        end
1046
                    16'b1011_1xxx_xxxx_xxxx: begin
1047
                        /* OUT */
1048
                        if (a==6'b111101) begin                 /* SPL */
1049
                                sp_next[7:0] = GPR_Rd;
1050
                                sp_update = 1;
1051
                        end else if (a==6'b111110) begin        /* SPH */
1052
                                sp_next[15:8] = GPR_Rd;
1053
                                sp_update = 1;
1054
                        end else if (a==6'b111111) begin        /* SREG */
1055
                                { nI, nT, nH, nS, nV, nN, nZ, nC } = GPR_Rd;
1056
                        end
1057
                        // in all other cases, the data flow is handled
1058
                        // by the IN/OUT persistent assignments (see earlier)
1059
                        pc_next = PC + 1;
1060
                        end
1061
 
1062
                    default:
1063
                        pc_next = PC + 1;
1064
                endcase
1065
 
1066
                if (update_nsz) begin
1067
                        nN = R[7];
1068
                        nS = nN ^ nV;
1069
                        nZ = (R == 8'h00) & (change_z|Z);
1070
                end
1071
 
1072
//              `ifdef AVR_INTERRUPT
1073
                if (is_interrupt) begin
1074
                        // An interrupt is equivalent to a CALL, however,
1075
                        // the actual program counter needed to be saved, not 
1076
                        // the PC corresponding to the following instruction.
1077
                        // Due to the two-stage pipeline, the current 
1078
                        // instruction is PC - 1, and not PC: 
1079
                        writeback = 0;
1080
                        pc_call_next = ivect;
1081
                        sp_next = SP - 1;
1082
                        sp_update = 1;
1083
                        next_state = STATE_CALL;
1084
                        pc_next = PC - 1;
1085
                        nI = 0;
1086
                end
1087
//              `endif
1088
 
1089
                end /* STATE_NORMAL */
1090
 
1091
            STATE_TWOWORD: begin
1092
                casex(PREVI)
1093
 
1094
                    16'b1001_000x_xxxx_0000: begin
1095
                        /* LDS Rd, 0xXXXX */
1096
                        next_state = STATE_LD;
1097
                        end
1098
 
1099
                    16'b1001_001x_xxxx_0000: begin
1100
                        /* STS 0xXXXX, Rd */
1101
                        pc_next = PC + 1;
1102
                        end
1103
 
1104
                `ifdef AVR_HAVE_22BITPC
1105
                    16'b1001_010x_xxxx_110x: begin
1106
                        /* JMP K */
1107
                        next_state = STATE_STALL;
1108
                        pc_next = INSTR;
1109
                        end
1110
                    16'b1001_010x_xxxx_111x: begin
1111
                        /* CALL K */
1112
                        pc_call_next = INSTR;
1113
                        sp_next = SP - 1;
1114
                        sp_update = 1;
1115
                        next_state = STATE_CALL;
1116
                        end
1117
                `endif
1118
 
1119
                    default:
1120
                        pc_next = PC + 1;
1121
 
1122
                endcase
1123
 
1124
                end /* STATE_TWOWORD */
1125
 
1126
            STATE_STALL: begin
1127
                pc_next = PC + 1;
1128
                next_state = STATE_NORMAL;
1129
                end /* STATE_STALL */
1130
 
1131
            STATE_LD: begin
1132
                pc_next = PC + 1;
1133
                next_state = STATE_NORMAL;
1134
                end /* STATE_LD */
1135
 
1136
            STATE_CALL: begin
1137
                sp_next = SP - 1;
1138
                sp_update = 1;
1139
                pc_next = pc_call;
1140
                next_state = STATE_STALL;
1141
                end /* STATE_CALL */
1142
 
1143
            STATE_RET: begin
1144
                pc_call_next = { 8'h00, dmem_di };
1145
                sp_next = SP + 1;
1146
                sp_update = 1;
1147
                next_state = STATE_RET2;
1148
                end /* STATE_RET2 */
1149
 
1150
            STATE_RET2: begin
1151
                pc_next = { dmem_di, pc_call[7:0] };
1152
                next_state = STATE_STALL;
1153
                end /* STATE_RET2 */
1154
 
1155
            STATE_SKIP: begin
1156
                if (two_word_instr)     next_state = STATE_STALL;
1157
                else                    next_state = STATE_NORMAL;
1158
                pc_next = PC + 1;
1159
                end /* STATE_SKIP */
1160
 
1161
            STATE_LPM: begin
1162
                pc_next = pc_call;
1163
                next_state = STATE_LPM2;
1164
                end
1165
 
1166
            STATE_LPM2: begin
1167
                pc_next = PC + 1;
1168
                next_state = STATE_NORMAL;
1169
                end
1170
 
1171
            STATE_ADIW: begin
1172
                if (PREVI[8]) begin
1173
                        /* SBIW */
1174
                        {nC, R_high} = GPR[24+2*Rp16+1] - C;
1175
                        nV =  GPR[24+2*Rp16+1][7] & ~R_high[7];
1176
                end else begin
1177
                        /* ADIW */
1178
                        {nC, R_high} = GPR[24+2*Rp16+1] + C;
1179
                        nV = ~GPR[24+2*Rp16+1][7] &  R_high[7];
1180
                end
1181
                nN = R_high[7];
1182
                nS = nN ^ nV;
1183
                nZ = (R_high==0) & Z;
1184
                pc_next = PC + 1;
1185
                next_state = STATE_NORMAL;
1186
                end
1187
 
1188
            STATE_IO_BIT: begin
1189
                pc_next = PC + 1;
1190
                next_state = STATE_NORMAL;
1191
                end
1192
 
1193
 
1194
        `ifdef AVR_INITIAL
1195
            STATE_INITIAL: begin
1196
                if (init_count[init_depth-1] == 1'b1)
1197
                        next_state = STATE_STALL;
1198
                else
1199
                        next_state = STATE_INITIAL;
1200
                end
1201
        `endif
1202
 
1203
        `ifdef AVR_HAVE_MUL
1204
            STATE_MUL: begin
1205
 
1206
                { R_high, R } = product;
1207
                if ( mul_type[0] & mul_rd[7] )
1208
                        R_high = R_high - mul_rr;
1209
                if ( mul_type[1] & mul_rr[7] )
1210
                        R_high = R_high - mul_rd;
1211
 
1212
                nZ = ( {R_high, R} == 16'h0000 );
1213
                nC = R_high[7];
1214
 
1215
                if ( mul_type[2] ) begin
1216
                        { R_high, R } = { R_high[6:0], R, 1'b0 };
1217
                end
1218
 
1219
                pc_next = PC + 1;
1220
                next_state = STATE_NORMAL;
1221
                end
1222
        `endif
1223
 
1224
        endcase
1225
 
1226
end /* always @(*) */
1227
 
1228
// Note: if `interrupt` is 1, then after this point:
1229
//  - state is STATE_NORMAL,
1230
//  - writeback is 0,
1231
//  - next_state is STATE_CALL.
1232
 
1233
`ifdef AVR_HAVE_MUL
1234
always @(posedge clk) if (next_state==STATE_MUL) begin
1235
        product <= GPR_Rd_mul * GPR_Rr_mul;
1236
        mul_rd <= GPR_Rd_mul;
1237
        mul_rr <= GPR_Rr_mul;
1238
        mul_type <= { fmulxx, xmulsx, xmulsu };
1239
end
1240
`endif
1241
 
1242
always @(posedge clk) begin
1243
 
1244
        `ifdef AVR_HAVE_MUL
1245
        if (state==STATE_MUL) begin
1246
        /* writeback: after two-cycle MUL: */
1247
                GPR[0] <= R;
1248
                GPR[1] <= R_high;
1249
        end else
1250
        `endif
1251
 
1252
        `ifdef AVR_HAVE_MOVW
1253
        /* writeback: after single cycle MOVW: */
1254
        if (state==STATE_NORMAL && INSTR[15:8]==8'b0000_0001 && ~is_interrupt) begin
1255
                GPR[2*RD16+0] <= R;                      // GPR[2*RR16+0];
1256
                GPR[2*RD16+1] <= R_high;                // GPR[2*RR16+1];
1257
        end else
1258
        `endif
1259
 
1260
        /* writeback: after the first and second cycle of ADIW and SUBW: */
1261
        if (next_state==STATE_ADIW)
1262
                GPR[24+2*Rd16+0] <= R;
1263
        else if (state==STATE_ADIW)
1264
                GPR[24+2*Rp16+1] <= R_high;
1265
        /* writeback after LD: */
1266
        else if ( state==STATE_LD )
1267
                GPR[Rd_ld_save] <= dmem_di;
1268
        else if ( state==STATE_LPM2 ) begin
1269
                if (~lpm_z_low) GPR[Rd_ld_save] <= INSTR[7:0];
1270
                else            GPR[Rd_ld_save] <= INSTR[15:8];
1271
        end else begin
1272
 
1273
        /* writeback: all of the another cases (ALU + X/Y/Z inc/dec): */
1274
        case (writeback)
1275
            WRITEBACK_GPR: begin
1276
                GPR[Rd] <= R;
1277
                end
1278
            WRITEBACK_ZINC: begin
1279
                GPR[30] <= RZ_inc[7:0];
1280
                GPR[31] <= RZ_inc[15:8];
1281
                end
1282
            WRITEBACK_ZY: begin
1283
                if (~INSTR[3]) begin
1284
                        GPR[30] <= RZ_inc_dec[7:0];
1285
                        GPR[31] <= RZ_inc_dec[15:8];
1286
                end else begin
1287
                        GPR[28] <= RY_inc_dec[7:0];
1288
                        GPR[29] <= RY_inc_dec[15:8];
1289
                end
1290
                end
1291
            WRITEBACK_X: begin
1292
                GPR[26] <= RX_inc_dec[7:0];
1293
                GPR[27] <= RX_inc_dec[15:8];
1294
                end
1295
        endcase
1296
 
1297
        end
1298
 
1299
        { I, T, H, S, V, N, Z, C } <= nSREG;
1300
 
1301
        if (~INSTR[9])  Rio <= Rin & ~(8'h01 << b);
1302
        else            Rio <= Rin |  (8'h01 << b);
1303
 
1304
        pc_call <= pc_call_next;
1305
 
1306
        if (next_state == STATE_LD)
1307
                Rd_ld_save <= (state == STATE_NORMAL ? Rd : Rd_prev);
1308
        else if (next_state == STATE_LPM) begin
1309
                Rd_ld_save <= (INSTR[10] ? 5'b00000: Rd);
1310
                lpm_z_low  <= RZ[0];
1311
        end
1312
 
1313
        `ifdef AVR_INITIAL
1314
        if ( ~init_count[init_depth-1] )
1315
                init_count <= init_count + 1;
1316
        `endif
1317
 
1318
        state <= next_state;
1319
        PC <= pc_next;
1320
 
1321
//      if ( sp_update )
1322
                SP <= sp_next;
1323
 
1324
end
1325
 
1326
/*****************************************************************************/
1327
 
1328
/* Debug section starts here */
1329
 
1330
wire [pmem_width:0] PC_double = {PC,1'b0};
1331
wire [7:0] R0 = GPR[0];
1332
wire [7:0] R1 = GPR[1];
1333
wire [7:0] R2 = GPR[2];
1334
wire [7:0] R3 = GPR[3];
1335
wire [7:0] R4 = GPR[4];
1336
wire [7:0] R5 = GPR[5];
1337
wire [7:0] R6 = GPR[6];
1338
wire [7:0] R7 = GPR[7];
1339
wire [7:0] R8 = GPR[8];
1340
wire [7:0] R9 = GPR[9];
1341
wire [7:0] R10 = GPR[10];
1342
wire [7:0] R11 = GPR[11];
1343
wire [7:0] R12 = GPR[12];
1344
wire [7:0] R13 = GPR[13];
1345
wire [7:0] R14 = GPR[14];
1346
wire [7:0] R15 = GPR[15];
1347
wire [7:0] R16 = GPR[16];
1348
wire [7:0] R17 = GPR[17];
1349
wire [7:0] R18 = GPR[18];
1350
wire [7:0] R19 = GPR[19];
1351
wire [7:0] R20 = GPR[20];
1352
wire [7:0] R21 = GPR[21];
1353
wire [7:0] R22 = GPR[22];
1354
wire [7:0] R23 = GPR[23];
1355
wire [7:0] R24 = GPR[24];
1356
wire [7:0] R25 = GPR[25];
1357
wire [7:0] R26 = GPR[26];
1358
wire [7:0] R27 = GPR[27];
1359
wire [7:0] R28 = GPR[28];
1360
wire [7:0] R29 = GPR[29];
1361
wire [7:0] R30 = GPR[30];
1362
wire [7:0] R31 = GPR[31];
1363
 
1364
`ifdef SIMULATOR
1365
initial begin
1366
        $dumpvars(1,PC,PC_double,INSTR,SP,SREG,state,pc_call,R);
1367
        $dumpvars(1,R0,R1,R16,R17,R18,R19,R20,R21,R22,R23,R24,R25,RX,RY,RZ);
1368
        $dumpvars(1,io_we,io_re,io_a,io_do,io_di,Rio);
1369
        $dumpvars(1,dmem_we,dmem_re,dmem_a,dmem_do,dmem_di);
1370
end
1371
`endif
1372
 
1373
/* end of debug section */
1374
/*****************************************************************************/
1375
 
1376
endmodule
1377
 
1378
/*****************************************************************************/

powered by: WebSVN 2.1.0

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