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

Subversion Repositories openmsp430

[/] [openmsp430/] [trunk/] [core/] [rtl/] [verilog/] [omsp_frontend.v] - Blame information for rev 118

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

Line No. Rev Author Line
1 2 olivier.gi
//----------------------------------------------------------------------------
2 117 olivier.gi
// Copyright (C) 2009 , Olivier Girard
3 2 olivier.gi
//
4 117 olivier.gi
// 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 2 olivier.gi
//
16 117 olivier.gi
// 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 2 olivier.gi
//
28
//----------------------------------------------------------------------------
29
//
30 34 olivier.gi
// *File Name: omsp_frontend.v
31 2 olivier.gi
// 
32
// *Module Description:
33
//                       openMSP430 Instruction fetch and decode unit
34
//
35
// *Author(s):
36
//              - Olivier Girard,    olgirard@gmail.com
37
//
38
//----------------------------------------------------------------------------
39 17 olivier.gi
// $Rev: 117 $
40
// $LastChangedBy: olivier.girard $
41
// $LastChangedDate: 2011-06-23 21:30:51 +0200 (Thu, 23 Jun 2011) $
42
//----------------------------------------------------------------------------
43 103 olivier.gi
`ifdef OMSP_NO_INCLUDE
44
`else
45 23 olivier.gi
`include "openMSP430_defines.v"
46 103 olivier.gi
`endif
47 2 olivier.gi
 
48 34 olivier.gi
module  omsp_frontend (
49 2 olivier.gi
 
50
// OUTPUTs
51
    dbg_halt_st,                   // Halt/Run status from CPU
52 53 olivier.gi
    decode_noirq,                  // Frontend decode instruction
53 2 olivier.gi
    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 105 olivier.gi
    inst_mov,                      // Decoded Inst: mov instruction
64 2 olivier.gi
    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
    nmi_acc,                       // Non-Maskable interrupt request accepted
72
    pc,                            // Program counter
73
    pc_nxt,                        // Next PC value (for CALL & IRQ)
74
 
75
// INPUTs
76 106 olivier.gi
    cpu_en_s,                      // Enable CPU code execution (synchronous)
77 2 olivier.gi
    cpuoff,                        // Turns off the CPU
78
    dbg_halt_cmd,                  // Halt CPU command
79
    dbg_reg_sel,                   // Debug selected register for rd/wr access
80 33 olivier.gi
    fe_pmem_wait,                  // Frontend wait for Instruction fetch
81 2 olivier.gi
    gie,                           // General interrupt enable
82
    irq,                           // Maskable interrupts
83
    mclk,                          // Main system clock
84
    mdb_in,                        // Frontend Memory data bus input
85
    nmi_evt,                       // Non-maskable interrupt event
86
    pc_sw,                         // Program counter software value
87
    pc_sw_wr,                      // Program counter software write
88 111 olivier.gi
    puc_rst,                       // Main system reset
89 2 olivier.gi
    wdt_irq                        // Watchdog-timer interrupt
90
);
91
 
92
// OUTPUTs
93
//=========
94
output              dbg_halt_st;   // Halt/Run status from CPU
95 53 olivier.gi
output              decode_noirq;  // Frontend decode instruction
96 2 olivier.gi
output        [3:0] e_state;       // Execution state
97
output              exec_done;     // Execution completed
98
output        [7:0] inst_ad;       // Decoded Inst: destination addressing mode
99
output        [7:0] inst_as;       // Decoded Inst: source addressing mode
100
output       [11:0] inst_alu;      // ALU control signals
101
output              inst_bw;       // Decoded Inst: byte width
102
output       [15:0] inst_dest;     // Decoded Inst: destination (one hot)
103
output       [15:0] inst_dext;     // Decoded Inst: destination extended instruction word
104
output              inst_irq_rst;  // Decoded Inst: Reset interrupt
105
output        [7:0] inst_jmp;      // Decoded Inst: Conditional jump
106 105 olivier.gi
output              inst_mov;      // Decoded Inst: mov instruction
107 2 olivier.gi
output       [15:0] inst_sext;     // Decoded Inst: source extended instruction word
108
output        [7:0] inst_so;       // Decoded Inst: Single-operand arithmetic
109
output       [15:0] inst_src;      // Decoded Inst: source (one hot)
110
output        [2:0] inst_type;     // Decoded Instruction type
111
output       [13:0] irq_acc;       // Interrupt request accepted (one-hot signal)
112
output       [15:0] mab;           // Frontend Memory address bus
113
output              mb_en;         // Frontend Memory bus enable
114
output              nmi_acc;       // Non-Maskable interrupt request accepted
115
output       [15:0] pc;            // Program counter
116
output       [15:0] pc_nxt;        // Next PC value (for CALL & IRQ)
117
 
118
// INPUTs
119
//=========
120 106 olivier.gi
input               cpu_en_s;      // Enable CPU code execution (synchronous)
121 2 olivier.gi
input               cpuoff;        // Turns off the CPU
122
input               dbg_halt_cmd;  // Halt CPU command
123
input         [3:0] dbg_reg_sel;   // Debug selected register for rd/wr access
124 33 olivier.gi
input               fe_pmem_wait;  // Frontend wait for Instruction fetch
125 2 olivier.gi
input               gie;           // General interrupt enable
126
input        [13:0] irq;           // Maskable interrupts
127
input               mclk;          // Main system clock
128
input        [15:0] mdb_in;        // Frontend Memory data bus input
129
input               nmi_evt;       // Non-maskable interrupt event
130
input        [15:0] pc_sw;         // Program counter software value
131
input               pc_sw_wr;      // Program counter software write
132 111 olivier.gi
input               puc_rst;       // Main system reset
133 2 olivier.gi
input               wdt_irq;       // Watchdog-timer interrupt
134
 
135
 
136
//=============================================================================
137 111 olivier.gi
// 1)  UTILITY FUNCTIONS
138 85 olivier.gi
//=============================================================================
139
 
140
// 16 bits one-hot decoder
141
function [15:0] one_hot16;
142
   input  [3:0] binary;
143
   begin
144
      one_hot16         = 16'h0000;
145
      one_hot16[binary] =  1'b1;
146
   end
147
endfunction
148
 
149
// 8 bits one-hot decoder
150
function [7:0] one_hot8;
151
   input  [2:0] binary;
152
   begin
153
      one_hot8         = 8'h00;
154
      one_hot8[binary] = 1'b1;
155
   end
156
endfunction
157
 
158
 
159
//=============================================================================
160 111 olivier.gi
// 2)  Parameter definitions
161 2 olivier.gi
//=============================================================================
162
 
163 111 olivier.gi
//
164
// 2.1) Instruction State machine definitons
165
//-------------------------------------------
166
 
167
parameter I_IRQ_FETCH = `I_IRQ_FETCH;
168
parameter I_IRQ_DONE  = `I_IRQ_DONE;
169
parameter I_DEC       = `I_DEC;        // New instruction ready for decode
170
parameter I_EXT1      = `I_EXT1;       // 1st Extension word
171
parameter I_EXT2      = `I_EXT2;       // 2nd Extension word
172
parameter I_IDLE      = `I_IDLE;       // CPU is in IDLE mode
173
 
174
//
175
// 2.2) Execution State machine definitons
176
//-------------------------------------------
177
 
178
parameter E_IRQ_0     = `E_IRQ_0;
179
parameter E_IRQ_1     = `E_IRQ_1;
180
parameter E_IRQ_2     = `E_IRQ_2;
181
parameter E_IRQ_3     = `E_IRQ_3;
182
parameter E_IRQ_4     = `E_IRQ_4;
183
parameter E_SRC_AD    = `E_SRC_AD;
184
parameter E_SRC_RD    = `E_SRC_RD;
185
parameter E_SRC_WR    = `E_SRC_WR;
186
parameter E_DST_AD    = `E_DST_AD;
187
parameter E_DST_RD    = `E_DST_RD;
188
parameter E_DST_WR    = `E_DST_WR;
189
parameter E_EXEC      = `E_EXEC;
190
parameter E_JUMP      = `E_JUMP;
191
parameter E_IDLE      = `E_IDLE;
192
 
193
 
194
//=============================================================================
195
// 3)  FRONTEND STATE MACHINE
196
//=============================================================================
197
 
198 2 olivier.gi
// The wire "conv" is used as state bits to calculate the next response
199
reg  [2:0] i_state;
200
reg  [2:0] i_state_nxt;
201
 
202
reg  [1:0] inst_sz;
203
wire [1:0] inst_sz_nxt;
204
wire       irq_detect;
205
wire [2:0] inst_type_nxt;
206
wire       is_const;
207
reg [15:0] sconst_nxt;
208
reg  [3:0] e_state_nxt;
209
 
210 106 olivier.gi
// CPU on/off through the debug interface or cpu_en port
211
wire   cpu_halt_cmd = dbg_halt_cmd | ~cpu_en_s;
212
 
213 2 olivier.gi
// States Transitions
214 111 olivier.gi
always @(i_state    or inst_sz  or inst_sz_nxt  or pc_sw_wr or exec_done or
215
         irq_detect or cpuoff   or cpu_halt_cmd or e_state)
216 2 olivier.gi
    case(i_state)
217 106 olivier.gi
      I_IDLE     : i_state_nxt = (irq_detect & ~cpu_halt_cmd) ? I_IRQ_FETCH :
218
                                 (~cpuoff    & ~cpu_halt_cmd) ? I_DEC       : I_IDLE;
219 2 olivier.gi
      I_IRQ_FETCH: i_state_nxt =  I_IRQ_DONE;
220
      I_IRQ_DONE : i_state_nxt =  I_DEC;
221
      I_DEC      : i_state_nxt =  irq_detect                  ? I_IRQ_FETCH :
222 106 olivier.gi
                          (cpuoff | cpu_halt_cmd) & exec_done ? I_IDLE      :
223 111 olivier.gi
                            cpu_halt_cmd & (e_state==E_IDLE)  ? I_IDLE      :
224 2 olivier.gi
                                  pc_sw_wr                    ? I_DEC       :
225 111 olivier.gi
                             ~exec_done & ~(e_state==E_IDLE)  ? I_DEC       :        // Wait in decode state
226 2 olivier.gi
                                  (inst_sz_nxt!=2'b00)        ? I_EXT1      : I_DEC; // until execution is completed
227
      I_EXT1     : i_state_nxt =  irq_detect                  ? I_IRQ_FETCH :
228
                                  pc_sw_wr                    ? I_DEC       :
229
                                  (inst_sz!=2'b01)            ? I_EXT2      : I_DEC;
230
      I_EXT2     : i_state_nxt =  irq_detect                  ? I_IRQ_FETCH : I_DEC;
231
      default    : i_state_nxt =  I_IRQ_FETCH;
232
    endcase
233
 
234
// State machine
235 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
236
  if (puc_rst) i_state  <= I_IRQ_FETCH;
237
  else         i_state  <= i_state_nxt;
238 2 olivier.gi
 
239
// Utility signals
240 111 olivier.gi
wire   decode_noirq =  ((i_state==I_DEC) &  (exec_done | (e_state==E_IDLE)));
241 53 olivier.gi
wire   decode       =  decode_noirq | irq_detect;
242 111 olivier.gi
wire   fetch        = ~((i_state==I_DEC) & ~(exec_done | (e_state==E_IDLE))) & ~(e_state_nxt==E_IDLE);
243 2 olivier.gi
 
244
// Debug interface cpu status
245
reg    dbg_halt_st;
246 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
247
  if (puc_rst)  dbg_halt_st <= 1'b0;
248
  else          dbg_halt_st <= cpu_halt_cmd & (i_state_nxt==I_IDLE);
249 2 olivier.gi
 
250
 
251
//=============================================================================
252 111 olivier.gi
// 4)  INTERRUPT HANDLING
253 2 olivier.gi
//=============================================================================
254
 
255
// Detect nmi interrupt
256
reg         inst_nmi;
257 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
258
  if (puc_rst)                  inst_nmi <= 1'b0;
259 2 olivier.gi
  else if (nmi_evt)             inst_nmi <= 1'b1;
260
  else if (i_state==I_IRQ_DONE) inst_nmi <= 1'b0;
261
 
262
 
263
// Detect reset interrupt
264
reg         inst_irq_rst;
265 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
266
  if (puc_rst)                  inst_irq_rst <= 1'b1;
267 2 olivier.gi
  else if (exec_done)           inst_irq_rst <= 1'b0;
268
 
269
//  Detect other interrupts
270 106 olivier.gi
assign  irq_detect = (inst_nmi | ((|irq | wdt_irq) & gie)) & ~cpu_halt_cmd & ~dbg_halt_st & (exec_done | (i_state==I_IDLE));
271 2 olivier.gi
 
272
// Select interrupt vector
273
reg  [3:0] irq_num;
274 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
275
  if (puc_rst)         irq_num <= 4'hf;
276 2 olivier.gi
  else if (irq_detect) irq_num <= inst_nmi           ?  4'he :
277
                                  irq[13]            ?  4'hd :
278
                                  irq[12]            ?  4'hc :
279
                                  irq[11]            ?  4'hb :
280
                                 (irq[10] | wdt_irq) ?  4'ha :
281
                                  irq[9]             ?  4'h9 :
282
                                  irq[8]             ?  4'h8 :
283
                                  irq[7]             ?  4'h7 :
284
                                  irq[6]             ?  4'h6 :
285
                                  irq[5]             ?  4'h5 :
286
                                  irq[4]             ?  4'h4 :
287
                                  irq[3]             ?  4'h3 :
288
                                  irq[2]             ?  4'h2 :
289
                                  irq[1]             ?  4'h1 :
290
                                  irq[0]             ?  4'h0 : 4'hf;
291
 
292
wire [15:0] irq_addr    = {11'h7ff, irq_num, 1'b0};
293
 
294
// Interrupt request accepted
295 85 olivier.gi
wire [15:0] irq_acc_all = one_hot16(irq_num) & {16{(i_state==I_IRQ_FETCH)}};
296 2 olivier.gi
wire [13:0] irq_acc     = irq_acc_all[13:0];
297
wire        nmi_acc     = irq_acc_all[14];
298
 
299
 
300
//=============================================================================
301 111 olivier.gi
// 5)  FETCH INSTRUCTION
302 2 olivier.gi
//=============================================================================
303
 
304
//
305 111 olivier.gi
// 5.1) PROGRAM COUNTER & MEMORY INTERFACE
306 2 olivier.gi
//-----------------------------------------
307
 
308
// Program counter
309
reg  [15:0] pc;
310
 
311 60 olivier.gi
// Compute next PC value
312
wire [15:0] pc_incr = pc + {14'h0000, fetch, 1'b0};
313
wire [15:0] pc_nxt  = pc_sw_wr               ? pc_sw    :
314 2 olivier.gi
                      (i_state==I_IRQ_FETCH) ? irq_addr :
315 60 olivier.gi
                      (i_state==I_IRQ_DONE)  ? mdb_in   :  pc_incr;
316 2 olivier.gi
 
317 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
318
  if (puc_rst)  pc <= 16'h0000;
319
  else          pc <= pc_nxt;
320 2 olivier.gi
 
321
// Check if ROM has been busy in order to retry ROM access
322 33 olivier.gi
reg pmem_busy;
323 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
324
  if (puc_rst)  pmem_busy <= 1'b0;
325
  else          pmem_busy <= fe_pmem_wait;
326 2 olivier.gi
 
327
// Memory interface
328
wire [15:0] mab      = pc_nxt;
329 106 olivier.gi
wire        mb_en    = fetch | pc_sw_wr | (i_state==I_IRQ_FETCH) | pmem_busy | (dbg_halt_st & ~cpu_halt_cmd);
330 2 olivier.gi
 
331
 
332
//
333 111 olivier.gi
// 5.2) INSTRUCTION REGISTER
334 2 olivier.gi
//--------------------------------
335
 
336
// Instruction register
337
wire [15:0] ir  = mdb_in;
338
 
339
// Detect if source extension word is required
340
wire is_sext = (inst_as[`IDX] | inst_as[`SYMB] | inst_as[`ABS] | inst_as[`IMM]);
341
 
342
// Detect if destination extension word is required
343
wire is_dext = (inst_ad[`IDX] | inst_ad[`SYMB] | inst_ad[`ABS]);
344
 
345
// For the Symbolic addressing mode, add -2 to the extension word in order
346
// to make up for the PC address
347
wire [15:0] ext_incr = ((i_state==I_EXT1)     &  inst_as[`SYMB]) |
348
                       ((i_state==I_EXT2)     &  inst_ad[`SYMB]) |
349
                       ((i_state==I_EXT1)     & ~inst_as[`SYMB] &
350
                       ~(i_state_nxt==I_EXT2) &  inst_ad[`SYMB])   ? 16'hfffe : 16'h0000;
351
 
352
wire [15:0] ext_nxt  = ir + ext_incr;
353
 
354
// Store source extension word
355
reg [15:0] inst_sext;
356 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
357
  if (puc_rst)                                 inst_sext <= 16'h0000;
358 2 olivier.gi
  else if (decode & is_const)                  inst_sext <= sconst_nxt;
359
  else if (decode & inst_type_nxt[`INST_JMP])  inst_sext <= {{5{ir[9]}},ir[9:0],1'b0};
360
  else if ((i_state==I_EXT1) & is_sext)        inst_sext <= ext_nxt;
361
 
362
// Source extension word is ready
363
wire inst_sext_rdy = (i_state==I_EXT1) & is_sext;
364
 
365
 
366
// Store destination extension word
367
reg [15:0] inst_dext;
368 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
369
  if (puc_rst)                           inst_dext <= 16'h0000;
370 2 olivier.gi
  else if ((i_state==I_EXT1) & ~is_sext) inst_dext <= ext_nxt;
371
  else if  (i_state==I_EXT2)             inst_dext <= ext_nxt;
372
 
373
// Destination extension word is ready
374
wire inst_dext_rdy = (((i_state==I_EXT1) & ~is_sext) | (i_state==I_EXT2));
375
 
376
 
377
//=============================================================================
378 111 olivier.gi
// 6)  DECODE INSTRUCTION
379 2 olivier.gi
//=============================================================================
380
 
381
//
382 111 olivier.gi
// 6.1) OPCODE: INSTRUCTION TYPE
383 2 olivier.gi
//----------------------------------------
384
// Instructions type is encoded in a one hot fashion as following:
385
//
386
// 3'b001: Single-operand arithmetic
387
// 3'b010: Conditional jump
388
// 3'b100: Two-operand arithmetic
389
 
390
reg  [2:0] inst_type;
391
assign     inst_type_nxt = {(ir[15:14]!=2'b00),
392
                            (ir[15:13]==3'b001),
393
                            (ir[15:13]==3'b000)} & {3{~irq_detect}};
394
 
395 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
396
  if (puc_rst)      inst_type <= 3'b000;
397
  else if (decode)  inst_type <= inst_type_nxt;
398 2 olivier.gi
 
399
//
400 111 olivier.gi
// 6.2) OPCODE: SINGLE-OPERAND ARITHMETIC
401 2 olivier.gi
//----------------------------------------
402
// Instructions are encoded in a one hot fashion as following:
403
//
404
// 8'b00000001: RRC
405
// 8'b00000010: SWPB
406
// 8'b00000100: RRA
407
// 8'b00001000: SXT
408
// 8'b00010000: PUSH
409
// 8'b00100000: CALL
410
// 8'b01000000: RETI
411
// 8'b10000000: IRQ
412
 
413
reg   [7:0] inst_so;
414 85 olivier.gi
wire  [7:0] inst_so_nxt = irq_detect ? 8'h80 : (one_hot8(ir[9:7]) & {8{inst_type_nxt[`INST_SO]}});
415 2 olivier.gi
 
416 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
417
  if (puc_rst)     inst_so <= 8'h00;
418 2 olivier.gi
  else if (decode) inst_so <= inst_so_nxt;
419
 
420
//
421 111 olivier.gi
// 6.3) OPCODE: CONDITIONAL JUMP
422 2 olivier.gi
//--------------------------------
423
// Instructions are encoded in a one hot fashion as following:
424
//
425
// 8'b00000001: JNE/JNZ
426
// 8'b00000010: JEQ/JZ
427
// 8'b00000100: JNC/JLO
428
// 8'b00001000: JC/JHS
429
// 8'b00010000: JN
430
// 8'b00100000: JGE
431
// 8'b01000000: JL
432
// 8'b10000000: JMP
433
 
434
reg   [2:0] inst_jmp_bin;
435 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
436
  if (puc_rst)     inst_jmp_bin <= 3'h0;
437 2 olivier.gi
  else if (decode) inst_jmp_bin <= ir[12:10];
438
 
439 85 olivier.gi
wire [7:0] inst_jmp = one_hot8(inst_jmp_bin) & {8{inst_type[`INST_JMP]}};
440 2 olivier.gi
 
441
 
442
//
443 111 olivier.gi
// 6.4) OPCODE: TWO-OPERAND ARITHMETIC
444 2 olivier.gi
//-------------------------------------
445
// Instructions are encoded in a one hot fashion as following:
446
//
447
// 12'b000000000001: MOV
448
// 12'b000000000010: ADD
449
// 12'b000000000100: ADDC
450
// 12'b000000001000: SUBC
451
// 12'b000000010000: SUB
452
// 12'b000000100000: CMP
453
// 12'b000001000000: DADD
454
// 12'b000010000000: BIT
455
// 12'b000100000000: BIC
456
// 12'b001000000000: BIS
457
// 12'b010000000000: XOR
458
// 12'b100000000000: AND
459
 
460 85 olivier.gi
wire [15:0] inst_to_1hot = one_hot16(ir[15:12]) & {16{inst_type_nxt[`INST_TO]}};
461 2 olivier.gi
wire [11:0] inst_to_nxt  = inst_to_1hot[15:4];
462
 
463 105 olivier.gi
reg         inst_mov;
464 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
465
  if (puc_rst)     inst_mov <= 1'b0;
466 105 olivier.gi
  else if (decode) inst_mov <= inst_to_nxt[`MOV];
467 2 olivier.gi
 
468 105 olivier.gi
 
469 2 olivier.gi
//
470 111 olivier.gi
// 6.5) SOURCE AND DESTINATION REGISTERS
471 2 olivier.gi
//---------------------------------------
472
 
473
// Destination register
474
reg [3:0] inst_dest_bin;
475 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
476
  if (puc_rst)     inst_dest_bin <= 4'h0;
477 2 olivier.gi
  else if (decode) inst_dest_bin <= ir[3:0];
478
 
479 85 olivier.gi
wire  [15:0] inst_dest = dbg_halt_st          ? one_hot16(dbg_reg_sel) :
480
                         inst_type[`INST_JMP] ? 16'h0001               :
481 2 olivier.gi
                         inst_so[`IRQ]  |
482
                         inst_so[`PUSH] |
483 85 olivier.gi
                         inst_so[`CALL]       ? 16'h0002               :
484
                                                one_hot16(inst_dest_bin);
485 2 olivier.gi
 
486
 
487
// Source register
488
reg [3:0] inst_src_bin;
489 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
490
  if (puc_rst)     inst_src_bin <= 4'h0;
491 2 olivier.gi
  else if (decode) inst_src_bin <= ir[11:8];
492
 
493 85 olivier.gi
wire  [15:0] inst_src = inst_type[`INST_TO] ? one_hot16(inst_src_bin)  :
494
                        inst_so[`RETI]      ? 16'h0002                 :
495
                        inst_so[`IRQ]       ? 16'h0001                 :
496
                        inst_type[`INST_SO] ? one_hot16(inst_dest_bin) : 16'h0000;
497 2 olivier.gi
 
498
 
499
//
500 111 olivier.gi
// 6.6) SOURCE ADDRESSING MODES
501 2 olivier.gi
//--------------------------------
502
// Source addressing modes are encoded in a one hot fashion as following:
503
//
504
// 13'b0000000000001: Register direct.
505
// 13'b0000000000010: Register indexed.
506
// 13'b0000000000100: Register indirect.
507
// 13'b0000000001000: Register indirect autoincrement.
508
// 13'b0000000010000: Symbolic (operand is in memory at address PC+x).
509
// 13'b0000000100000: Immediate (operand is next word in the instruction stream).
510
// 13'b0000001000000: Absolute (operand is in memory at address x).
511
// 13'b0000010000000: Constant 4.
512
// 13'b0000100000000: Constant 8.
513
// 13'b0001000000000: Constant 0.
514
// 13'b0010000000000: Constant 1.
515
// 13'b0100000000000: Constant 2.
516
// 13'b1000000000000: Constant -1.
517
 
518
reg [12:0] inst_as_nxt;
519
 
520
wire [3:0] src_reg = inst_type_nxt[`INST_SO] ? ir[3:0] : ir[11:8];
521
 
522
always @(src_reg or ir or inst_type_nxt)
523
  begin
524
     if (inst_type_nxt[`INST_JMP])
525
       inst_as_nxt =  13'b0000000000001;
526
     else if (src_reg==4'h3) // Addressing mode using R3
527
       case (ir[5:4])
528
         2'b11  : inst_as_nxt =  13'b1000000000000;
529
         2'b10  : inst_as_nxt =  13'b0100000000000;
530
         2'b01  : inst_as_nxt =  13'b0010000000000;
531
         default: inst_as_nxt =  13'b0001000000000;
532
       endcase
533
     else if (src_reg==4'h2) // Addressing mode using R2
534
       case (ir[5:4])
535
         2'b11  : inst_as_nxt =  13'b0000100000000;
536
         2'b10  : inst_as_nxt =  13'b0000010000000;
537
         2'b01  : inst_as_nxt =  13'b0000001000000;
538
         default: inst_as_nxt =  13'b0000000000001;
539
       endcase
540
     else if (src_reg==4'h0) // Addressing mode using R0
541
       case (ir[5:4])
542
         2'b11  : inst_as_nxt =  13'b0000000100000;
543
         2'b10  : inst_as_nxt =  13'b0000000000100;
544
         2'b01  : inst_as_nxt =  13'b0000000010000;
545
         default: inst_as_nxt =  13'b0000000000001;
546
       endcase
547
     else                    // General Addressing mode
548
       case (ir[5:4])
549
         2'b11  : inst_as_nxt =  13'b0000000001000;
550
         2'b10  : inst_as_nxt =  13'b0000000000100;
551
         2'b01  : inst_as_nxt =  13'b0000000000010;
552
         default: inst_as_nxt =  13'b0000000000001;
553
       endcase
554
  end
555
assign    is_const = |inst_as_nxt[12:7];
556
 
557
reg [7:0] inst_as;
558 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
559
  if (puc_rst)     inst_as <= 8'h00;
560 2 olivier.gi
  else if (decode) inst_as <= {is_const, inst_as_nxt[6:0]};
561
 
562
 
563
// 13'b0000010000000: Constant 4.
564
// 13'b0000100000000: Constant 8.
565
// 13'b0001000000000: Constant 0.
566
// 13'b0010000000000: Constant 1.
567
// 13'b0100000000000: Constant 2.
568
// 13'b1000000000000: Constant -1.
569
always @(inst_as_nxt)
570
  begin
571
     if (inst_as_nxt[7])        sconst_nxt = 16'h0004;
572
     else if (inst_as_nxt[8])   sconst_nxt = 16'h0008;
573
     else if (inst_as_nxt[9])   sconst_nxt = 16'h0000;
574
     else if (inst_as_nxt[10])  sconst_nxt = 16'h0001;
575
     else if (inst_as_nxt[11])  sconst_nxt = 16'h0002;
576
     else if (inst_as_nxt[12])  sconst_nxt = 16'hffff;
577
     else                       sconst_nxt = 16'h0000;
578
  end
579
 
580
 
581
//
582 111 olivier.gi
// 6.7) DESTINATION ADDRESSING MODES
583 2 olivier.gi
//-----------------------------------
584
// Destination addressing modes are encoded in a one hot fashion as following:
585
//
586
// 8'b00000001: Register direct.
587
// 8'b00000010: Register indexed.
588
// 8'b00010000: Symbolic (operand is in memory at address PC+x).
589
// 8'b01000000: Absolute (operand is in memory at address x).
590
 
591
reg  [7:0] inst_ad_nxt;
592
 
593
wire [3:0] dest_reg = ir[3:0];
594
 
595
always @(dest_reg or ir or inst_type_nxt)
596
  begin
597
     if (~inst_type_nxt[`INST_TO])
598
       inst_ad_nxt =  8'b00000000;
599
     else if (dest_reg==4'h2)   // Addressing mode using R2
600
       case (ir[7])
601
         1'b1   : inst_ad_nxt =  8'b01000000;
602
         default: inst_ad_nxt =  8'b00000001;
603
       endcase
604
     else if (dest_reg==4'h0)   // Addressing mode using R0
605
       case (ir[7])
606 106 olivier.gi
         1'b1   : inst_ad_nxt =  8'b00010000;
607 2 olivier.gi
         default: inst_ad_nxt =  8'b00000001;
608
       endcase
609
     else                       // General Addressing mode
610
       case (ir[7])
611 106 olivier.gi
         1'b1   : inst_ad_nxt =  8'b00000010;
612 2 olivier.gi
         default: inst_ad_nxt =  8'b00000001;
613
       endcase
614
  end
615
 
616
reg [7:0] inst_ad;
617 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
618
  if (puc_rst)     inst_ad <= 8'h00;
619 2 olivier.gi
  else if (decode) inst_ad <= inst_ad_nxt;
620
 
621
 
622
//
623 111 olivier.gi
// 6.8) REMAINING INSTRUCTION DECODING
624 2 olivier.gi
//-------------------------------------
625
 
626
// Operation size
627
reg       inst_bw;
628 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
629
  if (puc_rst)     inst_bw     <= 1'b0;
630 106 olivier.gi
  else if (decode) inst_bw     <= ir[6] & ~inst_type_nxt[`INST_JMP] & ~irq_detect & ~cpu_halt_cmd;
631 2 olivier.gi
 
632
// Extended instruction size
633
assign    inst_sz_nxt = {1'b0,  (inst_as_nxt[`IDX] | inst_as_nxt[`SYMB] | inst_as_nxt[`ABS] | inst_as_nxt[`IMM])} +
634
                        {1'b0, ((inst_ad_nxt[`IDX] | inst_ad_nxt[`SYMB] | inst_ad_nxt[`ABS]) & ~inst_type_nxt[`INST_SO])};
635 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
636
  if (puc_rst)     inst_sz     <= 2'b00;
637 2 olivier.gi
  else if (decode) inst_sz     <= inst_sz_nxt;
638
 
639
 
640
//=============================================================================
641 111 olivier.gi
// 7)  EXECUTION-UNIT STATE MACHINE
642 2 olivier.gi
//=============================================================================
643
 
644
// State machine registers
645
reg  [3:0] e_state;
646
 
647
 
648
// State machine control signals
649
//--------------------------------
650
 
651
wire src_acalc_pre =  inst_as_nxt[`IDX]   | inst_as_nxt[`SYMB]    | inst_as_nxt[`ABS];
652
wire src_rd_pre    =  inst_as_nxt[`INDIR] | inst_as_nxt[`INDIR_I] | inst_as_nxt[`IMM]  | inst_so_nxt[`RETI];
653
wire dst_acalc_pre =  inst_ad_nxt[`IDX]   | inst_ad_nxt[`SYMB]    | inst_ad_nxt[`ABS];
654
wire dst_acalc     =  inst_ad[`IDX]       | inst_ad[`SYMB]        | inst_ad[`ABS];
655
wire dst_rd_pre    =  inst_ad_nxt[`IDX]   | inst_so_nxt[`PUSH]    | inst_so_nxt[`CALL] | inst_so_nxt[`RETI];
656
wire dst_rd        =  inst_ad[`IDX]       | inst_so[`PUSH]        | inst_so[`CALL]     | inst_so[`RETI];
657
 
658
wire inst_branch   =  (inst_ad_nxt[`DIR] & (ir[3:0]==4'h0)) | inst_type_nxt[`INST_JMP] | inst_so_nxt[`RETI];
659
 
660
reg exec_jmp;
661 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
662
  if (puc_rst)                   exec_jmp <= 1'b0;
663 2 olivier.gi
  else if (inst_branch & decode) exec_jmp <= 1'b1;
664 111 olivier.gi
  else if (e_state==E_JUMP)      exec_jmp <= 1'b0;
665 2 olivier.gi
 
666
reg exec_dst_wr;
667 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
668
  if (puc_rst)                exec_dst_wr <= 1'b0;
669
  else if (e_state==E_DST_RD) exec_dst_wr <= 1'b1;
670
  else if (e_state==E_DST_WR) exec_dst_wr <= 1'b0;
671 2 olivier.gi
 
672
reg exec_src_wr;
673 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
674
  if (puc_rst)                                         exec_src_wr <= 1'b0;
675
  else if (inst_type[`INST_SO] & (e_state==E_SRC_RD))  exec_src_wr <= 1'b1;
676
  else if ((e_state==E_SRC_WR) || (e_state==E_DST_WR)) exec_src_wr <= 1'b0;
677 2 olivier.gi
 
678
reg exec_dext_rdy;
679 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
680
  if (puc_rst)                exec_dext_rdy <= 1'b0;
681
  else if (e_state==E_DST_RD) exec_dext_rdy <= 1'b0;
682
  else if (inst_dext_rdy)     exec_dext_rdy <= 1'b1;
683 2 olivier.gi
 
684
// Execution first state
685 111 olivier.gi
wire [3:0] e_first_state = ~dbg_halt_st  & inst_so_nxt[`IRQ] ? E_IRQ_0  :
686
                            cpu_halt_cmd | (i_state==I_IDLE) ? E_IDLE   :
687
                            cpuoff                           ? E_IDLE   :
688
                            src_acalc_pre                    ? E_SRC_AD :
689
                            src_rd_pre                       ? E_SRC_RD :
690
                            dst_acalc_pre                    ? E_DST_AD :
691
                            dst_rd_pre                       ? E_DST_RD : E_EXEC;
692 2 olivier.gi
 
693
 
694
// State machine
695
//--------------------------------
696
 
697
// States Transitions
698
always @(e_state       or dst_acalc     or dst_rd   or inst_sext_rdy or
699
         inst_dext_rdy or exec_dext_rdy or exec_jmp or exec_dst_wr   or
700
         e_first_state or exec_src_wr)
701
    case(e_state)
702 111 olivier.gi
      E_IDLE   : e_state_nxt =  e_first_state;
703
      E_IRQ_0  : e_state_nxt =  E_IRQ_1;
704
      E_IRQ_1  : e_state_nxt =  E_IRQ_2;
705
      E_IRQ_2  : e_state_nxt =  E_IRQ_3;
706
      E_IRQ_3  : e_state_nxt =  E_IRQ_4;
707
      E_IRQ_4  : e_state_nxt =  E_EXEC;
708 2 olivier.gi
 
709 111 olivier.gi
      E_SRC_AD : e_state_nxt =  inst_sext_rdy     ? E_SRC_RD : E_SRC_AD;
710 2 olivier.gi
 
711 111 olivier.gi
      E_SRC_RD : e_state_nxt =  dst_acalc         ? E_DST_AD :
712
                                 dst_rd           ? E_DST_RD : E_EXEC;
713 2 olivier.gi
 
714 111 olivier.gi
      E_DST_AD : e_state_nxt =  (inst_dext_rdy |
715
                                 exec_dext_rdy)   ? E_DST_RD : E_DST_AD;
716 2 olivier.gi
 
717 111 olivier.gi
      E_DST_RD : e_state_nxt =  E_EXEC;
718 2 olivier.gi
 
719 111 olivier.gi
      E_EXEC   : e_state_nxt =  exec_dst_wr       ? E_DST_WR :
720
                                exec_jmp          ? E_JUMP   :
721
                                exec_src_wr       ? E_SRC_WR : e_first_state;
722 2 olivier.gi
 
723 111 olivier.gi
      E_JUMP   : e_state_nxt =  e_first_state;
724
      E_DST_WR : e_state_nxt =  exec_jmp          ? E_JUMP   : e_first_state;
725
      E_SRC_WR : e_state_nxt =  e_first_state;
726
      default  : e_state_nxt =  E_IRQ_0;
727 2 olivier.gi
    endcase
728
 
729
// State machine
730 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
731
  if (puc_rst) e_state  <= E_IRQ_1;
732 2 olivier.gi
  else         e_state  <= e_state_nxt;
733
 
734
 
735
// Frontend State machine control signals
736
//----------------------------------------
737
 
738 111 olivier.gi
wire exec_done = exec_jmp        ? (e_state==E_JUMP)   :
739
                 exec_dst_wr     ? (e_state==E_DST_WR) :
740
                 exec_src_wr     ? (e_state==E_SRC_WR) : (e_state==E_EXEC);
741 2 olivier.gi
 
742
 
743
//=============================================================================
744 111 olivier.gi
// 8)  EXECUTION-UNIT STATE CONTROL
745 2 olivier.gi
//=============================================================================
746
 
747
//
748 111 olivier.gi
// 8.1) ALU CONTROL SIGNALS
749 2 olivier.gi
//-------------------------------------
750
//
751
// 12'b000000000001: Enable ALU source inverter
752
// 12'b000000000010: Enable Incrementer
753
// 12'b000000000100: Enable Incrementer on carry bit
754
// 12'b000000001000: Select Adder
755
// 12'b000000010000: Select AND
756
// 12'b000000100000: Select OR
757
// 12'b000001000000: Select XOR
758
// 12'b000010000000: Select DADD
759
// 12'b000100000000: Update N, Z & C (C=~Z)
760
// 12'b001000000000: Update all status bits
761
// 12'b010000000000: Update status bit for XOR instruction
762
// 12'b100000000000: Don't write to destination
763
 
764
reg  [11:0] inst_alu;
765
 
766
wire        alu_src_inv   = inst_to_nxt[`SUB]  | inst_to_nxt[`SUBC] |
767
                            inst_to_nxt[`CMP]  | inst_to_nxt[`BIC] ;
768
 
769
wire        alu_inc       = inst_to_nxt[`SUB]  | inst_to_nxt[`CMP];
770
 
771
wire        alu_inc_c     = inst_to_nxt[`ADDC] | inst_to_nxt[`DADD] |
772
                            inst_to_nxt[`SUBC];
773
 
774
wire        alu_add       = inst_to_nxt[`ADD]  | inst_to_nxt[`ADDC]       |
775
                            inst_to_nxt[`SUB]  | inst_to_nxt[`SUBC]       |
776
                            inst_to_nxt[`CMP]  | inst_type_nxt[`INST_JMP] |
777
                            inst_so_nxt[`RETI];
778
 
779
 
780
wire        alu_and       = inst_to_nxt[`AND]  | inst_to_nxt[`BIC]  |
781
                            inst_to_nxt[`BIT];
782
 
783
wire        alu_or        = inst_to_nxt[`BIS];
784
 
785
wire        alu_xor       = inst_to_nxt[`XOR];
786
 
787
wire        alu_dadd      = inst_to_nxt[`DADD];
788
 
789
wire        alu_stat_7    = inst_to_nxt[`BIT]  | inst_to_nxt[`AND]  |
790
                            inst_so_nxt[`SXT];
791
 
792
wire        alu_stat_f    = inst_to_nxt[`ADD]  | inst_to_nxt[`ADDC] |
793
                            inst_to_nxt[`SUB]  | inst_to_nxt[`SUBC] |
794
                            inst_to_nxt[`CMP]  | inst_to_nxt[`DADD] |
795
                            inst_to_nxt[`BIT]  | inst_to_nxt[`XOR]  |
796
                            inst_to_nxt[`AND]  |
797
                            inst_so_nxt[`RRC]  | inst_so_nxt[`RRA]  |
798
                            inst_so_nxt[`SXT];
799
 
800
wire        alu_shift     = inst_so_nxt[`RRC]  | inst_so_nxt[`RRA];
801
 
802
wire        exec_no_wr    = inst_to_nxt[`CMP] | inst_to_nxt[`BIT];
803
 
804 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
805
  if (puc_rst)     inst_alu <= 12'h000;
806 2 olivier.gi
  else if (decode) inst_alu <= {exec_no_wr,
807
                                alu_shift,
808
                                alu_stat_f,
809
                                alu_stat_7,
810
                                alu_dadd,
811
                                alu_xor,
812
                                alu_or,
813
                                alu_and,
814
                                alu_add,
815
                                alu_inc_c,
816
                                alu_inc,
817
                                alu_src_inv};
818
 
819
 
820 34 olivier.gi
endmodule // omsp_frontend
821 33 olivier.gi
 
822 103 olivier.gi
`ifdef OMSP_NO_INCLUDE
823
`else
824 33 olivier.gi
`include "openMSP430_undefines.v"
825 103 olivier.gi
`endif

powered by: WebSVN 2.1.0

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