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

Subversion Repositories eco32

[/] [eco32/] [trunk/] [fpga/] [mc/] [src/] [cpu/] [cpu_core.v] - Blame information for rev 314

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

Line No. Rev Author Line
1 290 hellwig
//
2
// cpu_core.v -- the ECO32 CPU core
3
//
4
 
5
 
6
`timescale 1ns/10ps
7
`default_nettype none
8
 
9
 
10
module cpu_core(clk, rst,
11
                bus_stb, bus_we, bus_size, bus_addr,
12
                bus_din, bus_dout, bus_ack, bus_irq);
13
    input clk;                          // system clock
14
    input rst;                          // system reset
15
    output bus_stb;                     // bus strobe
16
    output bus_we;                      // bus write enable
17
    output [1:0] bus_size;               // 00: byte, 01: halfword, 10: word
18
    output [31:0] bus_addr;              // bus address
19
    input [31:0] bus_din;                // bus data input, for reads
20
    output [31:0] bus_dout;              // bus data output, for writes
21
    input bus_ack;                      // bus acknowledge
22
    input [15:0] bus_irq;                // bus interrupt requests
23
 
24
  // program counter
25
  wire [31:0] pc;                // program counter
26
  wire pc_we;                   // pc write enable
27
  wire [2:0] pc_src;             // pc source selector
28
  wire [31:0] pc_next;           // value written into pc
29
 
30
  // bus & mmu
31
  wire [31:0] mar;               // memory address register
32
  wire mar_we;                  // mar write enable
33
  wire ma_src;                  // memory address source selector
34
  wire [2:0] mmu_fnc;            // mmu function
35
  wire [31:0] virt_addr; // virtual address
36
  wire [31:0] phys_addr; // physical address
37
  wire [31:0] mdor;              // memory data out register
38
  wire mdor_we;                 // mdor write enable
39
  wire [31:0] mdir;              // memory data in register
40
  wire mdir_we;                 // mdir write enable
41
  wire mdir_sx;                 // mdir sign-extend
42
 
43
  // instruction register & decoder
44
  wire ir_we;                   // ir write enable
45
  wire [5:0] opcode;             // opcode part of ir
46
  wire [4:0] reg1;               // register 1 part of ir
47
  wire [4:0] reg2;               // register 2 part of ir
48
  wire [4:0] reg3;               // register 3 part of ir
49
  wire [31:0] sx16;              // sign-extended 16-bit immediate
50
  wire [31:0] zx16;              // zero-extended 16-bit immediate
51
  wire [31:0] hi16;              // high 16-bit immediate
52
  wire [31:0] sx16s2;            // sign-extended 16-bit immediate << 2
53
  wire [31:0] sx26s2;            // sign-extended 26-bit immediate << 2
54
 
55
  // register file
56
  wire [4:0] reg_a1;             // register address 1
57
  wire [31:0] reg_do1;           // register data out 1
58
  wire [1:0] reg_src2;           // register source 2 selector
59
  wire [4:0] reg_a2;             // register address 2
60
  wire [31:0] reg_do2;           // register data out 2
61
  wire reg_we2;                 // register write enable 2
62
  wire reg_we2_prot;            // register write enable 2,
63
                                // protected against writes with a2 = 0
64
  wire [2:0] reg_di2_src;        // register data in 2 source selector
65
  wire [31:0] reg_di2;           // register data in 2
66
 
67
  // alu, shift, and muldiv units
68
  wire alu_src1;                // alu source 1 selector
69
  wire [31:0] alu_op1;           // alu operand 1
70
  wire [2:0] alu_src2;           // alu source 2 selector
71
  wire [31:0] alu_op2;           // alu operand 2
72
  wire [2:0] alu_fnc;            // alu function
73
  wire [31:0] alu_res;           // alu result
74
  wire alu_equ;                 // alu operand 1 = operand 2
75
  wire alu_ult;                 // alu operand 1 < operand 2 (unsigned)
76
  wire alu_slt;                 // alu operand 1 < operand 2 (signed)
77
  wire [1:0] shift_fnc;          // shift function
78
  wire [31:0] shift_res; // shift result
79
  wire [2:0] muldiv_fnc; // muldiv function
80
  wire muldiv_start;            // muldiv should start
81
  wire muldiv_done;             // muldiv has finished
82
  wire muldiv_error;            // muldiv detected division by zero
83
  wire [31:0] muldiv_res;        // muldiv result
84
 
85
  // special registers
86
  wire [2:0] sreg_num;           // special register number
87
  wire sreg_we;                 // special register write enable
88
  wire [31:0] sreg_di;           // special register data in
89
  wire [31:0] sreg_do;           // special register data out
90
  wire [31:0] psw;               // special register 0 (psw) contents
91
  wire psw_we;                  // psw write enable
92
  wire [31:0] psw_new;           // new psw contents
93
  wire [31:0] tlb_index; // special register 1 (tlb index) contents
94
  wire tlb_index_we;            // tlb index write enable
95
  wire [31:0] tlb_index_new;     // new tlb index contents
96
  wire [31:0] tlb_entry_hi;      // special register 2 (tlb entry hi) contents
97
  wire tlb_entry_hi_we;         // tlb entry hi write enable
98
  wire [31:0] tlb_entry_hi_new;  // new tlb entry hi contents
99
  wire [31:0] tlb_entry_lo;      // special register 3 (tlb entry lo) contents
100
  wire tlb_entry_lo_we;         // tlb entry lo write enable
101
  wire [31:0] tlb_entry_lo_new;  // new tlb entry lo contents
102
  wire [31:0] mmu_bad_addr;      // special register 4 (mmu bad addr) contents
103
  wire mmu_bad_addr_we;         // mmu bad addr write enable
104
  wire [31:0] mmu_bad_addr_new;  // new mmu bad addr contents
105
  wire [31:0] mmu_bad_accs;      // special register 5 (mmu bad accs) contents
106
  wire mmu_bad_accs_we;         // mmu bad accs write enable
107
  wire [31:0] mmu_bad_accs_new;  // new mmu bad accs contents
108
 
109
  // mmu & tlb
110
  wire tlb_kmissed;             // page not found in tlb, MSB of addr is 1
111
  wire tlb_umissed;             // page not found in tlb, MSB of addr is 0
112
  wire tlb_invalid;             // tlb entry is invalid
113
  wire tlb_wrtprot;             // frame is write-protected
114
 
115
  //------------------------------------------------------------
116
 
117
  // program counter
118
  assign pc_next = (pc_src == 3'b000) ? alu_res :
119
                   (pc_src == 3'b001) ? 32'hE0000000 :
120
                   (pc_src == 3'b010) ? 32'hE0000004 :
121
                   (pc_src == 3'b011) ? 32'hC0000004 :
122
                   (pc_src == 3'b100) ? 32'hE0000008 :
123
                   (pc_src == 3'b101) ? 32'hC0000008 :
124
                   32'hxxxxxxxx;
125
  pc pc_1(clk, pc_we, pc_next, pc);
126
 
127
  // bus & mmu
128
  mar mar_1(clk, mar_we, alu_res, mar);
129
  assign virt_addr = (ma_src == 0) ? pc : mar;
130
  mmu mmu_1(clk, rst, mmu_fnc, virt_addr, phys_addr,
131
            tlb_index, tlb_index_new,
132
            tlb_entry_hi, tlb_entry_hi_new,
133
            tlb_entry_lo, tlb_entry_lo_new,
134
            tlb_kmissed, tlb_umissed,
135
            tlb_invalid, tlb_wrtprot);
136
  assign bus_addr = phys_addr;
137
  mdor mdor_1(clk, mdor_we, reg_do2, mdor);
138
  assign bus_dout = mdor;
139
  mdir mdir_1(clk, mdir_we, bus_din, bus_size, mdir_sx, mdir);
140
 
141
  // instruction register & decoder
142
  ir ir_1(clk,
143
          ir_we, bus_din,
144
          opcode, reg1, reg2, reg3,
145
          sx16, zx16, hi16, sx16s2, sx26s2);
146
 
147
  // register file
148
  assign reg_a1 = reg1;
149
  assign reg_a2 = (reg_src2 == 2'b00) ? reg2 :
150
                  (reg_src2 == 2'b01) ? reg3 :
151
                  (reg_src2 == 2'b10) ? 5'b11111 :
152
                  (reg_src2 == 2'b11) ? 5'b11110 :
153
                  5'bxxxxx;
154
  assign reg_we2_prot = reg_we2 & (| reg_a2[4:0]);
155
  assign reg_di2 = (reg_di2_src == 3'b000) ? alu_res :
156
                   (reg_di2_src == 3'b001) ? shift_res :
157
                   (reg_di2_src == 3'b010) ? muldiv_res :
158
                   (reg_di2_src == 3'b011) ? mdir :
159
                   (reg_di2_src == 3'b100) ? sreg_do :
160
                   32'hxxxxxxxx;
161
  regs regs_1(clk,
162
              reg_a1, reg_do1,
163
              reg_a2, reg_do2, reg_we2_prot, reg_di2);
164
 
165
  // alu, shift, and muldiv units
166
  assign alu_op1 = (alu_src1 == 0) ? pc : reg_do1;
167
  assign alu_op2 = (alu_src2 == 3'b000) ? 32'h00000004 :
168
                   (alu_src2 == 3'b001) ? reg_do2 :
169
                   (alu_src2 == 3'b010) ? sx16 :
170
                   (alu_src2 == 3'b011) ? zx16 :
171
                   (alu_src2 == 3'b100) ? hi16 :
172
                   (alu_src2 == 3'b101) ? sx16s2 :
173
                   (alu_src2 == 3'b110) ? sx26s2 :
174
                   32'hxxxxxxxx;
175
  alu alu_1(alu_op1, alu_op2, alu_fnc,
176
            alu_res, alu_equ, alu_ult, alu_slt);
177
  shift shift_1(clk, alu_op1, alu_op2[4:0], shift_fnc, shift_res);
178
  muldiv muldiv_1(clk, alu_op1, alu_op2, muldiv_fnc, muldiv_start,
179
                  muldiv_done, muldiv_error, muldiv_res);
180
 
181
  // special registers
182
  assign sreg_num = zx16[2:0];
183
  assign sreg_di = reg_do2;
184
  sregs sregs_1(clk, rst,
185
                sreg_num, sreg_we, sreg_di, sreg_do,
186
                psw, psw_we, psw_new,
187
                tlb_index, tlb_index_we, tlb_index_new,
188
                tlb_entry_hi, tlb_entry_hi_we, tlb_entry_hi_new,
189
                tlb_entry_lo, tlb_entry_lo_we, tlb_entry_lo_new,
190
                mmu_bad_addr, mmu_bad_addr_we, mmu_bad_addr_new,
191
                mmu_bad_accs, mmu_bad_accs_we, mmu_bad_accs_new);
192
  assign mmu_bad_addr_new = virt_addr;
193
  assign mmu_bad_accs_we = mmu_bad_addr_we;
194
  assign mmu_bad_accs_new = { 29'b0, bus_we, bus_size[1:0] };
195
 
196
  // ctrl
197
  ctrl ctrl_1(clk, rst,
198
              opcode, alu_equ, alu_ult, alu_slt,
199
              bus_ack, bus_stb, bus_we, bus_size,
200
              pc_src, pc_we,
201
              mar_we, ma_src, mmu_fnc,
202
              mdor_we, mdir_we, mdir_sx, ir_we,
203
              reg_src2, reg_di2_src, reg_we2,
204
              alu_src1, alu_src2, alu_fnc, shift_fnc,
205
              muldiv_fnc, muldiv_start,
206
              muldiv_done, muldiv_error,
207
              sreg_we, bus_irq, psw, psw_we, psw_new,
208
              virt_addr[31], virt_addr[1], virt_addr[0],
209
              tlb_kmissed, tlb_umissed,
210
              tlb_invalid, tlb_wrtprot,
211
              tlb_index_we, tlb_entry_hi_we,
212
              tlb_entry_lo_we, mmu_bad_addr_we);
213
 
214
endmodule
215
 
216
 
217
//--------------------------------------------------------------
218
// ctrl -- the finite state machine within the CPU
219
//--------------------------------------------------------------
220
 
221
 
222
module ctrl(clk, rst,
223
            opcode, alu_equ, alu_ult, alu_slt,
224
            bus_ack, bus_stb, bus_we, bus_size,
225
            pc_src, pc_we,
226
            mar_we, ma_src, mmu_fnc,
227
            mdor_we, mdir_we, mdir_sx, ir_we,
228
            reg_src2, reg_di2_src, reg_we2,
229
            alu_src1, alu_src2, alu_fnc, shift_fnc,
230
            muldiv_fnc, muldiv_start,
231
            muldiv_done, muldiv_error,
232
            sreg_we, bus_irq, psw, psw_we, psw_new,
233
            va_31, va_1, va_0,
234
            tlb_kmissed, tlb_umissed,
235
            tlb_invalid, tlb_wrtprot,
236
            tlb_index_we, tlb_entry_hi_we,
237
            tlb_entry_lo_we, mmu_bad_addr_we);
238
    input clk;
239
    input rst;
240
    input [5:0] opcode;
241
    input alu_equ;
242
    input alu_ult;
243
    input alu_slt;
244
    input bus_ack;
245
    output reg bus_stb;
246
    output reg bus_we;
247
    output reg [1:0] bus_size;
248
    output reg [2:0] pc_src;
249
    output reg pc_we;
250
    output reg mar_we;
251
    output reg ma_src;
252
    output reg [2:0] mmu_fnc;
253
    output reg mdor_we;
254
    output reg mdir_we;
255
    output reg mdir_sx;
256
    output reg ir_we;
257
    output reg [1:0] reg_src2;
258
    output reg [2:0] reg_di2_src;
259
    output reg reg_we2;
260
    output reg alu_src1;
261
    output reg [2:0] alu_src2;
262
    output reg [2:0] alu_fnc;
263
    output reg [1:0] shift_fnc;
264
    output reg [2:0] muldiv_fnc;
265
    output reg muldiv_start;
266
    input muldiv_done;
267
    input muldiv_error;
268
    output reg sreg_we;
269
    input [15:0] bus_irq;
270
    input [31:0] psw;
271
    output reg psw_we;
272
    output reg [31:0] psw_new;
273
    input va_31, va_1, va_0;
274
    input tlb_kmissed;
275
    input tlb_umissed;
276
    input tlb_invalid;
277
    input tlb_wrtprot;
278
    output reg tlb_index_we;
279
    output reg tlb_entry_hi_we;
280
    output reg tlb_entry_lo_we;
281
    output reg mmu_bad_addr_we;
282
 
283
  wire type_rrr;                // instr type is RRR
284
  wire type_rrs;                // instr type is RRS
285
  wire type_rrh;                // instr type is RRH
286
  wire type_rhh;                // instr type is RHH
287
  wire type_rrb;                // instr type is RRB
288
  wire type_j;                  // instr type is J
289
  wire type_jr;                 // instr type is JR
290
  wire type_link;               // instr saves PC+4 in $31
291
  wire type_ld;                 // instr loads data
292
  wire type_st;                 // instr stores data
293
  wire type_ldst;               // instr loads or stores data
294
  wire [1:0] ldst_size;          // load/store transfer size
295
  wire type_shift;              // instr uses the shift unit
296
  wire type_muldiv;             // instr uses the muldiv unit
297
  wire type_fast;               // instr is not shift or muldiv
298
  wire type_mvfs;               // instr is mvfs
299
  wire type_mvts;               // instr is mvts
300
  wire type_rfx;                // instr is rfx
301
  wire type_trap;               // instr is trap
302
  wire type_tb;                 // instr is a TLB instr
303
  reg [4:0] state;               // cpu internal state
304
                                //  0: reset
305
                                //  1: fetch instr (addr xlat)
306
                                //  2: decode instr
307
                                //     increment pc by 4
308
                                //     possibly store pc+4 in $31
309
                                //  3: execute RRR-type instr
310
                                //  4: execute RRS-type instr
311
                                //  5: execute RRH-type instr
312
                                //  6: execute RHH-type instr
313
                                //  7: execute RRB-type instr (1)
314
                                //  8: execute RRB-type instr (2)
315
                                //  9: execute J-type instr
316
                                // 10: execute JR-type instr
317
                                // 11: execute LDST-type instr (1)
318
                                // 12: execute LD-type instr (addr xlat)
319
                                // 13: execute LD-type instr (3)
320
                                // 14: execute ST-type instr (addr xlat)
321
                                // 15: interrupt
322
                                // 16: extra state for RRR shift instr
323
                                // 17: extra state for RRH shift instr
324
                                // 18: extra state for RRR muldiv instr
325
                                // 19: extra state for RRS muldiv instr
326
                                // 20: extra state for RRH muldiv instr
327
                                // 21: execute mvfs instr
328
                                // 22: execute mvts instr
329
                                // 23: execute rfx instr
330
                                // 24: irq_trigger check for mvts and rfx
331
                                // 25: exception (locus is PC-4)
332
                                // 26: exception (locus is PC)
333
                                // 27: execute TLB instr
334
                                // 28: fetch instr (bus cycle)
335
                                // 29: execute LD-type instr (bus cycle)
336
                                // 30: execute ST-type instr (bus cycle)
337
                                // all other: unused
338
  reg branch;                   // take the branch iff true
339
  wire [15:0] irq_pending;       // the vector of pending unmasked irqs
340
  wire irq_trigger;             // true iff any pending irq is present
341
                                // and interrupts are globally enabled
342
  reg [3:0] irq_priority;        // highest priority of pending interrupts
343
  reg [3:0] exc_priority;        // exception, when entering state 25 or 26
344
  reg [7:0] bus_count;           // counter to detect bus timeout
345
  wire bus_timeout;             // bus timeout detected
346
  wire exc_prv_addr;            // privileged address exception detected
347
  wire exc_ill_addr;            // illegal address exception detected
348
  wire exc_tlb_but_wrtprot;     // any tlb exception but write protection
349
  wire exc_tlb_any;             // any tlb exception
350
 
351
  //------------------------------------------------------------
352
 
353
  // decode instr type
354
  assign type_rrr    = ((opcode == 6'h00) ||
355
                        (opcode == 6'h02) ||
356
                        (opcode == 6'h04) ||
357
                        (opcode == 6'h06) ||
358
                        (opcode == 6'h08) ||
359
                        (opcode == 6'h0A) ||
360
                        (opcode == 6'h0C) ||
361
                        (opcode == 6'h0E) ||
362
                        (opcode == 6'h10) ||
363
                        (opcode == 6'h12) ||
364
                        (opcode == 6'h14) ||
365
                        (opcode == 6'h16) ||
366
                        (opcode == 6'h18) ||
367
                        (opcode == 6'h1A) ||
368
                        (opcode == 6'h1C)) ? 1 : 0;
369
  assign type_rrs    = ((opcode == 6'h01) ||
370
                        (opcode == 6'h03) ||
371
                        (opcode == 6'h05) ||
372
                        (opcode == 6'h09) ||
373
                        (opcode == 6'h0D)) ? 1 : 0;
374
  assign type_rrh    = ((opcode == 6'h07) ||
375
                        (opcode == 6'h0B) ||
376
                        (opcode == 6'h0F) ||
377
                        (opcode == 6'h11) ||
378
                        (opcode == 6'h13) ||
379
                        (opcode == 6'h15) ||
380
                        (opcode == 6'h17) ||
381
                        (opcode == 6'h19) ||
382
                        (opcode == 6'h1B) ||
383
                        (opcode == 6'h1D)) ? 1 : 0;
384
  assign type_rhh    = (opcode == 6'h1F) ? 1 : 0;
385
  assign type_rrb    = ((opcode == 6'h20) ||
386
                        (opcode == 6'h21) ||
387
                        (opcode == 6'h22) ||
388
                        (opcode == 6'h23) ||
389
                        (opcode == 6'h24) ||
390
                        (opcode == 6'h25) ||
391
                        (opcode == 6'h26) ||
392
                        (opcode == 6'h27) ||
393
                        (opcode == 6'h28) ||
394
                        (opcode == 6'h29)) ? 1 : 0;
395
  assign type_j      = ((opcode == 6'h2A) ||
396
                        (opcode == 6'h2C)) ? 1 : 0;
397
  assign type_jr     = ((opcode == 6'h2B) ||
398
                        (opcode == 6'h2D)) ? 1 : 0;
399
  assign type_link   = ((opcode == 6'h2C) ||
400
                        (opcode == 6'h2D)) ? 1 : 0;
401
  assign type_ld     = ((opcode == 6'h30) ||
402
                        (opcode == 6'h31) ||
403
                        (opcode == 6'h32) ||
404
                        (opcode == 6'h33) ||
405
                        (opcode == 6'h34)) ? 1 : 0;
406
  assign type_st     = ((opcode == 6'h35) ||
407
                        (opcode == 6'h36) ||
408
                        (opcode == 6'h37)) ? 1 : 0;
409
  assign type_ldst   = type_ld | type_st;
410
  assign ldst_size   = ((opcode == 6'h30) ||
411
                        (opcode == 6'h35)) ? 2'b10 :
412
                       ((opcode == 6'h31) ||
413
                        (opcode == 6'h32) ||
414
                        (opcode == 6'h36)) ? 2'b01 :
415
                       ((opcode == 6'h33) ||
416
                        (opcode == 6'h34) ||
417
                        (opcode == 6'h37)) ? 2'b00 :
418
                       2'bxx;
419
  assign type_shift  = ((opcode == 6'h18) ||
420
                        (opcode == 6'h19) ||
421
                        (opcode == 6'h1A) ||
422
                        (opcode == 6'h1B) ||
423
                        (opcode == 6'h1C) ||
424
                        (opcode == 6'h1D)) ? 1 : 0;
425
  assign type_muldiv = ((opcode == 6'h04) ||
426
                        (opcode == 6'h05) ||
427
                        (opcode == 6'h06) ||
428
                        (opcode == 6'h07) ||
429
                        (opcode == 6'h08) ||
430
                        (opcode == 6'h09) ||
431
                        (opcode == 6'h0A) ||
432
                        (opcode == 6'h0B) ||
433
                        (opcode == 6'h0C) ||
434
                        (opcode == 6'h0D) ||
435
                        (opcode == 6'h0E) ||
436
                        (opcode == 6'h0F)) ? 1 : 0;
437
  assign type_fast   = ~(type_shift | type_muldiv);
438
  assign type_mvfs   = (opcode == 6'h38) ? 1 : 0;
439
  assign type_mvts   = (opcode == 6'h39) ? 1 : 0;
440
  assign type_rfx    = (opcode == 6'h2F) ? 1 : 0;
441
  assign type_trap   = (opcode == 6'h2E) ? 1 : 0;
442
  assign type_tb     = ((opcode == 6'h3A) ||
443
                        (opcode == 6'h3B) ||
444
                        (opcode == 6'h3C) ||
445
                        (opcode == 6'h3D)) ? 1 : 0;
446
 
447
  // state machine
448
  always @(posedge clk) begin
449
    if (rst == 1) begin
450
      state <= 0;
451
    end else begin
452
      case (state)
453
        5'd0:  // reset
454
          begin
455
            state <= 5'd1;
456
          end
457
        5'd1:  // fetch instr (addr xlat)
458
          begin
459
            if (exc_prv_addr) begin
460
              state <= 26;
461
              exc_priority <= 4'd9;
462
            end else
463
            if (exc_ill_addr) begin
464
              state <= 26;
465
              exc_priority <= 4'd8;
466
            end else begin
467
              state <= 5'd28;
468
            end
469
          end
470
        5'd2:  // decode instr
471
               // increment pc by 4
472
               // possibly store pc+4 in $31
473
          begin
474
            if (type_rrr) begin
475
              // RRR-type instruction
476
              state <= 5'd3;
477
            end else
478
            if (type_rrs) begin
479
              // RRS-type instruction
480
              state <= 5'd4;
481
            end else
482
            if (type_rrh) begin
483
              // RRH-type instruction
484
              state <= 5'd5;
485
            end else
486
            if (type_rhh) begin
487
              // RHH-type instruction
488
              state <= 5'd6;
489
            end else
490
            if (type_rrb) begin
491
              // RRB-type instr
492
              state <= 5'd7;
493
            end else
494
            if (type_j) begin
495
              // J-type instr
496
              state <= 5'd9;
497
            end else
498
            if (type_jr) begin
499
              // JR-type instr
500
              state <= 5'd10;
501
            end else
502
            if (type_ldst) begin
503
              // LDST-type instr
504
              state <= 5'd11;
505
            end else
506
            if (type_mvfs) begin
507
              // mvfs instr
508
              state <= 5'd21;
509
            end else
510
            if (type_mvts) begin
511
              // mvts instr
512
              if (psw[26] == 1) begin
513
                state <= 5'd25;
514
                exc_priority <= 4'd2;
515
              end else begin
516
                state <= 5'd22;
517
              end
518
            end else
519
            if (type_rfx) begin
520
              // rfx instr
521
              if (psw[26] == 1) begin
522
                state <= 5'd25;
523
                exc_priority <= 4'd2;
524
              end else begin
525
                state <= 5'd23;
526
              end
527
            end else
528
            if (type_trap) begin
529
              // trap instr
530
              state <= 5'd25;
531
              exc_priority <= 4'd4;
532
            end else
533
            if (type_tb) begin
534
              // TLB instr
535
              if (psw[26] == 1) begin
536
                state <= 5'd25;
537
                exc_priority <= 4'd2;
538
              end else begin
539
                state <= 5'd27;
540
              end
541
            end else begin
542
              // illegal instruction
543
              state <= 5'd25;
544
              exc_priority <= 4'd1;
545
            end
546
          end
547
        5'd3:  // execute RRR-type instr
548
          begin
549
            if (type_muldiv) begin
550
              state <= 5'd18;
551
            end else
552
            if (type_shift) begin
553
              state <= 5'd16;
554
            end else begin
555
              if (irq_trigger) begin
556
                state <= 5'd15;
557
              end else begin
558
                state <= 5'd1;
559
              end
560
            end
561
          end
562
        5'd4:  // execute RRS-type instr
563
          begin
564
            if (type_muldiv) begin
565
              state <= 5'd19;
566
            end else begin
567
              if (irq_trigger) begin
568
                state <= 5'd15;
569
              end else begin
570
                state <= 5'd1;
571
              end
572
            end
573
          end
574
        5'd5:  // execute RRH-type instr
575
          begin
576
            if (type_muldiv) begin
577
              state <= 5'd20;
578
            end else
579
            if (type_shift) begin
580
              state <= 5'd17;
581
            end else begin
582
              if (irq_trigger) begin
583
                state <= 5'd15;
584
              end else begin
585
                state <= 5'd1;
586
              end
587
            end
588
          end
589
        5'd6:  // execute RHH-type instr
590
          begin
591
            if (irq_trigger) begin
592
              state <= 5'd15;
593
            end else begin
594
              state <= 5'd1;
595
            end
596
          end
597
        5'd7:  // execute RRB-type instr (1)
598
          begin
599
            if (branch) begin
600
              state <= 5'd8;
601
            end else begin
602
              if (irq_trigger) begin
603
                state <= 5'd15;
604
              end else begin
605
                state <= 5'd1;
606
              end
607
            end
608
          end
609
        5'd8:  // execute RRB-type instr (2)
610
          begin
611
            if (irq_trigger) begin
612
              state <= 5'd15;
613
            end else begin
614
              state <= 5'd1;
615
            end
616
          end
617
        5'd9:  // execute J-type instr
618
          begin
619
            if (irq_trigger) begin
620
              state <= 5'd15;
621
            end else begin
622
              state <= 5'd1;
623
            end
624
          end
625
        5'd10:  // execute JR-type instr
626
          begin
627
            if (irq_trigger) begin
628
              state <= 5'd15;
629
            end else begin
630
              state <= 5'd1;
631
            end
632
          end
633
        5'd11:  // execute LDST-type instr (1)
634
          begin
635
            if (type_ld) begin
636
              state <= 5'd12;
637
            end else begin
638
              state <= 5'd14;
639
            end
640
          end
641
        5'd12:  // execute LD-type instr (addr xlat)
642
          begin
643
            if (exc_prv_addr) begin
644
              state <= 25;
645
              exc_priority <= 4'd9;
646
            end else
647
            if (exc_ill_addr) begin
648
              state <= 25;
649
              exc_priority <= 4'd8;
650
            end else begin
651
              state <= 5'd29;
652
            end
653
          end
654
        5'd13:  // execute LD-type instr (3)
655
          begin
656
            if (irq_trigger) begin
657
              state <= 5'd15;
658
            end else begin
659
              state <= 5'd1;
660
            end
661
          end
662
        5'd14:  // execute ST-type instr (addr xlat)
663
          begin
664
            if (exc_prv_addr) begin
665
              state <= 25;
666
              exc_priority <= 4'd9;
667
            end else
668
            if (exc_ill_addr) begin
669
              state <= 25;
670
              exc_priority <= 4'd8;
671
            end else begin
672
              state <= 5'd30;
673
            end
674
          end
675
        5'd15:  // interrupt
676
          begin
677
            state <= 5'd1;
678
          end
679
        5'd16:  // extra state for RRR shift instr
680
          begin
681
            if (irq_trigger) begin
682
              state <= 5'd15;
683
            end else begin
684
              state <= 5'd1;
685
            end
686
          end
687
        5'd17:  // extra state for RRH shift instr
688
          begin
689
            if (irq_trigger) begin
690
              state <= 5'd15;
691
            end else begin
692
              state <= 5'd1;
693
            end
694
          end
695
        5'd18:  // extra state for RRR muldiv instr
696
          begin
697
            if (muldiv_done) begin
698
              if (muldiv_error) begin
699
                state <= 5'd25;
700
                exc_priority <= 4'd3;
701
              end else
702
              if (irq_trigger) begin
703
                state <= 5'd15;
704
              end else begin
705
                state <= 5'd1;
706
              end
707
            end else begin
708
              state <= 5'd18;
709
            end
710
          end
711
        5'd19:  // extra state for RRS muldiv instr
712
          begin
713
            if (muldiv_done) begin
714
              if (muldiv_error) begin
715
                state <= 5'd25;
716
                exc_priority <= 4'd3;
717
              end else
718
              if (irq_trigger) begin
719
                state <= 5'd15;
720
              end else begin
721
                state <= 5'd1;
722
              end
723
            end else begin
724
              state <= 5'd19;
725
            end
726
          end
727
        5'd20:  // extra state for RRH muldiv instr
728
          begin
729
            if (muldiv_done) begin
730
              if (muldiv_error) begin
731
                state <= 5'd25;
732
                exc_priority <= 4'd3;
733
              end else
734
              if (irq_trigger) begin
735
                state <= 5'd15;
736
              end else begin
737
                state <= 5'd1;
738
              end
739
            end else begin
740
              state <= 5'd20;
741
            end
742
          end
743
        5'd21:  // execute mvfs instr
744
          begin
745
            if (irq_trigger) begin
746
              state <= 5'd15;
747
            end else begin
748
              state <= 5'd1;
749
            end
750
          end
751
        5'd22:  // execute mvts instr
752
          begin
753
            state <= 5'd24;
754
          end
755
        5'd23:  // execute rfx instr
756
          begin
757
            state <= 5'd24;
758
          end
759
        5'd24:  // irq_trigger check for mvts and rfx
760
          begin
761
            if (irq_trigger) begin
762
              state <= 5'd15;
763
            end else begin
764
              state <= 5'd1;
765
            end
766
          end
767
        5'd25:  // exception (locus is PC-4)
768
          begin
769
            state <= 5'd1;
770
          end
771
        5'd26:  // exception (locus is PC)
772
          begin
773
            state <= 5'd1;
774
          end
775
        5'd27:  // execute TLB instr
776
          begin
777
            if (irq_trigger) begin
778
              state <= 5'd15;
779
            end else begin
780
              state <= 5'd1;
781
            end
782
          end
783
        5'd28:  // fetch instr (bus cycle)
784
          begin
785
            if (tlb_kmissed == 1 || tlb_umissed == 1) begin
786
              state <= 5'd26;
787
              exc_priority <= 4'd5;
788
            end else
789
            if (tlb_invalid == 1) begin
790
              state <= 5'd26;
791
              exc_priority <= 4'd7;
792
            end else
793
            if (bus_ack == 0) begin
794
              if (bus_timeout == 1) begin
795
                state <= 5'd26;
796
                exc_priority <= 4'd0;
797
              end else begin
798
                state <= 5'd28;
799
              end
800
            end else begin
801
              state <= 5'd2;
802
            end
803
          end
804
        5'd29:  // execute LD-type instr (bus cycle)
805
          begin
806
            if (tlb_kmissed == 1 || tlb_umissed == 1) begin
807
              state <= 5'd25;
808
              exc_priority <= 4'd5;
809
            end else
810
            if (tlb_invalid == 1) begin
811
              state <= 5'd25;
812
              exc_priority <= 4'd7;
813
            end else
814
            if (bus_ack == 0) begin
815
              if (bus_timeout == 1) begin
816
                state <= 5'd25;
817
                exc_priority <= 4'd0;
818
              end else begin
819
                state <= 5'd29;
820
              end
821
            end else begin
822
              state <= 5'd13;
823
            end
824
          end
825
        5'd30:  // execute ST-type instr (bus cycle)
826
          begin
827
            if (tlb_kmissed == 1 || tlb_umissed == 1) begin
828
              state <= 5'd25;
829
              exc_priority <= 4'd5;
830
            end else
831
            if (tlb_invalid == 1) begin
832
              state <= 5'd25;
833
              exc_priority <= 4'd7;
834
            end else
835
            if (tlb_wrtprot == 1) begin
836
              state <= 5'd25;
837
              exc_priority <= 4'd6;
838
            end else
839
            if (bus_ack == 0) begin
840
              if (bus_timeout == 1) begin
841
                state <= 5'd25;
842
                exc_priority <= 4'd0;
843
              end else begin
844
                state <= 5'd30;
845
              end
846
            end else begin
847
              if (irq_trigger) begin
848
                state <= 5'd15;
849
              end else begin
850
                state <= 5'd1;
851
              end
852
            end
853
          end
854
        default:  // all other states: unused
855
          begin
856
            state <= 5'd0;
857
          end
858
      endcase
859
    end
860
  end
861
 
862
  // bus timeout detector
863
  assign bus_timeout = (bus_count == 8'h00) ? 1 : 0;
864
  always @(posedge clk) begin
865
    if (bus_stb == 1 && bus_ack == 0) begin
866
      // bus is waiting
867
      bus_count <= bus_count - 1;
868
    end else begin
869
      // bus is not waiting
870
      bus_count <= 8'hFF;
871
    end
872
  end
873
 
874
  // output logic
875
  always @(*) begin
876
    case (state)
877
      5'd0:  // reset
878
        begin
879
          pc_src = 3'b001;
880
          pc_we = 1'b1;
881
          mar_we = 1'b0;
882
          ma_src = 1'bx;
883
          mmu_fnc = 3'b000;
884
          mdor_we = 1'b0;
885
          bus_stb = 1'b0;
886
          bus_we = 1'bx;
887
          bus_size = 2'bxx;
888
          mdir_we = 1'b0;
889
          mdir_sx = 1'bx;
890
          ir_we = 1'b0;
891
          reg_src2 = 2'bxx;
892
          reg_di2_src = 3'bxxx;
893
          reg_we2 = 1'b0;
894
          alu_src1 = 1'bx;
895
          alu_src2 = 3'bxxx;
896
          alu_fnc = 3'bxxx;
897
          shift_fnc = 2'bxx;
898
          muldiv_fnc = 3'bxxx;
899
          muldiv_start = 1'b0;
900
          sreg_we = 1'b0;
901
          psw_we = 1'b0;
902
          psw_new = 32'hxxxxxxxx;
903
          tlb_index_we = 1'b0;
904
          tlb_entry_hi_we = 1'b0;
905
          tlb_entry_lo_we = 1'b0;
906
          mmu_bad_addr_we = 1'b0;
907
        end
908
      5'd1:  // fetch instr (addr xlat)
909
        begin
910
          pc_src = 3'bxxx;
911
          pc_we = 1'b0;
912
          mar_we = 1'b0;
913
          ma_src = 1'b0;
914
          mmu_fnc = (exc_prv_addr | exc_ill_addr) ? 3'b000 : 3'b001;
915
          mdor_we = 1'b0;
916
          bus_stb = 1'b0;
917
          bus_we = 1'b0;         // get bad_accs right in case of exc
918
          bus_size = 2'b10;      // enable illegal address detection
919
          mdir_we = 1'b0;
920
          mdir_sx = 1'bx;
921
          ir_we = 1'b0;
922
          reg_src2 = 2'bxx;
923
          reg_di2_src = 3'bxxx;
924
          reg_we2 = 1'b0;
925
          alu_src1 = 1'bx;
926
          alu_src2 = 3'bxxx;
927
          alu_fnc = 3'bxxx;
928
          shift_fnc = 2'bxx;
929
          muldiv_fnc = 3'bxxx;
930
          muldiv_start = 1'b0;
931
          sreg_we = 1'b0;
932
          psw_we = 1'b0;
933
          psw_new = 32'hxxxxxxxx;
934
          tlb_index_we = 1'b0;
935
          tlb_entry_hi_we = 1'b0;
936
          tlb_entry_lo_we = 1'b0;
937
          mmu_bad_addr_we = exc_prv_addr | exc_ill_addr;
938
        end
939
      5'd2:  // decode instr
940
             // increment pc by 4
941
             // possibly store pc+4 in $31
942
        begin
943
          pc_src = 3'b000;
944
          pc_we = 1'b1;
945
          mar_we = 1'b0;
946
          ma_src = 1'bx;
947
          mmu_fnc = 3'b000;
948
          mdor_we = 1'b0;
949
          bus_stb = 1'b0;
950
          bus_we = 1'bx;
951
          bus_size = 2'bxx;
952
          mdir_we = 1'b0;
953
          mdir_sx = 1'bx;
954
          ir_we = 1'b0;
955
          reg_src2 = (type_link == 1) ? 2'b10 :
956
                     (type_rfx == 1) ? 2'b11 :
957
                     2'b00;
958
          reg_di2_src = (type_link == 1) ? 3'b000 : 3'bxxx;
959
          reg_we2 = (type_link == 1) ? 1'b1 : 1'b0;
960
          alu_src1 = 1'b0;
961
          alu_src2 = 3'b000;
962
          alu_fnc = 3'b000;
963
          shift_fnc = 2'bxx;
964
          muldiv_fnc = 3'bxxx;
965
          muldiv_start = 1'b0;
966
          sreg_we = 1'b0;
967
          psw_we = 1'b0;
968
          psw_new = 32'hxxxxxxxx;
969
          tlb_index_we = 1'b0;
970
          tlb_entry_hi_we = 1'b0;
971
          tlb_entry_lo_we = 1'b0;
972
          mmu_bad_addr_we = 1'b0;
973
        end
974
      5'd3:  // execute RRR-type instr
975
        begin
976
          pc_src = 3'bxxx;
977
          pc_we = 1'b0;
978
          mar_we = 1'b0;
979
          ma_src = 1'bx;
980
          mmu_fnc = 3'b000;
981
          mdor_we = 1'b0;
982
          bus_stb = 1'b0;
983
          bus_we = 1'bx;
984
          bus_size = 2'bxx;
985
          mdir_we = 1'b0;
986
          mdir_sx = 1'bx;
987
          ir_we = 1'b0;
988
          reg_src2 = 2'b01;
989
          reg_di2_src = 3'b000;
990
          reg_we2 = type_fast;
991
          alu_src1 = 1'b1;
992
          alu_src2 = 3'b001;
993
          alu_fnc = { opcode[4], opcode[2], opcode[1] };
994
          shift_fnc = { opcode[2], opcode[1] };
995
          muldiv_fnc = { opcode[3], opcode[2], opcode[1] };
996
          muldiv_start = type_muldiv;
997
          sreg_we = 1'b0;
998
          psw_we = 1'b0;
999
          psw_new = 32'hxxxxxxxx;
1000
          tlb_index_we = 1'b0;
1001
          tlb_entry_hi_we = 1'b0;
1002
          tlb_entry_lo_we = 1'b0;
1003
          mmu_bad_addr_we = 1'b0;
1004
        end
1005
      5'd4:  // execute RRS-type instr
1006
        begin
1007
          pc_src = 3'bxxx;
1008
          pc_we = 1'b0;
1009
          mar_we = 1'b0;
1010
          ma_src = 1'bx;
1011
          mmu_fnc = 3'b000;
1012
          mdor_we = 1'b0;
1013
          bus_stb = 1'b0;
1014
          bus_we = 1'bx;
1015
          bus_size = 2'bxx;
1016
          mdir_we = 1'b0;
1017
          mdir_sx = 1'bx;
1018
          ir_we = 1'b0;
1019
          reg_src2 = 2'b00;
1020
          reg_di2_src = 3'b000;
1021
          reg_we2 = type_fast;
1022
          alu_src1 = 1'b1;
1023
          alu_src2 = 3'b010;
1024
          alu_fnc = { opcode[4], opcode[2], opcode[1] };
1025
          shift_fnc = 2'bxx;
1026
          muldiv_fnc = { opcode[3], opcode[2], opcode[1] };
1027
          muldiv_start = type_muldiv;
1028
          sreg_we = 1'b0;
1029
          psw_we = 1'b0;
1030
          psw_new = 32'hxxxxxxxx;
1031
          tlb_index_we = 1'b0;
1032
          tlb_entry_hi_we = 1'b0;
1033
          tlb_entry_lo_we = 1'b0;
1034
          mmu_bad_addr_we = 1'b0;
1035
        end
1036
      5'd5:  // execute RRH-type instr
1037
        begin
1038
          pc_src = 3'bxxx;
1039
          pc_we = 1'b0;
1040
          mar_we = 1'b0;
1041
          ma_src = 1'bx;
1042
          mmu_fnc = 3'b000;
1043
          mdor_we = 1'b0;
1044
          bus_stb = 1'b0;
1045
          bus_we = 1'bx;
1046
          bus_size = 2'bxx;
1047
          mdir_we = 1'b0;
1048
          mdir_sx = 1'bx;
1049
          ir_we = 1'b0;
1050
          reg_src2 = 2'b00;
1051
          reg_di2_src = 3'b000;
1052
          reg_we2 = type_fast;
1053
          alu_src1 = 1'b1;
1054
          alu_src2 = 3'b011;
1055
          alu_fnc = { opcode[4], opcode[2], opcode[1] };
1056
          shift_fnc = { opcode[2], opcode[1] };
1057
          muldiv_fnc = { opcode[3], opcode[2], opcode[1] };
1058
          muldiv_start = type_muldiv;
1059
          sreg_we = 1'b0;
1060
          psw_we = 1'b0;
1061
          psw_new = 32'hxxxxxxxx;
1062
          tlb_index_we = 1'b0;
1063
          tlb_entry_hi_we = 1'b0;
1064
          tlb_entry_lo_we = 1'b0;
1065
          mmu_bad_addr_we = 1'b0;
1066
        end
1067
      5'd6:  // execute RHH-type instr
1068
        begin
1069
          pc_src = 3'bxxx;
1070
          pc_we = 1'b0;
1071
          mar_we = 1'b0;
1072
          ma_src = 1'bx;
1073
          mmu_fnc = 3'b000;
1074
          mdor_we = 1'b0;
1075
          bus_stb = 1'b0;
1076
          bus_we = 1'bx;
1077
          bus_size = 2'bxx;
1078
          mdir_we = 1'b0;
1079
          mdir_sx = 1'bx;
1080
          ir_we = 1'b0;
1081
          reg_src2 = 2'b00;
1082
          reg_di2_src = 3'b000;
1083
          reg_we2 = 1'b1;
1084
          alu_src1 = 1'bx;
1085
          alu_src2 = 3'b100;
1086
          alu_fnc = 3'b011;
1087
          shift_fnc = 2'bxx;
1088
          muldiv_fnc = 3'bxxx;
1089
          muldiv_start = 1'b0;
1090
          sreg_we = 1'b0;
1091
          psw_we = 1'b0;
1092
          psw_new = 32'hxxxxxxxx;
1093
          tlb_index_we = 1'b0;
1094
          tlb_entry_hi_we = 1'b0;
1095
          tlb_entry_lo_we = 1'b0;
1096
          mmu_bad_addr_we = 1'b0;
1097
        end
1098
      5'd7:  // execute RRB-type instr (1)
1099
        begin
1100
          pc_src = 3'bxxx;
1101
          pc_we = 1'b0;
1102
          mar_we = 1'b0;
1103
          ma_src = 1'bx;
1104
          mmu_fnc = 3'b000;
1105
          mdor_we = 1'b0;
1106
          bus_stb = 1'b0;
1107
          bus_we = 1'bx;
1108
          bus_size = 2'bxx;
1109
          mdir_we = 1'b0;
1110
          mdir_sx = 1'bx;
1111
          ir_we = 1'b0;
1112
          reg_src2 = 2'bxx;
1113
          reg_di2_src = 3'bxxx;
1114
          reg_we2 = 1'b0;
1115
          alu_src1 = 1'b1;
1116
          alu_src2 = 3'b001;
1117
          alu_fnc = 3'b001;
1118
          shift_fnc = 2'bxx;
1119
          muldiv_fnc = 3'bxxx;
1120
          muldiv_start = 1'b0;
1121
          sreg_we = 1'b0;
1122
          psw_we = 1'b0;
1123
          psw_new = 32'hxxxxxxxx;
1124
          tlb_index_we = 1'b0;
1125
          tlb_entry_hi_we = 1'b0;
1126
          tlb_entry_lo_we = 1'b0;
1127
          mmu_bad_addr_we = 1'b0;
1128
        end
1129
      5'd8:  // execute RRB-type instr (2)
1130
        begin
1131
          pc_src = 3'b000;
1132
          pc_we = 1'b1;
1133
          mar_we = 1'b0;
1134
          ma_src = 1'bx;
1135
          mmu_fnc = 3'b000;
1136
          mdor_we = 1'b0;
1137
          bus_stb = 1'b0;
1138
          bus_we = 1'bx;
1139
          bus_size = 2'bxx;
1140
          mdir_we = 1'b0;
1141
          mdir_sx = 1'bx;
1142
          ir_we = 1'b0;
1143
          reg_src2 = 2'bxx;
1144
          reg_di2_src = 3'bxxx;
1145
          reg_we2 = 1'b0;
1146
          alu_src1 = 1'b0;
1147
          alu_src2 = 3'b101;
1148
          alu_fnc = 3'b000;
1149
          shift_fnc = 2'bxx;
1150
          muldiv_fnc = 3'bxxx;
1151
          muldiv_start = 1'b0;
1152
          sreg_we = 1'b0;
1153
          psw_we = 1'b0;
1154
          psw_new = 32'hxxxxxxxx;
1155
          tlb_index_we = 1'b0;
1156
          tlb_entry_hi_we = 1'b0;
1157
          tlb_entry_lo_we = 1'b0;
1158
          mmu_bad_addr_we = 1'b0;
1159
        end
1160
      5'd9:  // execute J-type instr
1161
        begin
1162
          pc_src = 3'b000;
1163
          pc_we = 1'b1;
1164
          mar_we = 1'b0;
1165
          ma_src = 1'bx;
1166
          mmu_fnc = 3'b000;
1167
          mdor_we = 1'b0;
1168
          bus_stb = 1'b0;
1169
          bus_we = 1'bx;
1170
          bus_size = 2'bxx;
1171
          mdir_we = 1'b0;
1172
          mdir_sx = 1'bx;
1173
          ir_we = 1'b0;
1174
          reg_src2 = 2'bxx;
1175
          reg_di2_src = 3'bxxx;
1176
          reg_we2 = 1'b0;
1177
          alu_src1 = 1'b0;
1178
          alu_src2 = 3'b110;
1179
          alu_fnc = 3'b000;
1180
          shift_fnc = 2'bxx;
1181
          muldiv_fnc = 3'bxxx;
1182
          muldiv_start = 1'b0;
1183
          sreg_we = 1'b0;
1184
          psw_we = 1'b0;
1185
          psw_new = 32'hxxxxxxxx;
1186
          tlb_index_we = 1'b0;
1187
          tlb_entry_hi_we = 1'b0;
1188
          tlb_entry_lo_we = 1'b0;
1189
          mmu_bad_addr_we = 1'b0;
1190
        end
1191
      5'd10:  // execute JR-type instr
1192
        begin
1193
          pc_src = 3'b000;
1194
          pc_we = 1'b1;
1195
          mar_we = 1'b0;
1196
          ma_src = 1'bx;
1197
          mmu_fnc = 3'b000;
1198
          mdor_we = 1'b0;
1199
          bus_stb = 1'b0;
1200
          bus_we = 1'bx;
1201
          bus_size = 2'bxx;
1202
          mdir_we = 1'b0;
1203
          mdir_sx = 1'bx;
1204
          ir_we = 1'b0;
1205
          reg_src2 = 2'bxx;
1206
          reg_di2_src = 3'bxxx;
1207
          reg_we2 = 1'b0;
1208
          alu_src1 = 1'b1;
1209
          alu_src2 = 3'bxxx;
1210
          alu_fnc = 3'b010;
1211
          shift_fnc = 2'bxx;
1212
          muldiv_fnc = 3'bxxx;
1213
          muldiv_start = 1'b0;
1214
          sreg_we = 1'b0;
1215
          psw_we = 1'b0;
1216
          psw_new = 32'hxxxxxxxx;
1217
          tlb_index_we = 1'b0;
1218
          tlb_entry_hi_we = 1'b0;
1219
          tlb_entry_lo_we = 1'b0;
1220
          mmu_bad_addr_we = 1'b0;
1221
        end
1222
      5'd11:  // execute LDST-type instr (1)
1223
        begin
1224
          pc_src = 3'bxxx;
1225
          pc_we = 1'b0;
1226
          mar_we = 1'b1;
1227
          ma_src = 1'bx;
1228
          mmu_fnc = 3'b000;
1229
          mdor_we = 1'b1;
1230
          bus_stb = 1'b0;
1231
          bus_we = 1'bx;
1232
          bus_size = 2'bxx;
1233
          mdir_we = 1'b0;
1234
          mdir_sx = 1'bx;
1235
          ir_we = 1'b0;
1236
          reg_src2 = 2'bxx;
1237
          reg_di2_src = 3'bxxx;
1238
          reg_we2 = 1'b0;
1239
          alu_src1 = 1'b1;
1240
          alu_src2 = 3'b010;
1241
          alu_fnc = 3'b000;
1242
          shift_fnc = 2'bxx;
1243
          muldiv_fnc = 3'bxxx;
1244
          muldiv_start = 1'b0;
1245
          sreg_we = 1'b0;
1246
          psw_we = 1'b0;
1247
          psw_new = 32'hxxxxxxxx;
1248
          tlb_index_we = 1'b0;
1249
          tlb_entry_hi_we = 1'b0;
1250
          tlb_entry_lo_we = 1'b0;
1251
          mmu_bad_addr_we = 1'b0;
1252
        end
1253
      5'd12:  // execute LD-type instr (addr xlat)
1254
        begin
1255
          pc_src = 3'bxxx;
1256
          pc_we = 1'b0;
1257
          mar_we = 1'b0;
1258
          ma_src = 1'b1;
1259
          mmu_fnc = (exc_prv_addr | exc_ill_addr) ? 3'b000 : 3'b001;
1260
          mdor_we = 1'b0;
1261
          bus_stb = 1'b0;
1262
          bus_we = 1'b0;         // get bad_accs right in case of exc
1263
          bus_size = ldst_size;  // enable illegal address detection
1264
          mdir_we = 1'b0;
1265
          mdir_sx = 1'bx;
1266
          ir_we = 1'b0;
1267
          reg_src2 = 2'bxx;
1268
          reg_di2_src = 3'bxxx;
1269
          reg_we2 = 1'b0;
1270
          alu_src1 = 1'bx;
1271
          alu_src2 = 3'bxxx;
1272
          alu_fnc = 3'bxxx;
1273
          shift_fnc = 2'bxx;
1274
          muldiv_fnc = 3'bxxx;
1275
          muldiv_start = 1'b0;
1276
          sreg_we = 1'b0;
1277
          psw_we = 1'b0;
1278
          psw_new = 32'hxxxxxxxx;
1279
          tlb_index_we = 1'b0;
1280
          tlb_entry_hi_we = 1'b0;
1281
          tlb_entry_lo_we = 1'b0;
1282
          mmu_bad_addr_we = exc_prv_addr | exc_ill_addr;
1283
        end
1284
      5'd13:  // execute LD-type instr (3)
1285
        begin
1286
          pc_src = 3'bxxx;
1287
          pc_we = 1'b0;
1288
          mar_we = 1'b0;
1289
          ma_src = 1'bx;
1290
          mmu_fnc = 3'b000;
1291
          mdor_we = 1'b0;
1292
          bus_stb = 1'b0;
1293
          bus_we = 1'bx;
1294
          bus_size = ldst_size;
1295
          mdir_we = 1'b0;
1296
          mdir_sx = opcode[0];
1297
          ir_we = 1'b0;
1298
          reg_src2 = 2'b00;
1299
          reg_di2_src = 3'b011;
1300
          reg_we2 = 1'b1;
1301
          alu_src1 = 1'bx;
1302
          alu_src2 = 3'bxxx;
1303
          alu_fnc = 3'bxxx;
1304
          shift_fnc = 2'bxx;
1305
          muldiv_fnc = 3'bxxx;
1306
          muldiv_start = 1'b0;
1307
          sreg_we = 1'b0;
1308
          psw_we = 1'b0;
1309
          psw_new = 32'hxxxxxxxx;
1310
          tlb_index_we = 1'b0;
1311
          tlb_entry_hi_we = 1'b0;
1312
          tlb_entry_lo_we = 1'b0;
1313
          mmu_bad_addr_we = 1'b0;
1314
        end
1315
      5'd14:  // execute ST-type instr (addr xlat)
1316
        begin
1317
          pc_src = 3'bxxx;
1318
          pc_we = 1'b0;
1319
          mar_we = 1'b0;
1320
          ma_src = 1'b1;
1321
          mmu_fnc = (exc_prv_addr | exc_ill_addr) ? 3'b000 : 3'b001;
1322
          mdor_we = 1'b0;
1323
          bus_stb = 1'b0;
1324
          bus_we = 1'b1;         // get bad_accs right in case of exc
1325
          bus_size = ldst_size;  // enable illegal address detection
1326
          mdir_we = 1'b0;
1327
          mdir_sx = 1'bx;
1328
          ir_we = 1'b0;
1329
          reg_src2 = 2'bxx;
1330
          reg_di2_src = 3'bxxx;
1331
          reg_we2 = 1'b0;
1332
          alu_src1 = 1'bx;
1333
          alu_src2 = 3'bxxx;
1334
          alu_fnc = 3'bxxx;
1335
          shift_fnc = 2'bxx;
1336
          muldiv_fnc = 3'bxxx;
1337
          muldiv_start = 1'b0;
1338
          sreg_we = 1'b0;
1339
          psw_we = 1'b0;
1340
          psw_new = 32'hxxxxxxxx;
1341
          tlb_index_we = 1'b0;
1342
          tlb_entry_hi_we = 1'b0;
1343
          tlb_entry_lo_we = 1'b0;
1344
          mmu_bad_addr_we = exc_prv_addr | exc_ill_addr;
1345
        end
1346
      5'd15:  // interrupt
1347
        begin
1348
          pc_src = (psw[27] == 0) ? 3'b010 : 3'b011;
1349
          pc_we = 1'b1;
1350
          mar_we = 1'b0;
1351
          ma_src = 1'bx;
1352
          mmu_fnc = 3'b000;
1353
          mdor_we = 1'b0;
1354
          bus_stb = 1'b0;
1355
          bus_we = 1'bx;
1356
          bus_size = 2'bxx;
1357
          mdir_we = 1'b0;
1358
          mdir_sx = 1'bx;
1359
          ir_we = 1'b0;
1360
          reg_src2 = 2'b11;
1361
          reg_di2_src = 3'b000;
1362
          reg_we2 = 1'b1;
1363
          alu_src1 = 1'b0;
1364
          alu_src2 = 3'bxxx;
1365
          alu_fnc = 3'b010;
1366
          shift_fnc = 2'bxx;
1367
          muldiv_fnc = 3'bxxx;
1368
          muldiv_start = 1'b0;
1369
          sreg_we = 1'b0;
1370
          psw_we = 1'b1;
1371
          psw_new = {
1372
            psw[31:28],
1373
            psw[27],
1374
            1'b0, psw[26], psw[25],
1375
            1'b0, psw[23], psw[22],
1376
            1'b0, irq_priority,
1377
            psw[15:0]
1378
          };
1379
          tlb_index_we = 1'b0;
1380
          tlb_entry_hi_we = 1'b0;
1381
          tlb_entry_lo_we = 1'b0;
1382
          mmu_bad_addr_we = 1'b0;
1383
        end
1384
      5'd16:  // extra state for RRR shift instr
1385
        begin
1386
          pc_src = 3'bxxx;
1387
          pc_we = 1'b0;
1388
          mar_we = 1'b0;
1389
          ma_src = 1'bx;
1390
          mmu_fnc = 3'b000;
1391
          mdor_we = 1'b0;
1392
          bus_stb = 1'b0;
1393
          bus_we = 1'bx;
1394
          bus_size = 2'bxx;
1395
          mdir_we = 1'b0;
1396
          mdir_sx = 1'bx;
1397
          ir_we = 1'b0;
1398
          reg_src2 = 2'b01;
1399
          reg_di2_src = 3'b001;
1400
          reg_we2 = 1'b1;
1401
          alu_src1 = 1'bx;
1402
          alu_src2 = 3'bxxx;
1403
          alu_fnc = 3'bxxx;
1404
          shift_fnc = 2'bxx;
1405
          muldiv_fnc = 3'bxxx;
1406
          muldiv_start = 1'b0;
1407
          sreg_we = 1'b0;
1408
          psw_we = 1'b0;
1409
          psw_new = 32'hxxxxxxxx;
1410
          tlb_index_we = 1'b0;
1411
          tlb_entry_hi_we = 1'b0;
1412
          tlb_entry_lo_we = 1'b0;
1413
          mmu_bad_addr_we = 1'b0;
1414
        end
1415
      5'd17:  // extra state for RRH shift instr
1416
        begin
1417
          pc_src = 3'bxxx;
1418
          pc_we = 1'b0;
1419
          mar_we = 1'b0;
1420
          ma_src = 1'bx;
1421
          mmu_fnc = 3'b000;
1422
          mdor_we = 1'b0;
1423
          bus_stb = 1'b0;
1424
          bus_we = 1'bx;
1425
          bus_size = 2'bxx;
1426
          mdir_we = 1'b0;
1427
          mdir_sx = 1'bx;
1428
          ir_we = 1'b0;
1429
          reg_src2 = 2'b00;
1430
          reg_di2_src = 3'b001;
1431
          reg_we2 = 1'b1;
1432
          alu_src1 = 1'bx;
1433
          alu_src2 = 3'bxxx;
1434
          alu_fnc = 3'bxxx;
1435
          shift_fnc = 2'bxx;
1436
          muldiv_fnc = 3'bxxx;
1437
          muldiv_start = 1'b0;
1438
          sreg_we = 1'b0;
1439
          psw_we = 1'b0;
1440
          psw_new = 32'hxxxxxxxx;
1441
          tlb_index_we = 1'b0;
1442
          tlb_entry_hi_we = 1'b0;
1443
          tlb_entry_lo_we = 1'b0;
1444
          mmu_bad_addr_we = 1'b0;
1445
        end
1446
      5'd18:  // extra state for RRR muldiv instr
1447
        begin
1448
          pc_src = 3'bxxx;
1449
          pc_we = 1'b0;
1450
          mar_we = 1'b0;
1451
          ma_src = 1'bx;
1452
          mmu_fnc = 3'b000;
1453
          mdor_we = 1'b0;
1454
          bus_stb = 1'b0;
1455
          bus_we = 1'bx;
1456
          bus_size = 2'bxx;
1457
          mdir_we = 1'b0;
1458
          mdir_sx = 1'bx;
1459
          ir_we = 1'b0;
1460
          reg_src2 = 2'b01;
1461
          reg_di2_src = 3'b010;
1462
          reg_we2 = muldiv_done & ~muldiv_error;
1463
          alu_src1 = 1'bx;
1464
          alu_src2 = 3'bxxx;
1465
          alu_fnc = 3'bxxx;
1466
          shift_fnc = 2'bxx;
1467
          muldiv_fnc = 3'bxxx;
1468
          muldiv_start = 1'b0;
1469
          sreg_we = 1'b0;
1470
          psw_we = 1'b0;
1471
          psw_new = 32'hxxxxxxxx;
1472
          tlb_index_we = 1'b0;
1473
          tlb_entry_hi_we = 1'b0;
1474
          tlb_entry_lo_we = 1'b0;
1475
          mmu_bad_addr_we = 1'b0;
1476
        end
1477
      5'd19:  // extra state for RRS muldiv instr
1478
        begin
1479
          pc_src = 3'bxxx;
1480
          pc_we = 1'b0;
1481
          mar_we = 1'b0;
1482
          ma_src = 1'bx;
1483
          mmu_fnc = 3'b000;
1484
          mdor_we = 1'b0;
1485
          bus_stb = 1'b0;
1486
          bus_we = 1'bx;
1487
          bus_size = 2'bxx;
1488
          mdir_we = 1'b0;
1489
          mdir_sx = 1'bx;
1490
          ir_we = 1'b0;
1491
          reg_src2 = 2'b00;
1492
          reg_di2_src = 3'b010;
1493
          reg_we2 = muldiv_done & ~muldiv_error;
1494
          alu_src1 = 1'bx;
1495
          alu_src2 = 3'bxxx;
1496
          alu_fnc = 3'bxxx;
1497
          shift_fnc = 2'bxx;
1498
          muldiv_fnc = 3'bxxx;
1499
          muldiv_start = 1'b0;
1500
          sreg_we = 1'b0;
1501
          psw_we = 1'b0;
1502
          psw_new = 32'hxxxxxxxx;
1503
          tlb_index_we = 1'b0;
1504
          tlb_entry_hi_we = 1'b0;
1505
          tlb_entry_lo_we = 1'b0;
1506
          mmu_bad_addr_we = 1'b0;
1507
        end
1508
      5'd20:  // extra state for RRH muldiv instr
1509
        begin
1510
          pc_src = 3'bxxx;
1511
          pc_we = 1'b0;
1512
          mar_we = 1'b0;
1513
          ma_src = 1'bx;
1514
          mmu_fnc = 3'b000;
1515
          mdor_we = 1'b0;
1516
          bus_stb = 1'b0;
1517
          bus_we = 1'bx;
1518
          bus_size = 2'bxx;
1519
          mdir_we = 1'b0;
1520
          mdir_sx = 1'bx;
1521
          ir_we = 1'b0;
1522
          reg_src2 = 2'b00;
1523
          reg_di2_src = 3'b010;
1524
          reg_we2 = muldiv_done & ~muldiv_error;
1525
          alu_src1 = 1'bx;
1526
          alu_src2 = 3'bxxx;
1527
          alu_fnc = 3'bxxx;
1528
          shift_fnc = 2'bxx;
1529
          muldiv_fnc = 3'bxxx;
1530
          muldiv_start = 1'b0;
1531
          sreg_we = 1'b0;
1532
          psw_we = 1'b0;
1533
          psw_new = 32'hxxxxxxxx;
1534
          tlb_index_we = 1'b0;
1535
          tlb_entry_hi_we = 1'b0;
1536
          tlb_entry_lo_we = 1'b0;
1537
          mmu_bad_addr_we = 1'b0;
1538
        end
1539
      5'd21:  // execute mvfs instr
1540
        begin
1541
          pc_src = 3'bxxx;
1542
          pc_we = 1'b0;
1543
          mar_we = 1'b0;
1544
          ma_src = 1'bx;
1545
          mmu_fnc = 3'b000;
1546
          mdor_we = 1'b0;
1547
          bus_stb = 1'b0;
1548
          bus_we = 1'bx;
1549
          bus_size = 2'bxx;
1550
          mdir_we = 1'b0;
1551
          mdir_sx = 1'bx;
1552
          ir_we = 1'b0;
1553
          reg_src2 = 2'b00;
1554
          reg_di2_src = 3'b100;
1555
          reg_we2 = 1'b1;
1556
          alu_src1 = 1'bx;
1557
          alu_src2 = 3'bxxx;
1558
          alu_fnc = 3'bxxx;
1559
          shift_fnc = 2'bxx;
1560
          muldiv_fnc = 3'bxxx;
1561
          muldiv_start = 1'b0;
1562
          sreg_we = 1'b0;
1563
          psw_we = 1'b0;
1564
          psw_new = 32'hxxxxxxxx;
1565
          tlb_index_we = 1'b0;
1566
          tlb_entry_hi_we = 1'b0;
1567
          tlb_entry_lo_we = 1'b0;
1568
          mmu_bad_addr_we = 1'b0;
1569
        end
1570
      5'd22:  // execute mvts instr
1571
        begin
1572
          pc_src = 3'bxxx;
1573
          pc_we = 1'b0;
1574
          mar_we = 1'b0;
1575
          ma_src = 1'bx;
1576
          mmu_fnc = 3'b000;
1577
          mdor_we = 1'b0;
1578
          bus_stb = 1'b0;
1579
          bus_we = 1'bx;
1580
          bus_size = 2'bxx;
1581
          mdir_we = 1'b0;
1582
          mdir_sx = 1'bx;
1583
          ir_we = 1'b0;
1584
          reg_src2 = 2'bxx;
1585
          reg_di2_src = 3'bxxx;
1586
          reg_we2 = 1'b0;
1587
          alu_src1 = 1'bx;
1588
          alu_src2 = 3'bxxx;
1589
          alu_fnc = 3'bxxx;
1590
          shift_fnc = 2'bxx;
1591
          muldiv_fnc = 3'bxxx;
1592
          muldiv_start = 1'b0;
1593
          sreg_we = 1'b1;
1594
          psw_we = 1'b0;
1595
          psw_new = 32'hxxxxxxxx;
1596
          tlb_index_we = 1'b0;
1597
          tlb_entry_hi_we = 1'b0;
1598
          tlb_entry_lo_we = 1'b0;
1599
          mmu_bad_addr_we = 1'b0;
1600
        end
1601
      5'd23:  // execute rfx instr
1602
        begin
1603
          pc_src = 3'b000;
1604
          pc_we = 1'b1;
1605
          mar_we = 1'b0;
1606
          ma_src = 1'bx;
1607
          mmu_fnc = 3'b000;
1608
          mdor_we = 1'b0;
1609
          bus_stb = 1'b0;
1610
          bus_we = 1'bx;
1611
          bus_size = 2'bxx;
1612
          mdir_we = 1'b0;
1613
          mdir_sx = 1'bx;
1614
          ir_we = 1'b0;
1615
          reg_src2 = 2'bxx;
1616
          reg_di2_src = 3'bxxx;
1617
          reg_we2 = 1'b0;
1618
          alu_src1 = 1'bx;
1619
          alu_src2 = 3'b001;
1620
          alu_fnc = 3'b011;
1621
          shift_fnc = 2'bxx;
1622
          muldiv_fnc = 3'bxxx;
1623
          muldiv_start = 1'b0;
1624
          sreg_we = 1'b0;
1625
          psw_we = 1'b1;
1626
          psw_new = {
1627
            psw[31:28],
1628
            psw[27],
1629
            psw[25], psw[24], psw[24],
1630
            psw[22], psw[21], psw[21],
1631
            psw[20:16],
1632
            psw[15:0]
1633
          };
1634
          tlb_index_we = 1'b0;
1635
          tlb_entry_hi_we = 1'b0;
1636
          tlb_entry_lo_we = 1'b0;
1637
          mmu_bad_addr_we = 1'b0;
1638
        end
1639
      5'd24:  // irq_trigger check for mvts and rfx
1640
        begin
1641
          pc_src = 3'bxxx;
1642
          pc_we = 1'b0;
1643
          mar_we = 1'b0;
1644
          ma_src = 1'bx;
1645
          mmu_fnc = 3'b000;
1646
          mdor_we = 1'b0;
1647
          bus_stb = 1'b0;
1648
          bus_we = 1'bx;
1649
          bus_size = 2'bxx;
1650
          mdir_we = 1'b0;
1651
          mdir_sx = 1'bx;
1652
          ir_we = 1'b0;
1653
          reg_src2 = 2'bxx;
1654
          reg_di2_src = 3'bxxx;
1655
          reg_we2 = 1'b0;
1656
          alu_src1 = 1'bx;
1657
          alu_src2 = 3'bxxx;
1658
          alu_fnc = 3'bxxx;
1659
          shift_fnc = 2'bxx;
1660
          muldiv_fnc = 3'bxxx;
1661
          muldiv_start = 1'b0;
1662
          sreg_we = 1'b0;
1663
          psw_we = 1'b0;
1664
          psw_new = 32'hxxxxxxxx;
1665
          tlb_index_we = 1'b0;
1666
          tlb_entry_hi_we = 1'b0;
1667
          tlb_entry_lo_we = 1'b0;
1668
          mmu_bad_addr_we = 1'b0;
1669
        end
1670
      5'd25:  // exception (locus is PC-4)
1671
        begin
1672
          pc_src = (psw[27] != 0) ?
1673
                     ((tlb_umissed != 0) ? 3'b101 : 3'b011) :
1674
                     ((tlb_umissed != 0) ? 3'b100 : 3'b010);
1675
          pc_we = 1'b1;
1676
          mar_we = 1'b0;
1677
          ma_src = 1'bx;
1678
          mmu_fnc = 3'b000;
1679
          mdor_we = 1'b0;
1680
          bus_stb = 1'b0;
1681
          bus_we = 1'bx;
1682
          bus_size = 2'bxx;
1683
          mdir_we = 1'b0;
1684
          mdir_sx = 1'bx;
1685
          ir_we = 1'b0;
1686
          reg_src2 = 2'b11;
1687
          reg_di2_src = 3'b000;
1688
          reg_we2 = 1'b1;
1689
          alu_src1 = 1'b0;
1690
          alu_src2 = 3'b000;
1691
          alu_fnc = 3'b001;
1692
          shift_fnc = 2'bxx;
1693
          muldiv_fnc = 3'bxxx;
1694
          muldiv_start = 1'b0;
1695
          sreg_we = 1'b0;
1696
          psw_we = 1'b1;
1697
          psw_new = {
1698
            psw[31:28],
1699
            psw[27],
1700
            1'b0, psw[26], psw[25],
1701
            1'b0, psw[23], psw[22],
1702
            1'b1, exc_priority,
1703
            psw[15:0]
1704
          };
1705
          tlb_index_we = 1'b0;
1706
          tlb_entry_hi_we = 1'b0;
1707
          tlb_entry_lo_we = 1'b0;
1708
          mmu_bad_addr_we = 1'b0;
1709
        end
1710
      5'd26:  // exception (locus is PC)
1711
        begin
1712
          pc_src = (psw[27] != 0) ?
1713
                     ((tlb_umissed != 0) ? 3'b101 : 3'b011) :
1714
                     ((tlb_umissed != 0) ? 3'b100 : 3'b010);
1715
          pc_we = 1'b1;
1716
          mar_we = 1'b0;
1717
          ma_src = 1'bx;
1718
          mmu_fnc = 3'b000;
1719
          mdor_we = 1'b0;
1720
          bus_stb = 1'b0;
1721
          bus_we = 1'bx;
1722
          bus_size = 2'bxx;
1723
          mdir_we = 1'b0;
1724
          mdir_sx = 1'bx;
1725
          ir_we = 1'b0;
1726
          reg_src2 = 2'b11;
1727
          reg_di2_src = 3'b000;
1728
          reg_we2 = 1'b1;
1729
          alu_src1 = 1'b0;
1730
          alu_src2 = 3'bxxx;
1731
          alu_fnc = 3'b010;
1732
          shift_fnc = 2'bxx;
1733
          muldiv_fnc = 3'bxxx;
1734
          muldiv_start = 1'b0;
1735
          sreg_we = 1'b0;
1736
          psw_we = 1'b1;
1737
          psw_new = {
1738
            psw[31:28],
1739
            psw[27],
1740
            1'b0, psw[26], psw[25],
1741
            1'b0, psw[23], psw[22],
1742
            1'b1, exc_priority,
1743
            psw[15:0]
1744
          };
1745
          tlb_index_we = 1'b0;
1746
          tlb_entry_hi_we = 1'b0;
1747
          tlb_entry_lo_we = 1'b0;
1748
          mmu_bad_addr_we = 1'b0;
1749
        end
1750
      5'd27:  // execute TLB instr
1751
        begin
1752
          pc_src = 3'bxxx;
1753
          pc_we = 1'b0;
1754
          mar_we = 1'b0;
1755
          ma_src = 1'bx;
1756
          mmu_fnc = opcode[2:0];
1757
          mdor_we = 1'b0;
1758
          bus_stb = 1'b0;
1759
          bus_we = 1'bx;
1760
          bus_size = 2'bxx;
1761
          mdir_we = 1'b0;
1762
          mdir_sx = 1'bx;
1763
          ir_we = 1'b0;
1764
          reg_src2 = 2'bxx;
1765
          reg_di2_src = 3'bxxx;
1766
          reg_we2 = 1'b0;
1767
          alu_src1 = 1'bx;
1768
          alu_src2 = 3'bxxx;
1769
          alu_fnc = 3'bxxx;
1770
          shift_fnc = 2'bxx;
1771
          muldiv_fnc = 3'bxxx;
1772
          muldiv_start = 1'b0;
1773
          sreg_we = 1'b0;
1774
          psw_we = 1'b0;
1775
          psw_new = 32'hxxxxxxxx;
1776
          tlb_index_we = (opcode[2:0] == 3'b010) ? 1 : 0;
1777
          tlb_entry_hi_we = (opcode[2:0] == 3'b100) ? 1 : 0;
1778
          tlb_entry_lo_we = (opcode[2:0] == 3'b100) ? 1 : 0;
1779
          mmu_bad_addr_we = 1'b0;
1780
        end
1781
      5'd28:  // fetch instr (bus cycle)
1782
        begin
1783
          pc_src = 3'bxxx;
1784
          pc_we = 1'b0;
1785
          mar_we = 1'b0;
1786
          ma_src = 1'b0;        // hold vaddr for latching in bad addr reg
1787
          mmu_fnc = 3'b000;
1788
          mdor_we = 1'b0;
1789
          bus_stb = ~exc_tlb_but_wrtprot;
1790
          bus_we = 1'b0;
1791
          bus_size = 2'b10;
1792
          mdir_we = 1'b0;
1793
          mdir_sx = 1'bx;
1794
          ir_we = 1'b1;
1795
          reg_src2 = 2'bxx;
1796
          reg_di2_src = 3'bxxx;
1797
          reg_we2 = 1'b0;
1798
          alu_src1 = 1'bx;
1799
          alu_src2 = 3'bxxx;
1800
          alu_fnc = 3'bxxx;
1801
          shift_fnc = 2'bxx;
1802
          muldiv_fnc = 3'bxxx;
1803
          muldiv_start = 1'b0;
1804
          sreg_we = 1'b0;
1805
          psw_we = 1'b0;
1806
          psw_new = 32'hxxxxxxxx;
1807
          tlb_index_we = 1'b0;
1808
          tlb_entry_hi_we = exc_tlb_but_wrtprot;
1809
          tlb_entry_lo_we = 1'b0;
1810
          mmu_bad_addr_we = exc_tlb_but_wrtprot;
1811
        end
1812
      5'd29:  // execute LD-type instr (bus cycle)
1813
        begin
1814
          pc_src = 3'bxxx;
1815
          pc_we = 1'b0;
1816
          mar_we = 1'b0;
1817
          ma_src = 1'b1;        // hold vaddr for latching in bad addr reg
1818
          mmu_fnc = 3'b000;
1819
          mdor_we = 1'b0;
1820
          bus_stb = ~exc_tlb_but_wrtprot;
1821
          bus_we = 1'b0;
1822
          bus_size = ldst_size;
1823
          mdir_we = 1'b1;
1824
          mdir_sx = 1'bx;
1825
          ir_we = 1'b0;
1826
          reg_src2 = 2'bxx;
1827
          reg_di2_src = 3'bxxx;
1828
          reg_we2 = 1'b0;
1829
          alu_src1 = 1'bx;
1830
          alu_src2 = 3'bxxx;
1831
          alu_fnc = 3'bxxx;
1832
          shift_fnc = 2'bxx;
1833
          muldiv_fnc = 3'bxxx;
1834
          muldiv_start = 1'b0;
1835
          sreg_we = 1'b0;
1836
          psw_we = 1'b0;
1837
          psw_new = 32'hxxxxxxxx;
1838
          tlb_index_we = 1'b0;
1839
          tlb_entry_hi_we = exc_tlb_but_wrtprot;
1840
          tlb_entry_lo_we = 1'b0;
1841
          mmu_bad_addr_we = exc_tlb_but_wrtprot;
1842
        end
1843
      5'd30:  // execute ST-type instr (bus cycle)
1844
        begin
1845
          pc_src = 3'bxxx;
1846
          pc_we = 1'b0;
1847
          mar_we = 1'b0;
1848
          ma_src = 1'b1;        // hold vaddr for latching in bad addr reg
1849
          mmu_fnc = 3'b000;
1850
          mdor_we = 1'b0;
1851
          bus_stb = ~exc_tlb_any;
1852
          bus_we = 1'b1;
1853
          bus_size = ldst_size;
1854
          mdir_we = 1'b0;
1855
          mdir_sx = 1'bx;
1856
          ir_we = 1'b0;
1857
          reg_src2 = 2'bxx;
1858
          reg_di2_src = 3'bxxx;
1859
          reg_we2 = 1'b0;
1860
          alu_src1 = 1'bx;
1861
          alu_src2 = 3'bxxx;
1862
          alu_fnc = 3'bxxx;
1863
          shift_fnc = 2'bxx;
1864
          muldiv_fnc = 3'bxxx;
1865
          muldiv_start = 1'b0;
1866
          sreg_we = 1'b0;
1867
          psw_we = 1'b0;
1868
          psw_new = 32'hxxxxxxxx;
1869
          tlb_index_we = 1'b0;
1870
          tlb_entry_hi_we = exc_tlb_any;
1871
          tlb_entry_lo_we = 1'b0;
1872
          mmu_bad_addr_we = exc_tlb_any;
1873
        end
1874
      default:  // all other states: unused
1875
        begin
1876
          pc_src = 3'bxxx;
1877
          pc_we = 1'bx;
1878
          mar_we = 1'bx;
1879
          ma_src = 1'bx;
1880
          mmu_fnc = 3'bxxx;
1881
          mdor_we = 1'bx;
1882
          bus_stb = 1'bx;
1883
          bus_we = 1'bx;
1884
          bus_size = 2'bxx;
1885
          mdir_we = 1'bx;
1886
          mdir_sx = 1'bx;
1887
          ir_we = 1'bx;
1888
          reg_src2 = 2'bxx;
1889
          reg_di2_src = 3'bxxx;
1890
          reg_we2 = 1'bx;
1891
          alu_src1 = 1'bx;
1892
          alu_src2 = 3'bxxx;
1893
          alu_fnc = 3'bxxx;
1894
          shift_fnc = 2'bxx;
1895
          muldiv_fnc = 3'bxxx;
1896
          muldiv_start = 1'bx;
1897
          sreg_we = 1'bx;
1898
          psw_we = 1'bx;
1899
          psw_new = 32'hxxxxxxxx;
1900
          tlb_index_we = 1'bx;
1901
          tlb_entry_hi_we = 1'bx;
1902
          tlb_entry_lo_we = 1'bx;
1903
          mmu_bad_addr_we = 1'bx;
1904
        end
1905
    endcase
1906
  end
1907
 
1908
  // branch logic
1909
  always @(*) begin
1910
    casex ( { opcode[3:0], alu_equ, alu_ult, alu_slt } )
1911
      // eq
1912
      7'b00000xx:  branch = 0;
1913
      7'b00001xx:  branch = 1;
1914
      // ne
1915
      7'b00010xx:  branch = 1;
1916
      7'b00011xx:  branch = 0;
1917
      // le
1918
      7'b00100x0:  branch = 0;
1919
      7'b00101xx:  branch = 1;
1920
      7'b0010xx1:  branch = 1;
1921
      // leu
1922
      7'b001100x:  branch = 0;
1923
      7'b00111xx:  branch = 1;
1924
      7'b0011x1x:  branch = 1;
1925
      // lt
1926
      7'b0100xx0:  branch = 0;
1927
      7'b0100xx1:  branch = 1;
1928
      // ltu
1929
      7'b0101x0x:  branch = 0;
1930
      7'b0101x1x:  branch = 1;
1931
      // ge
1932
      7'b0110xx0:  branch = 1;
1933
      7'b0110xx1:  branch = 0;
1934
      // geu
1935
      7'b0111x0x:  branch = 1;
1936
      7'b0111x1x:  branch = 0;
1937
      // gt
1938
      7'b10000x0:  branch = 1;
1939
      7'b10001xx:  branch = 0;
1940
      7'b1000xx1:  branch = 0;
1941
      // gtu
1942
      7'b100100x:  branch = 1;
1943
      7'b10011xx:  branch = 0;
1944
      7'b1001x1x:  branch = 0;
1945
      // other
1946
      default:     branch = 1'bx;
1947
    endcase
1948
  end
1949
 
1950
  // interrupts
1951
  assign irq_pending = bus_irq[15:0] & psw[15:0];
1952
  assign irq_trigger = (| irq_pending) & psw[23];
1953
  always @(*) begin
1954
    if ((| irq_pending[15:8]) != 0) begin
1955
      if ((| irq_pending[15:12]) != 0) begin
1956
        if ((| irq_pending[15:14]) != 0) begin
1957
          if (irq_pending[15] != 0) begin
1958
            irq_priority = 4'd15;
1959
          end else begin
1960
            irq_priority = 4'd14;
1961
          end
1962
        end else begin
1963
          if (irq_pending[13] != 0) begin
1964
            irq_priority = 4'd13;
1965
          end else begin
1966
            irq_priority = 4'd12;
1967
          end
1968
        end
1969
      end else begin
1970
        if ((| irq_pending[11:10]) != 0) begin
1971
          if (irq_pending[11] != 0) begin
1972
            irq_priority = 4'd11;
1973
          end else begin
1974
            irq_priority = 4'd10;
1975
          end
1976
        end else begin
1977
          if (irq_pending[9] != 0) begin
1978
            irq_priority = 4'd9;
1979
          end else begin
1980
            irq_priority = 4'd8;
1981
          end
1982
        end
1983
      end
1984
    end else begin
1985
      if ((| irq_pending[7:4]) != 0) begin
1986
        if ((| irq_pending[7:6]) != 0) begin
1987
          if (irq_pending[7] != 0) begin
1988
            irq_priority = 4'd7;
1989
          end else begin
1990
            irq_priority = 4'd6;
1991
          end
1992
        end else begin
1993
          if (irq_pending[5] != 0) begin
1994
            irq_priority = 4'd5;
1995
          end else begin
1996
            irq_priority = 4'd4;
1997
          end
1998
        end
1999
      end else begin
2000
        if ((| irq_pending[3:2]) != 0) begin
2001
          if (irq_pending[3] != 0) begin
2002
            irq_priority = 4'd3;
2003
          end else begin
2004
            irq_priority = 4'd2;
2005
          end
2006
        end else begin
2007
          if (irq_pending[1] != 0) begin
2008
            irq_priority = 4'd1;
2009
          end else begin
2010
            irq_priority = 4'd0;
2011
          end
2012
        end
2013
      end
2014
    end
2015
  end
2016
 
2017
  // exceptions
2018
  assign exc_prv_addr = psw[26] & va_31;
2019
  assign exc_ill_addr = (bus_size[0] & va_0) |
2020
                        (bus_size[1] & va_0) |
2021
                        (bus_size[1] & va_1);
2022
  assign exc_tlb_but_wrtprot = tlb_kmissed | tlb_umissed | tlb_invalid;
2023
  assign exc_tlb_any = exc_tlb_but_wrtprot | tlb_wrtprot;
2024
 
2025
endmodule
2026
 
2027
 
2028
//--------------------------------------------------------------
2029
// pc -- the program counter
2030
//--------------------------------------------------------------
2031
 
2032
 
2033
module pc(clk, pc_we, pc_next, pc);
2034
    input clk;
2035
    input pc_we;
2036
    input [31:0] pc_next;
2037
    output reg [31:0] pc;
2038
 
2039
  always @(posedge clk) begin
2040
    if (pc_we == 1) begin
2041
      pc <= pc_next;
2042
    end
2043
  end
2044
 
2045
endmodule
2046
 
2047
 
2048
//--------------------------------------------------------------
2049
// mar -- the memory address register
2050
//--------------------------------------------------------------
2051
 
2052
 
2053
module mar(clk, mar_we, mar_next, mar);
2054
    input clk;
2055
    input mar_we;
2056
    input [31:0] mar_next;
2057
    output reg [31:0] mar;
2058
 
2059
  always @(posedge clk) begin
2060
    if (mar_we == 1) begin
2061
      mar <= mar_next;
2062
    end
2063
  end
2064
 
2065
endmodule
2066
 
2067
 
2068
//--------------------------------------------------------------
2069
// mdor -- the memory data out register
2070
//--------------------------------------------------------------
2071
 
2072
 
2073
module mdor(clk, mdor_we, mdor_next, mdor);
2074
    input clk;
2075
    input mdor_we;
2076
    input [31:0] mdor_next;
2077
    output reg [31:0] mdor;
2078
 
2079
  always @(posedge clk) begin
2080
    if (mdor_we == 1) begin
2081
      mdor <= mdor_next;
2082
    end
2083
  end
2084
 
2085
endmodule
2086
 
2087
 
2088
//--------------------------------------------------------------
2089
// mdir -- the memory data in register
2090
//--------------------------------------------------------------
2091
 
2092
 
2093
module mdir(clk, mdir_we, mdir_next, size, sx, mdir);
2094
    input clk;
2095
    input mdir_we;
2096
    input [31:0] mdir_next;
2097
    input [1:0] size;
2098
    input sx;
2099
    output reg [31:0] mdir;
2100
 
2101
  reg [31:0] data;
2102
 
2103
  always @(posedge clk) begin
2104
    if (mdir_we == 1) begin
2105
      data <= mdir_next;
2106
    end
2107
  end
2108
 
2109
  always @(*) begin
2110
    case ({ size, sx })
2111
      3'b000:
2112
        begin
2113
          mdir[31:0] = { 24'h000000, data[7:0] };
2114
        end
2115
      3'b001:
2116
        begin
2117
          if (data[7] == 1) begin
2118
            mdir[31:0] = { 24'hFFFFFF, data[7:0] };
2119
          end else begin
2120
            mdir[31:0] = { 24'h000000, data[7:0] };
2121
          end
2122
        end
2123
      3'b010:
2124
        begin
2125
          mdir[31:0] = { 16'h0000, data[15:0] };
2126
        end
2127
      3'b011:
2128
        begin
2129
          if (data[15] == 1) begin
2130
            mdir[31:0] = { 16'hFFFF, data[15:0] };
2131
          end else begin
2132
            mdir[31:0] = { 16'h0000, data[15:0] };
2133
          end
2134
        end
2135
      default:
2136
        begin
2137
          mdir[31:0] = data[31:0];
2138
        end
2139
    endcase
2140
  end
2141
 
2142
endmodule
2143
 
2144
 
2145
//--------------------------------------------------------------
2146
// ir -- the instruction register and decoder
2147
//--------------------------------------------------------------
2148
 
2149
 
2150
module ir(clk,
2151
          ir_we, instr,
2152
          opcode, reg1, reg2, reg3,
2153
          sx16, zx16, hi16, sx16s2, sx26s2);
2154
    input clk;
2155
    input ir_we;
2156
    input [31:0] instr;
2157
    output [5:0] opcode;
2158
    output [4:0] reg1;
2159
    output [4:0] reg2;
2160
    output [4:0] reg3;
2161
    output [31:0] sx16;
2162
    output [31:0] zx16;
2163
    output [31:0] hi16;
2164
    output [31:0] sx16s2;
2165
    output [31:0] sx26s2;
2166
 
2167
  reg [31:0] ir;
2168
  wire [15:0] copy_sign_16;      // 16-bit copy of a 16-bit immediate's sign
2169
  wire [3:0] copy_sign_26;       // 4-bit copy of a 26-bit immediate's sign
2170
 
2171
  always @(posedge clk) begin
2172
    if (ir_we) begin
2173
      ir <= instr;
2174
    end
2175
  end
2176
 
2177
  assign opcode[5:0] = ir[31:26];
2178
  assign reg1[4:0] = ir[25:21];
2179
  assign reg2[4:0] = ir[20:16];
2180
  assign reg3[4:0] = ir[15:11];
2181
  assign copy_sign_16[15:0] = (ir[15] == 1) ? 16'hFFFF : 16'h0000;
2182
  assign copy_sign_26[3:0] = (ir[25] == 1) ? 4'hF : 4'h0;
2183
  assign sx16[31:0] = { copy_sign_16[15:0], ir[15:0] };
2184
  assign zx16[31:0] = { 16'h0000, ir[15:0] };
2185
  assign hi16[31:0] = { ir[15:0], 16'h0000 };
2186
  assign sx16s2[31:0] = { copy_sign_16[13:0], ir[15:0], 2'b00 };
2187
  assign sx26s2[31:0] = { copy_sign_26[3:0], ir[25:0], 2'b00 };
2188
 
2189
endmodule
2190
 
2191
 
2192
//--------------------------------------------------------------
2193
// regs -- the register file
2194
//--------------------------------------------------------------
2195
 
2196
 
2197
module regs(clk,
2198
            rn1, do1,
2199
            rn2, do2, we2, di2);
2200
    input clk;
2201
    input [4:0] rn1;
2202
    output reg [31:0] do1;
2203
    input [4:0] rn2;
2204
    output reg [31:0] do2;
2205
    input we2;
2206
    input [31:0] di2;
2207
 
2208
  reg [31:0] r[0:31];
2209
 
2210
  always @(posedge clk) begin
2211
    do1 <= r[rn1];
2212
    if (we2 == 0) begin
2213
      do2 <= r[rn2];
2214
    end else begin
2215
      do2 <= di2;
2216
      r[rn2] <= di2;
2217
    end
2218
  end
2219
 
2220
endmodule
2221
 
2222
 
2223
//--------------------------------------------------------------
2224
// alu -- the arithmetic/logic unit
2225
//--------------------------------------------------------------
2226
 
2227
 
2228
module alu(a, b, fnc,
2229
           res, equ, ult, slt);
2230
    input [31:0] a;
2231
    input [31:0] b;
2232
    input [2:0] fnc;
2233
    output [31:0] res;
2234
    output equ;
2235
    output ult;
2236
    output slt;
2237
 
2238
  wire [32:0] a1;
2239
  wire [32:0] b1;
2240
  reg [32:0] res1;
2241
 
2242
  assign a1 = { 1'b0, a };
2243
  assign b1 = { 1'b0, b };
2244
 
2245
  always @(*) begin
2246
    case (fnc)
2247
      3'b000:  res1 = a1 + b1;
2248
      3'b001:  res1 = a1 - b1;
2249
      3'b010:  res1 = a1;
2250
      3'b011:  res1 = b1;
2251
      3'b100:  res1 = a1 & b1;
2252
      3'b101:  res1 = a1 | b1;
2253
      3'b110:  res1 = a1 ^ b1;
2254
      3'b111:  res1 = a1 ~^ b1;
2255
      default: res1 = 33'hxxxxxxxx;
2256
    endcase
2257
  end
2258
 
2259
  assign res = res1[31:0];
2260
  assign equ = ~| res1[31:0];
2261
  assign ult = res1[32];
2262
  assign slt = res1[32] ^ a[31] ^ b[31];
2263
 
2264
endmodule
2265
 
2266
 
2267
//--------------------------------------------------------------
2268
// shift -- the shift unit
2269
//--------------------------------------------------------------
2270
 
2271
 
2272
module shift(clk, data_in, shamt, fnc, data_out);
2273
    input clk;
2274
    input [31:0] data_in;
2275
    input [4:0] shamt;
2276
    input [1:0] fnc;
2277
    output reg [31:0] data_out;
2278
 
2279
  always @(posedge clk) begin
2280
    if (fnc == 2'b00) begin
2281
      // sll
2282
      data_out <= data_in << shamt;
2283
    end else
2284
    if (fnc == 2'b01) begin
2285
      // slr
2286
      data_out <= data_in >> shamt;
2287
    end else
2288
    if (fnc == 2'b10) begin
2289
      // sar
2290
      if (data_in[31] == 1) begin
2291
        data_out <= ~(32'hFFFFFFFF >> shamt) |
2292
                    (data_in >> shamt);
2293
      end else begin
2294
        data_out <= data_in >> shamt;
2295
      end
2296
    end else begin
2297
      data_out <= 32'hxxxxxxxx;
2298
    end
2299
  end
2300
 
2301
endmodule
2302
 
2303
 
2304
//--------------------------------------------------------------
2305
// muldiv -- the multiplier/divide unit
2306
//--------------------------------------------------------------
2307
 
2308
 
2309
module muldiv(clk, a, b, fnc, start, done, error, res);
2310
    input clk;
2311
    input [31:0] a;
2312
    input [31:0] b;
2313
    input [2:0] fnc;
2314
    input start;
2315
    output reg done;
2316
    output reg error;
2317
    output reg [31:0] res;
2318
 
2319
  // fnc = 000    op = undefined
2320
  //       001         undefined
2321
  //       010         mul
2322
  //       011         mulu
2323
  //       100         div
2324
  //       101         divu
2325
  //       110         rem
2326
  //       111         remu
2327
 
2328
  reg div;
2329
  reg rem;
2330
  reg [5:0] count;
2331
  reg a_neg;
2332
  reg b_neg;
2333
  reg [31:0] b_abs;
2334
  reg [64:0] q;
2335
  wire [64:1] s;
2336
  wire [64:0] d;
2337
 
2338
  assign s[64:32] = q[64:32] + { 1'b0, b_abs };
2339
  assign s[31: 1] = q[31: 1];
2340
  assign d[64:32] = q[64:32] - { 1'b0, b_abs };
2341
  assign d[31: 0] = q[31: 0];
2342
 
2343
  always @(posedge clk) begin
2344
    if (start == 1) begin
2345
      if (fnc[2] == 1 && (| b[31:0]) == 0) begin
2346
        // division by zero
2347
        done <= 1;
2348
        error <= 1;
2349
      end else begin
2350
        // operands are ok
2351
        done <= 0;
2352
        error <= 0;
2353
      end
2354
      div <= fnc[2];
2355
      rem <= fnc[1];
2356
      count <= 6'd0;
2357
      if (fnc[0] == 0 && a[31] == 1) begin
2358
        // negate first operand
2359
        a_neg <= 1;
2360
        if (fnc[2] == 0) begin
2361
          // initialize q for multiplication
2362
          q[64:32] <= 33'b0;
2363
          q[31: 0] <= ~a + 1;
2364
        end else begin
2365
          // initialize q for division and remainder
2366
          q[64:33] <= 32'b0;
2367
          q[32: 1] <= ~a + 1;
2368
          q[ 0: 0] <= 1'b0;
2369
        end
2370
      end else begin
2371
        // use first operand as is
2372
        a_neg <= 0;
2373
        if (fnc[2] == 0) begin
2374
          // initialize q for multiplication
2375
          q[64:32] <= 33'b0;
2376
          q[31: 0] <= a;
2377
        end else begin
2378
          // initialize q for division and remainder
2379
          q[64:33] <= 32'b0;
2380
          q[32: 1] <= a;
2381
          q[ 0: 0] <= 1'b0;
2382
        end
2383
      end
2384
      if (fnc[0] == 0 && b[31] == 1) begin
2385
        // negate second operand
2386
        b_neg <= 1;
2387
        b_abs <= ~b + 1;
2388
      end else begin
2389
        // use second operand as is
2390
        b_neg <= 0;
2391
        b_abs <= b;
2392
      end
2393
    end else begin
2394
      if (done == 0) begin
2395
        // algorithm not yet finished
2396
        if (div == 0) begin
2397
          //
2398
          // multiplication
2399
          //
2400
          if (count == 6'd32) begin
2401
            // last step
2402
            done <= 1;
2403
            if (a_neg == b_neg) begin
2404
              res <= q[31:0];
2405
            end else begin
2406
              res <= ~q[31:0] + 1;
2407
            end
2408
          end else begin
2409
            // all other steps
2410
            count <= count + 1;
2411
            if (q[0] == 1) begin
2412
              q <= { 1'b0, s[64:1] };
2413
            end else begin
2414
              q <= { 1'b0, q[64:1] };
2415
            end
2416
          end
2417
        end else begin
2418
          //
2419
          // division and remainder
2420
          //
2421
          if (count == 6'd32) begin
2422
            // last step
2423
            done <= 1;
2424
            if (rem == 0) begin
2425
              // result <= quotient
2426
              if (a_neg == b_neg) begin
2427
                res <= q[31:0];
2428
              end else begin
2429
                res <= ~q[31:0] + 1;
2430
              end
2431
            end else begin
2432
              // result <= remainder
2433
              if (a_neg == 0) begin
2434
                res <= q[64:33];
2435
              end else begin
2436
                res <= ~q[64:33] + 1;
2437
              end
2438
            end
2439
          end else begin
2440
            // all other steps
2441
            count <= count + 1;
2442
            if (d[64] == 0) begin
2443
              q <= { d[63:0], 1'b1 };
2444
            end else begin
2445
              q <= { q[63:0], 1'b0 };
2446
            end
2447
          end
2448
        end
2449
      end
2450
    end
2451
  end
2452
 
2453
endmodule
2454
 
2455
 
2456
//--------------------------------------------------------------
2457
// sregs -- the special registers
2458
//--------------------------------------------------------------
2459
 
2460
 
2461
module sregs(clk, rst,
2462
             rn, we, din, dout,
2463
             psw, psw_we, psw_new,
2464
             tlb_index, tlb_index_we, tlb_index_new,
2465
             tlb_entry_hi, tlb_entry_hi_we, tlb_entry_hi_new,
2466
             tlb_entry_lo, tlb_entry_lo_we, tlb_entry_lo_new,
2467
             mmu_bad_addr, mmu_bad_addr_we, mmu_bad_addr_new,
2468
             mmu_bad_accs, mmu_bad_accs_we, mmu_bad_accs_new);
2469
    input clk;
2470
    input rst;
2471
    input [2:0] rn;
2472
    input we;
2473
    input [31:0] din;
2474
    output [31:0] dout;
2475
    output [31:0] psw;
2476
    input psw_we;
2477
    input [31:0] psw_new;
2478
    output [31:0] tlb_index;
2479
    input tlb_index_we;
2480
    input [31:0] tlb_index_new;
2481
    output [31:0] tlb_entry_hi;
2482
    input tlb_entry_hi_we;
2483
    input [31:0] tlb_entry_hi_new;
2484
    output [31:0] tlb_entry_lo;
2485
    input tlb_entry_lo_we;
2486
    input [31:0] tlb_entry_lo_new;
2487
    output [31:0] mmu_bad_addr;
2488
    input mmu_bad_addr_we;
2489
    input [31:0] mmu_bad_addr_new;
2490
    output [31:0] mmu_bad_accs;
2491
    input mmu_bad_accs_we;
2492
    input [31:0] mmu_bad_accs_new;
2493
 
2494
  // rn = 000   register = PSW
2495
  //      001              TLB index
2496
  //      010              TLB entry high
2497
  //      011              TLB entry low
2498
  //      100              MMU bad address
2499
  //      101              MMU bad access
2500
  //      110              - not used -
2501
  //      111              - not used -
2502
 
2503
  reg [31:0] sr[0:7];
2504
 
2505
  assign dout = sr[rn];
2506
  assign psw = sr[0];
2507
  assign tlb_index = sr[1];
2508
  assign tlb_entry_hi = sr[2];
2509
  assign tlb_entry_lo = sr[3];
2510
  assign mmu_bad_addr = sr[4];
2511
  assign mmu_bad_accs = sr[5];
2512
 
2513
  always @(posedge clk) begin
2514
    if (rst == 1) begin
2515
      sr[0] <= 32'h00000000;
2516
    end else begin
2517
      if (we == 1) begin
2518
        sr[rn] <= din;
2519
      end else begin
2520
        if (psw_we) begin
2521
          sr[0] <= psw_new;
2522
        end
2523
        if (tlb_index_we) begin
2524
          sr[1] <= tlb_index_new;
2525
        end
2526
        if (tlb_entry_hi_we) begin
2527
          sr[2] <= tlb_entry_hi_new;
2528
        end
2529
        if (tlb_entry_lo_we) begin
2530
          sr[3] <= tlb_entry_lo_new;
2531
        end
2532
        if (mmu_bad_addr_we) begin
2533
          sr[4] <= mmu_bad_addr_new;
2534
        end
2535
        if (mmu_bad_accs_we) begin
2536
          sr[5] <= mmu_bad_accs_new;
2537
        end
2538
      end
2539
    end
2540
  end
2541
 
2542
endmodule
2543
 
2544
 
2545
//--------------------------------------------------------------
2546
// mmu -- the memory management unit
2547
//--------------------------------------------------------------
2548
 
2549
 
2550
module mmu(clk, rst, fnc, virt, phys,
2551
           tlb_index, tlb_index_new,
2552
           tlb_entry_hi, tlb_entry_hi_new,
2553
           tlb_entry_lo, tlb_entry_lo_new,
2554
           tlb_kmissed, tlb_umissed,
2555
           tlb_invalid, tlb_wrtprot);
2556
    input clk;
2557
    input rst;
2558
    input [2:0] fnc;
2559
    input [31:0] virt;
2560
    output [31:0] phys;
2561
    input [31:0] tlb_index;
2562
    output [31:0] tlb_index_new;
2563
    input [31:0] tlb_entry_hi;
2564
    output [31:0] tlb_entry_hi_new;
2565
    input [31:0] tlb_entry_lo;
2566
    output [31:0] tlb_entry_lo_new;
2567
    output tlb_kmissed;
2568
    output tlb_umissed;
2569
    output tlb_invalid;
2570
    output tlb_wrtprot;
2571
 
2572
  // fnc = 000    no operation, hold output
2573
  //       001    map virt to phys address
2574
  //       010    tbs
2575
  //       011    tbwr
2576
  //       100    tbri
2577
  //       101    tbwi
2578
  //       110    undefined
2579
  //       111    undefined
2580
 
2581
  wire map;
2582
  wire tbs;
2583
  wire tbwr;
2584
  wire tbri;
2585
  wire tbwi;
2586
  reg [19:0] page;
2587
  reg [11:0] offset;
2588
  wire [19:0] tlb_page;
2589
  wire tlb_miss;
2590
  wire [4:0] tlb_found;
2591
  wire tlb_enable;
2592
  wire [19:0] tlb_frame;
2593
  wire tlb_wbit;
2594
  wire tlb_vbit;
2595
  wire [4:0] rw_index;
2596
  wire [19:0] r_page;
2597
  wire [19:0] r_frame;
2598
  wire w_enable;
2599
  wire [19:0] w_page;
2600
  wire [19:0] w_frame;
2601
  wire direct;
2602
  wire [17:0] frame;
2603
  reg [4:0] random_index;
2604
  reg tlb_miss_delayed;
2605
 
2606
  // decode function
2607
  assign map = (fnc == 3'b001) ? 1 : 0;
2608
  assign tbs = (fnc == 3'b010) ? 1 : 0;
2609
  assign tbwr = (fnc == 3'b011) ? 1 : 0;
2610
  assign tbri = (fnc == 3'b100) ? 1 : 0;
2611
  assign tbwi = (fnc == 3'b101) ? 1 : 0;
2612
 
2613
  // latch virtual address
2614
  always @(posedge clk) begin
2615
    if (map == 1) begin
2616
      page <= virt[31:12];
2617
      offset <= virt[11:0];
2618
    end
2619
  end
2620
 
2621
  // create tlb instance
2622
  assign tlb_page = (tbs == 1) ? tlb_entry_hi[31:12] : virt[31:12];
2623
  assign tlb_enable = map;
2624
  assign tlb_wbit = tlb_frame[1];
2625
  assign tlb_vbit = tlb_frame[0];
2626
  assign rw_index = (tbwr == 1) ? random_index : tlb_index[4:0];
2627
  assign tlb_index_new = { tlb_miss, 26'b0, tlb_found };
2628
  assign tlb_entry_hi_new = { ((tbri == 1) ? r_page : page),
2629
                              tlb_entry_hi[11:0] };
2630
  assign tlb_entry_lo_new = { tlb_entry_lo[31:30], r_frame[19:2],
2631
                              tlb_entry_lo[11:2], r_frame[1:0] };
2632
  assign w_enable = tbwr | tbwi;
2633
  assign w_page = tlb_entry_hi[31:12];
2634
  assign w_frame = { tlb_entry_lo[29:12], tlb_entry_lo[1:0] };
2635
  tlb tlb_1(tlb_page, tlb_miss, tlb_found,
2636
            clk, tlb_enable, tlb_frame,
2637
            rw_index, r_page, r_frame,
2638
            w_enable, w_page, w_frame);
2639
 
2640
  // construct physical address
2641
  assign direct = (page[19:18] == 2'b11) ? 1 : 0;
2642
  assign frame = (direct == 1) ? page[17:0] : tlb_frame[19:2];
2643
  assign phys = { 2'b00, frame, offset };
2644
 
2645
  // generate "random" index
2646
  always @(posedge clk) begin
2647
    if (rst == 1) begin
2648
      // the index register is counting down
2649
      // so we must start at topmost index
2650
      random_index <= 5'd31;
2651
    end else begin
2652
      // decrement index register "randomly"
2653
      // (whenever there is a mapping operation)
2654
      // skip "fixed" entries (0..3)
2655
      if (map == 1) begin
2656
        if (random_index == 5'd4) begin
2657
          random_index <= 5'd31;
2658
        end else begin
2659
          random_index <= random_index - 1;
2660
        end
2661
      end
2662
    end
2663
  end
2664
 
2665
  // generate TLB exceptions
2666
  always @(posedge clk) begin
2667
    if (map == 1) begin
2668
      tlb_miss_delayed <= tlb_miss;
2669
    end
2670
  end
2671
  assign tlb_kmissed = tlb_miss_delayed & ~direct & page[19];
2672
  assign tlb_umissed = tlb_miss_delayed & ~direct & ~page[19];
2673
  assign tlb_invalid = ~tlb_vbit & ~direct;
2674
  assign tlb_wrtprot = ~tlb_wbit & ~direct;
2675
 
2676
endmodule
2677
 
2678
 
2679
//--------------------------------------------------------------
2680
// tlb -- the translation lookaside buffer
2681
//--------------------------------------------------------------
2682
 
2683
 
2684
module tlb(page_in, miss, found,
2685
           clk, enable, frame_out,
2686
           rw_index, r_page, r_frame,
2687
           w_enable, w_page, w_frame);
2688
    input [19:0] page_in;
2689
    output miss;
2690
    output [4:0] found;
2691
    input clk;
2692
    input enable;
2693
    output reg [19:0] frame_out;
2694
    input [4:0] rw_index;
2695
    output reg [19:0] r_page;
2696
    output reg [19:0] r_frame;
2697
    input w_enable;
2698
    input [19:0] w_page;
2699
    input [19:0] w_frame;
2700
 
2701
  reg [19:0] page[0:31];
2702
  reg [19:0] frame[0:31];
2703
 
2704
  wire [19:0] p00, p01, p02, p03;
2705
  wire [19:0] p04, p05, p06, p07;
2706
  wire [19:0] p08, p09, p10, p11;
2707
  wire [19:0] p12, p13, p14, p15;
2708
  wire [19:0] p16, p17, p18, p19;
2709
  wire [19:0] p20, p21, p22, p23;
2710
  wire [19:0] p24, p25, p26, p27;
2711
  wire [19:0] p28, p29, p30, p31;
2712
  wire [31:0] match;
2713
 
2714
  assign p00 = page[ 0];
2715
  assign p01 = page[ 1];
2716
  assign p02 = page[ 2];
2717
  assign p03 = page[ 3];
2718
  assign p04 = page[ 4];
2719
  assign p05 = page[ 5];
2720
  assign p06 = page[ 6];
2721
  assign p07 = page[ 7];
2722
  assign p08 = page[ 8];
2723
  assign p09 = page[ 9];
2724
  assign p10 = page[10];
2725
  assign p11 = page[11];
2726
  assign p12 = page[12];
2727
  assign p13 = page[13];
2728
  assign p14 = page[14];
2729
  assign p15 = page[15];
2730
  assign p16 = page[16];
2731
  assign p17 = page[17];
2732
  assign p18 = page[18];
2733
  assign p19 = page[19];
2734
  assign p20 = page[20];
2735
  assign p21 = page[21];
2736
  assign p22 = page[22];
2737
  assign p23 = page[23];
2738
  assign p24 = page[24];
2739
  assign p25 = page[25];
2740
  assign p26 = page[26];
2741
  assign p27 = page[27];
2742
  assign p28 = page[28];
2743
  assign p29 = page[29];
2744
  assign p30 = page[30];
2745
  assign p31 = page[31];
2746
 
2747
  assign match[ 0] = (page_in == p00) ? 1 : 0;
2748
  assign match[ 1] = (page_in == p01) ? 1 : 0;
2749
  assign match[ 2] = (page_in == p02) ? 1 : 0;
2750
  assign match[ 3] = (page_in == p03) ? 1 : 0;
2751
  assign match[ 4] = (page_in == p04) ? 1 : 0;
2752
  assign match[ 5] = (page_in == p05) ? 1 : 0;
2753
  assign match[ 6] = (page_in == p06) ? 1 : 0;
2754
  assign match[ 7] = (page_in == p07) ? 1 : 0;
2755
  assign match[ 8] = (page_in == p08) ? 1 : 0;
2756
  assign match[ 9] = (page_in == p09) ? 1 : 0;
2757
  assign match[10] = (page_in == p10) ? 1 : 0;
2758
  assign match[11] = (page_in == p11) ? 1 : 0;
2759
  assign match[12] = (page_in == p12) ? 1 : 0;
2760
  assign match[13] = (page_in == p13) ? 1 : 0;
2761
  assign match[14] = (page_in == p14) ? 1 : 0;
2762
  assign match[15] = (page_in == p15) ? 1 : 0;
2763
  assign match[16] = (page_in == p16) ? 1 : 0;
2764
  assign match[17] = (page_in == p17) ? 1 : 0;
2765
  assign match[18] = (page_in == p18) ? 1 : 0;
2766
  assign match[19] = (page_in == p19) ? 1 : 0;
2767
  assign match[20] = (page_in == p20) ? 1 : 0;
2768
  assign match[21] = (page_in == p21) ? 1 : 0;
2769
  assign match[22] = (page_in == p22) ? 1 : 0;
2770
  assign match[23] = (page_in == p23) ? 1 : 0;
2771
  assign match[24] = (page_in == p24) ? 1 : 0;
2772
  assign match[25] = (page_in == p25) ? 1 : 0;
2773
  assign match[26] = (page_in == p26) ? 1 : 0;
2774
  assign match[27] = (page_in == p27) ? 1 : 0;
2775
  assign match[28] = (page_in == p28) ? 1 : 0;
2776
  assign match[29] = (page_in == p29) ? 1 : 0;
2777
  assign match[30] = (page_in == p30) ? 1 : 0;
2778
  assign match[31] = (page_in == p31) ? 1 : 0;
2779
 
2780
  assign miss = ~(| match[31:0]);
2781
 
2782
  assign found[0] = match[ 1] | match[ 3] | match[ 5] | match[ 7] |
2783
                    match[ 9] | match[11] | match[13] | match[15] |
2784
                    match[17] | match[19] | match[21] | match[23] |
2785
                    match[25] | match[27] | match[29] | match[31];
2786
  assign found[1] = match[ 2] | match[ 3] | match[ 6] | match[ 7] |
2787
                    match[10] | match[11] | match[14] | match[15] |
2788
                    match[18] | match[19] | match[22] | match[23] |
2789
                    match[26] | match[27] | match[30] | match[31];
2790
  assign found[2] = match[ 4] | match[ 5] | match[ 6] | match[ 7] |
2791
                    match[12] | match[13] | match[14] | match[15] |
2792
                    match[20] | match[21] | match[22] | match[23] |
2793
                    match[28] | match[29] | match[30] | match[31];
2794
  assign found[3] = match[ 8] | match[ 9] | match[10] | match[11] |
2795
                    match[12] | match[13] | match[14] | match[15] |
2796
                    match[24] | match[25] | match[26] | match[27] |
2797
                    match[28] | match[29] | match[30] | match[31];
2798
  assign found[4] = match[16] | match[17] | match[18] | match[19] |
2799
                    match[20] | match[21] | match[22] | match[23] |
2800
                    match[24] | match[25] | match[26] | match[27] |
2801
                    match[28] | match[29] | match[30] | match[31];
2802
 
2803
  always @(posedge clk) begin
2804
    if (enable == 1) begin
2805
      frame_out <= frame[found];
2806
    end
2807
  end
2808
 
2809
  always @(posedge clk) begin
2810
    if (w_enable == 1) begin
2811
      page[rw_index] <= w_page;
2812
      frame[rw_index] <= w_frame;
2813
    end else begin
2814
      r_page <= page[rw_index];
2815
      r_frame <= frame[rw_index];
2816
    end
2817
  end
2818
 
2819
endmodule

powered by: WebSVN 2.1.0

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