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

Subversion Repositories openmsp430

[/] [openmsp430/] [trunk/] [fpga/] [altera_de0_nano_soc/] [rtl/] [verilog/] [openmsp430/] [omsp_frontend.v] - Blame information for rev 221

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 221 olivier.gi
//----------------------------------------------------------------------------
2
// Copyright (C) 2009 , Olivier Girard
3
//
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions
6
// are met:
7
//     * Redistributions of source code must retain the above copyright
8
//       notice, this list of conditions and the following disclaimer.
9
//     * Redistributions in binary form must reproduce the above copyright
10
//       notice, this list of conditions and the following disclaimer in the
11
//       documentation and/or other materials provided with the distribution.
12
//     * Neither the name of the authors nor the names of its contributors
13
//       may be used to endorse or promote products derived from this software
14
//       without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
21
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26
// THE POSSIBILITY OF SUCH DAMAGE
27
//
28
//----------------------------------------------------------------------------
29
//
30
// *File Name: omsp_frontend.v
31
//
32
// *Module Description:
33
//                       openMSP430 Instruction fetch and decode unit
34
//
35
// *Author(s):
36
//              - Olivier Girard,    olgirard@gmail.com
37
//
38
//----------------------------------------------------------------------------
39
// $Rev: 103 $
40
// $LastChangedBy: olivier.girard $
41
// $LastChangedDate: 2011-03-05 15:44:48 +0100 (Sat, 05 Mar 2011) $
42
//----------------------------------------------------------------------------
43
`ifdef OMSP_NO_INCLUDE
44
`else
45
`include "openMSP430_defines.v"
46
`endif
47
 
48
module  omsp_frontend (
49
 
50
// OUTPUTs
51
    cpu_halt_st,                       // Halt/Run status from CPU
52
    decode_noirq,                      // Frontend decode instruction
53
    e_state,                           // Execution state
54
    exec_done,                         // Execution completed
55
    inst_ad,                           // Decoded Inst: destination addressing mode
56
    inst_as,                           // Decoded Inst: source addressing mode
57
    inst_alu,                          // ALU control signals
58
    inst_bw,                           // Decoded Inst: byte width
59
    inst_dest,                         // Decoded Inst: destination (one hot)
60
    inst_dext,                         // Decoded Inst: destination extended instruction word
61
    inst_irq_rst,                      // Decoded Inst: Reset interrupt
62
    inst_jmp,                          // Decoded Inst: Conditional jump
63
    inst_mov,                          // Decoded Inst: mov instruction
64
    inst_sext,                         // Decoded Inst: source extended instruction word
65
    inst_so,                           // Decoded Inst: Single-operand arithmetic
66
    inst_src,                          // Decoded Inst: source (one hot)
67
    inst_type,                         // Decoded Instruction type
68
    irq_acc,                           // Interrupt request accepted (one-hot signal)
69
    mab,                               // Frontend Memory address bus
70
    mb_en,                             // Frontend Memory bus enable
71
    mclk_dma_enable,                   // DMA Sub-System Clock enable
72
    mclk_dma_wkup,                     // DMA Sub-System Clock wake-up (asynchronous)
73
    mclk_enable,                       // Main System Clock enable
74
    mclk_wkup,                         // Main System Clock wake-up (asynchronous)
75
    nmi_acc,                           // Non-Maskable interrupt request accepted
76
    pc,                                // Program counter
77
    pc_nxt,                            // Next PC value (for CALL & IRQ)
78
 
79
// INPUTs
80
    cpu_en_s,                          // Enable CPU code execution (synchronous)
81
    cpu_halt_cmd,                      // Halt CPU command
82
    cpuoff,                            // Turns off the CPU
83
    dbg_reg_sel,                       // Debug selected register for rd/wr access
84
    dma_en,                            // Direct Memory Access enable (high active)
85
    dma_wkup,                          // DMA Sub-System Wake-up (asynchronous and non-glitchy)
86
    fe_pmem_wait,                      // Frontend wait for Instruction fetch
87
    gie,                               // General interrupt enable
88
    irq,                               // Maskable interrupts
89
    mclk,                              // Main system clock
90
    mdb_in,                            // Frontend Memory data bus input
91
    nmi_pnd,                           // Non-maskable interrupt pending
92
    nmi_wkup,                          // NMI Wakeup
93
    pc_sw,                             // Program counter software value
94
    pc_sw_wr,                          // Program counter software write
95
    puc_rst,                           // Main system reset
96
    scan_enable,                       // Scan enable (active during scan shifting)
97
    wdt_irq,                           // Watchdog-timer interrupt
98
    wdt_wkup,                          // Watchdog Wakeup
99
    wkup                               // System Wake-up (asynchronous)
100
);
101
 
102
// OUTPUTs
103
//=========
104
output               cpu_halt_st;      // Halt/Run status from CPU
105
output               decode_noirq;     // Frontend decode instruction
106
output         [3:0] e_state;          // Execution state
107
output               exec_done;        // Execution completed
108
output         [7:0] inst_ad;          // Decoded Inst: destination addressing mode
109
output         [7:0] inst_as;          // Decoded Inst: source addressing mode
110
output        [11:0] inst_alu;         // ALU control signals
111
output               inst_bw;          // Decoded Inst: byte width
112
output        [15:0] inst_dest;        // Decoded Inst: destination (one hot)
113
output        [15:0] inst_dext;        // Decoded Inst: destination extended instruction word
114
output               inst_irq_rst;     // Decoded Inst: Reset interrupt
115
output         [7:0] inst_jmp;         // Decoded Inst: Conditional jump
116
output               inst_mov;         // Decoded Inst: mov instruction
117
output        [15:0] inst_sext;        // Decoded Inst: source extended instruction word
118
output         [7:0] inst_so;          // Decoded Inst: Single-operand arithmetic
119
output        [15:0] inst_src;         // Decoded Inst: source (one hot)
120
output         [2:0] inst_type;        // Decoded Instruction type
121
output [`IRQ_NR-3:0] irq_acc;          // Interrupt request accepted (one-hot signal)
122
output        [15:0] mab;              // Frontend Memory address bus
123
output               mb_en;            // Frontend Memory bus enable
124
output               mclk_dma_enable;  // DMA Sub-System Clock enable
125
output               mclk_dma_wkup;    // DMA Sub-System Clock wake-up (asynchronous)
126
output               mclk_enable;      // Main System Clock enable
127
output               mclk_wkup;        // Main System Clock wake-up (asynchronous)
128
output               nmi_acc;          // Non-Maskable interrupt request accepted
129
output        [15:0] pc;               // Program counter
130
output        [15:0] pc_nxt;           // Next PC value (for CALL & IRQ)
131
 
132
// INPUTs
133
//=========
134
input                cpu_en_s;         // Enable CPU code execution (synchronous)
135
input                cpu_halt_cmd;     // Halt CPU command
136
input                cpuoff;           // Turns off the CPU
137
input          [3:0] dbg_reg_sel;      // Debug selected register for rd/wr access
138
input                dma_en;           // Direct Memory Access enable (high active)
139
input                dma_wkup;         // DMA Sub-System Wake-up (asynchronous and non-glitchy)
140
input                fe_pmem_wait;     // Frontend wait for Instruction fetch
141
input                gie;              // General interrupt enable
142
input  [`IRQ_NR-3:0] irq;              // Maskable interrupts
143
input                mclk;             // Main system clock
144
input         [15:0] mdb_in;           // Frontend Memory data bus input
145
input                nmi_pnd;          // Non-maskable interrupt pending
146
input                nmi_wkup;         // NMI Wakeup
147
input         [15:0] pc_sw;            // Program counter software value
148
input                pc_sw_wr;         // Program counter software write
149
input                puc_rst;          // Main system reset
150
input                scan_enable;      // Scan enable (active during scan shifting)
151
input                wdt_irq;          // Watchdog-timer interrupt
152
input                wdt_wkup;         // Watchdog Wakeup
153
input                wkup;             // System Wake-up (asynchronous)
154
 
155
 
156
//=============================================================================
157
// 1)  UTILITY FUNCTIONS
158
//=============================================================================
159
 
160
// 64 bits one-hot decoder
161
function [63:0] one_hot64;
162
   input  [5:0] binary;
163
   begin
164
      one_hot64         = 64'h0000_0000_0000_0000;
165
      one_hot64[binary] =  1'b1;
166
   end
167
endfunction
168
 
169
// 16 bits one-hot decoder
170
function [15:0] one_hot16;
171
   input  [3:0] binary;
172
   begin
173
      one_hot16         = 16'h0000;
174
      one_hot16[binary] =  1'b1;
175
   end
176
endfunction
177
 
178
// 8 bits one-hot decoder
179
function [7:0] one_hot8;
180
   input  [2:0] binary;
181
   begin
182
      one_hot8         = 8'h00;
183
      one_hot8[binary] = 1'b1;
184
   end
185
endfunction
186
 
187
// Get IRQ number
188
function  [5:0] get_irq_num;
189
   input [62:0] irq_all;
190
   integer      ii;
191
   begin
192
      get_irq_num = 6'h3f;
193
      for (ii = 62; ii >= 0; ii = ii - 1)
194
        if (&get_irq_num & irq_all[ii]) get_irq_num = ii[5:0];
195
   end
196
endfunction
197
 
198
 
199
//=============================================================================
200
// 2)  PARAMETER DEFINITIONS
201
//=============================================================================
202
 
203
//
204
// 2.1) Instruction State machine definitons
205
//-------------------------------------------
206
 
207
parameter I_IRQ_FETCH = `I_IRQ_FETCH;
208
parameter I_IRQ_DONE  = `I_IRQ_DONE;
209
parameter I_DEC       = `I_DEC;        // New instruction ready for decode
210
parameter I_EXT1      = `I_EXT1;       // 1st Extension word
211
parameter I_EXT2      = `I_EXT2;       // 2nd Extension word
212
parameter I_IDLE      = `I_IDLE;       // CPU is in IDLE mode
213
 
214
//
215
// 2.2) Execution State machine definitons
216
//-------------------------------------------
217
 
218
parameter E_IRQ_0     = `E_IRQ_0;
219
parameter E_IRQ_1     = `E_IRQ_1;
220
parameter E_IRQ_2     = `E_IRQ_2;
221
parameter E_IRQ_3     = `E_IRQ_3;
222
parameter E_IRQ_4     = `E_IRQ_4;
223
parameter E_SRC_AD    = `E_SRC_AD;
224
parameter E_SRC_RD    = `E_SRC_RD;
225
parameter E_SRC_WR    = `E_SRC_WR;
226
parameter E_DST_AD    = `E_DST_AD;
227
parameter E_DST_RD    = `E_DST_RD;
228
parameter E_DST_WR    = `E_DST_WR;
229
parameter E_EXEC      = `E_EXEC;
230
parameter E_JUMP      = `E_JUMP;
231
parameter E_IDLE      = `E_IDLE;
232
 
233
 
234
//=============================================================================
235
// 3)  FRONTEND STATE MACHINE
236
//=============================================================================
237
 
238
// The wire "conv" is used as state bits to calculate the next response
239
reg  [2:0] i_state;
240
reg  [2:0] i_state_nxt;
241
 
242
reg  [1:0] inst_sz;
243
wire [1:0] inst_sz_nxt;
244
wire       irq_detect;
245
wire [2:0] inst_type_nxt;
246
wire       is_const;
247
reg [15:0] sconst_nxt;
248
reg  [3:0] e_state_nxt;
249
 
250
// CPU on/off through an external interface (debug or mstr) or cpu_en port
251
wire   cpu_halt_req = cpu_halt_cmd | ~cpu_en_s;
252
 
253
// States Transitions
254
always @(i_state    or inst_sz  or inst_sz_nxt  or pc_sw_wr or exec_done or
255
         irq_detect or cpuoff   or cpu_halt_req or e_state)
256
    case(i_state)
257
      I_IDLE     : i_state_nxt = (irq_detect & ~cpu_halt_req) ? I_IRQ_FETCH :
258
                                 (~cpuoff    & ~cpu_halt_req) ? I_DEC       : I_IDLE;
259
      I_IRQ_FETCH: i_state_nxt =  I_IRQ_DONE;
260
      I_IRQ_DONE : i_state_nxt =  I_DEC;
261
      I_DEC      : i_state_nxt =  irq_detect                  ? I_IRQ_FETCH :
262
                          (cpuoff | cpu_halt_req) & exec_done ? I_IDLE      :
263
                            cpu_halt_req & (e_state==E_IDLE)  ? I_IDLE      :
264
                                  pc_sw_wr                    ? I_DEC       :
265
                             ~exec_done & ~(e_state==E_IDLE)  ? I_DEC       :        // Wait in decode state
266
                                  (inst_sz_nxt!=2'b00)        ? I_EXT1      : I_DEC; // until execution is completed
267
      I_EXT1     : i_state_nxt =  pc_sw_wr                    ? I_DEC       :
268
                                  (inst_sz!=2'b01)            ? I_EXT2      : I_DEC;
269
      I_EXT2     : i_state_nxt =  I_DEC;
270
    // pragma coverage off
271
      default    : i_state_nxt =  I_IRQ_FETCH;
272
    // pragma coverage on
273
    endcase
274
 
275
// State machine
276
always @(posedge mclk or posedge puc_rst)
277
  if (puc_rst) i_state  <= I_IRQ_FETCH;
278
  else         i_state  <= i_state_nxt;
279
 
280
// Utility signals
281
wire   decode_noirq =  ((i_state==I_DEC) &  (exec_done | (e_state==E_IDLE)));
282
wire   decode       =  decode_noirq | irq_detect;
283
wire   fetch        = ~((i_state==I_DEC) & ~(exec_done | (e_state==E_IDLE))) & ~(e_state_nxt==E_IDLE);
284
 
285
// Halt/Run CPU status
286
reg    cpu_halt_st;
287
always @(posedge mclk or posedge puc_rst)
288
  if (puc_rst)  cpu_halt_st <= 1'b0;
289
  else          cpu_halt_st <= cpu_halt_req & (i_state_nxt==I_IDLE);
290
 
291
 
292
//=============================================================================
293
// 4)  INTERRUPT HANDLING & SYSTEM WAKEUP
294
//=============================================================================
295
 
296
//
297
// 4.1) INTERRUPT HANDLING
298
//-----------------------------------------
299
 
300
// Detect reset interrupt
301
reg         inst_irq_rst;
302
always @(posedge mclk or posedge puc_rst)
303
  if (puc_rst)                  inst_irq_rst <= 1'b1;
304
  else if (exec_done)           inst_irq_rst <= 1'b0;
305
 
306
//  Detect other interrupts
307
assign  irq_detect = (nmi_pnd | ((|irq | wdt_irq) & gie)) & ~cpu_halt_req & ~cpu_halt_st & (exec_done | (i_state==I_IDLE));
308
 
309
`ifdef CLOCK_GATING
310
wire       mclk_irq_num;
311
omsp_clock_gate clock_gate_irq_num (.gclk(mclk_irq_num),
312
                                    .clk (mclk), .enable(irq_detect), .scan_enable(scan_enable));
313
`else
314
wire       UNUSED_scan_enable = scan_enable;
315
wire       mclk_irq_num       = mclk;
316
`endif
317
 
318
// Combine all IRQs
319
`ifdef  IRQ_16
320
wire [62:0] irq_all     = {nmi_pnd, irq, 48'h0000_0000_0000} |
321
`else
322
`ifdef  IRQ_32
323
wire [62:0] irq_all     = {nmi_pnd, irq, 32'h0000_0000}      |
324
`else
325
`ifdef  IRQ_64
326
wire [62:0] irq_all     = {nmi_pnd, irq}                     |
327
`endif
328
`endif
329
`endif
330
                          {1'b0,    3'h0, wdt_irq, {58{1'b0}}};
331
 
332
// Select highest priority IRQ
333
reg  [5:0] irq_num;
334
always @(posedge mclk_irq_num or posedge puc_rst)
335
  if (puc_rst)         irq_num <= 6'h3f;
336
`ifdef CLOCK_GATING
337
  else
338
`else
339
  else if (irq_detect)
340
`endif
341
                       irq_num <= get_irq_num(irq_all);
342
 
343
// Generate selected IRQ vector address
344
wire [15:0] irq_addr    = {9'h1ff, irq_num, 1'b0};
345
 
346
// Interrupt request accepted
347
wire        [63:0] irq_acc_all = one_hot64(irq_num) & {64{(i_state==I_IRQ_FETCH)}};
348
wire [`IRQ_NR-3:0] irq_acc     = irq_acc_all[61:64-`IRQ_NR];
349
wire               nmi_acc     = irq_acc_all[62];
350
 
351
//
352
// 4.2) SYSTEM WAKEUP
353
//-----------------------------------------
354
`ifdef CPUOFF_EN
355
 
356
// Generate the main system clock enable signal
357
                                                    // Keep the clock running if:
358
wire mclk_enable = inst_irq_rst ? cpu_en_s :        //      - the RESET interrupt is currently executing
359
                                                    //        and if the CPU is enabled
360
                                                    // otherwise if:
361
                  ~((cpuoff | ~cpu_en_s) &          //      - the CPUOFF flag, cpu_en command, instruction
362
                   (i_state==I_IDLE) &              //        and execution state machines are all two
363
                   (e_state==E_IDLE));              //        not idle.
364
 
365
 
366
// Wakeup condition from maskable interrupts
367
wire mirq_wkup;
368
omsp_and_gate and_mirq_wkup     (.y(mirq_wkup),     .a(wkup | wdt_wkup),      .b(gie));
369
 
370
// Combined asynchronous wakeup detection from nmi & irq (masked if the cpu is disabled)
371
omsp_and_gate and_mclk_wkup     (.y(mclk_wkup),     .a(nmi_wkup | mirq_wkup), .b(cpu_en_s));
372
 
373
// Wakeup condition from DMA interface
374
  `ifdef DMA_IF_EN
375
wire mclk_dma_enable = dma_en & cpu_en_s;
376
omsp_and_gate and_mclk_dma_wkup (.y(mclk_dma_wkup), .a(dma_wkup),             .b(cpu_en_s));
377
  `else
378
assign  mclk_dma_wkup   = 1'b0;
379
assign  mclk_dma_enable = 1'b0;
380
wire    UNUSED_dma_en   = dma_en;
381
wire    UNUSED_dma_wkup = dma_wkup;
382
  `endif
383
`else
384
 
385
// In the CPUOFF feature is disabled, the wake-up and enable signals are always 1
386
assign  mclk_dma_wkup   = 1'b1;
387
assign  mclk_dma_enable = 1'b1;
388
assign  mclk_wkup       = 1'b1;
389
assign  mclk_enable     = 1'b1;
390
wire    UNUSED_dma_en   = dma_en;
391
wire    UNUSED_wkup     = wkup;
392
wire    UNUSED_wdt_wkup = wdt_wkup;
393
wire    UNUSED_nmi_wkup = nmi_wkup;
394
wire    UNUSED_dma_wkup = dma_wkup;
395
`endif
396
 
397
//=============================================================================
398
// 5)  FETCH INSTRUCTION
399
//=============================================================================
400
 
401
//
402
// 5.1) PROGRAM COUNTER & MEMORY INTERFACE
403
//-----------------------------------------
404
 
405
// Program counter
406
reg  [15:0] pc;
407
 
408
// Compute next PC value
409
wire [15:0] pc_incr = pc + {14'h0000, fetch, 1'b0};
410
wire [15:0] pc_nxt  = pc_sw_wr               ? pc_sw    :
411
                      (i_state==I_IRQ_FETCH) ? irq_addr :
412
                      (i_state==I_IRQ_DONE)  ? mdb_in   :  pc_incr;
413
 
414
`ifdef CLOCK_GATING
415
wire       pc_en  = fetch                  |
416
                    pc_sw_wr               |
417
                    (i_state==I_IRQ_FETCH) |
418
                    (i_state==I_IRQ_DONE);
419
wire       mclk_pc;
420
omsp_clock_gate clock_gate_pc (.gclk(mclk_pc),
421
                               .clk (mclk), .enable(pc_en), .scan_enable(scan_enable));
422
`else
423
wire       mclk_pc = mclk;
424
`endif
425
 
426
always @(posedge mclk_pc or posedge puc_rst)
427
  if (puc_rst)  pc <= 16'h0000;
428
  else          pc <= pc_nxt;
429
 
430
// Check if Program-Memory has been busy in order to retry Program-Memory access
431
reg pmem_busy;
432
always @(posedge mclk or posedge puc_rst)
433
  if (puc_rst)  pmem_busy <= 1'b0;
434
  else          pmem_busy <= fe_pmem_wait;
435
 
436
// Memory interface
437
wire [15:0] mab      = pc_nxt;
438
wire        mb_en    = fetch | pc_sw_wr | (i_state==I_IRQ_FETCH) | pmem_busy | (cpu_halt_st & ~cpu_halt_req);
439
 
440
 
441
//
442
// 5.2) INSTRUCTION REGISTER
443
//--------------------------------
444
 
445
// Instruction register
446
wire [15:0] ir  = mdb_in;
447
 
448
// Detect if source extension word is required
449
wire is_sext = (inst_as[`IDX] | inst_as[`SYMB] | inst_as[`ABS] | inst_as[`IMM]);
450
 
451
// For the Symbolic addressing mode, add -2 to the extension word in order
452
// to make up for the PC address
453
wire [15:0] ext_incr = ((i_state==I_EXT1)     &  inst_as[`SYMB]) |
454
                       ((i_state==I_EXT2)     &  inst_ad[`SYMB]) |
455
                       ((i_state==I_EXT1)     & ~inst_as[`SYMB] &
456
                       ~(i_state_nxt==I_EXT2) &  inst_ad[`SYMB])   ? 16'hfffe : 16'h0000;
457
 
458
wire [15:0] ext_nxt  = ir + ext_incr;
459
 
460
// Store source extension word
461
reg [15:0] inst_sext;
462
 
463
`ifdef CLOCK_GATING
464
wire       inst_sext_en  = (decode & is_const)                 |
465
                           (decode & inst_type_nxt[`INST_JMP]) |
466
                           ((i_state==I_EXT1) & is_sext);
467
wire       mclk_inst_sext;
468
omsp_clock_gate clock_gate_inst_sext (.gclk(mclk_inst_sext),
469
                                      .clk (mclk), .enable(inst_sext_en), .scan_enable(scan_enable));
470
`else
471
wire       mclk_inst_sext = mclk;
472
`endif
473
 
474
always @(posedge mclk_inst_sext or posedge puc_rst)
475
  if (puc_rst)                                 inst_sext <= 16'h0000;
476
  else if (decode & is_const)                  inst_sext <= sconst_nxt;
477
  else if (decode & inst_type_nxt[`INST_JMP])  inst_sext <= {{5{ir[9]}},ir[9:0],1'b0};
478
`ifdef CLOCK_GATING
479
  else                                         inst_sext <= ext_nxt;
480
`else
481
  else if ((i_state==I_EXT1) & is_sext)        inst_sext <= ext_nxt;
482
`endif
483
 
484
// Source extension word is ready
485
wire inst_sext_rdy = (i_state==I_EXT1) & is_sext;
486
 
487
 
488
// Store destination extension word
489
reg [15:0] inst_dext;
490
 
491
`ifdef CLOCK_GATING
492
wire       inst_dext_en  = ((i_state==I_EXT1) & ~is_sext) |
493
                            (i_state==I_EXT2);
494
wire       mclk_inst_dext;
495
omsp_clock_gate clock_gate_inst_dext (.gclk(mclk_inst_dext),
496
                                      .clk (mclk), .enable(inst_dext_en), .scan_enable(scan_enable));
497
`else
498
wire       mclk_inst_dext = mclk;
499
`endif
500
 
501
always @(posedge mclk_inst_dext or posedge puc_rst)
502
  if (puc_rst)                           inst_dext <= 16'h0000;
503
  else if ((i_state==I_EXT1) & ~is_sext) inst_dext <= ext_nxt;
504
`ifdef CLOCK_GATING
505
  else                                   inst_dext <= ext_nxt;
506
`else
507
  else if  (i_state==I_EXT2)             inst_dext <= ext_nxt;
508
`endif
509
 
510
// Destination extension word is ready
511
wire inst_dext_rdy = (((i_state==I_EXT1) & ~is_sext) | (i_state==I_EXT2));
512
 
513
 
514
//=============================================================================
515
// 6)  DECODE INSTRUCTION
516
//=============================================================================
517
 
518
`ifdef CLOCK_GATING
519
wire       mclk_decode;
520
omsp_clock_gate clock_gate_decode (.gclk(mclk_decode),
521
                                   .clk (mclk), .enable(decode), .scan_enable(scan_enable));
522
`else
523
wire       mclk_decode = mclk;
524
`endif
525
 
526
//
527
// 6.1) OPCODE: INSTRUCTION TYPE
528
//----------------------------------------
529
// Instructions type is encoded in a one hot fashion as following:
530
//
531
// 3'b001: Single-operand arithmetic
532
// 3'b010: Conditional jump
533
// 3'b100: Two-operand arithmetic
534
 
535
reg  [2:0] inst_type;
536
assign     inst_type_nxt = {(ir[15:14]!=2'b00),
537
                            (ir[15:13]==3'b001),
538
                            (ir[15:13]==3'b000)} & {3{~irq_detect}};
539
 
540
always @(posedge mclk_decode or posedge puc_rst)
541
  if (puc_rst)      inst_type <= 3'b000;
542
`ifdef CLOCK_GATING
543
  else              inst_type <= inst_type_nxt;
544
`else
545
  else if (decode)  inst_type <= inst_type_nxt;
546
`endif
547
 
548
//
549
// 6.2) OPCODE: SINGLE-OPERAND ARITHMETIC
550
//----------------------------------------
551
// Instructions are encoded in a one hot fashion as following:
552
//
553
// 8'b00000001: RRC
554
// 8'b00000010: SWPB
555
// 8'b00000100: RRA
556
// 8'b00001000: SXT
557
// 8'b00010000: PUSH
558
// 8'b00100000: CALL
559
// 8'b01000000: RETI
560
// 8'b10000000: IRQ
561
 
562
reg   [7:0] inst_so;
563
wire  [7:0] inst_so_nxt = irq_detect ? 8'h80 : (one_hot8(ir[9:7]) & {8{inst_type_nxt[`INST_SO]}});
564
 
565
always @(posedge mclk_decode or posedge puc_rst)
566
  if (puc_rst)     inst_so <= 8'h00;
567
`ifdef CLOCK_GATING
568
  else             inst_so <= inst_so_nxt;
569
`else
570
  else if (decode) inst_so <= inst_so_nxt;
571
`endif
572
 
573
//
574
// 6.3) OPCODE: CONDITIONAL JUMP
575
//--------------------------------
576
// Instructions are encoded in a one hot fashion as following:
577
//
578
// 8'b00000001: JNE/JNZ
579
// 8'b00000010: JEQ/JZ
580
// 8'b00000100: JNC/JLO
581
// 8'b00001000: JC/JHS
582
// 8'b00010000: JN
583
// 8'b00100000: JGE
584
// 8'b01000000: JL
585
// 8'b10000000: JMP
586
 
587
reg   [2:0] inst_jmp_bin;
588
always @(posedge mclk_decode or posedge puc_rst)
589
  if (puc_rst)     inst_jmp_bin <= 3'h0;
590
`ifdef CLOCK_GATING
591
  else             inst_jmp_bin <= ir[12:10];
592
`else
593
  else if (decode) inst_jmp_bin <= ir[12:10];
594
`endif
595
 
596
wire [7:0] inst_jmp = one_hot8(inst_jmp_bin) & {8{inst_type[`INST_JMP]}};
597
 
598
 
599
//
600
// 6.4) OPCODE: TWO-OPERAND ARITHMETIC
601
//-------------------------------------
602
// Instructions are encoded in a one hot fashion as following:
603
//
604
// 12'b000000000001: MOV
605
// 12'b000000000010: ADD
606
// 12'b000000000100: ADDC
607
// 12'b000000001000: SUBC
608
// 12'b000000010000: SUB
609
// 12'b000000100000: CMP
610
// 12'b000001000000: DADD
611
// 12'b000010000000: BIT
612
// 12'b000100000000: BIC
613
// 12'b001000000000: BIS
614
// 12'b010000000000: XOR
615
// 12'b100000000000: AND
616
 
617
wire [15:0] inst_to_1hot = one_hot16(ir[15:12]) & {16{inst_type_nxt[`INST_TO]}};
618
wire [11:0] inst_to_nxt  = inst_to_1hot[15:4];
619
 
620
reg         inst_mov;
621
always @(posedge mclk_decode or posedge puc_rst)
622
  if (puc_rst)     inst_mov <= 1'b0;
623
`ifdef CLOCK_GATING
624
  else             inst_mov <= inst_to_nxt[`MOV];
625
`else
626
  else if (decode) inst_mov <= inst_to_nxt[`MOV];
627
`endif
628
 
629
 
630
//
631
// 6.5) SOURCE AND DESTINATION REGISTERS
632
//---------------------------------------
633
 
634
// Destination register
635
reg [3:0] inst_dest_bin;
636
always @(posedge mclk_decode or posedge puc_rst)
637
  if (puc_rst)     inst_dest_bin <= 4'h0;
638
`ifdef CLOCK_GATING
639
  else             inst_dest_bin <= ir[3:0];
640
`else
641
  else if (decode) inst_dest_bin <= ir[3:0];
642
`endif
643
 
644
wire  [15:0] inst_dest = cpu_halt_st          ? one_hot16(dbg_reg_sel) :
645
                         inst_type[`INST_JMP] ? 16'h0001               :
646
                         inst_so[`IRQ]  |
647
                         inst_so[`PUSH] |
648
                         inst_so[`CALL]       ? 16'h0002               :
649
                                                one_hot16(inst_dest_bin);
650
 
651
 
652
// Source register
653
reg [3:0] inst_src_bin;
654
always @(posedge mclk_decode or posedge puc_rst)
655
  if (puc_rst)     inst_src_bin <= 4'h0;
656
`ifdef CLOCK_GATING
657
  else             inst_src_bin <= ir[11:8];
658
`else
659
  else if (decode) inst_src_bin <= ir[11:8];
660
`endif
661
 
662
wire  [15:0] inst_src = inst_type[`INST_TO] ? one_hot16(inst_src_bin)  :
663
                        inst_so[`RETI]      ? 16'h0002                 :
664
                        inst_so[`IRQ]       ? 16'h0001                 :
665
                        inst_type[`INST_SO] ? one_hot16(inst_dest_bin) : 16'h0000;
666
 
667
 
668
//
669
// 6.6) SOURCE ADDRESSING MODES
670
//--------------------------------
671
// Source addressing modes are encoded in a one hot fashion as following:
672
//
673
// 13'b0000000000001: Register direct.
674
// 13'b0000000000010: Register indexed.
675
// 13'b0000000000100: Register indirect.
676
// 13'b0000000001000: Register indirect autoincrement.
677
// 13'b0000000010000: Symbolic (operand is in memory at address PC+x).
678
// 13'b0000000100000: Immediate (operand is next word in the instruction stream).
679
// 13'b0000001000000: Absolute (operand is in memory at address x).
680
// 13'b0000010000000: Constant 4.
681
// 13'b0000100000000: Constant 8.
682
// 13'b0001000000000: Constant 0.
683
// 13'b0010000000000: Constant 1.
684
// 13'b0100000000000: Constant 2.
685
// 13'b1000000000000: Constant -1.
686
 
687
reg [12:0] inst_as_nxt;
688
 
689
wire [3:0] src_reg = inst_type_nxt[`INST_SO] ? ir[3:0] : ir[11:8];
690
 
691
always @(src_reg or ir or inst_type_nxt)
692
  begin
693
     if (inst_type_nxt[`INST_JMP])
694
       inst_as_nxt =  13'b0000000000001;
695
     else if (src_reg==4'h3) // Addressing mode using R3
696
       case (ir[5:4])
697
         2'b11  : inst_as_nxt =  13'b1000000000000;
698
         2'b10  : inst_as_nxt =  13'b0100000000000;
699
         2'b01  : inst_as_nxt =  13'b0010000000000;
700
         default: inst_as_nxt =  13'b0001000000000;
701
       endcase
702
     else if (src_reg==4'h2) // Addressing mode using R2
703
       case (ir[5:4])
704
         2'b11  : inst_as_nxt =  13'b0000100000000;
705
         2'b10  : inst_as_nxt =  13'b0000010000000;
706
         2'b01  : inst_as_nxt =  13'b0000001000000;
707
         default: inst_as_nxt =  13'b0000000000001;
708
       endcase
709
     else if (src_reg==4'h0) // Addressing mode using R0
710
       case (ir[5:4])
711
         2'b11  : inst_as_nxt =  13'b0000000100000;
712
         2'b10  : inst_as_nxt =  13'b0000000000100;
713
         2'b01  : inst_as_nxt =  13'b0000000010000;
714
         default: inst_as_nxt =  13'b0000000000001;
715
       endcase
716
     else                    // General Addressing mode
717
       case (ir[5:4])
718
         2'b11  : inst_as_nxt =  13'b0000000001000;
719
         2'b10  : inst_as_nxt =  13'b0000000000100;
720
         2'b01  : inst_as_nxt =  13'b0000000000010;
721
         default: inst_as_nxt =  13'b0000000000001;
722
       endcase
723
  end
724
assign    is_const = |inst_as_nxt[12:7];
725
 
726
reg [7:0] inst_as;
727
always @(posedge mclk_decode or posedge puc_rst)
728
  if (puc_rst)     inst_as <= 8'h00;
729
`ifdef CLOCK_GATING
730
  else             inst_as <= {is_const, inst_as_nxt[6:0]};
731
`else
732
  else if (decode) inst_as <= {is_const, inst_as_nxt[6:0]};
733
`endif
734
 
735
 
736
// 13'b0000010000000: Constant 4.
737
// 13'b0000100000000: Constant 8.
738
// 13'b0001000000000: Constant 0.
739
// 13'b0010000000000: Constant 1.
740
// 13'b0100000000000: Constant 2.
741
// 13'b1000000000000: Constant -1.
742
always @(inst_as_nxt)
743
  begin
744
     if (inst_as_nxt[7])        sconst_nxt = 16'h0004;
745
     else if (inst_as_nxt[8])   sconst_nxt = 16'h0008;
746
     else if (inst_as_nxt[9])   sconst_nxt = 16'h0000;
747
     else if (inst_as_nxt[10])  sconst_nxt = 16'h0001;
748
     else if (inst_as_nxt[11])  sconst_nxt = 16'h0002;
749
     else if (inst_as_nxt[12])  sconst_nxt = 16'hffff;
750
     else                       sconst_nxt = 16'h0000;
751
  end
752
 
753
 
754
//
755
// 6.7) DESTINATION ADDRESSING MODES
756
//-----------------------------------
757
// Destination addressing modes are encoded in a one hot fashion as following:
758
//
759
// 8'b00000001: Register direct.
760
// 8'b00000010: Register indexed.
761
// 8'b00010000: Symbolic (operand is in memory at address PC+x).
762
// 8'b01000000: Absolute (operand is in memory at address x).
763
 
764
reg  [7:0] inst_ad_nxt;
765
 
766
wire [3:0] dest_reg = ir[3:0];
767
 
768
always @(dest_reg or ir or inst_type_nxt)
769
  begin
770
     if (~inst_type_nxt[`INST_TO])
771
       inst_ad_nxt =  8'b00000000;
772
     else if (dest_reg==4'h2)   // Addressing mode using R2
773
       case (ir[7])
774
         1'b1   : inst_ad_nxt =  8'b01000000;
775
         default: inst_ad_nxt =  8'b00000001;
776
       endcase
777
     else if (dest_reg==4'h0)   // Addressing mode using R0
778
       case (ir[7])
779
         1'b1   : inst_ad_nxt =  8'b00010000;
780
         default: inst_ad_nxt =  8'b00000001;
781
       endcase
782
     else                       // General Addressing mode
783
       case (ir[7])
784
         1'b1   : inst_ad_nxt =  8'b00000010;
785
         default: inst_ad_nxt =  8'b00000001;
786
       endcase
787
  end
788
 
789
reg [7:0] inst_ad;
790
always @(posedge mclk_decode or posedge puc_rst)
791
  if (puc_rst)     inst_ad <= 8'h00;
792
`ifdef CLOCK_GATING
793
  else             inst_ad <= inst_ad_nxt;
794
`else
795
  else if (decode) inst_ad <= inst_ad_nxt;
796
`endif
797
 
798
 
799
//
800
// 6.8) REMAINING INSTRUCTION DECODING
801
//-------------------------------------
802
 
803
// Operation size
804
reg       inst_bw;
805
always @(posedge mclk or posedge puc_rst)
806
  if (puc_rst)     inst_bw     <= 1'b0;
807
  else if (decode) inst_bw     <= ir[6] & ~inst_type_nxt[`INST_JMP] & ~irq_detect & ~cpu_halt_req;
808
 
809
// Extended instruction size
810
assign    inst_sz_nxt = {1'b0,  (inst_as_nxt[`IDX] | inst_as_nxt[`SYMB] | inst_as_nxt[`ABS] | inst_as_nxt[`IMM])} +
811
                        {1'b0, ((inst_ad_nxt[`IDX] | inst_ad_nxt[`SYMB] | inst_ad_nxt[`ABS]) & ~inst_type_nxt[`INST_SO])};
812
always @(posedge mclk_decode or posedge puc_rst)
813
  if (puc_rst)     inst_sz     <= 2'b00;
814
`ifdef CLOCK_GATING
815
  else             inst_sz     <= inst_sz_nxt;
816
`else
817
  else if (decode) inst_sz     <= inst_sz_nxt;
818
`endif
819
 
820
 
821
//=============================================================================
822
// 7)  EXECUTION-UNIT STATE MACHINE
823
//=============================================================================
824
 
825
// State machine registers
826
reg  [3:0] e_state;
827
 
828
 
829
// State machine control signals
830
//--------------------------------
831
 
832
wire src_acalc_pre =  inst_as_nxt[`IDX]   | inst_as_nxt[`SYMB]    | inst_as_nxt[`ABS];
833
wire src_rd_pre    =  inst_as_nxt[`INDIR] | inst_as_nxt[`INDIR_I] | inst_as_nxt[`IMM]  | inst_so_nxt[`RETI];
834
wire dst_acalc_pre =  inst_ad_nxt[`IDX]   | inst_ad_nxt[`SYMB]    | inst_ad_nxt[`ABS];
835
wire dst_acalc     =  inst_ad[`IDX]       | inst_ad[`SYMB]        | inst_ad[`ABS];
836
wire dst_rd_pre    =  inst_ad_nxt[`IDX]   | inst_so_nxt[`PUSH]    | inst_so_nxt[`CALL] | inst_so_nxt[`RETI];
837
wire dst_rd        =  inst_ad[`IDX]       | inst_so[`PUSH]        | inst_so[`CALL]     | inst_so[`RETI];
838
 
839
wire inst_branch   =  (inst_ad_nxt[`DIR] & (ir[3:0]==4'h0)) | inst_type_nxt[`INST_JMP] | inst_so_nxt[`RETI];
840
 
841
reg exec_jmp;
842
always @(posedge mclk or posedge puc_rst)
843
  if (puc_rst)                   exec_jmp <= 1'b0;
844
  else if (inst_branch & decode) exec_jmp <= 1'b1;
845
  else if (e_state==E_JUMP)      exec_jmp <= 1'b0;
846
 
847
reg exec_dst_wr;
848
always @(posedge mclk or posedge puc_rst)
849
  if (puc_rst)                exec_dst_wr <= 1'b0;
850
  else if (e_state==E_DST_RD) exec_dst_wr <= 1'b1;
851
  else if (e_state==E_DST_WR) exec_dst_wr <= 1'b0;
852
 
853
reg exec_src_wr;
854
always @(posedge mclk or posedge puc_rst)
855
  if (puc_rst)                                         exec_src_wr <= 1'b0;
856
  else if (inst_type[`INST_SO] & (e_state==E_SRC_RD))  exec_src_wr <= 1'b1;
857
  else if ((e_state==E_SRC_WR) || (e_state==E_DST_WR)) exec_src_wr <= 1'b0;
858
 
859
reg exec_dext_rdy;
860
always @(posedge mclk or posedge puc_rst)
861
  if (puc_rst)                exec_dext_rdy <= 1'b0;
862
  else if (e_state==E_DST_RD) exec_dext_rdy <= 1'b0;
863
  else if (inst_dext_rdy)     exec_dext_rdy <= 1'b1;
864
 
865
// Execution first state
866
wire [3:0] e_first_state = ~cpu_halt_st  & inst_so_nxt[`IRQ] ? E_IRQ_0  :
867
                            cpu_halt_req | (i_state==I_IDLE) ? E_IDLE   :
868
                            cpuoff                           ? E_IDLE   :
869
                            src_acalc_pre                    ? E_SRC_AD :
870
                            src_rd_pre                       ? E_SRC_RD :
871
                            dst_acalc_pre                    ? E_DST_AD :
872
                            dst_rd_pre                       ? E_DST_RD : E_EXEC;
873
 
874
 
875
// State machine
876
//--------------------------------
877
 
878
// States Transitions
879
always @(e_state       or dst_acalc     or dst_rd   or inst_sext_rdy or
880
         inst_dext_rdy or exec_dext_rdy or exec_jmp or exec_dst_wr   or
881
         e_first_state or exec_src_wr)
882
    case(e_state)
883
      E_IDLE   : e_state_nxt =  e_first_state;
884
      E_IRQ_0  : e_state_nxt =  E_IRQ_1;
885
      E_IRQ_1  : e_state_nxt =  E_IRQ_2;
886
      E_IRQ_2  : e_state_nxt =  E_IRQ_3;
887
      E_IRQ_3  : e_state_nxt =  E_IRQ_4;
888
      E_IRQ_4  : e_state_nxt =  E_EXEC;
889
 
890
      E_SRC_AD : e_state_nxt =  inst_sext_rdy     ? E_SRC_RD : E_SRC_AD;
891
 
892
      E_SRC_RD : e_state_nxt =  dst_acalc         ? E_DST_AD :
893
                                 dst_rd           ? E_DST_RD : E_EXEC;
894
 
895
      E_DST_AD : e_state_nxt =  (inst_dext_rdy |
896
                                 exec_dext_rdy)   ? E_DST_RD : E_DST_AD;
897
 
898
      E_DST_RD : e_state_nxt =  E_EXEC;
899
 
900
      E_EXEC   : e_state_nxt =  exec_dst_wr       ? E_DST_WR :
901
                                exec_jmp          ? E_JUMP   :
902
                                exec_src_wr       ? E_SRC_WR : e_first_state;
903
 
904
      E_JUMP   : e_state_nxt =  e_first_state;
905
      E_DST_WR : e_state_nxt =  exec_jmp          ? E_JUMP   : e_first_state;
906
      E_SRC_WR : e_state_nxt =  e_first_state;
907
    // pragma coverage off
908
      default  : e_state_nxt =  E_IRQ_0;
909
    // pragma coverage on
910
    endcase
911
 
912
// State machine
913
always @(posedge mclk or posedge puc_rst)
914
  if (puc_rst) e_state  <= E_IRQ_1;
915
  else         e_state  <= e_state_nxt;
916
 
917
 
918
// Frontend State machine control signals
919
//----------------------------------------
920
 
921
wire exec_done = exec_jmp        ? (e_state==E_JUMP)   :
922
                 exec_dst_wr     ? (e_state==E_DST_WR) :
923
                 exec_src_wr     ? (e_state==E_SRC_WR) : (e_state==E_EXEC);
924
 
925
 
926
//=============================================================================
927
// 8)  EXECUTION-UNIT STATE CONTROL
928
//=============================================================================
929
 
930
//
931
// 8.1) ALU CONTROL SIGNALS
932
//-------------------------------------
933
//
934
// 12'b000000000001: Enable ALU source inverter
935
// 12'b000000000010: Enable Incrementer
936
// 12'b000000000100: Enable Incrementer on carry bit
937
// 12'b000000001000: Select Adder
938
// 12'b000000010000: Select AND
939
// 12'b000000100000: Select OR
940
// 12'b000001000000: Select XOR
941
// 12'b000010000000: Select DADD
942
// 12'b000100000000: Update N, Z & C (C=~Z)
943
// 12'b001000000000: Update all status bits
944
// 12'b010000000000: Update status bit for XOR instruction
945
// 12'b100000000000: Don't write to destination
946
 
947
reg  [11:0] inst_alu;
948
 
949
wire        alu_src_inv   = inst_to_nxt[`SUB]  | inst_to_nxt[`SUBC] |
950
                            inst_to_nxt[`CMP]  | inst_to_nxt[`BIC] ;
951
 
952
wire        alu_inc       = inst_to_nxt[`SUB]  | inst_to_nxt[`CMP];
953
 
954
wire        alu_inc_c     = inst_to_nxt[`ADDC] | inst_to_nxt[`DADD] |
955
                            inst_to_nxt[`SUBC];
956
 
957
wire        alu_add       = inst_to_nxt[`ADD]  | inst_to_nxt[`ADDC]       |
958
                            inst_to_nxt[`SUB]  | inst_to_nxt[`SUBC]       |
959
                            inst_to_nxt[`CMP]  | inst_type_nxt[`INST_JMP] |
960
                            inst_so_nxt[`RETI];
961
 
962
 
963
wire        alu_and       = inst_to_nxt[`AND]  | inst_to_nxt[`BIC]  |
964
                            inst_to_nxt[`BIT];
965
 
966
wire        alu_or        = inst_to_nxt[`BIS];
967
 
968
wire        alu_xor       = inst_to_nxt[`XOR];
969
 
970
wire        alu_dadd      = inst_to_nxt[`DADD];
971
 
972
wire        alu_stat_7    = inst_to_nxt[`BIT]  | inst_to_nxt[`AND]  |
973
                            inst_so_nxt[`SXT];
974
 
975
wire        alu_stat_f    = inst_to_nxt[`ADD]  | inst_to_nxt[`ADDC] |
976
                            inst_to_nxt[`SUB]  | inst_to_nxt[`SUBC] |
977
                            inst_to_nxt[`CMP]  | inst_to_nxt[`DADD] |
978
                            inst_to_nxt[`BIT]  | inst_to_nxt[`XOR]  |
979
                            inst_to_nxt[`AND]  |
980
                            inst_so_nxt[`RRC]  | inst_so_nxt[`RRA]  |
981
                            inst_so_nxt[`SXT];
982
 
983
wire        alu_shift     = inst_so_nxt[`RRC]  | inst_so_nxt[`RRA];
984
 
985
wire        exec_no_wr    = inst_to_nxt[`CMP] | inst_to_nxt[`BIT];
986
 
987
wire [11:0] inst_alu_nxt  = {exec_no_wr,
988
                             alu_shift,
989
                             alu_stat_f,
990
                             alu_stat_7,
991
                             alu_dadd,
992
                             alu_xor,
993
                             alu_or,
994
                             alu_and,
995
                             alu_add,
996
                             alu_inc_c,
997
                             alu_inc,
998
                             alu_src_inv};
999
 
1000
always @(posedge mclk_decode or posedge puc_rst)
1001
  if (puc_rst)     inst_alu <= 12'h000;
1002
`ifdef CLOCK_GATING
1003
  else             inst_alu <= inst_alu_nxt;
1004
`else
1005
  else if (decode) inst_alu <= inst_alu_nxt;
1006
`endif
1007
 
1008
 
1009
endmodule // omsp_frontend
1010
 
1011
`ifdef OMSP_NO_INCLUDE
1012
`else
1013
`include "openMSP430_undefines.v"
1014
`endif

powered by: WebSVN 2.1.0

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