]> rtime.felk.cvut.cz Git - fpga/openmsp430.git/blob - core/omsp_execution_unit.v
OpenMSP430 core verilog source files moved to "core" subdirectory.
[fpga/openmsp430.git] / core / omsp_execution_unit.v
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2001 Authors
3 //
4 // This source file may be used and distributed without restriction provided
5 // that this copyright statement is not removed from the file and that any
6 // derivative work contains the original copyright notice and the associated
7 // disclaimer.
8 //
9 // This source file is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU Lesser General Public License as published
11 // by the Free Software Foundation; either version 2.1 of the License, or
12 // (at your option) any later version.
13 //
14 // This source is distributed in the hope that it will be useful, but WITHOUT
15 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 // License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public License
20 // along with this source; if not, write to the Free Software Foundation,
21 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 //
23 //----------------------------------------------------------------------------
24 //
25 // *File Name: omsp_execution_unit.v
26 // 
27 // *Module Description:
28 //                       openMSP430 Execution unit
29 //
30 // *Author(s):
31 //              - Olivier Girard,    olgirard@gmail.com
32 //
33 //----------------------------------------------------------------------------
34 // $Rev: 34 $
35 // $LastChangedBy: olivier.girard $
36 // $LastChangedDate: 2009-12-29 20:10:34 +0100 (Tue, 29 Dec 2009) $
37 //----------------------------------------------------------------------------
38 `include "timescale.v"
39 `include "openMSP430_defines.v"
40
41 module  omsp_execution_unit (
42
43 // OUTPUTs
44     cpuoff,                        // Turns off the CPU
45     dbg_reg_din,                   // Debug unit CPU register data input
46     gie,                           // General interrupt enable
47     mab,                           // Memory address bus
48     mb_en,                         // Memory bus enable
49     mb_wr,                         // Memory bus write transfer
50     mdb_out,                       // Memory data bus output
51     oscoff,                        // Turns off LFXT1 clock input
52     pc_sw,                         // Program counter software value
53     pc_sw_wr,                      // Program counter software write
54     scg1,                          // System clock generator 1. Turns off the SMCLK
55
56 // INPUTs
57     dbg_halt_st,                   // Halt/Run status from CPU
58     dbg_mem_dout,                  // Debug unit data output
59     dbg_reg_wr,                    // Debug unit CPU register write
60     e_state,                       // Execution state
61     exec_done,                     // Execution completed
62     inst_ad,                       // Decoded Inst: destination addressing mode
63     inst_as,                       // Decoded Inst: source addressing mode
64     inst_alu,                      // ALU control signals
65     inst_bw,                       // Decoded Inst: byte width
66     inst_dest,                     // Decoded Inst: destination (one hot)
67     inst_dext,                     // Decoded Inst: destination extended instruction word
68     inst_irq_rst,                  // Decoded Inst: reset interrupt
69     inst_jmp,                      // Decoded Inst: Conditional jump
70     inst_sext,                     // Decoded Inst: source extended instruction word
71     inst_so,                       // Decoded Inst: Single-operand arithmetic
72     inst_src,                      // Decoded Inst: source (one hot)
73     inst_type,                     // Decoded Instruction type
74     mclk,                          // Main system clock
75     mdb_in,                        // Memory data bus input
76     pc,                            // Program counter
77     pc_nxt,                        // Next PC value (for CALL & IRQ)
78     puc                            // Main system reset
79 );
80
81 // OUTPUTs
82 //=========
83 output              cpuoff;        // Turns off the CPU
84 output       [15:0] dbg_reg_din;   // Debug unit CPU register data input
85 output              gie;           // General interrupt enable
86 output       [15:0] mab;           // Memory address bus
87 output              mb_en;         // Memory bus enable
88 output        [1:0] mb_wr;         // Memory bus write transfer
89 output       [15:0] mdb_out;       // Memory data bus output
90 output              oscoff;        // Turns off LFXT1 clock input
91 output       [15:0] pc_sw;         // Program counter software value
92 output              pc_sw_wr;      // Program counter software write
93 output              scg1;          // System clock generator 1. Turns off the SMCLK
94
95 // INPUTs
96 //=========
97 input               dbg_halt_st;   // Halt/Run status from CPU
98 input        [15:0] dbg_mem_dout;  // Debug unit data output
99 input               dbg_reg_wr;    // Debug unit CPU register write
100 input         [3:0] e_state;       // Execution state
101 input               exec_done;     // Execution completed
102 input         [7:0] inst_ad;       // Decoded Inst: destination addressing mode
103 input         [7:0] inst_as;       // Decoded Inst: source addressing mode
104 input        [11:0] inst_alu;      // ALU control signals
105 input               inst_bw;       // Decoded Inst: byte width
106 input        [15:0] inst_dest;     // Decoded Inst: destination (one hot)
107 input        [15:0] inst_dext;     // Decoded Inst: destination extended instruction word
108 input               inst_irq_rst;  // Decoded Inst: reset interrupt
109 input         [7:0] inst_jmp;      // Decoded Inst: Conditional jump
110 input        [15:0] inst_sext;     // Decoded Inst: source extended instruction word
111 input         [7:0] inst_so;       // Decoded Inst: Single-operand arithmetic
112 input        [15:0] inst_src;      // Decoded Inst: source (one hot)
113 input         [2:0] inst_type;     // Decoded Instruction type
114 input               mclk;          // Main system clock
115 input        [15:0] mdb_in;        // Memory data bus input
116 input        [15:0] pc;            // Program counter
117 input        [15:0] pc_nxt;        // Next PC value (for CALL & IRQ)
118 input               puc;           // Main system reset
119
120
121 //=============================================================================
122 // 1)  INTERNAL WIRES/REGISTERS/PARAMETERS DECLARATION
123 //=============================================================================
124
125 wire         [15:0] alu_out;
126 wire         [15:0] alu_out_add;
127 wire          [3:0] alu_stat;
128 wire          [3:0] alu_stat_wr;
129 wire         [15:0] op_dst;
130 wire         [15:0] op_src;
131 wire         [15:0] reg_dest;
132 wire         [15:0] reg_src;
133 wire         [15:0] mdb_in_bw;
134 wire         [15:0] mdb_in_val;
135 wire          [3:0] status;
136
137
138 //=============================================================================
139 // 2)  REGISTER FILE
140 //=============================================================================
141
142 wire reg_dest_wr  = ((e_state==`E_EXEC) & (
143                      (inst_type[`INST_TO] & inst_ad[`DIR] & ~inst_alu[`EXEC_NO_WR])  |
144                      (inst_type[`INST_SO] & inst_as[`DIR] & ~(inst_so[`PUSH] | inst_so[`CALL] | inst_so[`RETI])) |
145                       inst_type[`INST_JMP])) | dbg_reg_wr;
146
147 wire reg_sp_wr    = (((e_state==`E_IRQ_1) | (e_state==`E_IRQ_3)) & ~inst_irq_rst) |
148                      ((e_state==`E_DST_RD) & (inst_so[`PUSH] | inst_so[`CALL]));
149
150 wire reg_sr_wr    =  (e_state==`E_DST_RD) & inst_so[`RETI];
151
152 wire reg_sr_clr   =  (e_state==`E_IRQ_2);
153
154 wire reg_pc_call  = ((e_state==`E_EXEC)   & inst_so[`CALL]) | 
155                     ((e_state==`E_DST_WR) & inst_so[`RETI]);
156
157 wire reg_incr     =  (exec_done          & inst_as[`INDIR_I]) |
158                     ((e_state==`E_SRC_RD) & inst_so[`RETI])    |
159                     ((e_state==`E_EXEC)   & inst_so[`RETI]);
160
161 assign dbg_reg_din = reg_dest;
162
163
164 omsp_register_file register_file_0 (
165
166 // OUTPUTs
167     .cpuoff       (cpuoff),       // Turns off the CPU
168     .gie          (gie),          // General interrupt enable
169     .oscoff       (oscoff),       // Turns off LFXT1 clock input
170     .pc_sw        (pc_sw),        // Program counter software value
171     .pc_sw_wr     (pc_sw_wr),     // Program counter software write
172     .reg_dest     (reg_dest),     // Selected register destination content
173     .reg_src      (reg_src),      // Selected register source content
174     .scg1         (scg1),         // System clock generator 1. Turns off the SMCLK
175     .status       (status),       // R2 Status {V,N,Z,C}
176
177 // INPUTs
178     .alu_stat     (alu_stat),     // ALU Status {V,N,Z,C}
179     .alu_stat_wr  (alu_stat_wr),  // ALU Status write {V,N,Z,C}
180     .inst_bw      (inst_bw),      // Decoded Inst: byte width
181     .inst_dest    (inst_dest),    // Register destination selection
182     .inst_src     (inst_src),     // Register source selection
183     .mclk         (mclk),         // Main system clock
184     .pc           (pc),           // Program counter
185     .puc          (puc),          // Main system reset
186     .reg_dest_val (alu_out),      // Selected register destination value
187     .reg_dest_wr  (reg_dest_wr),  // Write selected register destination
188     .reg_pc_call  (reg_pc_call),  // Trigger PC update for a CALL instruction
189     .reg_sp_val   (alu_out_add),  // Stack Pointer next value
190     .reg_sp_wr    (reg_sp_wr),    // Stack Pointer write
191     .reg_sr_clr   (reg_sr_clr),   // Status register clear for interrupts
192     .reg_sr_wr    (reg_sr_wr),    // Status Register update for RETI instruction
193     .reg_incr     (reg_incr)      // Increment source register
194 );
195
196
197 //=============================================================================
198 // 3)  SOURCE OPERAND MUXING
199 //=============================================================================
200 // inst_as[`DIR]    : Register direct.   -> Source is in register
201 // inst_as[`IDX]    : Register indexed.  -> Source is in memory, address is register+offset
202 // inst_as[`INDIR]  : Register indirect.
203 // inst_as[`INDIR_I]: Register indirect autoincrement.
204 // inst_as[`SYMB]   : Symbolic (operand is in memory at address PC+x).
205 // inst_as[`IMM]    : Immediate (operand is next word in the instruction stream).
206 // inst_as[`ABS]    : Absolute (operand is in memory at address x).
207 // inst_as[`CONST]  : Constant.
208
209 wire src_reg_src_sel    =  (e_state==`E_IRQ_0)                    |
210                            (e_state==`E_IRQ_2)                    |
211                           ((e_state==`E_SRC_RD) & ~inst_as[`ABS]) |
212                           ((e_state==`E_SRC_WR) & ~inst_as[`ABS]) |
213                           ((e_state==`E_EXEC)   &  inst_as[`DIR] & ~inst_type[`INST_JMP]);
214
215 wire src_reg_dest_sel   =  (e_state==`E_IRQ_1)                    |
216                            (e_state==`E_IRQ_3)                    |
217                           ((e_state==`E_DST_RD) & (inst_so[`PUSH] | inst_so[`CALL]));
218
219 wire src_mdb_in_val_sel = ((e_state==`E_DST_RD) &  inst_so[`RETI])                     |
220                           ((e_state==`E_EXEC)   & (inst_as[`INDIR] | inst_as[`INDIR_I] |
221                                                    inst_as[`IDX]   | inst_as[`SYMB]    |
222                                                    inst_as[`ABS]));
223
224 wire src_inst_dext_sel =  ((e_state==`E_DST_RD) & ~(inst_so[`PUSH] | inst_so[`CALL])) |
225                           ((e_state==`E_DST_WR) & ~(inst_so[`PUSH] | inst_so[`CALL]   |
226                                                     inst_so[`RETI]));
227
228 wire src_inst_sext_sel =  ((e_state==`E_EXEC)   &  (inst_type[`INST_JMP] | inst_as[`IMM] |
229                                                     inst_as[`CONST]      | inst_so[`RETI]));
230
231
232 assign op_src = src_reg_src_sel     ?  reg_src    :
233                 src_reg_dest_sel    ?  reg_dest   :
234                 src_mdb_in_val_sel  ?  mdb_in_val :
235                 src_inst_dext_sel   ?  inst_dext  :
236                 src_inst_sext_sel   ?  inst_sext  : 16'h0000;
237
238
239 //=============================================================================
240 // 4)  DESTINATION OPERAND MUXING
241 //=============================================================================
242 // inst_ad[`DIR]    : Register direct.
243 // inst_ad[`IDX]    : Register indexed.
244 // inst_ad[`SYMB]   : Symbolic (operand is in memory at address PC+x).
245 // inst_ad[`ABS]    : Absolute (operand is in memory at address x).
246
247
248 wire dst_inst_sext_sel  = ((e_state==`E_SRC_RD) & (inst_as[`IDX] | inst_as[`SYMB] |
249                                                    inst_as[`ABS]))                |
250                           ((e_state==`E_SRC_WR) & (inst_as[`IDX] | inst_as[`SYMB] |
251                                                    inst_as[`ABS]));
252
253 wire dst_mdb_in_bw_sel  = ((e_state==`E_DST_WR) &   inst_so[`RETI]) |
254                           ((e_state==`E_EXEC)   & ~(inst_ad[`DIR] | inst_type[`INST_JMP] |
255                                                     inst_type[`INST_SO]) & ~inst_so[`RETI]);
256
257 wire dst_fffe_sel       =  (e_state==`E_IRQ_0)  |
258                            (e_state==`E_IRQ_1)  |
259                            (e_state==`E_IRQ_3)  |
260                           ((e_state==`E_DST_RD) & (inst_so[`PUSH] | inst_so[`CALL]) & ~inst_so[`RETI]);
261
262 wire dst_reg_dest_sel   = ((e_state==`E_DST_RD) & ~(inst_so[`PUSH] | inst_so[`CALL] | inst_ad[`ABS] | inst_so[`RETI])) |
263                           ((e_state==`E_DST_WR) &  ~inst_ad[`ABS]) |
264                           ((e_state==`E_EXEC)   &  (inst_ad[`DIR] | inst_type[`INST_JMP] |
265                                                     inst_type[`INST_SO]) & ~inst_so[`RETI]);
266
267
268 assign op_dst = dbg_halt_st        ? dbg_mem_dout  :
269                 dst_inst_sext_sel  ? inst_sext     :
270                 dst_mdb_in_bw_sel  ? mdb_in_bw     :
271                 dst_reg_dest_sel   ? reg_dest      :
272                 dst_fffe_sel       ? 16'hfffe      : 16'h0000;
273
274
275 //=============================================================================
276 // 5)  ALU
277 //=============================================================================
278
279 wire exec_cycle = (e_state==`E_EXEC);
280
281 omsp_alu alu_0 (
282
283 // OUTPUTs
284     .alu_out      (alu_out),      // ALU output value
285     .alu_out_add  (alu_out_add),  // ALU adder output value
286     .alu_stat     (alu_stat),     // ALU Status {V,N,Z,C}
287     .alu_stat_wr  (alu_stat_wr),  // ALU Status write {V,N,Z,C}
288
289 // INPUTs
290     .dbg_halt_st  (dbg_halt_st),  // Halt/Run status from CPU
291     .exec_cycle   (exec_cycle),   // Instruction execution cycle
292     .inst_alu     (inst_alu),     // ALU control signals
293     .inst_bw      (inst_bw),      // Decoded Inst: byte width
294     .inst_jmp     (inst_jmp),     // Decoded Inst: Conditional jump
295     .inst_so      (inst_so),      // Single-operand arithmetic
296     .op_dst       (op_dst),       // Destination operand
297     .op_src       (op_src),       // Source operand
298     .status       (status)        // R2 Status {V,N,Z,C}
299 );
300
301
302 //=============================================================================
303 // 6)  MEMORY INTERFACE
304 //=============================================================================
305
306 // Detect memory read/write access
307 assign      mb_en     = ((e_state==`E_IRQ_1)  & ~inst_irq_rst)      |
308                         ((e_state==`E_IRQ_3)  & ~inst_irq_rst)      |
309                         ((e_state==`E_SRC_RD) & ~inst_as[`IMM])     |
310                          (e_state==`E_SRC_WR)                       |
311                         ((e_state==`E_EXEC)   & inst_so[`RETI])     |
312                          (e_state==`E_DST_RD)                       |
313                          (e_state==`E_DST_WR);
314
315 wire  [1:0] mb_wr_msk =  inst_alu[`EXEC_NO_WR]  ? 2'b00 :
316                         ~inst_bw                ? 2'b11 :
317                          alu_out_add[0]         ? 2'b10 : 2'b01;
318 assign      mb_wr     = ({2{(e_state==`E_IRQ_1)}}  |
319                          {2{(e_state==`E_IRQ_3)}}  |
320                          {2{(e_state==`E_DST_WR)}} |
321                          {2{(e_state==`E_SRC_WR)}}) & mb_wr_msk;
322
323 // Memory address bus
324 assign      mab       = alu_out_add[15:0];
325
326 // Memory data bus output
327 reg  [15:0] mdb_out_nxt;
328 always @(posedge mclk or posedge puc)
329   if (puc)                                            mdb_out_nxt <= 16'h0000;
330   else if (e_state==`E_DST_RD)                        mdb_out_nxt <= pc_nxt;
331   else if ((e_state==`E_EXEC & ~inst_so[`CALL]) |
332            (e_state==`E_IRQ_0) | (e_state==`E_IRQ_2)) mdb_out_nxt <= alu_out;
333
334 assign      mdb_out = inst_bw ? {2{mdb_out_nxt[7:0]}} : mdb_out_nxt;
335
336 // Format memory data bus input depending on BW
337 reg        mab_lsb;
338 always @(posedge mclk or posedge puc)
339   if (puc)        mab_lsb <= 1'b0;
340   else if (mb_en) mab_lsb <= alu_out_add[0];
341
342 assign mdb_in_bw  = ~inst_bw ? mdb_in :
343                      mab_lsb ? {2{mdb_in[15:8]}} : mdb_in;
344
345 // Memory data bus input buffer (buffer after a source read)
346 reg         mdb_in_buf_en;
347 always @(posedge mclk or posedge puc)
348   if (puc)  mdb_in_buf_en <= 1'b0;
349   else      mdb_in_buf_en <= (e_state==`E_SRC_RD);
350
351 reg         mdb_in_buf_valid;
352 always @(posedge mclk or posedge puc)
353   if (puc)                   mdb_in_buf_valid <= 1'b0;
354   else if (e_state==`E_EXEC) mdb_in_buf_valid <= 1'b0;
355   else if (mdb_in_buf_en)    mdb_in_buf_valid <= 1'b1;
356
357 reg  [15:0] mdb_in_buf;
358 always @(posedge mclk or posedge puc)
359   if (puc)                mdb_in_buf <= 16'h0000;
360   else if (mdb_in_buf_en) mdb_in_buf <= mdb_in_bw;
361
362 assign mdb_in_val = mdb_in_buf_valid ? mdb_in_buf : mdb_in_bw;
363
364
365 endmodule // omsp_execution_unit
366
367 `include "openMSP430_undefines.v"