]> rtime.felk.cvut.cz Git - fpga/openmsp430.git/commitdiff
Added partial copy of openMSP430.
authorVladimir Burian <buriavl2@fel.cvut.cz>
Sat, 8 Jan 2011 16:15:45 +0000 (17:15 +0100)
committerVladimir Burian <buriavl2@fel.cvut.cz>
Sat, 8 Jan 2011 16:15:45 +0000 (17:15 +0100)
Only core source files weve added.

20 files changed:
omsp_alu.v [new file with mode: 0644]
omsp_clock_module.v [new file with mode: 0644]
omsp_dbg.v [new file with mode: 0644]
omsp_dbg_hwbrk.v [new file with mode: 0644]
omsp_dbg_uart.v [new file with mode: 0644]
omsp_execution_unit.v [new file with mode: 0644]
omsp_frontend.v [new file with mode: 0644]
omsp_mem_backbone.v [new file with mode: 0644]
omsp_multiplier.v [new file with mode: 0644]
omsp_register_file.v [new file with mode: 0644]
omsp_sfr.v [new file with mode: 0644]
omsp_watchdog.v [new file with mode: 0644]
openMSP430.v [new file with mode: 0644]
openMSP430_defines.v [new file with mode: 0644]
openMSP430_undefines.v [new file with mode: 0644]
periph/omsp_gpio.v [new file with mode: 0644]
periph/omsp_timerA.v [new file with mode: 0644]
periph/template_periph_16b.v [new file with mode: 0644]
periph/template_periph_8b.v [new file with mode: 0644]
timescale.v [new file with mode: 0644]

diff --git a/omsp_alu.v b/omsp_alu.v
new file mode 100644 (file)
index 0000000..81813c8
--- /dev/null
@@ -0,0 +1,248 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2001 Authors
+//
+// This source file may be used and distributed without restriction provided
+// that this copyright statement is not removed from the file and that any
+// derivative work contains the original copyright notice and the associated
+// disclaimer.
+//
+// This source file is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// This source is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+// License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this source; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+//----------------------------------------------------------------------------
+//
+// *File Name: omsp_alu.v
+// 
+// *Module Description:
+//                       openMSP430 ALU
+//
+// *Author(s):
+//              - Olivier Girard,    olgirard@gmail.com
+//
+//----------------------------------------------------------------------------
+// $Rev: 34 $
+// $LastChangedBy: olivier.girard $
+// $LastChangedDate: 2009-12-29 20:10:34 +0100 (Tue, 29 Dec 2009) $
+//----------------------------------------------------------------------------
+`include "timescale.v"
+`include "openMSP430_defines.v"
+
+module  omsp_alu (
+
+// OUTPUTs
+    alu_out,                       // ALU output value
+    alu_out_add,                   // ALU adder output value
+    alu_stat,                      // ALU Status {V,N,Z,C}
+    alu_stat_wr,                   // ALU Status write {V,N,Z,C}
+
+// INPUTs
+    dbg_halt_st,                   // Halt/Run status from CPU
+    exec_cycle,                    // Instruction execution cycle
+    inst_alu,                      // ALU control signals
+    inst_bw,                       // Decoded Inst: byte width
+    inst_jmp,                      // Decoded Inst: Conditional jump
+    inst_so,                       // Single-operand arithmetic
+    op_dst,                        // Destination operand
+    op_src,                        // Source operand
+    status                         // R2 Status {V,N,Z,C}
+);
+
+// OUTPUTs
+//=========
+output       [15:0] alu_out;       // ALU output value
+output       [15:0] alu_out_add;   // ALU adder output value
+output        [3:0] alu_stat;      // ALU Status {V,N,Z,C}
+output        [3:0] alu_stat_wr;   // ALU Status write {V,N,Z,C}
+
+// INPUTs
+//=========
+input               dbg_halt_st;   // Halt/Run status from CPU
+input               exec_cycle;    // Instruction execution cycle
+input        [11:0] inst_alu;      // ALU control signals
+input               inst_bw;       // Decoded Inst: byte width
+input         [7:0] inst_jmp;      // Decoded Inst: Conditional jump
+input         [7:0] inst_so;       // Single-operand arithmetic
+input        [15:0] op_dst;        // Destination operand
+input        [15:0] op_src;        // Source operand
+input         [3:0] status;        // R2 Status {V,N,Z,C}
+
+
+//=============================================================================
+// 1)  FUNCTIONS
+//=============================================================================
+
+function [4:0] bcd_add;
+
+   input [3:0] X;
+   input [3:0] Y;
+   input       C;
+
+   reg   [4:0] Z;
+   begin
+      Z = {1'b0,X}+{1'b0,Y}+C;
+      if (Z<10) bcd_add = Z;
+      else      bcd_add = Z+6;
+   end
+
+endfunction
+
+
+//=============================================================================
+// 2)  INSTRUCTION FETCH/DECODE CONTROL STATE MACHINE
+//=============================================================================
+// SINGLE-OPERAND ARITHMETIC:
+//-----------------------------------------------------------------------------
+//   Mnemonic   S-Reg,   Operation                               Status bits
+//              D-Reg,                                            V  N  Z  C
+//
+//   RRC         dst     C->MSB->...LSB->C                        *  *  *  *
+//   RRA         dst     MSB->MSB->...LSB->C                      0  *  *  *
+//   SWPB        dst     Swap bytes                               -  -  -  -
+//   SXT         dst     Bit7->Bit8...Bit15                       0  *  *  *
+//   PUSH        src     SP-2->SP, src->@SP                       -  -  -  -
+//   CALL        dst     SP-2->SP, PC+2->@SP, dst->PC             -  -  -  -
+//   RETI                TOS->SR, SP+2->SP, TOS->PC, SP+2->SP     *  *  *  *
+//
+//-----------------------------------------------------------------------------
+// TWO-OPERAND ARITHMETIC:
+//-----------------------------------------------------------------------------
+//   Mnemonic   S-Reg,   Operation                               Status bits
+//              D-Reg,                                            V  N  Z  C
+//
+//   MOV       src,dst    src            -> dst                   -  -  -  -
+//   ADD       src,dst    src +  dst     -> dst                   *  *  *  *
+//   ADDC      src,dst    src +  dst + C -> dst                   *  *  *  *
+//   SUB       src,dst    dst + ~src + 1 -> dst                   *  *  *  *
+//   SUBC      src,dst    dst + ~src + C -> dst                   *  *  *  *
+//   CMP       src,dst    dst + ~src + 1                          *  *  *  *
+//   DADD      src,dst    src +  dst + C -> dst (decimaly)        *  *  *  *
+//   BIT       src,dst    src &  dst                              0  *  *  *
+//   BIC       src,dst   ~src &  dst     -> dst                   -  -  -  -
+//   BIS       src,dst    src |  dst     -> dst                   -  -  -  -
+//   XOR       src,dst    src ^  dst     -> dst                   *  *  *  *
+//   AND       src,dst    src &  dst     -> dst                   0  *  *  *
+//
+//-----------------------------------------------------------------------------
+// * the status bit is affected
+// - the status bit is not affected
+// 0 the status bit is cleared
+// 1 the status bit is set
+//-----------------------------------------------------------------------------
+
+// Invert source for substract and compare instructions.
+wire        op_src_inv_cmd = exec_cycle & (inst_alu[`ALU_SRC_INV]);
+wire [15:0] op_src_inv     = {16{op_src_inv_cmd}} ^ op_src;
+
+
+// Mask the bit 8 for the Byte instructions for correct flags generation
+wire        op_bit8_msk     = ~exec_cycle | ~inst_bw;
+wire [16:0] op_src_in       = {1'b0, op_src_inv[15:9], op_src_inv[8] & op_bit8_msk, op_src_inv[7:0]};
+wire [16:0] op_dst_in       = {1'b0, op_dst[15:9],     op_dst[8]     & op_bit8_msk, op_dst[7:0]};
+
+// Clear the source operand (= jump offset) for conditional jumps
+wire        jmp_not_taken  = (inst_jmp[`JL]  & ~(status[3]^status[2])) |
+                             (inst_jmp[`JGE] &  (status[3]^status[2])) |
+                             (inst_jmp[`JN]  &  ~status[2])            |
+                             (inst_jmp[`JC]  &  ~status[0])            |
+                             (inst_jmp[`JNC] &   status[0])            |
+                             (inst_jmp[`JEQ] &  ~status[1])            |
+                             (inst_jmp[`JNE] &   status[1]);
+wire [16:0] op_src_in_jmp  = op_src_in & {17{~jmp_not_taken}};
+
+// Adder / AND / OR / XOR
+wire [16:0] alu_add        = op_src_in_jmp + op_dst_in;
+wire [16:0] alu_and        = op_src_in     & op_dst_in;
+wire [16:0] alu_or         = op_src_in     | op_dst_in;
+wire [16:0] alu_xor        = op_src_in     ^ op_dst_in;
+
+
+// Incrementer
+wire        alu_inc         = exec_cycle & ((inst_alu[`ALU_INC_C] & status[0]) |
+                                             inst_alu[`ALU_INC]);
+wire [16:0] alu_add_inc    = alu_add + {16'h0000, alu_inc};
+
+
+
+// Decimal adder (DADD)
+wire  [4:0] alu_dadd0      = bcd_add(op_src_in[3:0],   op_dst_in[3:0],  status[0]);
+wire  [4:0] alu_dadd1      = bcd_add(op_src_in[7:4],   op_dst_in[7:4],  alu_dadd0[4]);
+wire  [4:0] alu_dadd2      = bcd_add(op_src_in[11:8],  op_dst_in[11:8], alu_dadd1[4]);
+wire  [4:0] alu_dadd3      = bcd_add(op_src_in[15:12], op_dst_in[15:12],alu_dadd2[4]);
+wire [16:0] alu_dadd       = {alu_dadd3, alu_dadd2[3:0], alu_dadd1[3:0], alu_dadd0[3:0]};
+
+
+// Shifter for rotate instructions (RRC & RRA)
+wire        alu_shift_msb  = inst_so[`RRC] ? status[0]     :
+                            inst_bw       ? op_src[7]     : op_src[15];
+wire        alu_shift_7    = inst_bw       ? alu_shift_msb : op_src[8];
+wire [16:0] alu_shift      = {1'b0, alu_shift_msb, op_src[15:9], alu_shift_7, op_src[7:1]};
+
+
+// Swap bytes / Extend Sign
+wire [16:0] alu_swpb       = {1'b0, op_src[7:0],op_src[15:8]};
+wire [16:0] alu_sxt        = {1'b0, {8{op_src[7]}},op_src[7:0]};
+
+
+// Combine short paths toghether to simplify final ALU mux
+wire        alu_short_thro = ~(inst_alu[`ALU_AND]   |
+                               inst_alu[`ALU_OR]    |
+                               inst_alu[`ALU_XOR]   |
+                               inst_alu[`ALU_SHIFT] |
+                               inst_so[`SWPB]       |
+                               inst_so[`SXT]);
+
+wire [16:0] alu_short      = ({16{inst_alu[`ALU_AND]}}   & alu_and)   |
+                             ({16{inst_alu[`ALU_OR]}}    & alu_or)    |
+                             ({16{inst_alu[`ALU_XOR]}}   & alu_xor)   |
+                             ({16{inst_alu[`ALU_SHIFT]}} & alu_shift) |
+                             ({16{inst_so[`SWPB]}}       & alu_swpb)  |
+                             ({16{inst_so[`SXT]}}        & alu_sxt)   |
+                             ({16{alu_short_thro}}       & op_src_in);
+
+
+// ALU output mux
+wire [16:0] alu_out_nxt    = (inst_so[`IRQ] | dbg_halt_st |
+                              inst_alu[`ALU_ADD]) ? alu_add_inc :
+                              inst_alu[`ALU_DADD] ? alu_dadd    : alu_short;
+
+assign      alu_out        =  alu_out_nxt[15:0];
+assign      alu_out_add    =  alu_add[15:0];
+
+
+//-----------------------------------------------------------------------------
+// STATUS FLAG GENERATION
+//-----------------------------------------------------------------------------
+
+wire    V_xor       = inst_bw ? (op_src_in[7]  & op_dst_in[7])  :
+                                (op_src_in[15] & op_dst_in[15]);
+
+wire    V           = inst_bw ? ((~op_src_in[7]  & ~op_dst_in[7]  &  alu_out[7])  |
+                                 ( op_src_in[7]  &  op_dst_in[7]  & ~alu_out[7])) :
+                                ((~op_src_in[15] & ~op_dst_in[15] &  alu_out[15]) |
+                                 ( op_src_in[15] &  op_dst_in[15] & ~alu_out[15]));
+
+wire    N           = inst_bw ?  alu_out[7]       : alu_out[15];
+wire    Z           = inst_bw ? (alu_out[7:0]==0) : (alu_out==0);
+wire    C           = inst_bw ?  alu_out[8]       : alu_out_nxt[16];
+
+assign  alu_stat    = inst_alu[`ALU_SHIFT]  ? {1'b0, N,Z,op_src_in[0]} :
+                      inst_alu[`ALU_STAT_7] ? {1'b0, N,Z,~Z}           :
+                      inst_alu[`ALU_XOR]    ? {V_xor,N,Z,~Z}           : {V,N,Z,C};
+
+assign  alu_stat_wr = (inst_alu[`ALU_STAT_F] & exec_cycle) ? 4'b1111 : 4'b0000;
+
+
+endmodule // omsp_alu
+
+`include "openMSP430_undefines.v"
diff --git a/omsp_clock_module.v b/omsp_clock_module.v
new file mode 100644 (file)
index 0000000..b740737
--- /dev/null
@@ -0,0 +1,247 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2001 Authors
+//
+// This source file may be used and distributed without restriction provided
+// that this copyright statement is not removed from the file and that any
+// derivative work contains the original copyright notice and the associated
+// disclaimer.
+//
+// This source file is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// This source is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+// License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this source; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+//----------------------------------------------------------------------------
+//
+// *File Name: omsp_clock_module.v
+// 
+// *Module Description:
+//                       Basic clock module implementation.
+//                      Since the openMSP430 mainly targets FPGA and hobby
+//                     designers. The clock structure has been greatly
+//                     symplified in order to ease integration.
+//                      See online wiki for more info.
+//
+// *Author(s):
+//              - Olivier Girard,    olgirard@gmail.com
+//
+//----------------------------------------------------------------------------
+// $Rev: 34 $
+// $LastChangedBy: olivier.girard $
+// $LastChangedDate: 2009-12-29 20:10:34 +0100 (Tue, 29 Dec 2009) $
+//----------------------------------------------------------------------------
+`include "timescale.v"
+`include "openMSP430_defines.v"
+
+module  omsp_clock_module (
+
+// OUTPUTs
+    aclk_en,                      // ACLK enable
+    mclk,                         // Main system clock
+    per_dout,                     // Peripheral data output
+    por,                          // Power-on reset
+    puc,                          // Main system reset
+    smclk_en,                     // SMCLK enable
+            
+// INPUTs
+    dbg_reset,                    // Reset CPU from debug interface
+    dco_clk,                      // Fast oscillator (fast clock)
+    lfxt_clk,                     // Low frequency oscillator (typ 32kHz)
+    oscoff,                       // Turns off LFXT1 clock input
+    per_addr,                     // Peripheral address
+    per_din,                      // Peripheral data input
+    per_en,                       // Peripheral enable (high active)
+    per_wen,                      // Peripheral write enable (high active)
+    reset_n,                      // Reset Pin (low active)
+    scg1,                         // System clock generator 1. Turns off the SMCLK
+    wdt_reset                     // Watchdog-timer reset
+);
+
+// OUTPUTs
+//=========
+output              aclk_en;      // ACLK enable
+output              mclk;         // Main system clock
+output       [15:0] per_dout;     // Peripheral data output
+output              por;          // Power-on reset
+output              puc;          // Main system reset
+output              smclk_en;     // SMCLK enable
+
+// INPUTs
+//=========
+input               dbg_reset;    // Reset CPU from debug interface
+input               dco_clk;      // Fast oscillator (fast clock)
+input               lfxt_clk;     // Low frequency oscillator (typ 32kHz)
+input               oscoff;       // Turns off LFXT1 clock input
+input         [7:0] per_addr;     // Peripheral address
+input        [15:0] per_din;      // Peripheral data input
+input               per_en;       // Peripheral enable (high active)
+input         [1:0] per_wen;      // Peripheral write enable (high active)
+input               reset_n;      // Reset Pin (low active)
+input               scg1;         // System clock generator 1. Turns off the SMCLK
+input               wdt_reset;    // Watchdog-timer reset
+
+
+//=============================================================================
+// 1)  PARAMETER DECLARATION
+//=============================================================================
+
+// Register addresses
+parameter           BCSCTL1    = 9'h057;
+parameter           BCSCTL2    = 9'h058;
+
+// Register one-hot decoder
+parameter           BCSCTL1_D  = (256'h1 << (BCSCTL1 /2));
+parameter           BCSCTL2_D  = (256'h1 << (BCSCTL2 /2)); 
+
+
+//============================================================================
+// 2)  REGISTER DECODER
+//============================================================================
+
+// Register address decode
+reg  [255:0]  reg_dec; 
+always @(per_addr)
+  case (per_addr)
+    (BCSCTL1 /2):     reg_dec  =  BCSCTL1_D;
+    (BCSCTL2 /2):     reg_dec  =  BCSCTL2_D;
+    default     :     reg_dec  =  {256{1'b0}};
+  endcase
+
+// Read/Write probes
+wire         reg_lo_write =  per_wen[0] & per_en;
+wire         reg_hi_write =  per_wen[1] & per_en;
+wire         reg_read     = ~|per_wen   & per_en;
+
+// Read/Write vectors
+wire [255:0] reg_hi_wr    = reg_dec & {256{reg_hi_write}};
+wire [255:0] reg_lo_wr    = reg_dec & {256{reg_lo_write}};
+wire [255:0] reg_rd       = reg_dec & {256{reg_read}};
+
+
+//============================================================================
+// 3) REGISTERS
+//============================================================================
+
+// BCSCTL1 Register
+//--------------
+reg  [7:0] bcsctl1;
+wire       bcsctl1_wr  = BCSCTL1[0] ? reg_hi_wr[BCSCTL1/2] : reg_lo_wr[BCSCTL1/2];
+wire [7:0] bcsctl1_nxt = BCSCTL1[0] ? per_din[15:8]        : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)              bcsctl1  <=  8'h00;
+  else if (bcsctl1_wr)  bcsctl1  <=  bcsctl1_nxt & 8'h30; // Mask unused bits
+
+
+// BCSCTL2 Register
+//--------------
+reg  [7:0] bcsctl2;
+wire       bcsctl2_wr  = BCSCTL2[0] ? reg_hi_wr[BCSCTL2/2] : reg_lo_wr[BCSCTL2/2];
+wire [7:0] bcsctl2_nxt = BCSCTL2[0] ? per_din[15:8]        : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)              bcsctl2  <=  8'h00;
+  else if (bcsctl2_wr)  bcsctl2  <=  bcsctl2_nxt & 8'h0e; // Mask unused bits
+
+
+//============================================================================
+// 4) DATA OUTPUT GENERATION
+//============================================================================
+
+// Data output mux
+wire [15:0] bcsctl1_rd   = (bcsctl1  & {8{reg_rd[BCSCTL1/2]}})  << (8 & {4{BCSCTL1[0]}});
+wire [15:0] bcsctl2_rd   = (bcsctl2  & {8{reg_rd[BCSCTL2/2]}})  << (8 & {4{BCSCTL2[0]}});
+
+wire [15:0] per_dout =  bcsctl1_rd   |
+                        bcsctl2_rd;
+
+
+//=============================================================================
+// 5)  CLOCK GENERATION
+//=============================================================================
+
+// Synchronize LFXT_CLK & edge detection
+//---------------------------------------
+reg  [2:0] lfxt_clk_s;
+   
+always @ (posedge mclk or posedge puc)
+  if (puc) lfxt_clk_s <=  3'b000;
+  else     lfxt_clk_s <=  {lfxt_clk_s[1:0], lfxt_clk};    
+
+wire lfxt_clk_en = (lfxt_clk_s[1] & ~lfxt_clk_s[2]) & ~(oscoff & ~bcsctl2[`SELS]);
+     
+   
+// Generate main system clock
+//----------------------------
+
+wire  mclk   =  dco_clk;
+wire  mclk_n = !dco_clk;
+
+
+// Generate ACLK
+//----------------------------
+
+reg [2:0] aclk_div;
+
+wire      aclk_en = lfxt_clk_en & ((bcsctl1[`DIVAx]==2'b00) ?  1'b1          :
+                                   (bcsctl1[`DIVAx]==2'b01) ?  aclk_div[0]   :
+                                   (bcsctl1[`DIVAx]==2'b10) ? &aclk_div[1:0] :
+                                                              &aclk_div[2:0]);
+   
+always @ (posedge mclk or posedge puc)
+  if (puc)                                         aclk_div <=  3'h0;
+  else if ((bcsctl1[`DIVAx]!=2'b00) & lfxt_clk_en) aclk_div <=  aclk_div+3'h1;
+   
+
+// Generate SMCLK
+//----------------------------
+
+reg [2:0] smclk_div;
+
+wire      smclk_in = ~scg1 & (bcsctl2[`SELS] ? lfxt_clk_en : 1'b1);
+
+wire      smclk_en = smclk_in & ((bcsctl2[`DIVSx]==2'b00) ?  1'b1           :
+                                 (bcsctl2[`DIVSx]==2'b01) ?  smclk_div[0]   :
+                                 (bcsctl2[`DIVSx]==2'b10) ? &smclk_div[1:0] :
+                                                            &smclk_div[2:0]);
+   
+always @ (posedge mclk or posedge puc)
+  if (puc)                                      smclk_div <=  3'h0;
+  else if ((bcsctl2[`DIVSx]!=2'b00) & smclk_in) smclk_div <=  smclk_div+3'h1;
+
+
+//=============================================================================
+// 6)  RESET GENERATION
+//=============================================================================
+
+// Generate synchronized POR
+wire      por_reset  =  !reset_n;
+
+reg [1:0] por_s;
+always @(posedge mclk_n or posedge por_reset)
+  if (por_reset) por_s  <=  2'b11;
+  else           por_s  <=  {por_s[0], 1'b0};
+wire   por = por_s[1];
+
+// Generate main system reset
+wire      puc_reset  = por_reset | wdt_reset | dbg_reset;
+
+reg [1:0] puc_s;
+always @(posedge mclk_n or posedge puc_reset)
+  if (puc_reset) puc_s  <=  2'b11;
+  else           puc_s  <=  {puc_s[0], 1'b0};
+wire   puc = puc_s[1];
+
+
+endmodule // omsp_clock_module
+
+`include "openMSP430_undefines.v"
diff --git a/omsp_dbg.v b/omsp_dbg.v
new file mode 100644 (file)
index 0000000..aef9e83
--- /dev/null
@@ -0,0 +1,792 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2001 Authors
+//
+// This source file may be used and distributed without restriction provided
+// that this copyright statement is not removed from the file and that any
+// derivative work contains the original copyright notice and the associated
+// disclaimer.
+//
+// This source file is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// This source is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+// License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this source; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+//----------------------------------------------------------------------------
+//
+// *File Name: omsp_dbg.v
+// 
+// *Module Description:
+//                       Debug interface
+//
+// *Author(s):
+//              - Olivier Girard,    olgirard@gmail.com
+//
+//----------------------------------------------------------------------------
+// $Rev: 74 $
+// $LastChangedBy: olivier.girard $
+// $LastChangedDate: 2010-08-28 21:53:08 +0200 (Sat, 28 Aug 2010) $
+//----------------------------------------------------------------------------
+`include "timescale.v"
+`include "openMSP430_defines.v"
+
+module  omsp_dbg (
+
+// OUTPUTs
+    dbg_freeze,                     // Freeze peripherals
+    dbg_halt_cmd,                   // Halt CPU command
+    dbg_mem_addr,                   // Debug address for rd/wr access
+    dbg_mem_dout,                   // Debug unit data output
+    dbg_mem_en,                     // Debug unit memory enable
+    dbg_mem_wr,                     // Debug unit memory write
+    dbg_reg_wr,                     // Debug unit CPU register write
+    dbg_reset,                      // Reset CPU from debug interface
+    dbg_uart_txd,                   // Debug interface: UART TXD
+                            
+// INPUTs
+    dbg_halt_st,                    // Halt/Run status from CPU
+    dbg_mem_din,                    // Debug unit Memory data input
+    dbg_reg_din,                    // Debug unit CPU register data input
+    dbg_uart_rxd,                   // Debug interface: UART RXD
+    decode_noirq,                   // Frontend decode instruction
+    eu_mab,                         // Execution-Unit Memory address bus
+    eu_mb_en,                       // Execution-Unit Memory bus enable
+    eu_mb_wr,                       // Execution-Unit Memory bus write transfer
+    eu_mdb_in,                      // Memory data bus input
+    eu_mdb_out,                     // Memory data bus output
+    exec_done,                      // Execution completed
+    fe_mb_en,                       // Frontend Memory bus enable
+    fe_mdb_in,                      // Frontend Memory data bus input
+    mclk,                           // Main system clock
+    pc,                             // Program counter
+    por,                            // Power on reset
+    puc                             // Main system reset
+);
+
+// OUTPUTs
+//=========
+output              dbg_freeze;     // Freeze peripherals
+output              dbg_halt_cmd;   // Halt CPU command
+output       [15:0] dbg_mem_addr;   // Debug address for rd/wr access
+output       [15:0] dbg_mem_dout;   // Debug unit data output
+output              dbg_mem_en;     // Debug unit memory enable
+output        [1:0] dbg_mem_wr;     // Debug unit memory write
+output              dbg_reg_wr;     // Debug unit CPU register write
+output              dbg_reset;      // Reset CPU from debug interface
+output              dbg_uart_txd;   // Debug interface: UART TXD
+
+// INPUTs
+//=========
+input               dbg_halt_st;    // Halt/Run status from CPU
+input        [15:0] dbg_mem_din;    // Debug unit Memory data input
+input        [15:0] dbg_reg_din;    // Debug unit CPU register data input
+input               dbg_uart_rxd;   // Debug interface: UART RXD
+input               decode_noirq;   // Frontend decode instruction
+input        [15:0] eu_mab;         // Execution-Unit Memory address bus
+input               eu_mb_en;       // Execution-Unit Memory bus enable
+input         [1:0] eu_mb_wr;       // Execution-Unit Memory bus write transfer
+input        [15:0] eu_mdb_in;      // Memory data bus input
+input        [15:0] eu_mdb_out;     // Memory data bus output
+input               exec_done;      // Execution completed
+input               fe_mb_en;       // Frontend Memory bus enable
+input        [15:0] fe_mdb_in;      // Frontend Memory data bus input
+input               mclk;           // Main system clock
+input        [15:0] pc;             // Program counter
+input               por;            // Power on reset
+input               puc;            // Main system reset
+
+
+//=============================================================================
+// 1)  WIRE & PARAMETER DECLARATION
+//=============================================================================
+
+// Diverse wires and registers
+wire  [5:0] dbg_addr;
+wire [15:0] dbg_din;
+wire        dbg_wr;
+reg        mem_burst;
+wire        dbg_reg_rd;
+wire        dbg_mem_rd;
+reg         dbg_mem_rd_dly;
+wire        dbg_swbrk;
+wire        dbg_rd;
+reg         dbg_rd_rdy;
+wire        mem_burst_rd;
+wire        mem_burst_wr;
+wire        brk0_halt;
+wire        brk0_pnd;
+wire [15:0] brk0_dout;
+wire        brk1_halt;
+wire        brk1_pnd;
+wire [15:0] brk1_dout;
+wire        brk2_halt;
+wire        brk2_pnd;
+wire [15:0] brk2_dout;
+wire        brk3_halt;
+wire        brk3_pnd;
+wire [15:0] brk3_dout;
+    
+// Register addresses
+parameter           CPU_ID_LO    = 6'h00;
+parameter           CPU_ID_HI    = 6'h01;
+parameter           CPU_CTL      = 6'h02;
+parameter           CPU_STAT     = 6'h03;
+parameter           MEM_CTL      = 6'h04;
+parameter           MEM_ADDR     = 6'h05;
+parameter           MEM_DATA     = 6'h06;
+parameter           MEM_CNT      = 6'h07;
+`ifdef DBG_HWBRK_0
+parameter           BRK0_CTL     = 6'h08;
+parameter           BRK0_STAT    = 6'h09;
+parameter           BRK0_ADDR0   = 6'h0A;
+parameter           BRK0_ADDR1   = 6'h0B;
+`endif
+`ifdef DBG_HWBRK_1
+parameter           BRK1_CTL     = 6'h0C;
+parameter           BRK1_STAT    = 6'h0D;
+parameter           BRK1_ADDR0   = 6'h0E;
+parameter           BRK1_ADDR1   = 6'h0F;
+`endif
+`ifdef DBG_HWBRK_2
+parameter           BRK2_CTL     = 6'h10;
+parameter           BRK2_STAT    = 6'h11;
+parameter           BRK2_ADDR0   = 6'h12;
+parameter           BRK2_ADDR1   = 6'h13;
+`endif
+`ifdef DBG_HWBRK_3
+parameter           BRK3_CTL     = 6'h14;
+parameter           BRK3_STAT    = 6'h15;
+parameter           BRK3_ADDR0   = 6'h16;
+parameter           BRK3_ADDR1   = 6'h17;
+`endif
+
+// Register one-hot decoder
+parameter           CPU_ID_LO_D  = (64'h1 << CPU_ID_LO);
+parameter           CPU_ID_HI_D  = (64'h1 << CPU_ID_HI);
+parameter           CPU_CTL_D    = (64'h1 << CPU_CTL);
+parameter           CPU_STAT_D   = (64'h1 << CPU_STAT);
+parameter           MEM_CTL_D    = (64'h1 << MEM_CTL);
+parameter           MEM_ADDR_D   = (64'h1 << MEM_ADDR);
+parameter           MEM_DATA_D   = (64'h1 << MEM_DATA);
+parameter           MEM_CNT_D    = (64'h1 << MEM_CNT);
+`ifdef DBG_HWBRK_0
+parameter           BRK0_CTL_D   = (64'h1 << BRK0_CTL);
+parameter           BRK0_STAT_D  = (64'h1 << BRK0_STAT);
+parameter           BRK0_ADDR0_D = (64'h1 << BRK0_ADDR0);
+parameter           BRK0_ADDR1_D = (64'h1 << BRK0_ADDR1);
+`endif
+`ifdef DBG_HWBRK_1
+parameter           BRK1_CTL_D   = (64'h1 << BRK1_CTL);
+parameter           BRK1_STAT_D  = (64'h1 << BRK1_STAT);
+parameter           BRK1_ADDR0_D = (64'h1 << BRK1_ADDR0);
+parameter           BRK1_ADDR1_D = (64'h1 << BRK1_ADDR1);
+`endif
+`ifdef DBG_HWBRK_2
+parameter           BRK2_CTL_D   = (64'h1 << BRK2_CTL);
+parameter           BRK2_STAT_D  = (64'h1 << BRK2_STAT);
+parameter           BRK2_ADDR0_D = (64'h1 << BRK2_ADDR0);
+parameter           BRK2_ADDR1_D = (64'h1 << BRK2_ADDR1);
+`endif
+`ifdef DBG_HWBRK_3
+parameter           BRK3_CTL_D   = (64'h1 << BRK3_CTL);
+parameter           BRK3_STAT_D  = (64'h1 << BRK3_STAT);
+parameter           BRK3_ADDR0_D = (64'h1 << BRK3_ADDR0);
+parameter           BRK3_ADDR1_D = (64'h1 << BRK3_ADDR1);
+`endif
+
+   
+//============================================================================
+// 2)  REGISTER DECODER
+//============================================================================
+
+// Select Data register during a burst
+wire  [5:0] dbg_addr_in = mem_burst ? MEM_DATA : dbg_addr;
+
+// Register address decode
+reg  [63:0]  reg_dec; 
+always @(dbg_addr_in)
+  case (dbg_addr_in)
+    CPU_ID_LO :  reg_dec  =  CPU_ID_LO_D;
+    CPU_ID_HI :  reg_dec  =  CPU_ID_HI_D;
+    CPU_CTL   :  reg_dec  =  CPU_CTL_D;
+    CPU_STAT  :  reg_dec  =  CPU_STAT_D;
+    MEM_CTL   :  reg_dec  =  MEM_CTL_D;
+    MEM_ADDR  :  reg_dec  =  MEM_ADDR_D;
+    MEM_DATA  :  reg_dec  =  MEM_DATA_D;
+    MEM_CNT   :  reg_dec  =  MEM_CNT_D;
+`ifdef DBG_HWBRK_0
+    BRK0_CTL  :  reg_dec  =  BRK0_CTL_D;
+    BRK0_STAT :  reg_dec  =  BRK0_STAT_D;
+    BRK0_ADDR0:  reg_dec  =  BRK0_ADDR0_D;
+    BRK0_ADDR1:  reg_dec  =  BRK0_ADDR1_D;
+`endif
+`ifdef DBG_HWBRK_1
+    BRK1_CTL  :  reg_dec  =  BRK1_CTL_D;
+    BRK1_STAT :  reg_dec  =  BRK1_STAT_D;
+    BRK1_ADDR0:  reg_dec  =  BRK1_ADDR0_D;
+    BRK1_ADDR1:  reg_dec  =  BRK1_ADDR1_D;
+`endif
+`ifdef DBG_HWBRK_2
+    BRK2_CTL  :  reg_dec  =  BRK2_CTL_D;
+    BRK2_STAT :  reg_dec  =  BRK2_STAT_D;
+    BRK2_ADDR0:  reg_dec  =  BRK2_ADDR0_D;
+    BRK2_ADDR1:  reg_dec  =  BRK2_ADDR1_D;
+`endif
+`ifdef DBG_HWBRK_3
+    BRK3_CTL  :  reg_dec  =  BRK3_CTL_D;
+    BRK3_STAT :  reg_dec  =  BRK3_STAT_D;
+    BRK3_ADDR0:  reg_dec  =  BRK3_ADDR0_D;
+    BRK3_ADDR1:  reg_dec  =  BRK3_ADDR1_D;
+`endif
+    default:     reg_dec  =  {64{1'b0}};
+  endcase
+
+// Read/Write probes
+wire         reg_write =  dbg_wr;
+wire         reg_read  =  1'b1;
+
+// Read/Write vectors
+wire [511:0] reg_wr    = reg_dec & {64{reg_write}};
+wire [511:0] reg_rd    = reg_dec & {64{reg_read}};
+
+
+//=============================================================================
+// 3)  REGISTER: CORE INTERFACE
+//=============================================================================
+
+// CPU_ID Register
+//-----------------   
+
+wire [15:0] cpu_id_pmem = `PMEM_SIZE;
+wire [15:0] cpu_id_dmem = `DMEM_SIZE;
+wire [31:0] cpu_id      = {cpu_id_pmem, cpu_id_dmem};
+
+
+// CPU_CTL Register
+//-----------------------------------------------------------------------------
+//       7         6          5          4           3        2     1    0
+//   Reserved   CPU_RST  RST_BRK_EN  FRZ_BRK_EN  SW_BRK_EN  ISTEP  RUN  HALT
+//-----------------------------------------------------------------------------
+reg   [6:3] cpu_ctl;
+
+wire        cpu_ctl_wr = reg_wr[CPU_CTL];
+   
+always @ (posedge mclk or posedge por)
+  if (por)             cpu_ctl <=  4'h0;
+  else if (cpu_ctl_wr) cpu_ctl <=  dbg_din[6:3];
+
+wire  [7:0] cpu_ctl_full = {1'b0, cpu_ctl, 3'b000};
+
+wire        halt_cpu = cpu_ctl_wr & dbg_din[`HALT]  & ~dbg_halt_st;
+wire        run_cpu  = cpu_ctl_wr & dbg_din[`RUN]   &  dbg_halt_st;
+wire        istep    = cpu_ctl_wr & dbg_din[`ISTEP] &  dbg_halt_st;
+
+   
+// CPU_STAT Register
+//------------------------------------------------------------------------------------
+//      7           6          5           4           3         2      1       0
+// HWBRK3_PND  HWBRK2_PND  HWBRK1_PND  HWBRK0_PND  SWBRK_PND  PUC_PND  Res.  HALT_RUN
+//------------------------------------------------------------------------------------
+reg   [3:2] cpu_stat;
+
+wire        cpu_stat_wr  = reg_wr[CPU_STAT];
+wire  [3:2] cpu_stat_set = {dbg_swbrk, puc};
+wire  [3:2] cpu_stat_clr = ~dbg_din[3:2];
+
+always @ (posedge mclk or posedge por)
+  if (por)              cpu_stat <=  2'b00;
+  else if (cpu_stat_wr) cpu_stat <= ((cpu_stat & cpu_stat_clr) | cpu_stat_set);
+  else                  cpu_stat <=  (cpu_stat                 | cpu_stat_set);
+
+wire  [7:0] cpu_stat_full = {brk3_pnd, brk2_pnd, brk1_pnd, brk0_pnd,
+                             cpu_stat, 1'b0, dbg_halt_st};
+
+   
+//=============================================================================
+// 4)  REGISTER: MEMORY INTERFACE
+//=============================================================================
+
+// MEM_CTL Register
+//-----------------------------------------------------------------------------
+//       7     6     5     4          3        2         1       0
+//            Reserved               B/W    MEM/REG    RD/WR   START
+//
+// START  :  -  0 : Do nothing.
+//           -  1 : Initiate memory transfer.
+//
+// RD/WR  :  -  0 : Read access.
+//           -  1 : Write access.
+//
+// MEM/REG:  -  0 : Memory access.
+//           -  1 : CPU Register access.
+//
+// B/W    :  -  0 : 16 bit access.
+//           -  1 :  8 bit access (not valid for CPU Registers).
+//
+//-----------------------------------------------------------------------------
+reg   [3:1] mem_ctl;
+
+wire        mem_ctl_wr = reg_wr[MEM_CTL];
+   
+always @ (posedge mclk or posedge por)
+  if (por)             mem_ctl <=  3'h0;
+  else if (mem_ctl_wr) mem_ctl <=  dbg_din[3:1];
+
+wire  [7:0] mem_ctl_full  = {4'b0000, mem_ctl, 1'b0};
+
+reg         mem_start;
+always @ (posedge mclk or posedge por)
+  if (por)  mem_start <=  1'b0;
+  else      mem_start <=  mem_ctl_wr & dbg_din[0];
+
+wire        mem_bw    = mem_ctl[3];
+   
+// MEM_DATA Register
+//------------------   
+reg  [15:0] mem_data;
+reg  [15:0] mem_addr;
+wire        mem_access;
+   
+wire        mem_data_wr = reg_wr[MEM_DATA];
+
+wire [15:0] dbg_mem_din_bw = ~mem_bw      ? dbg_mem_din                :
+                             mem_addr[0] ? {8'h00, dbg_mem_din[15:8]} :
+                                           {8'h00, dbg_mem_din[7:0]};
+   
+always @ (posedge mclk or posedge por)
+  if (por)                 mem_data <=  16'h0000;
+  else if (mem_data_wr)    mem_data <=  dbg_din;
+  else if (dbg_reg_rd)     mem_data <=  dbg_reg_din;
+  else if (dbg_mem_rd_dly) mem_data <=  dbg_mem_din_bw;
+
+   
+// MEM_ADDR Register
+//------------------   
+reg  [15:0] mem_cnt;
+
+wire        mem_addr_wr  = reg_wr[MEM_ADDR];
+wire        dbg_mem_acc  = (|dbg_mem_wr | (dbg_rd_rdy & ~mem_ctl[2]));
+wire        dbg_reg_acc  = ( dbg_reg_wr | (dbg_rd_rdy &  mem_ctl[2]));
+   
+wire [15:0] mem_addr_inc = (mem_cnt==16'h0000)         ? 16'h0000 :
+                           (dbg_mem_acc & ~mem_bw)     ? 16'h0002 :
+                           (dbg_mem_acc | dbg_reg_acc) ? 16'h0001 : 16'h0000;
+   
+always @ (posedge mclk or posedge por)
+  if (por)              mem_addr <=  16'h0000;
+  else if (mem_addr_wr) mem_addr <=  dbg_din;
+  else                  mem_addr <=  mem_addr + mem_addr_inc;
+   
+// MEM_CNT Register
+//------------------   
+
+wire        mem_cnt_wr  = reg_wr[MEM_CNT];
+
+wire [15:0] mem_cnt_dec = (mem_cnt==16'h0000)         ? 16'h0000 :
+                          (dbg_mem_acc | dbg_reg_acc) ? 16'hffff : 16'h0000;
+   
+always @ (posedge mclk or posedge por)
+  if (por)             mem_cnt <=  16'h0000;
+  else if (mem_cnt_wr) mem_cnt <=  dbg_din;
+  else                 mem_cnt <=  mem_cnt + mem_cnt_dec;
+
+
+//=============================================================================
+// 5)  BREAKPOINTS / WATCHPOINTS
+//=============================================================================
+
+`ifdef DBG_HWBRK_0
+// Hardware Breakpoint/Watchpoint Register read select
+wire [3:0] brk0_reg_rd = {reg_rd[BRK0_ADDR1],
+                          reg_rd[BRK0_ADDR0],
+                          reg_rd[BRK0_STAT],
+                          reg_rd[BRK0_CTL]};
+
+// Hardware Breakpoint/Watchpoint Register write select
+wire [3:0] brk0_reg_wr = {reg_wr[BRK0_ADDR1],
+                          reg_wr[BRK0_ADDR0],
+                          reg_wr[BRK0_STAT],
+                          reg_wr[BRK0_CTL]};
+
+omsp_dbg_hwbrk dbg_hwbr_0 (
+
+// OUTPUTs
+    .brk_halt   (brk0_halt),   // Hardware breakpoint command
+    .brk_pnd    (brk0_pnd),    // Hardware break/watch-point pending
+    .brk_dout   (brk0_dout),   // Hardware break/watch-point register data input
+                            
+// INPUTs
+    .brk_reg_rd (brk0_reg_rd), // Hardware break/watch-point register read select
+    .brk_reg_wr (brk0_reg_wr), // Hardware break/watch-point register write select
+    .dbg_din    (dbg_din),     // Debug register data input
+    .eu_mab     (eu_mab),      // Execution-Unit Memory address bus
+    .eu_mb_en   (eu_mb_en),    // Execution-Unit Memory bus enable
+    .eu_mb_wr   (eu_mb_wr),    // Execution-Unit Memory bus write transfer
+    .eu_mdb_in  (eu_mdb_in),   // Memory data bus input
+    .eu_mdb_out (eu_mdb_out),  // Memory data bus output
+    .exec_done  (exec_done),   // Execution completed
+    .fe_mb_en   (fe_mb_en),    // Frontend Memory bus enable
+    .mclk       (mclk),        // Main system clock
+    .pc         (pc),          // Program counter
+    .por        (por)          // Power on reset
+);
+
+`else
+assign brk0_halt =  1'b0;
+assign brk0_pnd  =  1'b0;
+assign brk0_dout = 16'h0000;
+`endif
+
+`ifdef DBG_HWBRK_1
+// Hardware Breakpoint/Watchpoint Register read select
+wire [3:0] brk1_reg_rd = {reg_rd[BRK1_ADDR1],
+                          reg_rd[BRK1_ADDR0],
+                          reg_rd[BRK1_STAT],
+                          reg_rd[BRK1_CTL]};
+
+// Hardware Breakpoint/Watchpoint Register write select
+wire [3:0] brk1_reg_wr = {reg_wr[BRK1_ADDR1],
+                          reg_wr[BRK1_ADDR0],
+                          reg_wr[BRK1_STAT],
+                          reg_wr[BRK1_CTL]};
+
+omsp_dbg_hwbrk dbg_hwbr_1 (
+
+// OUTPUTs
+    .brk_halt   (brk1_halt),   // Hardware breakpoint command
+    .brk_pnd    (brk1_pnd),    // Hardware break/watch-point pending
+    .brk_dout   (brk1_dout),   // Hardware break/watch-point register data input
+                            
+// INPUTs
+    .brk_reg_rd (brk1_reg_rd), // Hardware break/watch-point register read select
+    .brk_reg_wr (brk1_reg_wr), // Hardware break/watch-point register write select
+    .dbg_din    (dbg_din),     // Debug register data input
+    .eu_mab     (eu_mab),      // Execution-Unit Memory address bus
+    .eu_mb_en   (eu_mb_en),    // Execution-Unit Memory bus enable
+    .eu_mb_wr   (eu_mb_wr),    // Execution-Unit Memory bus write transfer
+    .eu_mdb_in  (eu_mdb_in),   // Memory data bus input
+    .eu_mdb_out (eu_mdb_out),  // Memory data bus output
+    .exec_done  (exec_done),   // Execution completed
+    .fe_mb_en   (fe_mb_en),    // Frontend Memory bus enable
+    .mclk       (mclk),        // Main system clock
+    .pc         (pc),          // Program counter
+    .por        (por)          // Power on reset
+);
+
+`else
+assign brk1_halt =  1'b0;
+assign brk1_pnd  =  1'b0;
+assign brk1_dout = 16'h0000;
+`endif
+
+ `ifdef DBG_HWBRK_2
+// Hardware Breakpoint/Watchpoint Register read select
+wire [3:0] brk2_reg_rd = {reg_rd[BRK2_ADDR1],
+                          reg_rd[BRK2_ADDR0],
+                          reg_rd[BRK2_STAT],
+                          reg_rd[BRK2_CTL]};
+
+// Hardware Breakpoint/Watchpoint Register write select
+wire [3:0] brk2_reg_wr = {reg_wr[BRK2_ADDR1],
+                          reg_wr[BRK2_ADDR0],
+                          reg_wr[BRK2_STAT],
+                          reg_wr[BRK2_CTL]};
+
+omsp_dbg_hwbrk dbg_hwbr_2 (
+
+// OUTPUTs
+    .brk_halt   (brk2_halt),   // Hardware breakpoint command
+    .brk_pnd    (brk2_pnd),    // Hardware break/watch-point pending
+    .brk_dout   (brk2_dout),   // Hardware break/watch-point register data input
+                            
+// INPUTs
+    .brk_reg_rd (brk2_reg_rd), // Hardware break/watch-point register read select
+    .brk_reg_wr (brk2_reg_wr), // Hardware break/watch-point register write select
+    .dbg_din    (dbg_din),     // Debug register data input
+    .eu_mab     (eu_mab),      // Execution-Unit Memory address bus
+    .eu_mb_en   (eu_mb_en),    // Execution-Unit Memory bus enable
+    .eu_mb_wr   (eu_mb_wr),    // Execution-Unit Memory bus write transfer
+    .eu_mdb_in  (eu_mdb_in),   // Memory data bus input
+    .eu_mdb_out (eu_mdb_out),  // Memory data bus output
+    .exec_done  (exec_done),   // Execution completed
+    .fe_mb_en   (fe_mb_en),    // Frontend Memory bus enable
+    .mclk       (mclk),        // Main system clock
+    .pc         (pc),          // Program counter
+    .por        (por)          // Power on reset
+);
+
+`else
+assign brk2_halt =  1'b0;
+assign brk2_pnd  =  1'b0;
+assign brk2_dout = 16'h0000;
+`endif
+
+`ifdef DBG_HWBRK_3
+// Hardware Breakpoint/Watchpoint Register read select
+wire [3:0] brk3_reg_rd = {reg_rd[BRK3_ADDR1],
+                          reg_rd[BRK3_ADDR0],
+                          reg_rd[BRK3_STAT],
+                          reg_rd[BRK3_CTL]};
+
+// Hardware Breakpoint/Watchpoint Register write select
+wire [3:0] brk3_reg_wr = {reg_wr[BRK3_ADDR1],
+                          reg_wr[BRK3_ADDR0],
+                          reg_wr[BRK3_STAT],
+                          reg_wr[BRK3_CTL]};
+
+omsp_dbg_hwbrk dbg_hwbr_3 (
+
+// OUTPUTs
+    .brk_halt   (brk3_halt),   // Hardware breakpoint command
+    .brk_pnd    (brk3_pnd),    // Hardware break/watch-point pending
+    .brk_dout   (brk3_dout),   // Hardware break/watch-point register data input
+                            
+// INPUTs
+    .brk_reg_rd (brk3_reg_rd), // Hardware break/watch-point register read select
+    .brk_reg_wr (brk3_reg_wr), // Hardware break/watch-point register write select
+    .dbg_din    (dbg_din),     // Debug register data input
+    .eu_mab     (eu_mab),      // Execution-Unit Memory address bus
+    .eu_mb_en   (eu_mb_en),    // Execution-Unit Memory bus enable
+    .eu_mb_wr   (eu_mb_wr),    // Execution-Unit Memory bus write transfer
+    .eu_mdb_in  (eu_mdb_in),   // Memory data bus input
+    .eu_mdb_out (eu_mdb_out),  // Memory data bus output
+    .exec_done  (exec_done),   // Execution completed
+    .fe_mb_en   (fe_mb_en),    // Frontend Memory bus enable
+    .mclk       (mclk),        // Main system clock
+    .pc         (pc),          // Program counter
+    .por        (por)          // Power on reset
+);
+
+`else
+assign brk3_halt =  1'b0;
+assign brk3_pnd  =  1'b0;
+assign brk3_dout = 16'h0000;
+`endif
+
+
+//============================================================================
+// 6) DATA OUTPUT GENERATION
+//============================================================================
+
+wire [15:0] cpu_id_lo_rd = cpu_id[15:0]           & {16{reg_rd[CPU_ID_LO]}};
+wire [15:0] cpu_id_hi_rd = cpu_id[31:16]          & {16{reg_rd[CPU_ID_HI]}};
+wire [15:0] cpu_ctl_rd   = {8'h00, cpu_ctl_full}  & {16{reg_rd[CPU_CTL]}};
+wire [15:0] cpu_stat_rd  = {8'h00, cpu_stat_full} & {16{reg_rd[CPU_STAT]}};
+wire [15:0] mem_ctl_rd   = {8'h00, mem_ctl_full}  & {16{reg_rd[MEM_CTL]}};
+wire [15:0] mem_data_rd  = mem_data               & {16{reg_rd[MEM_DATA]}};
+wire [15:0] mem_addr_rd  = mem_addr               & {16{reg_rd[MEM_ADDR]}};
+wire [15:0] mem_cnt_rd   = mem_cnt                & {16{reg_rd[MEM_CNT]}};
+
+wire [15:0] dbg_dout = cpu_id_lo_rd |
+                       cpu_id_hi_rd |
+                       cpu_ctl_rd   |
+                       cpu_stat_rd  |
+                       mem_ctl_rd   |
+                       mem_data_rd  |
+                       mem_addr_rd  |
+                       mem_cnt_rd   |
+                       brk0_dout    |
+                       brk1_dout    |
+                       brk2_dout    |
+                       brk3_dout;
+
+// Tell UART/JTAG interface that the data is ready to be read
+always @ (posedge mclk or posedge por)
+  if (por)                           dbg_rd_rdy  <=  1'b0;
+  else if (mem_burst | mem_burst_rd) dbg_rd_rdy  <= (dbg_reg_rd | dbg_mem_rd_dly);
+  else                               dbg_rd_rdy  <=  dbg_rd;
+
+
+//============================================================================
+// 7) CPU CONTROL
+//============================================================================
+
+// Reset CPU
+//--------------------------
+wire dbg_reset  = cpu_ctl[`CPU_RST];
+
+   
+// Break after reset
+//--------------------------
+wire halt_rst = cpu_ctl[`RST_BRK_EN] & puc;
+
+   
+// Freeze peripherals
+//--------------------------
+wire dbg_freeze = dbg_halt_st & cpu_ctl[`FRZ_BRK_EN];
+
+   
+// Software break
+//--------------------------
+assign dbg_swbrk = (fe_mdb_in==`DBG_SWBRK_OP) & decode_noirq & cpu_ctl[`SW_BRK_EN];
+
+
+// Single step
+//--------------------------
+reg [1:0] inc_step;
+always @(posedge mclk or posedge por)
+  if (por)        inc_step <= 2'b00;
+  else if (istep) inc_step <= 2'b11;
+  else            inc_step <= {inc_step[0], 1'b0};
+
+   
+// Run / Halt
+//--------------------------
+reg   halt_flag;
+
+wire  mem_halt_cpu;
+wire  mem_run_cpu;
+
+wire  halt_flag_clr = run_cpu   | mem_run_cpu;
+wire  halt_flag_set = halt_cpu  | halt_rst  | dbg_swbrk | mem_halt_cpu |
+                      brk0_halt | brk1_halt | brk2_halt | brk3_halt;
+
+always @(posedge mclk or posedge por)
+  if (por)                halt_flag <= 1'b0;
+  else if (halt_flag_clr) halt_flag <= 1'b0;
+  else if (halt_flag_set) halt_flag <= 1'b1;
+
+wire dbg_halt_cmd = (halt_flag | halt_flag_set) & ~inc_step[1];
+
+     
+//============================================================================
+// 8) MEMORY CONTROL
+//============================================================================
+
+// Control Memory bursts
+//------------------------------
+
+wire mem_burst_start = (mem_start             &  |mem_cnt);
+wire mem_burst_end   = ((dbg_wr | dbg_rd_rdy) & ~|mem_cnt);
+
+// Detect when burst is on going
+always @(posedge mclk or posedge por)
+  if (por)                  mem_burst <= 1'b0;
+  else if (mem_burst_start) mem_burst <= 1'b1;
+  else if (mem_burst_end)   mem_burst <= 1'b0;
+
+// Control signals for UART/JTAG interface
+assign mem_burst_rd = (mem_burst_start & ~mem_ctl[1]);
+assign mem_burst_wr = (mem_burst_start &  mem_ctl[1]);
+
+// Trigger CPU Register or memory access during a burst
+reg        mem_startb;   
+always @(posedge mclk or posedge por)
+  if (por) mem_startb <= 1'b0;
+  else     mem_startb <= (mem_burst & (dbg_wr | dbg_rd)) | mem_burst_rd;
+
+// Combine single and burst memory start of sequence
+wire       mem_seq_start = ((mem_start & ~|mem_cnt) | mem_startb);
+
+   
+// Memory access state machine
+//------------------------------
+reg  [1:0] mem_state;
+reg  [1:0] mem_state_nxt;
+
+// State machine definition
+parameter  M_IDLE       = 2'h0;
+parameter  M_SET_BRK    = 2'h1;
+parameter  M_ACCESS_BRK = 2'h2;
+parameter  M_ACCESS     = 2'h3;
+
+// State transition
+always @(mem_state or mem_seq_start or dbg_halt_st)
+  case (mem_state)
+    M_IDLE       : mem_state_nxt = ~mem_seq_start ? M_IDLE       : 
+                                    dbg_halt_st   ? M_ACCESS     : M_SET_BRK;
+    M_SET_BRK    : mem_state_nxt =  dbg_halt_st   ? M_ACCESS_BRK : M_SET_BRK;
+    M_ACCESS_BRK : mem_state_nxt =  M_IDLE;
+    M_ACCESS     : mem_state_nxt =  M_IDLE;
+    default      : mem_state_nxt =  M_IDLE;
+  endcase
+
+// State machine
+always @(posedge mclk or posedge por)
+  if (por) mem_state <= M_IDLE;
+  else     mem_state <= mem_state_nxt;
+
+// Utility signals
+assign mem_halt_cpu = (mem_state==M_IDLE)       & (mem_state_nxt==M_SET_BRK);
+assign mem_run_cpu  = (mem_state==M_ACCESS_BRK) & (mem_state_nxt==M_IDLE);
+assign mem_access   = (mem_state==M_ACCESS)     | (mem_state==M_ACCESS_BRK);
+
+
+// Interface to CPU Registers and Memory bacbkone
+//------------------------------------------------
+assign      dbg_mem_addr   =  mem_addr;
+assign      dbg_mem_dout   = ~mem_bw      ? mem_data               :
+                              mem_addr[0] ? {mem_data[7:0], 8'h00} :
+                                            {8'h00, mem_data[7:0]};
+
+assign      dbg_reg_wr     = mem_access &  mem_ctl[1] &  mem_ctl[2];
+assign      dbg_reg_rd     = mem_access & ~mem_ctl[1] &  mem_ctl[2];
+
+assign      dbg_mem_en     = mem_access & ~mem_ctl[2];
+assign      dbg_mem_rd     = dbg_mem_en & ~mem_ctl[1];
+
+wire  [1:0] dbg_mem_wr_msk = ~mem_bw      ? 2'b11 :
+                              mem_addr[0] ? 2'b10 : 2'b01;
+assign      dbg_mem_wr     = {2{dbg_mem_en & mem_ctl[1]}} & dbg_mem_wr_msk;
+
+
+// It takes one additional cycle to read from Memory as from registers
+always @(posedge mclk or posedge por)
+  if (por) dbg_mem_rd_dly <= 1'b0;
+  else     dbg_mem_rd_dly <= dbg_mem_rd;
+
+      
+//=============================================================================
+// 9)  UART COMMUNICATION
+//=============================================================================
+`ifdef DBG_UART
+omsp_dbg_uart dbg_uart_0 (
+
+// OUTPUTs
+    .dbg_addr     (dbg_addr),      // Debug register address
+    .dbg_din      (dbg_din),       // Debug register data input
+    .dbg_rd       (dbg_rd),        // Debug register data read
+    .dbg_uart_txd (dbg_uart_txd),  // Debug interface: UART TXD
+    .dbg_wr       (dbg_wr),        // Debug register data write
+                            
+// INPUTs
+    .dbg_dout     (dbg_dout),      // Debug register data output
+    .dbg_rd_rdy   (dbg_rd_rdy),    // Debug register data is ready for read
+    .dbg_uart_rxd (dbg_uart_rxd),  // Debug interface: UART RXD
+    .mclk         (mclk),          // Main system clock
+    .mem_burst    (mem_burst),     // Burst on going
+    .mem_burst_end(mem_burst_end), // End TX/RX burst
+    .mem_burst_rd (mem_burst_rd),  // Start TX burst
+    .mem_burst_wr (mem_burst_wr),  // Start RX burst
+    .mem_bw       (mem_bw),        // Burst byte width
+    .por          (por)            // Power on reset
+);
+
+`else
+assign dbg_addr     =  6'h00;
+assign dbg_din      = 16'h0000;
+assign dbg_rd       =  1'b0;
+assign dbg_uart_txd =  1'b0;
+assign dbg_wr       =  1'b0;
+`endif
+
+   
+//=============================================================================
+// 10)  JTAG COMMUNICATION
+//=============================================================================
+`ifdef DBG_JTAG
+JTAG INTERFACE IS NOT SUPPORTED YET
+`else
+`endif
+
+endmodule // dbg
+
+`include "openMSP430_undefines.v"
diff --git a/omsp_dbg_hwbrk.v b/omsp_dbg_hwbrk.v
new file mode 100644 (file)
index 0000000..daadf69
--- /dev/null
@@ -0,0 +1,272 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2001 Authors
+//
+// This source file may be used and distributed without restriction provided
+// that this copyright statement is not removed from the file and that any
+// derivative work contains the original copyright notice and the associated
+// disclaimer.
+//
+// This source file is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// This source is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+// License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this source; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+//----------------------------------------------------------------------------
+//
+// *File Name: omsp_dbg_hwbrk.v
+// 
+// *Module Description:
+//                       Hardware Breakpoint / Watchpoint module
+//
+// *Author(s):
+//              - Olivier Girard,    olgirard@gmail.com
+//
+//----------------------------------------------------------------------------
+// $Rev: 57 $
+// $LastChangedBy: olivier.girard $
+// $LastChangedDate: 2010-02-01 23:56:03 +0100 (Mon, 01 Feb 2010) $
+//----------------------------------------------------------------------------
+`include "timescale.v"
+`include "openMSP430_defines.v"
+
+module  omsp_dbg_hwbrk (
+
+// OUTPUTs
+    brk_halt,                // Hardware breakpoint command
+    brk_pnd,                 // Hardware break/watch-point pending
+    brk_dout,                // Hardware break/watch-point register data input
+                            
+// INPUTs
+    brk_reg_rd,              // Hardware break/watch-point register read select
+    brk_reg_wr,              // Hardware break/watch-point register write select
+    dbg_din,                 // Debug register data input
+    eu_mab,                  // Execution-Unit Memory address bus
+    eu_mb_en,                // Execution-Unit Memory bus enable
+    eu_mb_wr,                // Execution-Unit Memory bus write transfer
+    eu_mdb_in,               // Memory data bus input
+    eu_mdb_out,              // Memory data bus output
+    exec_done,               // Execution completed
+    fe_mb_en,                // Frontend Memory bus enable
+    mclk,                    // Main system clock
+    pc,                      // Program counter
+    por                      // Power on reset
+);
+
+// OUTPUTs
+//=========
+output         brk_halt;     // Hardware breakpoint command
+output         brk_pnd;      // Hardware break/watch-point pending
+output  [15:0] brk_dout;     // Hardware break/watch-point register data input
+
+// INPUTs
+//=========
+input    [3:0] brk_reg_rd;   // Hardware break/watch-point register read select
+input    [3:0] brk_reg_wr;   // Hardware break/watch-point register write select
+input   [15:0] dbg_din;      // Debug register data input
+input   [15:0] eu_mab;       // Execution-Unit Memory address bus
+input          eu_mb_en;     // Execution-Unit Memory bus enable
+input    [1:0] eu_mb_wr;     // Execution-Unit Memory bus write transfer
+input   [15:0] eu_mdb_in;    // Memory data bus input
+input   [15:0] eu_mdb_out;   // Memory data bus output
+input          exec_done;    // Execution completed
+input          fe_mb_en;     // Frontend Memory bus enable
+input          mclk;         // Main system clock
+input   [15:0] pc;           // Program counter
+input          por;          // Power on reset
+
+
+//=============================================================================
+// 1)  WIRE & PARAMETER DECLARATION
+//=============================================================================
+
+wire      range_wr_set;
+wire      range_rd_set;
+wire      addr1_wr_set;
+wire      addr1_rd_set;
+wire      addr0_wr_set;
+wire      addr0_rd_set;
+
+   
+parameter BRK_CTL   = 0,
+          BRK_STAT  = 1,
+          BRK_ADDR0 = 2,
+          BRK_ADDR1 = 3;
+
+   
+//=============================================================================
+// 2)  CONFIGURATION REGISTERS
+//=============================================================================
+
+// BRK_CTL Register
+//-----------------------------------------------------------------------------
+//       7   6   5        4            3          2            1  0
+//        Reserved    RANGE_MODE    INST_EN    BREAK_EN    ACCESS_MODE
+//
+// ACCESS_MODE: - 00 : Disabled
+//              - 01 : Detect read access
+//              - 10 : Detect write access
+//              - 11 : Detect read/write access
+//              NOTE: '10' & '11' modes are not supported on the instruction flow
+//
+// BREAK_EN:    -  0 : Watchmode enable
+//              -  1 : Break enable
+//
+// INST_EN:     -  0 : Checks are done on the execution unit (data flow)
+//              -  1 : Checks are done on the frontend (instruction flow)
+//
+// RANGE_MODE:  -  0 : Address match on BRK_ADDR0 or BRK_ADDR1
+//              -  1 : Address match on BRK_ADDR0->BRK_ADDR1 range
+//
+//-----------------------------------------------------------------------------
+reg   [4:0] brk_ctl;
+
+wire        brk_ctl_wr = brk_reg_wr[BRK_CTL];
+   
+always @ (posedge mclk or posedge por)
+  if (por)             brk_ctl <=  5'h00;
+  else if (brk_ctl_wr) brk_ctl <=  {`HWBRK_RANGE & dbg_din[4], dbg_din[3:0]};
+
+wire  [7:0] brk_ctl_full = {3'b000, brk_ctl};
+
+   
+// BRK_STAT Register
+//-----------------------------------------------------------------------------
+//     7    6       5         4         3         2         1         0
+//    Reserved  RANGE_WR  RANGE_RD  ADDR1_WR  ADDR1_RD  ADDR0_WR  ADDR0_RD
+//-----------------------------------------------------------------------------
+reg   [5:0] brk_stat;
+
+wire        brk_stat_wr  = brk_reg_wr[BRK_STAT];
+wire  [5:0] brk_stat_set = {range_wr_set & `HWBRK_RANGE,
+                            range_rd_set & `HWBRK_RANGE,
+                           addr1_wr_set, addr1_rd_set,
+                           addr0_wr_set, addr0_rd_set};
+wire  [5:0] brk_stat_clr = ~dbg_din[5:0];
+
+always @ (posedge mclk or posedge por)
+  if (por)              brk_stat <=  6'h00;
+  else if (brk_stat_wr) brk_stat <= ((brk_stat & brk_stat_clr) | brk_stat_set);
+  else                  brk_stat <=  (brk_stat                 | brk_stat_set);
+
+wire  [7:0] brk_stat_full = {2'b00, brk_stat};
+wire        brk_pnd       = |brk_stat;
+
+
+// BRK_ADDR0 Register
+//-----------------------------------------------------------------------------
+reg  [15:0] brk_addr0;
+
+wire        brk_addr0_wr = brk_reg_wr[BRK_ADDR0];
+   
+always @ (posedge mclk or posedge por)
+  if (por)               brk_addr0 <=  16'h0000;
+  else if (brk_addr0_wr) brk_addr0 <=  dbg_din;
+
+   
+// BRK_ADDR1/DATA0 Register
+//-----------------------------------------------------------------------------
+reg  [15:0] brk_addr1;
+
+wire        brk_addr1_wr = brk_reg_wr[BRK_ADDR1];
+   
+always @ (posedge mclk or posedge por)
+  if (por)               brk_addr1 <=  16'h0000;
+  else if (brk_addr1_wr) brk_addr1 <=  dbg_din;
+
+   
+//============================================================================
+// 3) DATA OUTPUT GENERATION
+//============================================================================
+
+wire [15:0] brk_ctl_rd   = {8'h00, brk_ctl_full}  & {16{brk_reg_rd[BRK_CTL]}};
+wire [15:0] brk_stat_rd  = {8'h00, brk_stat_full} & {16{brk_reg_rd[BRK_STAT]}};
+wire [15:0] brk_addr0_rd = brk_addr0              & {16{brk_reg_rd[BRK_ADDR0]}};
+wire [15:0] brk_addr1_rd = brk_addr1              & {16{brk_reg_rd[BRK_ADDR1]}};
+
+wire [15:0] brk_dout = brk_ctl_rd   |
+                       brk_stat_rd  |
+                       brk_addr0_rd |
+                       brk_addr1_rd;
+
+   
+//============================================================================
+// 4) BREAKPOINT / WATCHPOINT GENERATION
+//============================================================================
+
+// Comparators
+//---------------------------
+// Note: here the comparison logic is instanciated several times in order
+//       to improve the timings, at the cost of a bit more area.
+   
+wire        equ_d_addr0 = eu_mb_en & (eu_mab==brk_addr0) & ~brk_ctl[`BRK_RANGE];
+wire        equ_d_addr1 = eu_mb_en & (eu_mab==brk_addr1) & ~brk_ctl[`BRK_RANGE];
+wire        equ_d_range = eu_mb_en & ((eu_mab>=brk_addr0) & (eu_mab<=brk_addr1)) & 
+                          brk_ctl[`BRK_RANGE] & `HWBRK_RANGE;
+
+reg         fe_mb_en_buf;
+always @ (posedge mclk or posedge por)
+  if (por)  fe_mb_en_buf <=  1'b0;
+  else      fe_mb_en_buf <=  fe_mb_en;
+
+wire        equ_i_addr0 = fe_mb_en_buf & (pc==brk_addr0) & ~brk_ctl[`BRK_RANGE];
+wire        equ_i_addr1 = fe_mb_en_buf & (pc==brk_addr1) & ~brk_ctl[`BRK_RANGE];
+wire        equ_i_range = fe_mb_en_buf & ((pc>=brk_addr0) & (pc<=brk_addr1)) &
+                          brk_ctl[`BRK_RANGE] & `HWBRK_RANGE;
+
+
+// Detect accesses
+//---------------------------
+
+// Detect Instruction read access
+wire i_addr0_rd =  equ_i_addr0 &  brk_ctl[`BRK_I_EN];
+wire i_addr1_rd =  equ_i_addr1 &  brk_ctl[`BRK_I_EN];
+wire i_range_rd =  equ_i_range &  brk_ctl[`BRK_I_EN];
+
+// Detect Execution-Unit write access
+wire d_addr0_wr =  equ_d_addr0 & ~brk_ctl[`BRK_I_EN] &  |eu_mb_wr;
+wire d_addr1_wr =  equ_d_addr1 & ~brk_ctl[`BRK_I_EN] &  |eu_mb_wr;
+wire d_range_wr =  equ_d_range & ~brk_ctl[`BRK_I_EN] &  |eu_mb_wr;
+
+// Detect DATA read access
+// Whenever an "ADD r9. &0x200" instruction is executed, &0x200 will be read
+// before being written back. In that case, the read flag should not be set.
+// In general, We should here make sure no write access occures during the
+// same instruction cycle before setting the read flag.
+reg [2:0] d_rd_trig;
+always @ (posedge mclk or posedge por)
+  if (por)            d_rd_trig <=  3'h0;
+  else if (exec_done) d_rd_trig <=  3'h0;
+  else                d_rd_trig <=  {equ_d_range & ~brk_ctl[`BRK_I_EN] & ~|eu_mb_wr,
+                                     equ_d_addr1 & ~brk_ctl[`BRK_I_EN] & ~|eu_mb_wr,
+                                     equ_d_addr0 & ~brk_ctl[`BRK_I_EN] & ~|eu_mb_wr};
+   
+wire d_addr0_rd =  d_rd_trig[0] & exec_done & ~d_addr0_wr;
+wire d_addr1_rd =  d_rd_trig[1] & exec_done & ~d_addr1_wr;
+wire d_range_rd =  d_rd_trig[2] & exec_done & ~d_range_wr;
+
+
+// Set flags
+assign addr0_rd_set = brk_ctl[`BRK_MODE_RD] & (d_addr0_rd  | i_addr0_rd);
+assign addr0_wr_set = brk_ctl[`BRK_MODE_WR] &  d_addr0_wr;
+assign addr1_rd_set = brk_ctl[`BRK_MODE_RD] & (d_addr1_rd  | i_addr1_rd);
+assign addr1_wr_set = brk_ctl[`BRK_MODE_WR] &  d_addr1_wr;
+assign range_rd_set = brk_ctl[`BRK_MODE_RD] & (d_range_rd  | i_range_rd);
+assign range_wr_set = brk_ctl[`BRK_MODE_WR] &  d_range_wr;
+
+   
+// Break CPU
+assign brk_halt     = brk_ctl[`BRK_EN] & |brk_stat_set;
+   
+     
+endmodule // omsp_dbg_hwbrk
+
+`include "openMSP430_undefines.v"
diff --git a/omsp_dbg_uart.v b/omsp_dbg_uart.v
new file mode 100644 (file)
index 0000000..e52b2b5
--- /dev/null
@@ -0,0 +1,268 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2001 Authors
+//
+// This source file may be used and distributed without restriction provided
+// that this copyright statement is not removed from the file and that any
+// derivative work contains the original copyright notice and the associated
+// disclaimer.
+//
+// This source file is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// This source is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+// License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this source; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+//----------------------------------------------------------------------------
+//
+// *File Name: omsp_dbg_uart.v
+// 
+// *Module Description:
+//                       Debug UART communication interface (8N1, Half-duplex)
+//
+// *Author(s):
+//              - Olivier Girard,    olgirard@gmail.com
+//
+//----------------------------------------------------------------------------
+// $Rev: 74 $
+// $LastChangedBy: olivier.girard $
+// $LastChangedDate: 2010-08-28 21:53:08 +0200 (Sat, 28 Aug 2010) $
+//----------------------------------------------------------------------------
+`include "timescale.v"
+`include "openMSP430_defines.v"
+
+module  omsp_dbg_uart (
+
+// OUTPUTs
+    dbg_addr,                       // Debug register address
+    dbg_din,                        // Debug register data input
+    dbg_rd,                         // Debug register data read
+    dbg_uart_txd,                   // Debug interface: UART TXD
+    dbg_wr,                         // Debug register data write
+                            
+// INPUTs
+    dbg_dout,                       // Debug register data output
+    dbg_rd_rdy,                     // Debug register data is ready for read
+    dbg_uart_rxd,                   // Debug interface: UART RXD
+    mclk,                           // Main system clock
+    mem_burst,                      // Burst on going
+    mem_burst_end,                  // End TX/RX burst
+    mem_burst_rd,                   // Start TX burst
+    mem_burst_wr,                   // Start RX burst
+    mem_bw,                         // Burst byte width
+    por                             // Power on reset
+);
+
+// OUTPUTs
+//=========
+output        [5:0] dbg_addr;       // Debug register address
+output       [15:0] dbg_din;        // Debug register data input
+output              dbg_rd;         // Debug register data read
+output              dbg_uart_txd;   // Debug interface: UART TXD
+output              dbg_wr;         // Debug register data write
+
+// INPUTs
+//=========
+input        [15:0] dbg_dout;       // Debug register data output
+input               dbg_rd_rdy;     // Debug register data is ready for read
+input               dbg_uart_rxd;   // Debug interface: UART RXD
+input               mclk;           // Main system clock
+input               mem_burst;      // Burst on going
+input               mem_burst_end;  // End TX/RX burst
+input               mem_burst_rd;   // Start TX burst
+input               mem_burst_wr;   // Start RX burst
+input               mem_bw;         // Burst byte width
+input               por;            // Power on reset
+
+
+//=============================================================================
+// 1)  UART RECEIVE LINE SYNCHRONIZTION & FILTERING
+//=============================================================================
+
+// Synchronize RXD input & buffer
+//--------------------------------
+reg  [3:0] rxd_sync;
+always @ (posedge mclk or posedge por)
+  if (por) rxd_sync <=  4'h0;
+  else     rxd_sync <=  {rxd_sync[2:0], dbg_uart_rxd};
+
+// Majority decision
+//------------------------
+reg        rxd_maj;
+
+wire [1:0] rxd_maj_cnt = {1'b0, rxd_sync[1]} +
+                         {1'b0, rxd_sync[2]} +
+                         {1'b0, rxd_sync[3]};
+wire       rxd_maj_nxt = (rxd_maj_cnt>=2'b10);
+   
+always @ (posedge mclk or posedge por)
+  if (por) rxd_maj <=  1'b0;
+  else     rxd_maj <=  rxd_maj_nxt;
+
+wire rxd_s  =  rxd_maj;
+wire rxd_fe =  rxd_maj & ~rxd_maj_nxt;
+wire rxd_re = ~rxd_maj &  rxd_maj_nxt;
+
+   
+//=============================================================================
+// 2)  UART STATE MACHINE
+//=============================================================================
+
+// Receive state
+//------------------------
+reg  [2:0] uart_state;
+reg  [2:0] uart_state_nxt;
+
+wire       sync_done;
+wire       xfer_done;
+reg [19:0] xfer_buf;
+
+// State machine definition
+parameter  RX_SYNC  = 3'h0;
+parameter  RX_CMD   = 3'h1;
+parameter  RX_DATA1 = 3'h2;
+parameter  RX_DATA2 = 3'h3;
+parameter  TX_DATA1 = 3'h4;
+parameter  TX_DATA2 = 3'h5;
+
+// State transition
+always @(uart_state or xfer_buf or mem_burst or mem_burst_wr or mem_burst_rd or mem_burst_end or mem_bw)
+  case (uart_state)
+    RX_SYNC  : uart_state_nxt =  RX_CMD;
+    RX_CMD   : uart_state_nxt =  mem_burst_wr                ?
+                                (mem_bw                      ? RX_DATA2 : RX_DATA1) :
+                                 mem_burst_rd                ?
+                                (mem_bw                      ? TX_DATA2 : TX_DATA1) :
+                                (xfer_buf[`DBG_UART_WR]      ?
+                                (xfer_buf[`DBG_UART_BW]      ? RX_DATA2 : RX_DATA1) :
+                                (xfer_buf[`DBG_UART_BW]      ? TX_DATA2 : TX_DATA1));
+    RX_DATA1 : uart_state_nxt =  RX_DATA2;
+    RX_DATA2 : uart_state_nxt = (mem_burst & ~mem_burst_end) ?
+                                (mem_bw                      ? RX_DATA2 : RX_DATA1) :
+                                 RX_CMD;
+    TX_DATA1 : uart_state_nxt =  TX_DATA2;
+    TX_DATA2 : uart_state_nxt = (mem_burst & ~mem_burst_end) ?
+                                (mem_bw                      ? TX_DATA2 : TX_DATA1) :
+                                 RX_CMD;
+    default  : uart_state_nxt =  RX_CMD;
+  endcase
+   
+// State machine
+always @(posedge mclk or posedge por)
+  if (por)                              uart_state <= RX_SYNC;
+  else if (xfer_done    | sync_done |
+           mem_burst_wr | mem_burst_rd) uart_state <= uart_state_nxt;
+
+// Utility signals
+wire cmd_valid = (uart_state==RX_CMD) & xfer_done;
+wire tx_active = (uart_state==TX_DATA1) | (uart_state==TX_DATA2);
+
+   
+//=============================================================================
+// 3)  UART SYNCHRONIZATION
+//=============================================================================
+// After POR, the host needs to fist send a synchronization character (0x80)
+// If this feature doesn't work properly, it is possible to disable it by
+// commenting the DBG_UART_AUTO_SYNC define in the openMSP430.inc file.
+
+reg        sync_busy;
+always @ (posedge mclk or posedge por)
+  if (por)                                 sync_busy <=  1'b0;
+  else if ((uart_state==RX_SYNC) & rxd_fe) sync_busy <=  1'b1;
+  else if ((uart_state==RX_SYNC) & rxd_re) sync_busy <=  1'b0;
+
+assign sync_done =  (uart_state==RX_SYNC) & rxd_re & sync_busy;
+
+`ifdef DBG_UART_AUTO_SYNC
+
+reg [`DBG_UART_XFER_CNT_W+2:0] sync_cnt;
+always @ (posedge mclk or posedge por)
+  if (por)            sync_cnt <=  {{`DBG_UART_XFER_CNT_W{1'b1}}, 3'b000};
+  else if (sync_busy) sync_cnt <=  sync_cnt+{{`DBG_UART_XFER_CNT_W+2{1'b0}}, 1'b1};
+
+wire [`DBG_UART_XFER_CNT_W-1:0] bit_cnt_max = sync_cnt[`DBG_UART_XFER_CNT_W+2:3];
+`else
+wire [`DBG_UART_XFER_CNT_W-1:0] bit_cnt_max = `DBG_UART_CNT;
+`endif
+   
+   
+//=============================================================================
+// 4)  UART RECEIVE / TRANSMIT
+//=============================================================================
+   
+// Transfer counter
+//------------------------
+reg                      [3:0] xfer_bit;
+reg [`DBG_UART_XFER_CNT_W-1:0] xfer_cnt;
+
+wire       txd_start    = dbg_rd_rdy | (xfer_done & (uart_state==TX_DATA1));
+wire       rxd_start    = (xfer_bit==4'h0) & rxd_fe & ((uart_state!=RX_SYNC));
+wire       xfer_bit_inc = (xfer_bit!=4'h0) & (xfer_cnt=={`DBG_UART_XFER_CNT_W{1'b0}});
+assign     xfer_done    = (xfer_bit==4'hb);
+   
+always @ (posedge mclk or posedge por)
+  if (por)                           xfer_bit <=  4'h0;
+  else if (txd_start | rxd_start)    xfer_bit <=  4'h1;
+  else if (xfer_done)                xfer_bit <=  4'h0;
+  else if (xfer_bit_inc)             xfer_bit <=  xfer_bit+4'h1;
+
+always @ (posedge mclk or posedge por)
+  if (por)                           xfer_cnt <=  {`DBG_UART_XFER_CNT_W{1'b0}};
+  else if (rxd_start)                xfer_cnt <=  {1'b0, bit_cnt_max[`DBG_UART_XFER_CNT_W-1:1]};
+  else if (txd_start | xfer_bit_inc) xfer_cnt <=  bit_cnt_max;
+  else                               xfer_cnt <=  xfer_cnt+{`DBG_UART_XFER_CNT_W{1'b1}};
+
+
+// Receive/Transmit buffer
+//-------------------------
+wire [19:0] xfer_buf_nxt =  {rxd_s, xfer_buf[19:1]};
+
+always @ (posedge mclk or posedge por)
+  if (por)               xfer_buf <=  18'h00000;
+  else if (dbg_rd_rdy)   xfer_buf <=  {1'b1, dbg_dout[15:8], 2'b01, dbg_dout[7:0], 1'b0};
+  else if (xfer_bit_inc) xfer_buf <=  xfer_buf_nxt;
+
+
+// Generate TXD output
+//------------------------
+reg dbg_uart_txd;
+   
+always @ (posedge mclk or posedge por)
+  if (por)                           dbg_uart_txd <=  1'b1;
+  else if (xfer_bit_inc & tx_active) dbg_uart_txd <=  xfer_buf[0];
+
+//=============================================================================
+// 5) INTERFACE TO DEBUG REGISTERS
+//=============================================================================
+
+reg [5:0] dbg_addr;
+ always @ (posedge mclk or posedge por)
+  if (por)            dbg_addr <=  6'h00;
+  else if (cmd_valid) dbg_addr <=  xfer_buf[`DBG_UART_ADDR];
+
+reg       dbg_bw;
+always @ (posedge mclk or posedge por)
+  if (por)            dbg_bw   <=  1'b0;
+  else if (cmd_valid) dbg_bw   <=  xfer_buf[`DBG_UART_BW];
+
+wire        dbg_din_bw =  mem_burst  ? mem_bw : dbg_bw;
+
+wire [15:0] dbg_din    =  dbg_din_bw ? {8'h00,           xfer_buf[18:11]} :
+                                       {xfer_buf[18:11], xfer_buf[8:1]};
+wire        dbg_wr     = (xfer_done & (uart_state==RX_DATA2));
+wire        dbg_rd     = mem_burst ? (xfer_done & (uart_state==TX_DATA2)) :
+                                     (cmd_valid & ~xfer_buf[`DBG_UART_WR]) | mem_burst_rd;
+
+           
+   
+endmodule // omsp_dbg_uart
+
+`include "openMSP430_undefines.v"
diff --git a/omsp_execution_unit.v b/omsp_execution_unit.v
new file mode 100644 (file)
index 0000000..9404696
--- /dev/null
@@ -0,0 +1,367 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2001 Authors
+//
+// This source file may be used and distributed without restriction provided
+// that this copyright statement is not removed from the file and that any
+// derivative work contains the original copyright notice and the associated
+// disclaimer.
+//
+// This source file is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// This source is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+// License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this source; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+//----------------------------------------------------------------------------
+//
+// *File Name: omsp_execution_unit.v
+// 
+// *Module Description:
+//                       openMSP430 Execution unit
+//
+// *Author(s):
+//              - Olivier Girard,    olgirard@gmail.com
+//
+//----------------------------------------------------------------------------
+// $Rev: 34 $
+// $LastChangedBy: olivier.girard $
+// $LastChangedDate: 2009-12-29 20:10:34 +0100 (Tue, 29 Dec 2009) $
+//----------------------------------------------------------------------------
+`include "timescale.v"
+`include "openMSP430_defines.v"
+
+module  omsp_execution_unit (
+
+// OUTPUTs
+    cpuoff,                        // Turns off the CPU
+    dbg_reg_din,                   // Debug unit CPU register data input
+    gie,                           // General interrupt enable
+    mab,                           // Memory address bus
+    mb_en,                         // Memory bus enable
+    mb_wr,                         // Memory bus write transfer
+    mdb_out,                       // Memory data bus output
+    oscoff,                        // Turns off LFXT1 clock input
+    pc_sw,                         // Program counter software value
+    pc_sw_wr,                      // Program counter software write
+    scg1,                          // System clock generator 1. Turns off the SMCLK
+
+// INPUTs
+    dbg_halt_st,                   // Halt/Run status from CPU
+    dbg_mem_dout,                  // Debug unit data output
+    dbg_reg_wr,                    // Debug unit CPU register write
+    e_state,                       // Execution state
+    exec_done,                     // Execution completed
+    inst_ad,                       // Decoded Inst: destination addressing mode
+    inst_as,                       // Decoded Inst: source addressing mode
+    inst_alu,                      // ALU control signals
+    inst_bw,                       // Decoded Inst: byte width
+    inst_dest,                     // Decoded Inst: destination (one hot)
+    inst_dext,                     // Decoded Inst: destination extended instruction word
+    inst_irq_rst,                  // Decoded Inst: reset interrupt
+    inst_jmp,                      // Decoded Inst: Conditional jump
+    inst_sext,                     // Decoded Inst: source extended instruction word
+    inst_so,                       // Decoded Inst: Single-operand arithmetic
+    inst_src,                      // Decoded Inst: source (one hot)
+    inst_type,                     // Decoded Instruction type
+    mclk,                          // Main system clock
+    mdb_in,                        // Memory data bus input
+    pc,                            // Program counter
+    pc_nxt,                        // Next PC value (for CALL & IRQ)
+    puc                            // Main system reset
+);
+
+// OUTPUTs
+//=========
+output                     cpuoff;        // Turns off the CPU
+output       [15:0] dbg_reg_din;   // Debug unit CPU register data input
+output                     gie;           // General interrupt enable
+output       [15:0] mab;           // Memory address bus
+output              mb_en;         // Memory bus enable
+output        [1:0] mb_wr;         // Memory bus write transfer
+output       [15:0] mdb_out;       // Memory data bus output
+output                     oscoff;        // Turns off LFXT1 clock input
+output       [15:0] pc_sw;         // Program counter software value
+output              pc_sw_wr;      // Program counter software write
+output              scg1;          // System clock generator 1. Turns off the SMCLK
+
+// INPUTs
+//=========
+input               dbg_halt_st;   // Halt/Run status from CPU
+input        [15:0] dbg_mem_dout;  // Debug unit data output
+input               dbg_reg_wr;    // Debug unit CPU register write
+input         [3:0] e_state;       // Execution state
+input               exec_done;     // Execution completed
+input         [7:0] inst_ad;       // Decoded Inst: destination addressing mode
+input         [7:0] inst_as;       // Decoded Inst: source addressing mode
+input        [11:0] inst_alu;      // ALU control signals
+input               inst_bw;       // Decoded Inst: byte width
+input        [15:0] inst_dest;     // Decoded Inst: destination (one hot)
+input        [15:0] inst_dext;     // Decoded Inst: destination extended instruction word
+input               inst_irq_rst;  // Decoded Inst: reset interrupt
+input         [7:0] inst_jmp;      // Decoded Inst: Conditional jump
+input        [15:0] inst_sext;     // Decoded Inst: source extended instruction word
+input         [7:0] inst_so;       // Decoded Inst: Single-operand arithmetic
+input        [15:0] inst_src;      // Decoded Inst: source (one hot)
+input         [2:0] inst_type;     // Decoded Instruction type
+input               mclk;          // Main system clock
+input        [15:0] mdb_in;        // Memory data bus input
+input        [15:0] pc;            // Program counter
+input        [15:0] pc_nxt;        // Next PC value (for CALL & IRQ)
+input               puc;           // Main system reset
+
+
+//=============================================================================
+// 1)  INTERNAL WIRES/REGISTERS/PARAMETERS DECLARATION
+//=============================================================================
+
+wire         [15:0] alu_out;
+wire         [15:0] alu_out_add;
+wire          [3:0] alu_stat;
+wire          [3:0] alu_stat_wr;
+wire         [15:0] op_dst;
+wire         [15:0] op_src;
+wire         [15:0] reg_dest;
+wire         [15:0] reg_src;
+wire         [15:0] mdb_in_bw;
+wire         [15:0] mdb_in_val;
+wire          [3:0] status;
+
+
+//=============================================================================
+// 2)  REGISTER FILE
+//=============================================================================
+
+wire reg_dest_wr  = ((e_state==`E_EXEC) & (
+                     (inst_type[`INST_TO] & inst_ad[`DIR] & ~inst_alu[`EXEC_NO_WR])  |
+                     (inst_type[`INST_SO] & inst_as[`DIR] & ~(inst_so[`PUSH] | inst_so[`CALL] | inst_so[`RETI])) |
+                      inst_type[`INST_JMP])) | dbg_reg_wr;
+
+wire reg_sp_wr    = (((e_state==`E_IRQ_1) | (e_state==`E_IRQ_3)) & ~inst_irq_rst) |
+                     ((e_state==`E_DST_RD) & (inst_so[`PUSH] | inst_so[`CALL]));
+
+wire reg_sr_wr    =  (e_state==`E_DST_RD) & inst_so[`RETI];
+
+wire reg_sr_clr   =  (e_state==`E_IRQ_2);
+
+wire reg_pc_call  = ((e_state==`E_EXEC)   & inst_so[`CALL]) | 
+                    ((e_state==`E_DST_WR) & inst_so[`RETI]);
+
+wire reg_incr     =  (exec_done          & inst_as[`INDIR_I]) |
+                    ((e_state==`E_SRC_RD) & inst_so[`RETI])    |
+                    ((e_state==`E_EXEC)   & inst_so[`RETI]);
+
+assign dbg_reg_din = reg_dest;
+
+
+omsp_register_file register_file_0 (
+
+// OUTPUTs
+    .cpuoff       (cpuoff),       // Turns off the CPU
+    .gie          (gie),          // General interrupt enable
+    .oscoff       (oscoff),       // Turns off LFXT1 clock input
+    .pc_sw        (pc_sw),        // Program counter software value
+    .pc_sw_wr     (pc_sw_wr),     // Program counter software write
+    .reg_dest     (reg_dest),     // Selected register destination content
+    .reg_src      (reg_src),      // Selected register source content
+    .scg1         (scg1),         // System clock generator 1. Turns off the SMCLK
+    .status       (status),       // R2 Status {V,N,Z,C}
+
+// INPUTs
+    .alu_stat     (alu_stat),     // ALU Status {V,N,Z,C}
+    .alu_stat_wr  (alu_stat_wr),  // ALU Status write {V,N,Z,C}
+    .inst_bw      (inst_bw),      // Decoded Inst: byte width
+    .inst_dest    (inst_dest),    // Register destination selection
+    .inst_src     (inst_src),     // Register source selection
+    .mclk         (mclk),         // Main system clock
+    .pc           (pc),           // Program counter
+    .puc          (puc),          // Main system reset
+    .reg_dest_val (alu_out),      // Selected register destination value
+    .reg_dest_wr  (reg_dest_wr),  // Write selected register destination
+    .reg_pc_call  (reg_pc_call),  // Trigger PC update for a CALL instruction
+    .reg_sp_val   (alu_out_add),  // Stack Pointer next value
+    .reg_sp_wr    (reg_sp_wr),    // Stack Pointer write
+    .reg_sr_clr   (reg_sr_clr),   // Status register clear for interrupts
+    .reg_sr_wr    (reg_sr_wr),    // Status Register update for RETI instruction
+    .reg_incr     (reg_incr)      // Increment source register
+);
+
+
+//=============================================================================
+// 3)  SOURCE OPERAND MUXING
+//=============================================================================
+// inst_as[`DIR]    : Register direct.   -> Source is in register
+// inst_as[`IDX]    : Register indexed.  -> Source is in memory, address is register+offset
+// inst_as[`INDIR]  : Register indirect.
+// inst_as[`INDIR_I]: Register indirect autoincrement.
+// inst_as[`SYMB]   : Symbolic (operand is in memory at address PC+x).
+// inst_as[`IMM]    : Immediate (operand is next word in the instruction stream).
+// inst_as[`ABS]    : Absolute (operand is in memory at address x).
+// inst_as[`CONST]  : Constant.
+
+wire src_reg_src_sel    =  (e_state==`E_IRQ_0)                    |
+                           (e_state==`E_IRQ_2)                    |
+                          ((e_state==`E_SRC_RD) & ~inst_as[`ABS]) |
+                          ((e_state==`E_SRC_WR) & ~inst_as[`ABS]) |
+                          ((e_state==`E_EXEC)   &  inst_as[`DIR] & ~inst_type[`INST_JMP]);
+
+wire src_reg_dest_sel   =  (e_state==`E_IRQ_1)                    |
+                           (e_state==`E_IRQ_3)                    |
+                          ((e_state==`E_DST_RD) & (inst_so[`PUSH] | inst_so[`CALL]));
+
+wire src_mdb_in_val_sel = ((e_state==`E_DST_RD) &  inst_so[`RETI])                     |
+                          ((e_state==`E_EXEC)   & (inst_as[`INDIR] | inst_as[`INDIR_I] |
+                                                   inst_as[`IDX]   | inst_as[`SYMB]    |
+                                                   inst_as[`ABS]));
+
+wire src_inst_dext_sel =  ((e_state==`E_DST_RD) & ~(inst_so[`PUSH] | inst_so[`CALL])) |
+                          ((e_state==`E_DST_WR) & ~(inst_so[`PUSH] | inst_so[`CALL]   |
+                                                    inst_so[`RETI]));
+
+wire src_inst_sext_sel =  ((e_state==`E_EXEC)   &  (inst_type[`INST_JMP] | inst_as[`IMM] |
+                                                    inst_as[`CONST]      | inst_so[`RETI]));
+
+
+assign op_src = src_reg_src_sel     ?  reg_src    :
+                src_reg_dest_sel    ?  reg_dest   :
+                src_mdb_in_val_sel  ?  mdb_in_val :
+                src_inst_dext_sel   ?  inst_dext  :
+                src_inst_sext_sel   ?  inst_sext  : 16'h0000;
+
+
+//=============================================================================
+// 4)  DESTINATION OPERAND MUXING
+//=============================================================================
+// inst_ad[`DIR]    : Register direct.
+// inst_ad[`IDX]    : Register indexed.
+// inst_ad[`SYMB]   : Symbolic (operand is in memory at address PC+x).
+// inst_ad[`ABS]    : Absolute (operand is in memory at address x).
+
+
+wire dst_inst_sext_sel  = ((e_state==`E_SRC_RD) & (inst_as[`IDX] | inst_as[`SYMB] |
+                                                   inst_as[`ABS]))                |
+                          ((e_state==`E_SRC_WR) & (inst_as[`IDX] | inst_as[`SYMB] |
+                                                   inst_as[`ABS]));
+
+wire dst_mdb_in_bw_sel  = ((e_state==`E_DST_WR) &   inst_so[`RETI]) |
+                          ((e_state==`E_EXEC)   & ~(inst_ad[`DIR] | inst_type[`INST_JMP] |
+                                                    inst_type[`INST_SO]) & ~inst_so[`RETI]);
+
+wire dst_fffe_sel       =  (e_state==`E_IRQ_0)  |
+                           (e_state==`E_IRQ_1)  |
+                           (e_state==`E_IRQ_3)  |
+                          ((e_state==`E_DST_RD) & (inst_so[`PUSH] | inst_so[`CALL]) & ~inst_so[`RETI]);
+
+wire dst_reg_dest_sel   = ((e_state==`E_DST_RD) & ~(inst_so[`PUSH] | inst_so[`CALL] | inst_ad[`ABS] | inst_so[`RETI])) |
+                          ((e_state==`E_DST_WR) &  ~inst_ad[`ABS]) |
+                          ((e_state==`E_EXEC)   &  (inst_ad[`DIR] | inst_type[`INST_JMP] |
+                                                    inst_type[`INST_SO]) & ~inst_so[`RETI]);
+
+
+assign op_dst = dbg_halt_st        ? dbg_mem_dout  :
+                dst_inst_sext_sel  ? inst_sext     :
+                dst_mdb_in_bw_sel  ? mdb_in_bw     :
+                dst_reg_dest_sel   ? reg_dest      :
+                dst_fffe_sel       ? 16'hfffe      : 16'h0000;
+
+
+//=============================================================================
+// 5)  ALU
+//=============================================================================
+
+wire exec_cycle = (e_state==`E_EXEC);
+
+omsp_alu alu_0 (
+
+// OUTPUTs
+    .alu_out      (alu_out),      // ALU output value
+    .alu_out_add  (alu_out_add),  // ALU adder output value
+    .alu_stat     (alu_stat),     // ALU Status {V,N,Z,C}
+    .alu_stat_wr  (alu_stat_wr),  // ALU Status write {V,N,Z,C}
+
+// INPUTs
+    .dbg_halt_st  (dbg_halt_st),  // Halt/Run status from CPU
+    .exec_cycle   (exec_cycle),   // Instruction execution cycle
+    .inst_alu     (inst_alu),     // ALU control signals
+    .inst_bw      (inst_bw),      // Decoded Inst: byte width
+    .inst_jmp     (inst_jmp),     // Decoded Inst: Conditional jump
+    .inst_so      (inst_so),      // Single-operand arithmetic
+    .op_dst       (op_dst),       // Destination operand
+    .op_src       (op_src),       // Source operand
+    .status       (status)        // R2 Status {V,N,Z,C}
+);
+
+
+//=============================================================================
+// 6)  MEMORY INTERFACE
+//=============================================================================
+
+// Detect memory read/write access
+assign      mb_en     = ((e_state==`E_IRQ_1)  & ~inst_irq_rst)      |
+                        ((e_state==`E_IRQ_3)  & ~inst_irq_rst)      |
+                        ((e_state==`E_SRC_RD) & ~inst_as[`IMM])     |
+                         (e_state==`E_SRC_WR)                       |
+                        ((e_state==`E_EXEC)   & inst_so[`RETI])     |
+                         (e_state==`E_DST_RD)                       |
+                         (e_state==`E_DST_WR);
+
+wire  [1:0] mb_wr_msk =  inst_alu[`EXEC_NO_WR]  ? 2'b00 :
+                        ~inst_bw                ? 2'b11 :
+                         alu_out_add[0]         ? 2'b10 : 2'b01;
+assign      mb_wr     = ({2{(e_state==`E_IRQ_1)}}  |
+                         {2{(e_state==`E_IRQ_3)}}  |
+                         {2{(e_state==`E_DST_WR)}} |
+                         {2{(e_state==`E_SRC_WR)}}) & mb_wr_msk;
+
+// Memory address bus
+assign      mab       = alu_out_add[15:0];
+
+// Memory data bus output
+reg  [15:0] mdb_out_nxt;
+always @(posedge mclk or posedge puc)
+  if (puc)                                            mdb_out_nxt <= 16'h0000;
+  else if (e_state==`E_DST_RD)                        mdb_out_nxt <= pc_nxt;
+  else if ((e_state==`E_EXEC & ~inst_so[`CALL]) |
+           (e_state==`E_IRQ_0) | (e_state==`E_IRQ_2)) mdb_out_nxt <= alu_out;
+
+assign      mdb_out = inst_bw ? {2{mdb_out_nxt[7:0]}} : mdb_out_nxt;
+
+// Format memory data bus input depending on BW
+reg        mab_lsb;
+always @(posedge mclk or posedge puc)
+  if (puc)        mab_lsb <= 1'b0;
+  else if (mb_en) mab_lsb <= alu_out_add[0];
+
+assign mdb_in_bw  = ~inst_bw ? mdb_in :
+                     mab_lsb ? {2{mdb_in[15:8]}} : mdb_in;
+
+// Memory data bus input buffer (buffer after a source read)
+reg         mdb_in_buf_en;
+always @(posedge mclk or posedge puc)
+  if (puc)  mdb_in_buf_en <= 1'b0;
+  else      mdb_in_buf_en <= (e_state==`E_SRC_RD);
+
+reg         mdb_in_buf_valid;
+always @(posedge mclk or posedge puc)
+  if (puc)                   mdb_in_buf_valid <= 1'b0;
+  else if (e_state==`E_EXEC) mdb_in_buf_valid <= 1'b0;
+  else if (mdb_in_buf_en)    mdb_in_buf_valid <= 1'b1;
+
+reg  [15:0] mdb_in_buf;
+always @(posedge mclk or posedge puc)
+  if (puc)                mdb_in_buf <= 16'h0000;
+  else if (mdb_in_buf_en) mdb_in_buf <= mdb_in_bw;
+
+assign mdb_in_val = mdb_in_buf_valid ? mdb_in_buf : mdb_in_bw;
+
+
+endmodule // omsp_execution_unit
+
+`include "openMSP430_undefines.v"
diff --git a/omsp_frontend.v b/omsp_frontend.v
new file mode 100644 (file)
index 0000000..8545812
--- /dev/null
@@ -0,0 +1,754 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2001 Authors
+//
+// This source file may be used and distributed without restriction provided
+// that this copyright statement is not removed from the file and that any
+// derivative work contains the original copyright notice and the associated
+// disclaimer.
+//
+// This source file is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// This source is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+// License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this source; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+//----------------------------------------------------------------------------
+//
+// *File Name: omsp_frontend.v
+// 
+// *Module Description:
+//                       openMSP430 Instruction fetch and decode unit
+//
+// *Author(s):
+//              - Olivier Girard,    olgirard@gmail.com
+//
+//----------------------------------------------------------------------------
+// $Rev: 60 $
+// $LastChangedBy: olivier.girard $
+// $LastChangedDate: 2010-02-03 22:12:25 +0100 (Wed, 03 Feb 2010) $
+//----------------------------------------------------------------------------
+`include "timescale.v"
+`include "openMSP430_defines.v"
+
+module  omsp_frontend (
+
+// OUTPUTs
+    dbg_halt_st,                   // Halt/Run status from CPU
+    decode_noirq,                  // Frontend decode instruction
+    e_state,                       // Execution state
+    exec_done,                     // Execution completed
+    inst_ad,                       // Decoded Inst: destination addressing mode
+    inst_as,                       // Decoded Inst: source addressing mode
+    inst_alu,                      // ALU control signals
+    inst_bw,                       // Decoded Inst: byte width
+    inst_dest,                     // Decoded Inst: destination (one hot)
+    inst_dext,                     // Decoded Inst: destination extended instruction word
+    inst_irq_rst,                  // Decoded Inst: Reset interrupt
+    inst_jmp,                      // Decoded Inst: Conditional jump
+    inst_sext,                     // Decoded Inst: source extended instruction word
+    inst_so,                       // Decoded Inst: Single-operand arithmetic
+    inst_src,                      // Decoded Inst: source (one hot)
+    inst_type,                     // Decoded Instruction type
+    irq_acc,                       // Interrupt request accepted (one-hot signal)
+    mab,                           // Frontend Memory address bus
+    mb_en,                         // Frontend Memory bus enable
+    nmi_acc,                       // Non-Maskable interrupt request accepted
+    pc,                            // Program counter
+    pc_nxt,                        // Next PC value (for CALL & IRQ)
+
+// INPUTs
+    cpuoff,                        // Turns off the CPU
+    dbg_halt_cmd,                  // Halt CPU command
+    dbg_reg_sel,                   // Debug selected register for rd/wr access
+    fe_pmem_wait,                  // Frontend wait for Instruction fetch
+    gie,                           // General interrupt enable
+    irq,                           // Maskable interrupts
+    mclk,                          // Main system clock
+    mdb_in,                        // Frontend Memory data bus input
+    nmi_evt,                       // Non-maskable interrupt event
+    pc_sw,                         // Program counter software value
+    pc_sw_wr,                      // Program counter software write
+    puc,                           // Main system reset
+    wdt_irq                        // Watchdog-timer interrupt
+);
+
+// OUTPUTs
+//=========
+output              dbg_halt_st;   // Halt/Run status from CPU
+output              decode_noirq;  // Frontend decode instruction
+output        [3:0] e_state;       // Execution state
+output              exec_done;     // Execution completed
+output        [7:0] inst_ad;       // Decoded Inst: destination addressing mode
+output        [7:0] inst_as;       // Decoded Inst: source addressing mode
+output       [11:0] inst_alu;      // ALU control signals
+output              inst_bw;       // Decoded Inst: byte width
+output       [15:0] inst_dest;     // Decoded Inst: destination (one hot)
+output       [15:0] inst_dext;     // Decoded Inst: destination extended instruction word
+output              inst_irq_rst;  // Decoded Inst: Reset interrupt
+output        [7:0] inst_jmp;      // Decoded Inst: Conditional jump
+output       [15:0] inst_sext;     // Decoded Inst: source extended instruction word
+output        [7:0] inst_so;       // Decoded Inst: Single-operand arithmetic
+output       [15:0] inst_src;      // Decoded Inst: source (one hot)
+output        [2:0] inst_type;     // Decoded Instruction type
+output       [13:0] irq_acc;       // Interrupt request accepted (one-hot signal)
+output       [15:0] mab;           // Frontend Memory address bus
+output              mb_en;         // Frontend Memory bus enable
+output              nmi_acc;       // Non-Maskable interrupt request accepted
+output       [15:0] pc;            // Program counter
+output       [15:0] pc_nxt;        // Next PC value (for CALL & IRQ)
+
+// INPUTs
+//=========
+input               cpuoff;        // Turns off the CPU
+input               dbg_halt_cmd;  // Halt CPU command
+input         [3:0] dbg_reg_sel;   // Debug selected register for rd/wr access
+input               fe_pmem_wait;  // Frontend wait for Instruction fetch
+input              gie;           // General interrupt enable
+input       [13:0] irq;           // Maskable interrupts
+input               mclk;          // Main system clock
+input        [15:0] mdb_in;        // Frontend Memory data bus input
+input              nmi_evt;       // Non-maskable interrupt event
+input        [15:0] pc_sw;         // Program counter software value
+input               pc_sw_wr;      // Program counter software write
+input               puc;           // Main system reset
+input               wdt_irq;       // Watchdog-timer interrupt
+
+
+//=============================================================================
+// 1)  FRONTEND STATE MACHINE
+//=============================================================================
+
+// The wire "conv" is used as state bits to calculate the next response
+reg  [2:0] i_state;
+reg  [2:0] i_state_nxt;
+
+reg  [1:0] inst_sz;
+wire [1:0] inst_sz_nxt;
+wire       irq_detect;
+wire [2:0] inst_type_nxt;
+wire       is_const;
+reg [15:0] sconst_nxt;
+reg  [3:0] e_state_nxt;
+          
+// State machine definitons
+parameter I_IRQ_FETCH = 3'h0;
+parameter I_IRQ_DONE  = 3'h1;
+parameter I_DEC       = 3'h2; // New instruction ready for decode
+parameter I_EXT1      = 3'h3; // 1st Extension word
+parameter I_EXT2      = 3'h4; // 2nd Extension word
+parameter I_IDLE      = 3'h5; // CPU is in IDLE mode
+
+// States Transitions
+always @(i_state   or inst_sz    or inst_sz_nxt or pc_sw_wr     or exec_done or
+         exec_done or irq_detect or cpuoff      or dbg_halt_cmd or e_state)
+    case(i_state)
+      I_IDLE     : i_state_nxt = (irq_detect & ~dbg_halt_cmd) ? I_IRQ_FETCH :
+                                 (~cpuoff    & ~dbg_halt_cmd) ? I_DEC       : I_IDLE;
+      I_IRQ_FETCH: i_state_nxt =  I_IRQ_DONE;
+      I_IRQ_DONE : i_state_nxt =  I_DEC;
+      I_DEC      : i_state_nxt =  irq_detect                  ? I_IRQ_FETCH :
+                          (cpuoff | dbg_halt_cmd) & exec_done ? I_IDLE      :
+                            dbg_halt_cmd & (e_state==`E_IDLE) ? I_IDLE      :
+                                  pc_sw_wr                    ? I_DEC       :
+                            ~exec_done & ~(e_state==`E_IDLE) ? I_DEC       :        // Wait in decode state
+                                  (inst_sz_nxt!=2'b00)        ? I_EXT1      : I_DEC; // until execution is completed
+      I_EXT1     : i_state_nxt =  irq_detect                  ? I_IRQ_FETCH :
+                                  pc_sw_wr                    ? I_DEC       : 
+                                  (inst_sz!=2'b01)            ? I_EXT2      : I_DEC;
+      I_EXT2     : i_state_nxt =  irq_detect                  ? I_IRQ_FETCH : I_DEC;
+      default    : i_state_nxt =  I_IRQ_FETCH;
+    endcase
+
+// State machine
+always @(posedge mclk or posedge puc)
+  if (puc) i_state  <= I_IRQ_FETCH;
+  else     i_state  <= i_state_nxt;
+
+// Utility signals
+wire   decode_noirq =  ((i_state==I_DEC) &  (exec_done | (e_state==`E_IDLE)));
+wire   decode       =  decode_noirq | irq_detect;
+wire   fetch        = ~((i_state==I_DEC) & ~(exec_done | (e_state==`E_IDLE))) & ~(e_state_nxt==`E_IDLE);
+
+// Debug interface cpu status
+reg    dbg_halt_st;
+always @(posedge mclk or posedge puc)
+  if (puc)  dbg_halt_st <= 1'b0;
+  else      dbg_halt_st <= dbg_halt_cmd & (i_state_nxt==I_IDLE);
+
+
+//=============================================================================
+// 2)  INTERRUPT HANDLING
+//=============================================================================
+
+// Detect nmi interrupt
+reg         inst_nmi;
+always @(posedge mclk or posedge puc)
+  if (puc)                      inst_nmi <= 1'b0;
+  else if (nmi_evt)             inst_nmi <= 1'b1;
+  else if (i_state==I_IRQ_DONE) inst_nmi <= 1'b0;
+
+
+// Detect reset interrupt
+reg         inst_irq_rst;
+always @(posedge mclk or posedge puc)
+  if (puc)                      inst_irq_rst <= 1'b1;
+  else if (exec_done)           inst_irq_rst <= 1'b0;
+
+//  Detect other interrupts
+assign  irq_detect = (inst_nmi | ((|irq | wdt_irq) & gie)) & ~dbg_halt_cmd & (exec_done | (i_state==I_IDLE));
+
+// Select interrupt vector
+reg  [3:0] irq_num;
+always @(posedge mclk or posedge puc)
+  if (puc)             irq_num <= 4'hf;
+  else if (irq_detect) irq_num <= inst_nmi           ?  4'he :
+                                  irq[13]            ?  4'hd :
+                                  irq[12]            ?  4'hc :
+                                  irq[11]            ?  4'hb :
+                                 (irq[10] | wdt_irq) ?  4'ha :
+                                  irq[9]             ?  4'h9 :
+                                  irq[8]             ?  4'h8 :
+                                  irq[7]             ?  4'h7 :
+                                  irq[6]             ?  4'h6 :
+                                  irq[5]             ?  4'h5 :
+                                  irq[4]             ?  4'h4 :
+                                  irq[3]             ?  4'h3 :
+                                  irq[2]             ?  4'h2 :
+                                  irq[1]             ?  4'h1 :
+                                  irq[0]             ?  4'h0 : 4'hf;
+
+wire [15:0] irq_addr    = {11'h7ff, irq_num, 1'b0};
+
+// Interrupt request accepted
+wire [15:0] irq_acc_all = (16'h0001 << irq_num) & {16{(i_state==I_IRQ_FETCH)}};
+wire [13:0] irq_acc     = irq_acc_all[13:0];
+wire        nmi_acc     = irq_acc_all[14];
+
+
+//=============================================================================
+// 3)  FETCH INSTRUCTION
+//=============================================================================
+
+//
+// 3.1) PROGRAM COUNTER & MEMORY INTERFACE
+//-----------------------------------------
+
+// Program counter
+reg  [15:0] pc;
+
+// Compute next PC value
+wire [15:0] pc_incr = pc + {14'h0000, fetch, 1'b0};
+wire [15:0] pc_nxt  = pc_sw_wr               ? pc_sw    :
+                      (i_state==I_IRQ_FETCH) ? irq_addr :
+                      (i_state==I_IRQ_DONE)  ? mdb_in   :  pc_incr;
+
+always @(posedge mclk or posedge puc)
+  if (puc)  pc <= 16'h0000;
+  else      pc <= pc_nxt;
+
+// Check if ROM has been busy in order to retry ROM access
+reg pmem_busy;
+always @(posedge mclk or posedge puc)
+  if (puc)  pmem_busy <= 16'h0000;
+  else      pmem_busy <= fe_pmem_wait;
+   
+// Memory interface
+wire [15:0] mab      = pc_nxt;
+wire        mb_en    = fetch | pc_sw_wr | (i_state==I_IRQ_FETCH) | pmem_busy | (dbg_halt_st & ~dbg_halt_cmd);
+
+
+//
+// 3.2) INSTRUCTION REGISTER
+//--------------------------------
+
+// Instruction register
+wire [15:0] ir  = mdb_in;
+
+// Detect if source extension word is required
+wire is_sext = (inst_as[`IDX] | inst_as[`SYMB] | inst_as[`ABS] | inst_as[`IMM]);
+
+// Detect if destination extension word is required
+wire is_dext = (inst_ad[`IDX] | inst_ad[`SYMB] | inst_ad[`ABS]);
+
+// For the Symbolic addressing mode, add -2 to the extension word in order
+// to make up for the PC address
+wire [15:0] ext_incr = ((i_state==I_EXT1)     &  inst_as[`SYMB]) |
+                       ((i_state==I_EXT2)     &  inst_ad[`SYMB]) |
+                       ((i_state==I_EXT1)     & ~inst_as[`SYMB] &
+                       ~(i_state_nxt==I_EXT2) &  inst_ad[`SYMB])   ? 16'hfffe : 16'h0000;
+
+wire [15:0] ext_nxt  = ir + ext_incr;
+
+// Store source extension word
+reg [15:0] inst_sext;
+always @(posedge mclk or posedge puc)
+  if (puc)                                     inst_sext <= 16'h0000;
+  else if (decode & is_const)                  inst_sext <= sconst_nxt;
+  else if (decode & inst_type_nxt[`INST_JMP])  inst_sext <= {{5{ir[9]}},ir[9:0],1'b0};
+  else if ((i_state==I_EXT1) & is_sext)        inst_sext <= ext_nxt;
+
+// Source extension word is ready
+wire inst_sext_rdy = (i_state==I_EXT1) & is_sext;
+
+
+// Store destination extension word
+reg [15:0] inst_dext;
+always @(posedge mclk or posedge puc)
+  if (puc)                               inst_dext <= 16'h0000;
+  else if ((i_state==I_EXT1) & ~is_sext) inst_dext <= ext_nxt;
+  else if  (i_state==I_EXT2)             inst_dext <= ext_nxt;
+
+// Destination extension word is ready
+wire inst_dext_rdy = (((i_state==I_EXT1) & ~is_sext) | (i_state==I_EXT2));
+
+
+//=============================================================================
+// 4)  DECODE INSTRUCTION
+//=============================================================================
+
+//
+// 4.1) OPCODE: INSTRUCTION TYPE
+//----------------------------------------
+// Instructions type is encoded in a one hot fashion as following:
+//
+// 3'b001: Single-operand arithmetic
+// 3'b010: Conditional jump
+// 3'b100: Two-operand arithmetic
+
+reg  [2:0] inst_type;
+assign     inst_type_nxt = {(ir[15:14]!=2'b00),
+                            (ir[15:13]==3'b001),
+                            (ir[15:13]==3'b000)} & {3{~irq_detect}};
+   
+always @(posedge mclk or posedge puc)
+  if (puc)                      inst_type <= 3'b000;
+  else if (decode)              inst_type <= inst_type_nxt;
+
+//
+// 4.2) OPCODE: SINGLE-OPERAND ARITHMETIC
+//----------------------------------------
+// Instructions are encoded in a one hot fashion as following:
+//
+// 8'b00000001: RRC
+// 8'b00000010: SWPB
+// 8'b00000100: RRA
+// 8'b00001000: SXT
+// 8'b00010000: PUSH
+// 8'b00100000: CALL
+// 8'b01000000: RETI
+// 8'b10000000: IRQ
+
+reg   [7:0] inst_so;
+wire  [7:0] inst_so_nxt = irq_detect ? 8'h80 : ((8'h01<<ir[9:7]) & {8{inst_type_nxt[`INST_SO]}});
+
+always @(posedge mclk or posedge puc)
+  if (puc)         inst_so <= 8'h00;
+  else if (decode) inst_so <= inst_so_nxt;
+
+//
+// 4.3) OPCODE: CONDITIONAL JUMP
+//--------------------------------
+// Instructions are encoded in a one hot fashion as following:
+//
+// 8'b00000001: JNE/JNZ
+// 8'b00000010: JEQ/JZ
+// 8'b00000100: JNC/JLO
+// 8'b00001000: JC/JHS
+// 8'b00010000: JN
+// 8'b00100000: JGE
+// 8'b01000000: JL
+// 8'b10000000: JMP
+
+reg   [2:0] inst_jmp_bin;
+always @(posedge mclk or posedge puc)
+  if (puc)         inst_jmp_bin <= 3'h0;
+  else if (decode) inst_jmp_bin <= ir[12:10];
+
+wire [7:0] inst_jmp = (8'h01<<inst_jmp_bin) & {8{inst_type[`INST_JMP]}};
+
+
+//
+// 4.4) OPCODE: TWO-OPERAND ARITHMETIC
+//-------------------------------------
+// Instructions are encoded in a one hot fashion as following:
+//
+// 12'b000000000001: MOV
+// 12'b000000000010: ADD
+// 12'b000000000100: ADDC
+// 12'b000000001000: SUBC
+// 12'b000000010000: SUB
+// 12'b000000100000: CMP
+// 12'b000001000000: DADD
+// 12'b000010000000: BIT
+// 12'b000100000000: BIC
+// 12'b001000000000: BIS
+// 12'b010000000000: XOR
+// 12'b100000000000: AND
+
+wire [15:0] inst_to_1hot = (16'h0001<<ir[15:12]) & {16{inst_type_nxt[`INST_TO]}};
+wire [11:0] inst_to_nxt  = inst_to_1hot[15:4];
+
+
+//
+// 4.5) SOURCE AND DESTINATION REGISTERS
+//---------------------------------------
+
+// Destination register
+reg [3:0] inst_dest_bin;
+always @(posedge mclk or posedge puc)
+  if (puc)         inst_dest_bin <= 4'h0;
+  else if (decode) inst_dest_bin <= ir[3:0];
+
+wire  [15:0] inst_dest = dbg_halt_st          ? (16'h0001 << dbg_reg_sel) :
+                         inst_type[`INST_JMP] ? 16'h0001                  :
+                         inst_so[`IRQ]  |
+                         inst_so[`PUSH] |
+                         inst_so[`CALL]       ? 16'h0002                  :
+                                                (16'h0001 << inst_dest_bin);
+
+
+// Source register
+reg [3:0] inst_src_bin;
+always @(posedge mclk or posedge puc)
+  if (puc)         inst_src_bin <= 4'h0;
+  else if (decode) inst_src_bin <= ir[11:8];
+
+wire  [15:0] inst_src = inst_type[`INST_TO] ? (16'h0001 << inst_src_bin)  :
+                        inst_so[`RETI]      ? 16'h0002                    :
+                        inst_so[`IRQ]       ? 16'h0001                    :
+                        inst_type[`INST_SO] ? (16'h0001 << inst_dest_bin) : 16'h0000;
+
+
+//
+// 4.6) SOURCE ADDRESSING MODES
+//--------------------------------
+// Source addressing modes are encoded in a one hot fashion as following:
+//
+// 13'b0000000000001: Register direct.
+// 13'b0000000000010: Register indexed.
+// 13'b0000000000100: Register indirect.
+// 13'b0000000001000: Register indirect autoincrement.
+// 13'b0000000010000: Symbolic (operand is in memory at address PC+x).
+// 13'b0000000100000: Immediate (operand is next word in the instruction stream).
+// 13'b0000001000000: Absolute (operand is in memory at address x).
+// 13'b0000010000000: Constant 4.
+// 13'b0000100000000: Constant 8.
+// 13'b0001000000000: Constant 0.
+// 13'b0010000000000: Constant 1.
+// 13'b0100000000000: Constant 2.
+// 13'b1000000000000: Constant -1.
+
+reg [12:0] inst_as_nxt;
+
+wire [3:0] src_reg = inst_type_nxt[`INST_SO] ? ir[3:0] : ir[11:8];
+
+always @(src_reg or ir or inst_type_nxt)
+  begin
+     if (inst_type_nxt[`INST_JMP])
+       inst_as_nxt =  13'b0000000000001;
+     else if (src_reg==4'h3) // Addressing mode using R3
+       case (ir[5:4])
+        2'b11  : inst_as_nxt =  13'b1000000000000;
+        2'b10  : inst_as_nxt =  13'b0100000000000;
+        2'b01  : inst_as_nxt =  13'b0010000000000;
+        default: inst_as_nxt =  13'b0001000000000;
+       endcase
+     else if (src_reg==4'h2) // Addressing mode using R2
+       case (ir[5:4])
+        2'b11  : inst_as_nxt =  13'b0000100000000;
+        2'b10  : inst_as_nxt =  13'b0000010000000;
+        2'b01  : inst_as_nxt =  13'b0000001000000;
+        default: inst_as_nxt =  13'b0000000000001;
+       endcase
+     else if (src_reg==4'h0) // Addressing mode using R0
+       case (ir[5:4])
+        2'b11  : inst_as_nxt =  13'b0000000100000;
+        2'b10  : inst_as_nxt =  13'b0000000000100;
+        2'b01  : inst_as_nxt =  13'b0000000010000;
+        default: inst_as_nxt =  13'b0000000000001;
+       endcase
+     else                    // General Addressing mode
+       case (ir[5:4])
+        2'b11  : inst_as_nxt =  13'b0000000001000;
+        2'b10  : inst_as_nxt =  13'b0000000000100;
+        2'b01  : inst_as_nxt =  13'b0000000000010;
+        default: inst_as_nxt =  13'b0000000000001;
+       endcase
+  end
+assign    is_const = |inst_as_nxt[12:7];
+
+reg [7:0] inst_as;
+always @(posedge mclk or posedge puc)
+  if (puc)         inst_as <= 8'h00;
+  else if (decode) inst_as <= {is_const, inst_as_nxt[6:0]};
+
+
+// 13'b0000010000000: Constant 4.
+// 13'b0000100000000: Constant 8.
+// 13'b0001000000000: Constant 0.
+// 13'b0010000000000: Constant 1.
+// 13'b0100000000000: Constant 2.
+// 13'b1000000000000: Constant -1.
+always @(inst_as_nxt)
+  begin
+     if (inst_as_nxt[7])        sconst_nxt = 16'h0004;
+     else if (inst_as_nxt[8])   sconst_nxt = 16'h0008;
+     else if (inst_as_nxt[9])   sconst_nxt = 16'h0000;
+     else if (inst_as_nxt[10])  sconst_nxt = 16'h0001;
+     else if (inst_as_nxt[11])  sconst_nxt = 16'h0002;
+     else if (inst_as_nxt[12])  sconst_nxt = 16'hffff;
+     else                       sconst_nxt = 16'h0000;
+  end
+
+
+//
+// 4.7) DESTINATION ADDRESSING MODES
+//-----------------------------------
+// Destination addressing modes are encoded in a one hot fashion as following:
+//
+// 8'b00000001: Register direct.
+// 8'b00000010: Register indexed.
+// 8'b00010000: Symbolic (operand is in memory at address PC+x).
+// 8'b01000000: Absolute (operand is in memory at address x).
+
+reg  [7:0] inst_ad_nxt;
+
+wire [3:0] dest_reg = ir[3:0];
+
+always @(dest_reg or ir or inst_type_nxt)
+  begin
+     if (~inst_type_nxt[`INST_TO])
+       inst_ad_nxt =  8'b00000000;
+     else if (dest_reg==4'h2)   // Addressing mode using R2
+       case (ir[7])
+        1'b1   : inst_ad_nxt =  8'b01000000;
+        default: inst_ad_nxt =  8'b00000001;
+       endcase
+     else if (dest_reg==4'h0)   // Addressing mode using R0
+       case (ir[7])
+        2'b1   : inst_ad_nxt =  8'b00010000;
+        default: inst_ad_nxt =  8'b00000001;
+       endcase
+     else                       // General Addressing mode
+       case (ir[7])
+        2'b1   : inst_ad_nxt =  8'b00000010;
+        default: inst_ad_nxt =  8'b00000001;
+       endcase
+  end
+
+reg [7:0] inst_ad;
+always @(posedge mclk or posedge puc)
+  if (puc)         inst_ad <= 8'h00;
+  else if (decode) inst_ad <= inst_ad_nxt;
+
+
+//
+// 4.8) REMAINING INSTRUCTION DECODING
+//-------------------------------------
+
+// Operation size
+reg       inst_bw;
+always @(posedge mclk or posedge puc)
+  if (puc)         inst_bw     <= 1'b0;
+  else if (decode) inst_bw     <= ir[6] & ~inst_type_nxt[`INST_JMP] & ~irq_detect & ~dbg_halt_cmd;
+
+// Extended instruction size
+assign    inst_sz_nxt = {1'b0,  (inst_as_nxt[`IDX] | inst_as_nxt[`SYMB] | inst_as_nxt[`ABS] | inst_as_nxt[`IMM])} +
+                        {1'b0, ((inst_ad_nxt[`IDX] | inst_ad_nxt[`SYMB] | inst_ad_nxt[`ABS]) & ~inst_type_nxt[`INST_SO])};
+always @(posedge mclk or posedge puc)
+  if (puc)         inst_sz     <= 2'b00;
+  else if (decode) inst_sz     <= inst_sz_nxt;
+
+
+//=============================================================================
+// 5)  EXECUTION-UNIT STATE MACHINE
+//=============================================================================
+
+// State machine registers
+reg  [3:0] e_state;
+
+
+// State machine control signals
+//--------------------------------
+
+wire src_acalc_pre =  inst_as_nxt[`IDX]   | inst_as_nxt[`SYMB]    | inst_as_nxt[`ABS];
+wire src_rd_pre    =  inst_as_nxt[`INDIR] | inst_as_nxt[`INDIR_I] | inst_as_nxt[`IMM]  | inst_so_nxt[`RETI];
+wire dst_acalc_pre =  inst_ad_nxt[`IDX]   | inst_ad_nxt[`SYMB]    | inst_ad_nxt[`ABS];
+wire dst_acalc     =  inst_ad[`IDX]       | inst_ad[`SYMB]        | inst_ad[`ABS];
+wire dst_rd_pre    =  inst_ad_nxt[`IDX]   | inst_so_nxt[`PUSH]    | inst_so_nxt[`CALL] | inst_so_nxt[`RETI];
+wire dst_rd        =  inst_ad[`IDX]       | inst_so[`PUSH]        | inst_so[`CALL]     | inst_so[`RETI];
+
+wire inst_branch   =  (inst_ad_nxt[`DIR] & (ir[3:0]==4'h0)) | inst_type_nxt[`INST_JMP] | inst_so_nxt[`RETI];
+
+reg exec_jmp;
+always @(posedge mclk or posedge puc)
+  if (puc)                       exec_jmp <= 1'b0;
+  else if (inst_branch & decode) exec_jmp <= 1'b1;
+  else if (e_state==`E_JUMP)     exec_jmp <= 1'b0;
+
+reg exec_dst_wr;
+always @(posedge mclk or posedge puc)
+  if (puc)                     exec_dst_wr <= 1'b0;
+  else if (e_state==`E_DST_RD) exec_dst_wr <= 1'b1;
+  else if (e_state==`E_DST_WR) exec_dst_wr <= 1'b0;
+
+reg exec_src_wr;
+always @(posedge mclk or posedge puc)
+  if (puc)                                               exec_src_wr <= 1'b0;
+  else if (inst_type[`INST_SO] & (e_state==`E_SRC_RD))   exec_src_wr <= 1'b1;
+  else if ((e_state==`E_SRC_WR) || (e_state==`E_DST_WR)) exec_src_wr <= 1'b0;
+
+reg exec_dext_rdy;
+always @(posedge mclk or posedge puc)
+  if (puc)                     exec_dext_rdy <= 1'b0;
+  else if (e_state==`E_DST_RD) exec_dext_rdy <= 1'b0;
+  else if (inst_dext_rdy)      exec_dext_rdy <= 1'b1;
+
+// Execution first state
+//wire [3:0] e_first_state = dbg_halt_cmd        ? `E_IDLE   :
+wire [3:0] e_first_state = ~dbg_halt_st  & inst_so_nxt[`IRQ] ? `E_IRQ_0  :
+                            dbg_halt_cmd | (i_state==I_IDLE) ? `E_IDLE   :
+                            cpuoff                           ? `E_IDLE   :
+                            src_acalc_pre                    ? `E_SRC_AD :
+                            src_rd_pre                       ? `E_SRC_RD :
+                            dst_acalc_pre                    ? `E_DST_AD :
+                            dst_rd_pre                       ? `E_DST_RD : `E_EXEC;
+
+
+// State machine
+//--------------------------------
+
+// States Transitions
+always @(e_state       or dst_acalc     or dst_rd   or inst_sext_rdy or
+         inst_dext_rdy or exec_dext_rdy or exec_jmp or exec_dst_wr   or
+         e_first_state or exec_src_wr)
+    case(e_state)
+      `E_IDLE   : e_state_nxt =  e_first_state;
+      `E_IRQ_0  : e_state_nxt =  `E_IRQ_1;
+      `E_IRQ_1  : e_state_nxt =  `E_IRQ_2;
+      `E_IRQ_2  : e_state_nxt =  `E_IRQ_3;
+      `E_IRQ_3  : e_state_nxt =  `E_IRQ_4;
+      `E_IRQ_4  : e_state_nxt =  `E_EXEC;
+
+      `E_SRC_AD : e_state_nxt =  inst_sext_rdy     ? `E_SRC_RD : `E_SRC_AD;
+
+      `E_SRC_RD : e_state_nxt =  dst_acalc         ? `E_DST_AD : 
+                                 dst_rd            ? `E_DST_RD : `E_EXEC;
+
+      `E_DST_AD : e_state_nxt =  (inst_dext_rdy |
+                                 exec_dext_rdy)    ? `E_DST_RD : `E_DST_AD;
+
+      `E_DST_RD : e_state_nxt =  `E_EXEC;
+
+      `E_EXEC   : e_state_nxt =  exec_dst_wr       ? `E_DST_WR :
+                                exec_jmp           ? `E_JUMP   :
+                                exec_src_wr        ? `E_SRC_WR : e_first_state;
+
+      `E_JUMP   : e_state_nxt =  e_first_state;
+      `E_DST_WR : e_state_nxt =  exec_jmp           ? `E_JUMP   : e_first_state;
+      `E_SRC_WR : e_state_nxt =  e_first_state;
+      default  : e_state_nxt =  `E_IRQ_0;
+    endcase
+
+// State machine
+always @(posedge mclk or posedge puc)
+  if (puc)     e_state  <= `E_IRQ_1;
+  else         e_state  <= e_state_nxt;
+
+
+// Frontend State machine control signals
+//----------------------------------------
+
+wire exec_done = exec_jmp        ? (e_state==`E_JUMP)   :
+                 exec_dst_wr     ? (e_state==`E_DST_WR) :
+                 exec_src_wr     ? (e_state==`E_SRC_WR) : (e_state==`E_EXEC);
+
+
+//=============================================================================
+// 6)  EXECUTION-UNIT STATE CONTROL
+//=============================================================================
+
+//
+// 6.1) ALU CONTROL SIGNALS
+//-------------------------------------
+//
+// 12'b000000000001: Enable ALU source inverter
+// 12'b000000000010: Enable Incrementer
+// 12'b000000000100: Enable Incrementer on carry bit
+// 12'b000000001000: Select Adder
+// 12'b000000010000: Select AND
+// 12'b000000100000: Select OR
+// 12'b000001000000: Select XOR
+// 12'b000010000000: Select DADD
+// 12'b000100000000: Update N, Z & C (C=~Z)
+// 12'b001000000000: Update all status bits
+// 12'b010000000000: Update status bit for XOR instruction
+// 12'b100000000000: Don't write to destination
+
+reg  [11:0] inst_alu;
+
+wire        alu_src_inv   = inst_to_nxt[`SUB]  | inst_to_nxt[`SUBC] |
+                            inst_to_nxt[`CMP]  | inst_to_nxt[`BIC] ;
+
+wire        alu_inc       = inst_to_nxt[`SUB]  | inst_to_nxt[`CMP];
+
+wire        alu_inc_c     = inst_to_nxt[`ADDC] | inst_to_nxt[`DADD] |
+                            inst_to_nxt[`SUBC];
+
+wire        alu_add       = inst_to_nxt[`ADD]  | inst_to_nxt[`ADDC]       |
+                            inst_to_nxt[`SUB]  | inst_to_nxt[`SUBC]       |
+                            inst_to_nxt[`CMP]  | inst_type_nxt[`INST_JMP] |
+                            inst_so_nxt[`RETI];
+
+wire        alu_and       = inst_to_nxt[`AND]  | inst_to_nxt[`BIC]  |
+                            inst_to_nxt[`BIT];
+
+wire        alu_or        = inst_to_nxt[`BIS];
+
+wire        alu_xor       = inst_to_nxt[`XOR];
+
+wire        alu_dadd      = inst_to_nxt[`DADD];
+
+wire        alu_stat_7    = inst_to_nxt[`BIT]  | inst_to_nxt[`AND]  |
+                            inst_so_nxt[`SXT];
+
+wire        alu_stat_f    = inst_to_nxt[`ADD]  | inst_to_nxt[`ADDC] |
+                            inst_to_nxt[`SUB]  | inst_to_nxt[`SUBC] |
+                            inst_to_nxt[`CMP]  | inst_to_nxt[`DADD] |
+                            inst_to_nxt[`BIT]  | inst_to_nxt[`XOR]  |
+                            inst_to_nxt[`AND]  |
+                            inst_so_nxt[`RRC]  | inst_so_nxt[`RRA]  |
+                            inst_so_nxt[`SXT];
+
+wire        alu_shift     = inst_so_nxt[`RRC]  | inst_so_nxt[`RRA];
+
+wire        exec_no_wr    = inst_to_nxt[`CMP] | inst_to_nxt[`BIT];
+
+always @(posedge mclk or posedge puc)
+  if (puc)         inst_alu <= 12'h000;
+  else if (decode) inst_alu <= {exec_no_wr,
+                                alu_shift,
+                                alu_stat_f,
+                                alu_stat_7,
+                                alu_dadd,
+                                alu_xor,
+                                alu_or,
+                                alu_and,
+                                alu_add,
+                                alu_inc_c,
+                                alu_inc,
+                                alu_src_inv};
+
+
+endmodule // omsp_frontend
+
+`include "openMSP430_undefines.v"
diff --git a/omsp_mem_backbone.v b/omsp_mem_backbone.v
new file mode 100644 (file)
index 0000000..7c3422a
--- /dev/null
@@ -0,0 +1,244 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2001 Authors
+//
+// This source file may be used and distributed without restriction provided
+// that this copyright statement is not removed from the file and that any
+// derivative work contains the original copyright notice and the associated
+// disclaimer.
+//
+// This source file is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// This source is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+// License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this source; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+//----------------------------------------------------------------------------
+//
+// *File Name: omsp_mem_backbone.v
+// 
+// *Module Description:
+//                       Memory interface backbone (decoder + arbiter)
+//
+// *Author(s):
+//              - Olivier Girard,    olgirard@gmail.com
+//
+//----------------------------------------------------------------------------
+// $Rev: 34 $
+// $LastChangedBy: olivier.girard $
+// $LastChangedDate: 2009-12-29 20:10:34 +0100 (Tue, 29 Dec 2009) $
+//----------------------------------------------------------------------------
+`include "timescale.v"
+`include "openMSP430_defines.v"
+
+module  omsp_mem_backbone (
+
+// OUTPUTs
+    dbg_mem_din,                    // Debug unit Memory data input
+    dmem_addr,                      // Data Memory address
+    dmem_cen,                       // Data Memory chip enable (low active)
+    dmem_din,                       // Data Memory data input
+    dmem_wen,                       // Data Memory write enable (low active)
+    eu_mdb_in,                      // Execution Unit Memory data bus input
+    fe_mdb_in,                      // Frontend Memory data bus input
+    fe_pmem_wait,                   // Frontend wait for Instruction fetch
+    per_addr,                       // Peripheral address
+    per_din,                        // Peripheral data input
+    per_wen,                        // Peripheral write enable (high active)
+    per_en,                         // Peripheral enable (high active)
+    pmem_addr,                      // Program Memory address
+    pmem_cen,                       // Program Memory chip enable (low active)
+    pmem_din,                       // Program Memory data input (optional)
+    pmem_wen,                       // Program Memory write enable (low active) (optional)
+
+// INPUTs
+    dbg_halt_st,                    // Halt/Run status from CPU
+    dbg_mem_addr,                   // Debug address for rd/wr access
+    dbg_mem_dout,                   // Debug unit data output
+    dbg_mem_en,                     // Debug unit memory enable
+    dbg_mem_wr,                     // Debug unit memory write
+    dmem_dout,                      // Data Memory data output
+    eu_mab,                         // Execution Unit Memory address bus
+    eu_mb_en,                       // Execution Unit Memory bus enable
+    eu_mb_wr,                       // Execution Unit Memory bus write transfer
+    eu_mdb_out,                     // Execution Unit Memory data bus output
+    fe_mab,                         // Frontend Memory address bus
+    fe_mb_en,                       // Frontend Memory bus enable
+    mclk,                           // Main system clock
+    per_dout,                       // Peripheral data output
+    pmem_dout,                      // Program Memory data output
+    puc                             // Main system reset
+);
+
+// OUTPUTs
+//=========
+output        [15:0] dbg_mem_din;   // Debug unit Memory data input
+output [`DMEM_MSB:0] dmem_addr;     // Data Memory address
+output               dmem_cen;      // Data Memory chip enable (low active)
+output        [15:0] dmem_din;      // Data Memory data input
+output         [1:0] dmem_wen;      // Data Memory write enable (low active)
+output        [15:0] eu_mdb_in;     // Execution Unit Memory data bus input
+output        [15:0] fe_mdb_in;     // Frontend Memory data bus input
+output               fe_pmem_wait;  // Frontend wait for Instruction fetch
+output         [7:0] per_addr;      // Peripheral address
+output        [15:0] per_din;       // Peripheral data input
+output         [1:0] per_wen;       // Peripheral write enable (high active)
+output               per_en;        // Peripheral enable (high active)
+output [`PMEM_MSB:0] pmem_addr;     // Program Memory address
+output               pmem_cen;      // Program Memory chip enable (low active)
+output        [15:0] pmem_din;      // Program Memory data input (optional)
+output         [1:0] pmem_wen;      // Program Memory write enable (low active) (optional)
+
+// INPUTs
+//=========
+input                dbg_halt_st;   // Halt/Run status from CPU
+input         [15:0] dbg_mem_addr;  // Debug address for rd/wr access
+input         [15:0] dbg_mem_dout;  // Debug unit data output
+input                dbg_mem_en;    // Debug unit memory enable
+input          [1:0] dbg_mem_wr;    // Debug unit memory write
+input         [15:0] dmem_dout;     // Data Memory data output
+input         [14:0] eu_mab;        // Execution Unit Memory address bus
+input                eu_mb_en;      // Execution Unit Memory bus enable
+input          [1:0] eu_mb_wr;      // Execution Unit Memory bus write transfer
+input         [15:0] eu_mdb_out;    // Execution Unit Memory data bus output
+input         [14:0] fe_mab;        // Frontend Memory address bus
+input                fe_mb_en;      // Frontend Memory bus enable
+input                mclk;          // Main system clock
+input         [15:0] per_dout;      // Peripheral data output
+input         [15:0] pmem_dout;     // Program Memory data output
+input                puc;           // Main system reset
+
+
+//=============================================================================
+// 1)  DECODER
+//=============================================================================
+
+// RAM Interface
+//------------------
+
+// Execution unit access
+wire               eu_dmem_cen   = ~(eu_mb_en & (eu_mab>=(`DMEM_BASE>>1)) &
+                                                (eu_mab<((`DMEM_BASE+`DMEM_SIZE)>>1)));
+wire        [15:0] eu_dmem_addr  = eu_mab-(`DMEM_BASE>>1);
+
+// Debug interface access
+wire               dbg_dmem_cen  = ~(dbg_mem_en & (dbg_mem_addr[15:1]>=(`DMEM_BASE>>1)) &
+                                                  (dbg_mem_addr[15:1]<((`DMEM_BASE+`DMEM_SIZE)>>1)));
+wire        [15:0] dbg_dmem_addr = dbg_mem_addr[15:1]-(`DMEM_BASE>>1);
+
+   
+// RAM Interface
+wire [`DMEM_MSB:0] dmem_addr     = ~dbg_dmem_cen ? dbg_dmem_addr[`DMEM_MSB:0] : eu_dmem_addr[`DMEM_MSB:0];
+wire               dmem_cen      =  dbg_dmem_cen & eu_dmem_cen;
+wire         [1:0] dmem_wen      = ~(dbg_mem_wr | eu_mb_wr);
+wire        [15:0] dmem_din      = ~dbg_dmem_cen ? dbg_mem_dout : eu_mdb_out;
+
+
+// ROM Interface
+//------------------
+parameter          PMEM_OFFSET   = (16'hFFFF-`PMEM_SIZE+1);
+
+// Execution unit access (only read access are accepted)
+wire               eu_pmem_cen   = ~(eu_mb_en & ~|eu_mb_wr & (eu_mab>=(PMEM_OFFSET>>1)));
+wire        [15:0] eu_pmem_addr  = eu_mab-(PMEM_OFFSET>>1);
+
+// Front-end access
+wire               fe_pmem_cen   = ~(fe_mb_en & (fe_mab>=(PMEM_OFFSET>>1)));
+wire        [15:0] fe_pmem_addr  = fe_mab-(PMEM_OFFSET>>1);
+
+// Debug interface access
+wire               dbg_pmem_cen  = ~(dbg_mem_en & (dbg_mem_addr[15:1]>=(PMEM_OFFSET>>1)));
+wire        [15:0] dbg_pmem_addr = dbg_mem_addr[15:1]-(PMEM_OFFSET>>1);
+
+   
+// ROM Interface (Execution unit has priority)
+wire [`PMEM_MSB:0] pmem_addr     = ~dbg_pmem_cen ? dbg_pmem_addr[`PMEM_MSB:0] :
+                                   ~eu_pmem_cen  ? eu_pmem_addr[`PMEM_MSB:0]  : fe_pmem_addr[`PMEM_MSB:0];
+wire               pmem_cen      =  fe_pmem_cen & eu_pmem_cen & dbg_pmem_cen;
+wire         [1:0] pmem_wen      = ~dbg_mem_wr;
+wire        [15:0] pmem_din      =  dbg_mem_dout;
+
+wire               fe_pmem_wait  = (~fe_pmem_cen & ~eu_pmem_cen);
+
+
+// Peripherals
+//--------------------
+wire         dbg_per_en    =  dbg_mem_en & (dbg_mem_addr[15:9]==7'h00);
+wire         eu_per_en     =  eu_mb_en   & (eu_mab[14:8]==7'h00);
+
+wire   [7:0] per_addr      =  dbg_mem_en ? dbg_mem_addr[8:1] : eu_mab[7:0];
+wire  [15:0] per_din       =  dbg_mem_en ? dbg_mem_dout      : eu_mdb_out;
+wire   [1:0] per_wen       =  dbg_mem_en ? dbg_mem_wr        : eu_mb_wr;
+wire         per_en        =  dbg_mem_en ? dbg_per_en        : eu_per_en;
+
+reg   [15:0] per_dout_val;
+always @ (posedge mclk or posedge puc)
+  if (puc)      per_dout_val <= 16'h0000;
+  else          per_dout_val <= per_dout;
+
+
+// Frontend data Mux
+//---------------------------------
+// Whenever the frontend doesn't access the ROM,  backup the data
+
+// Detect whenever the data should be backuped and restored
+reg        fe_pmem_cen_dly;
+always @(posedge mclk or posedge puc)
+  if (puc)     fe_pmem_cen_dly <=  1'b0;
+  else         fe_pmem_cen_dly <=  fe_pmem_cen;
+
+wire fe_pmem_save    = ( fe_pmem_cen & ~fe_pmem_cen_dly) & ~dbg_halt_st;
+wire fe_pmem_restore = (~fe_pmem_cen &  fe_pmem_cen_dly) |  dbg_halt_st;
+   
+reg  [15:0] pmem_dout_bckup;
+always @(posedge mclk or posedge puc)
+  if (puc)               pmem_dout_bckup     <=  16'h0000;
+  else if (fe_pmem_save) pmem_dout_bckup     <=  pmem_dout;
+
+// Mux between the ROM data and the backup
+reg         pmem_dout_bckup_sel;
+always @(posedge mclk or posedge puc)
+  if (puc)                  pmem_dout_bckup_sel <=  1'b0;
+  else if (fe_pmem_save)    pmem_dout_bckup_sel <=  1'b1;
+  else if (fe_pmem_restore) pmem_dout_bckup_sel <=  1'b0;
+    
+assign fe_mdb_in = pmem_dout_bckup_sel ? pmem_dout_bckup : pmem_dout;
+
+
+// Execution-Unit data Mux
+//---------------------------------
+
+// Select between peripherals, RAM and ROM
+reg [1:0] eu_mdb_in_sel;
+always @(posedge mclk or posedge puc)
+  if (puc)  eu_mdb_in_sel <= 2'b00;
+  else      eu_mdb_in_sel <= {~eu_pmem_cen, per_en};
+
+// Mux
+assign      eu_mdb_in      = eu_mdb_in_sel[1] ? pmem_dout    :
+                             eu_mdb_in_sel[0] ? per_dout_val : dmem_dout;
+
+// Debug interface  data Mux
+//---------------------------------
+
+// Select between peripherals, RAM and ROM
+reg [1:0] dbg_mem_din_sel;
+always @(posedge mclk or posedge puc)
+  if (puc)  dbg_mem_din_sel <= 2'b00;
+  else      dbg_mem_din_sel <= {~dbg_pmem_cen, dbg_per_en};
+
+// Mux
+assign      dbg_mem_din  = dbg_mem_din_sel[1] ? pmem_dout    :
+                           dbg_mem_din_sel[0] ? per_dout_val : dmem_dout;
+
+   
+endmodule // omsp_mem_backbone
+
+`include "openMSP430_undefines.v"
diff --git a/omsp_multiplier.v b/omsp_multiplier.v
new file mode 100644 (file)
index 0000000..8bf78ac
--- /dev/null
@@ -0,0 +1,341 @@
+
+//----------------------------------------------------------------------------
+// Copyright (C) 2001 Authors
+//
+// This source file may be used and distributed without restriction provided
+// that this copyright statement is not removed from the file and that any
+// derivative work contains the original copyright notice and the associated
+// disclaimer.
+//
+// This source file is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// This source is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+// License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this source; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+//----------------------------------------------------------------------------
+//
+// *File Name: omsp_multiplier.v
+// 
+// *Module Description:
+//                       16x16 Hardware multiplier.
+//
+// *Author(s):
+//              - Olivier Girard,    olgirard@gmail.com
+//
+//----------------------------------------------------------------------------
+// $Rev: 23 $
+// $LastChangedBy: olivier.girard $
+// $LastChangedDate: 2009-08-30 18:39:26 +0200 (Sun, 30 Aug 2009) $
+//----------------------------------------------------------------------------
+`include "timescale.v"
+`include "openMSP430_defines.v"
+
+module  omsp_multiplier (
+
+// OUTPUTs
+    per_dout,                       // Peripheral data output
+
+// INPUTs
+    mclk,                           // Main system clock
+    per_addr,                       // Peripheral address
+    per_din,                        // Peripheral data input
+    per_en,                         // Peripheral enable (high active)
+    per_wen,                        // Peripheral write enable (high active)
+    puc                             // Main system reset
+);
+
+// OUTPUTs
+//=========
+output       [15:0] per_dout;       // Peripheral data output
+
+// INPUTs
+//=========
+input               mclk;           // Main system clock
+input         [7:0] per_addr;       // Peripheral address
+input        [15:0] per_din;        // Peripheral data input
+input               per_en;         // Peripheral enable (high active)
+input         [1:0] per_wen;        // Peripheral write enable (high active)
+input               puc;            // Main system reset
+
+
+//=============================================================================
+// 1)  PARAMETER/REGISTERS & WIRE DECLARATION
+//=============================================================================
+
+// Register addresses
+parameter           OP1_MPY    = 9'h130;
+parameter           OP1_MPYS   = 9'h132;
+parameter           OP1_MAC    = 9'h134;
+parameter           OP1_MACS   = 9'h136;
+parameter           OP2        = 9'h138;
+parameter           RESLO      = 9'h13A;
+parameter           RESHI      = 9'h13C;
+parameter           SUMEXT     = 9'h13E;
+
+
+// Register one-hot decoder
+parameter           OP1_MPY_D  = (512'h1 << OP1_MPY);
+parameter           OP1_MPYS_D = (512'h1 << OP1_MPYS);
+parameter           OP1_MAC_D  = (512'h1 << OP1_MAC);
+parameter           OP1_MACS_D = (512'h1 << OP1_MACS);
+parameter           OP2_D      = (512'h1 << OP2);
+parameter           RESLO_D    = (512'h1 << RESLO);
+parameter           RESHI_D    = (512'h1 << RESHI);
+parameter           SUMEXT_D   = (512'h1 << SUMEXT);
+
+
+// Wire pre-declarations
+wire  result_wr;
+wire  result_clr;
+wire  early_read;
+
+
+//============================================================================
+// 2)  REGISTER DECODER
+//============================================================================
+
+// Register address decode
+reg  [511:0]  reg_dec; 
+always @(per_addr)
+  case ({per_addr,1'b0})
+    OP1_MPY  :  reg_dec  =  OP1_MPY_D;
+    OP1_MPYS :  reg_dec  =  OP1_MPYS_D;
+    OP1_MAC  :  reg_dec  =  OP1_MAC_D;
+    OP1_MACS :  reg_dec  =  OP1_MACS_D;
+    OP2      :  reg_dec  =  OP2_D;
+    RESLO    :  reg_dec  =  RESLO_D;
+    RESHI    :  reg_dec  =  RESHI_D;
+    SUMEXT   :  reg_dec  =  SUMEXT_D;
+    default  :  reg_dec  =  {512{1'b0}};
+  endcase
+
+// Read/Write probes
+wire         reg_write =  |per_wen   & per_en;
+wire         reg_read  = ~|per_wen   & per_en;
+
+// Read/Write vectors
+wire [511:0] reg_wr    = reg_dec & {512{reg_write}};
+wire [511:0] reg_rd    = reg_dec & {512{reg_read}};
+
+
+//============================================================================
+// 3) REGISTERS
+//============================================================================
+
+// OP1 Register
+//-----------------   
+reg  [15:0] op1;
+
+wire        op1_wr = reg_wr[OP1_MPY]  |
+                     reg_wr[OP1_MPYS] |
+                     reg_wr[OP1_MAC]  |
+                     reg_wr[OP1_MACS];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)          op1 <=  16'h0000;
+  else if (op1_wr)  op1 <=  per_din;
+   
+wire [15:0] op1_rd  = op1;
+
+   
+// OP2 Register
+//-----------------   
+reg  [15:0] op2;
+
+wire        op2_wr = reg_wr[OP2];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)          op2 <=  16'h0000;
+  else if (op2_wr)  op2 <=  per_din;
+
+wire [15:0] op2_rd  = op2;
+
+   
+// RESLO Register
+//-----------------   
+reg  [15:0] reslo;
+
+wire [15:0] reslo_nxt;
+wire        reslo_wr = reg_wr[RESLO];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)             reslo <=  16'h0000;
+  else if (reslo_wr)   reslo <=  per_din;
+  else if (result_clr) reslo <=  16'h0000;
+  else if (result_wr)  reslo <=  reslo_nxt;
+
+wire [15:0] reslo_rd = early_read ? reslo_nxt : reslo;
+
+
+// RESHI Register
+//-----------------   
+reg  [15:0] reshi;
+
+wire [15:0] reshi_nxt;
+wire        reshi_wr = reg_wr[RESHI];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)             reshi <=  16'h0000;
+  else if (reshi_wr)   reshi <=  per_din;
+  else if (result_clr) reshi <=  16'h0000;
+  else if (result_wr)  reshi <=  reshi_nxt;
+
+wire [15:0] reshi_rd = early_read ? reshi_nxt  : reshi;
+
+// SUMEXT Register
+//-----------------   
+reg  [1:0] sumext_s;
+
+wire [1:0] sumext_s_nxt;
+
+always @ (posedge mclk or posedge puc)
+  if (puc)             sumext_s <=  2'b00;
+  else if (op2_wr)     sumext_s <=  2'b00;
+  else if (result_wr)  sumext_s <=  sumext_s_nxt;
+
+wire [15:0] sumext_nxt = {{14{sumext_s_nxt[1]}}, sumext_s_nxt};
+wire [15:0] sumext     = {{14{sumext_s[1]}},     sumext_s};
+wire [15:0] sumext_rd  = early_read ? sumext_nxt : sumext;
+
+
+//============================================================================
+// 4) DATA OUTPUT GENERATION
+//============================================================================
+
+// Data output mux
+wire [15:0] op1_mux    = op1_rd     & {16{reg_rd[OP1_MPY]  |
+                                          reg_rd[OP1_MPYS] |
+                                          reg_rd[OP1_MAC]  |
+                                          reg_rd[OP1_MACS]}};
+wire [15:0] op2_mux    = op2_rd     & {16{reg_rd[OP2]}};
+wire [15:0] reslo_mux  = reslo_rd   & {16{reg_rd[RESLO]}};
+wire [15:0] reshi_mux  = reshi_rd   & {16{reg_rd[RESHI]}};
+wire [15:0] sumext_mux = sumext_rd  & {16{reg_rd[SUMEXT]}};
+
+wire [15:0] per_dout   = op1_mux    |
+                         op2_mux    |
+                         reslo_mux  |
+                         reshi_mux  |
+                         sumext_mux;
+
+
+//============================================================================
+// 5) HARDWARE MULTIPLIER FUNCTIONAL LOGIC
+//============================================================================
+
+// Multiplier configuration
+//--------------------------
+
+// Detect signed mode
+reg sign_sel;
+always @ (posedge mclk or posedge puc)
+  if (puc)         sign_sel <=  1'b0;
+  else if (op1_wr) sign_sel <=  reg_wr[OP1_MPYS] | reg_wr[OP1_MACS];
+
+
+// Detect accumulate mode
+reg acc_sel;
+always @ (posedge mclk or posedge puc)
+  if (puc)         acc_sel  <=  1'b0;
+  else if (op1_wr) acc_sel  <=  reg_wr[OP1_MAC]  | reg_wr[OP1_MACS];
+
+
+// Detect whenever the RESHI and RESLO registers should be cleared
+assign      result_clr = op2_wr & ~acc_sel;
+
+// Combine RESHI & RESLO 
+wire [31:0] result     = {reshi, reslo};
+
+   
+// 16x16 Multiplier (result computed in 1 clock cycle)
+//-----------------------------------------------------
+`ifdef MPY_16x16
+
+// Detect start of a multiplication
+reg cycle;
+always @ (posedge mclk or posedge puc)
+  if (puc) cycle <=  1'b0;
+  else     cycle <=  op2_wr;
+
+assign result_wr = cycle;
+
+// Expand the operands to support signed & unsigned operations
+wire signed [16:0] op1_xp = {sign_sel & op1[15], op1};
+wire signed [16:0] op2_xp = {sign_sel & op2[15], op2};
+
+
+// 17x17 signed multiplication
+wire signed [33:0] product = op1_xp * op2_xp;
+
+// Accumulate
+wire [32:0] result_nxt = {1'b0, result} + {1'b0, product[31:0]};
+
+
+// Next register values
+assign reslo_nxt    = result_nxt[15:0];
+assign reshi_nxt    = result_nxt[31:16];
+assign sumext_s_nxt =  sign_sel ? {2{result_nxt[31]}} :
+                                  {1'b0, result_nxt[32]};
+
+
+// Since the MAC is completed within 1 clock cycle,
+// an early read can't happen.
+assign early_read   = 1'b0;
+
+
+// 16x8 Multiplier (result computed in 2 clock cycles)
+//-----------------------------------------------------
+`else
+  
+// Detect start of a multiplication
+reg [1:0] cycle;
+always @ (posedge mclk or posedge puc)
+  if (puc) cycle <=  2'b00;
+  else     cycle <=  {cycle[0], op2_wr};
+
+assign result_wr = |cycle;
+
+
+// Expand the operands to support signed & unsigned operations
+wire signed [16:0] op1_xp    = {sign_sel & op1[15], op1};
+wire signed  [8:0] op2_hi_xp = {sign_sel & op2[15], op2[15:8]};
+wire signed  [8:0] op2_lo_xp = {              1'b0, op2[7:0]};
+wire signed  [8:0] op2_xp    = cycle[0] ? op2_hi_xp : op2_lo_xp;
+
+     
+// 17x9 signed multiplication
+wire signed [25:0] product    = op1_xp * op2_xp;
+
+wire        [31:0] product_xp = cycle[0] ? {product[23:0], 8'h00} :
+                                           {{8{sign_sel & product[23]}}, product[23:0]};
+   
+// Accumulate
+wire [32:0] result_nxt  = {1'b0, result} + {1'b0, product_xp[31:0]};
+
+
+// Next register values
+assign reslo_nxt    = result_nxt[15:0];
+assign reshi_nxt    = result_nxt[31:16];
+assign sumext_s_nxt =  sign_sel ? {2{result_nxt[31]}} :
+                                  {1'b0, result_nxt[32] | sumext_s[0]};
+
+// Since the MAC is completed within 2 clock cycle,
+// an early read can happen during the second cycle.
+assign early_read   = cycle[1];
+
+`endif
+
+
+endmodule // omsp_multiplier
+
+`include "openMSP430_undefines.v"
diff --git a/omsp_register_file.v b/omsp_register_file.v
new file mode 100644 (file)
index 0000000..66d8458
--- /dev/null
@@ -0,0 +1,345 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2001 Authors
+//
+// This source file may be used and distributed without restriction provided
+// that this copyright statement is not removed from the file and that any
+// derivative work contains the original copyright notice and the associated
+// disclaimer.
+//
+// This source file is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// This source is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+// License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this source; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+//----------------------------------------------------------------------------
+//
+// *File Name: omsp_register_file.v
+// 
+// *Module Description:
+//                       openMSP430 Register files
+//
+// *Author(s):
+//              - Olivier Girard,    olgirard@gmail.com
+//
+//----------------------------------------------------------------------------
+// $Rev: 34 $
+// $LastChangedBy: olivier.girard $
+// $LastChangedDate: 2009-12-29 20:10:34 +0100 (Tue, 29 Dec 2009) $
+//----------------------------------------------------------------------------
+`include "timescale.v"
+`include "openMSP430_defines.v"
+
+module  omsp_register_file (
+
+// OUTPUTs
+    cpuoff,                       // Turns off the CPU
+    gie,                          // General interrupt enable
+    oscoff,                       // Turns off LFXT1 clock input
+    pc_sw,                        // Program counter software value
+    pc_sw_wr,                     // Program counter software write
+    reg_dest,                     // Selected register destination content
+    reg_src,                      // Selected register source content
+    scg1,                         // System clock generator 1. Turns off the SMCLK
+    status,                       // R2 Status {V,N,Z,C}
+
+// INPUTs
+    alu_stat,                     // ALU Status {V,N,Z,C}
+    alu_stat_wr,                  // ALU Status write {V,N,Z,C}
+    inst_bw,                      // Decoded Inst: byte width
+    inst_dest,                    // Register destination selection
+    inst_src,                     // Register source selection
+    mclk,                         // Main system clock
+    pc,                           // Program counter
+    puc,                          // Main system reset
+    reg_dest_val,                 // Selected register destination value
+    reg_dest_wr,                  // Write selected register destination
+    reg_pc_call,                  // Trigger PC update for a CALL instruction
+    reg_sp_val,                   // Stack Pointer next value
+    reg_sp_wr,                    // Stack Pointer write
+    reg_sr_wr,                    // Status register update for RETI instruction
+    reg_sr_clr,                   // Status register clear for interrupts
+    reg_incr                      // Increment source register
+);
+
+// OUTPUTs
+//=========
+output                     cpuoff;       // Turns off the CPU
+output                     gie;          // General interrupt enable
+output                     oscoff;       // Turns off LFXT1 clock input
+output       [15:0] pc_sw;        // Program counter software value
+output              pc_sw_wr;     // Program counter software write
+output       [15:0] reg_dest;     // Selected register destination content
+output       [15:0] reg_src;      // Selected register source content
+output              scg1;         // System clock generator 1. Turns off the SMCLK
+output        [3:0] status;       // R2 Status {V,N,Z,C}
+
+// INPUTs
+//=========
+input         [3:0] alu_stat;     // ALU Status {V,N,Z,C}
+input         [3:0] alu_stat_wr;  // ALU Status write {V,N,Z,C}
+input               inst_bw;      // Decoded Inst: byte width
+input        [15:0] inst_dest;    // Register destination selection
+input        [15:0] inst_src;     // Register source selection
+input               mclk;         // Main system clock
+input        [15:0] pc;           // Program counter
+input               puc;          // Main system reset
+input        [15:0] reg_dest_val; // Selected register destination value
+input               reg_dest_wr;  // Write selected register destination
+input               reg_pc_call;  // Trigger PC update for a CALL instruction
+input        [15:0] reg_sp_val;   // Stack Pointer next value
+input               reg_sp_wr;    // Stack Pointer write
+input               reg_sr_wr;    // Status register update for RETI instruction
+input               reg_sr_clr;   // Status register clear for interrupts
+input               reg_incr;     // Increment source register
+
+
+//=============================================================================
+// 1)  AUTOINCREMENT UNIT
+//=============================================================================
+
+wire [15:0] incr_op         = inst_bw ? 16'h0001 : 16'h0002;
+wire [15:0] reg_incr_val    = reg_src+incr_op;
+
+wire [15:0] reg_dest_val_in = inst_bw ? {8'h00,reg_dest_val[7:0]} : reg_dest_val;
+
+
+//=============================================================================
+// 2)  SPECIAL REGISTERS (R1/R2/R3)
+//=============================================================================
+
+// Source input selection mask (for interrupt support)
+//-----------------------------------------------------
+
+wire [15:0] inst_src_in = reg_sr_clr ? 16'h0004 : inst_src;
+
+
+// R0: Program counter
+//---------------------
+
+wire [15:0] r0       = pc;
+
+wire [15:0] pc_sw    = reg_dest_val_in;
+wire        pc_sw_wr = (inst_dest[0] & reg_dest_wr) | reg_pc_call;
+
+
+// R1: Stack pointer
+//-------------------
+reg [15:0] r1;
+wire       r1_wr  = inst_dest[1] & reg_dest_wr;
+wire       r1_inc = inst_src_in[1]  & reg_incr;
+
+always @(posedge mclk or posedge puc)
+  if (puc)            r1 <= 16'h0000;
+  else if (r1_wr)     r1 <= reg_dest_val_in & 16'hfffe;
+  else if (reg_sp_wr) r1 <= reg_sp_val      & 16'hfffe;
+  else if (r1_inc)    r1 <= reg_incr_val    & 16'hfffe;
+
+
+// R2: Status register
+//---------------------
+reg  [15:0] r2;
+wire        r2_wr  = (inst_dest[2] & reg_dest_wr) | reg_sr_wr;
+
+wire        r2_c   = alu_stat_wr[0] ? alu_stat[0]       :
+                     r2_wr          ? reg_dest_val_in[0]   : r2[0]; // C
+
+wire        r2_z   = alu_stat_wr[1] ? alu_stat[1]       :
+                     r2_wr          ? reg_dest_val_in[1]   : r2[1]; // Z
+
+wire        r2_n   = alu_stat_wr[2] ? alu_stat[2]       :
+                     r2_wr          ? reg_dest_val_in[2]   : r2[2]; // N
+
+wire  [7:3] r2_nxt = r2_wr          ? reg_dest_val_in[7:3] : r2[7:3];
+
+wire        r2_v   = alu_stat_wr[3] ? alu_stat[3]       :
+                     r2_wr          ? reg_dest_val_in[8]   : r2[8]; // V
+
+
+always @(posedge mclk or posedge puc)
+  if (puc)             r2 <= 16'h0000;
+  else if (reg_sr_clr) r2 <= 16'h0000;
+  else                 r2 <= {7'h00, r2_v, r2_nxt, r2_n, r2_z, r2_c};
+
+assign status = {r2[8], r2[2:0]};
+assign gie    =  r2[3];
+assign cpuoff =  r2[4] | (r2_nxt[4] & r2_wr);
+assign oscoff =  r2[5];
+assign scg1   =  r2[7];
+
+
+// R3: Constant generator
+//------------------------
+reg [15:0] r3;
+wire       r3_wr  = inst_dest[3] & reg_dest_wr;
+wire       r3_inc = inst_src_in[3]  & reg_incr;
+
+always @(posedge mclk or posedge puc)
+  if (puc)         r3 <= 16'h0000;
+  else if (r3_wr)  r3 <= reg_dest_val_in;
+  else if (r3_inc) r3 <= reg_incr_val;
+
+
+//=============================================================================
+// 4)  GENERAL PURPOSE REGISTERS (R4...R15)
+//=============================================================================
+
+// R4
+reg [15:0] r4;
+wire       r4_wr  = inst_dest[4] & reg_dest_wr;
+wire       r4_inc = inst_src_in[4]  & reg_incr;
+always @(posedge mclk or posedge puc)
+  if (puc)          r4  <= 16'h0000;
+  else if (r4_wr)   r4  <= reg_dest_val_in;
+  else if (r4_inc)  r4  <= reg_incr_val;
+
+// R5
+reg [15:0] r5;
+wire       r5_wr  = inst_dest[5] & reg_dest_wr;
+wire       r5_inc = inst_src_in[5]  & reg_incr;
+always @(posedge mclk or posedge puc)
+  if (puc)          r5  <= 16'h0000;
+  else if (r5_wr)   r5  <= reg_dest_val_in;
+  else if (r5_inc)  r5  <= reg_incr_val;
+
+// R6
+reg [15:0] r6;
+wire       r6_wr  = inst_dest[6] & reg_dest_wr;
+wire       r6_inc = inst_src_in[6]  & reg_incr;
+always @(posedge mclk or posedge puc)
+  if (puc)          r6  <= 16'h0000;
+  else if (r6_wr)   r6  <= reg_dest_val_in;
+  else if (r6_inc)  r6  <= reg_incr_val;
+
+// R7
+reg [15:0] r7;
+wire       r7_wr  = inst_dest[7] & reg_dest_wr;
+wire       r7_inc = inst_src_in[7]  & reg_incr;
+always @(posedge mclk or posedge puc)
+  if (puc)          r7  <= 16'h0000;
+  else if (r7_wr)   r7  <= reg_dest_val_in;
+  else if (r7_inc)  r7  <= reg_incr_val;
+
+// R8
+reg [15:0] r8;
+wire       r8_wr  = inst_dest[8] & reg_dest_wr;
+wire       r8_inc = inst_src_in[8]  & reg_incr;
+always @(posedge mclk or posedge puc)
+  if (puc)          r8  <= 16'h0000;
+  else if (r8_wr)   r8  <= reg_dest_val_in;
+  else if (r8_inc)  r8  <= reg_incr_val;
+
+// R9
+reg [15:0] r9;
+wire       r9_wr  = inst_dest[9] & reg_dest_wr;
+wire       r9_inc = inst_src_in[9]  & reg_incr;
+always @(posedge mclk or posedge puc)
+  if (puc)          r9  <= 16'h0000;
+  else if (r9_wr)   r9  <= reg_dest_val_in;
+  else if (r9_inc)  r9  <= reg_incr_val;
+
+// R10
+reg [15:0] r10;
+wire       r10_wr  = inst_dest[10] & reg_dest_wr;
+wire       r10_inc = inst_src_in[10]  & reg_incr;
+always @(posedge mclk or posedge puc)
+  if (puc)          r10 <= 16'h0000;
+  else if (r10_wr)  r10 <= reg_dest_val_in;
+  else if (r10_inc) r10 <= reg_incr_val;
+
+// R11
+reg [15:0] r11;
+wire       r11_wr  = inst_dest[11] & reg_dest_wr;
+wire       r11_inc = inst_src_in[11]  & reg_incr;
+always @(posedge mclk or posedge puc)
+  if (puc)          r11 <= 16'h0000;
+  else if (r11_wr)  r11 <= reg_dest_val_in;
+  else if (r11_inc) r11 <= reg_incr_val;
+
+// R12
+reg [15:0] r12;
+wire       r12_wr  = inst_dest[12] & reg_dest_wr;
+wire       r12_inc = inst_src_in[12]  & reg_incr;
+always @(posedge mclk or posedge puc)
+  if (puc)          r12 <= 16'h0000;
+  else if (r12_wr)  r12 <= reg_dest_val_in;
+  else if (r12_inc) r12 <= reg_incr_val;
+
+// R13
+reg [15:0] r13;
+wire       r13_wr  = inst_dest[13] & reg_dest_wr;
+wire       r13_inc = inst_src_in[13]  & reg_incr;
+always @(posedge mclk or posedge puc)
+  if (puc)          r13 <= 16'h0000;
+  else if (r13_wr)  r13 <= reg_dest_val_in;
+  else if (r13_inc) r13 <= reg_incr_val;
+
+// R14
+reg [15:0] r14;
+wire       r14_wr  = inst_dest[14] & reg_dest_wr;
+wire       r14_inc = inst_src_in[14]  & reg_incr;
+always @(posedge mclk or posedge puc)
+  if (puc)          r14 <= 16'h0000;
+  else if (r14_wr)  r14 <= reg_dest_val_in;
+  else if (r14_inc) r14 <= reg_incr_val;
+
+// R15
+reg [15:0] r15;
+wire       r15_wr  = inst_dest[15] & reg_dest_wr;
+wire       r15_inc = inst_src_in[15]  & reg_incr;
+always @(posedge mclk or posedge puc)
+  if (puc)          r15 <= 16'h0000;
+  else if (r15_wr)  r15 <= reg_dest_val_in;
+  else if (r15_inc) r15 <= reg_incr_val;
+
+
+//=============================================================================
+// 5)  READ MUX
+//=============================================================================
+
+assign reg_src  = (r0      & {16{inst_src_in[0]}})   | 
+                  (r1      & {16{inst_src_in[1]}})   | 
+                  (r2      & {16{inst_src_in[2]}})   | 
+                  (r3      & {16{inst_src_in[3]}})   | 
+                  (r4      & {16{inst_src_in[4]}})   | 
+                  (r5      & {16{inst_src_in[5]}})   | 
+                  (r6      & {16{inst_src_in[6]}})   | 
+                  (r7      & {16{inst_src_in[7]}})   | 
+                  (r8      & {16{inst_src_in[8]}})   | 
+                  (r9      & {16{inst_src_in[9]}})   | 
+                  (r10     & {16{inst_src_in[10]}})  | 
+                  (r11     & {16{inst_src_in[11]}})  | 
+                  (r12     & {16{inst_src_in[12]}})  | 
+                  (r13     & {16{inst_src_in[13]}})  | 
+                  (r14     & {16{inst_src_in[14]}})  | 
+                  (r15     & {16{inst_src_in[15]}});
+
+assign reg_dest = (r0      & {16{inst_dest[0]}})  | 
+                  (r1      & {16{inst_dest[1]}})  | 
+                  (r2      & {16{inst_dest[2]}})  | 
+                  (r3      & {16{inst_dest[3]}})  | 
+                  (r4      & {16{inst_dest[4]}})  | 
+                  (r5      & {16{inst_dest[5]}})  | 
+                  (r6      & {16{inst_dest[6]}})  | 
+                  (r7      & {16{inst_dest[7]}})  | 
+                  (r8      & {16{inst_dest[8]}})  | 
+                  (r9      & {16{inst_dest[9]}})  | 
+                  (r10     & {16{inst_dest[10]}}) | 
+                  (r11     & {16{inst_dest[11]}}) | 
+                  (r12     & {16{inst_dest[12]}}) | 
+                  (r13     & {16{inst_dest[13]}}) | 
+                  (r14     & {16{inst_dest[14]}}) | 
+                  (r15     & {16{inst_dest[15]}});
+
+
+endmodule // omsp_register_file
+
+`include "openMSP430_undefines.v"
diff --git a/omsp_sfr.v b/omsp_sfr.v
new file mode 100644 (file)
index 0000000..29d3a36
--- /dev/null
@@ -0,0 +1,204 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2001 Authors
+//
+// This source file may be used and distributed without restriction provided
+// that this copyright statement is not removed from the file and that any
+// derivative work contains the original copyright notice and the associated
+// disclaimer.
+//
+// This source file is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// This source is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+// License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this source; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+//----------------------------------------------------------------------------
+//
+// *File Name: omsp_sfr.v
+// 
+// *Module Description:
+//                       Processor Special function register
+//
+// *Author(s):
+//              - Olivier Girard,    olgirard@gmail.com
+//
+//----------------------------------------------------------------------------
+// $Rev: 34 $
+// $LastChangedBy: olivier.girard $
+// $LastChangedDate: 2009-12-29 20:10:34 +0100 (Tue, 29 Dec 2009) $
+//----------------------------------------------------------------------------
+`include "timescale.v"
+`include "openMSP430_defines.v"
+
+module  omsp_sfr (
+
+// OUTPUTs
+    nmie,                         // Non-maskable interrupt enable
+    per_dout,                     // Peripheral data output
+    wdt_irq,                      // Watchdog-timer interrupt
+    wdt_reset,                    // Watchdog-timer reset
+    wdtie,                        // Watchdog-timer interrupt enable
+
+// INPUTs
+    mclk,                         // Main system clock
+    nmi_acc,                      // Non-Maskable interrupt request accepted
+    per_addr,                     // Peripheral address
+    per_din,                      // Peripheral data input
+    per_en,                       // Peripheral enable (high active)
+    per_wen,                      // Peripheral write enable (high active)
+    por,                          // Power-on reset
+    puc,                          // Main system reset
+    wdtifg_clr,                   // Clear Watchdog-timer interrupt flag
+    wdtifg_set,                   // Set Watchdog-timer interrupt flag
+    wdtpw_error,                  // Watchdog-timer password error
+    wdttmsel                      // Watchdog-timer mode select
+);
+
+// OUTPUTs
+//=========
+output              nmie;         // Non-maskable interrupt enable
+output       [15:0] per_dout;     // Peripheral data output
+output              wdt_irq;      // Watchdog-timer interrupt
+output              wdt_reset;    // Watchdog-timer reset
+output              wdtie;        // Watchdog-timer interrupt enable
+
+// INPUTs
+//=========
+input               mclk;         // Main system clock
+input               nmi_acc;      // Non-Maskable interrupt request accepted
+input         [7:0] per_addr;     // Peripheral address
+input        [15:0] per_din;      // Peripheral data input
+input               per_en;       // Peripheral enable (high active)
+input         [1:0] per_wen;      // Peripheral write enable (high active)
+input               por;          // Power-on reset
+input               puc;          // Main system reset
+input               wdtifg_clr;   // Clear Watchdog-timer interrupt flag
+input               wdtifg_set;   // Set Watchdog-timer interrupt flag
+input               wdtpw_error;  // Watchdog-timer password error
+input               wdttmsel;     // Watchdog-timer mode select
+
+
+//=============================================================================
+// 1)  PARAMETER DECLARATION
+//=============================================================================
+
+// Register addresses
+parameter           IE1        = 9'h000;
+parameter           IFG1       = 9'h002;
+
+// Register one-hot decoder
+parameter           IE1_D      = (256'h1 << (IE1  /2));
+parameter           IFG1_D     = (256'h1 << (IFG1 /2)); 
+
+
+//============================================================================
+// 2)  REGISTER DECODER
+//============================================================================
+
+// Register address decode
+reg  [255:0]  reg_dec; 
+always @(per_addr)
+  case (per_addr)
+    (IE1  /2):     reg_dec  =  IE1_D;
+    (IFG1 /2):     reg_dec  =  IFG1_D;
+    default  :     reg_dec  =  {256{1'b0}};
+  endcase
+
+// Read/Write probes
+wire         reg_lo_write =  per_wen[0] & per_en;
+wire         reg_hi_write =  per_wen[1] & per_en;
+wire         reg_read     = ~|per_wen   & per_en;
+
+// Read/Write vectors
+wire [255:0] reg_hi_wr    = reg_dec & {256{reg_hi_write}};
+wire [255:0] reg_lo_wr    = reg_dec & {256{reg_lo_write}};
+wire [255:0] reg_rd       = reg_dec & {256{reg_read}};
+
+
+//============================================================================
+// 3) REGISTERS
+//============================================================================
+
+// IE1 Register
+//--------------
+wire [7:0] ie1;
+wire       ie1_wr  = IE1[0] ? reg_hi_wr[IE1/2] : reg_lo_wr[IE1/2];
+wire [7:0] ie1_nxt = IE1[0] ? per_din[15:8]    : per_din[7:0];
+
+reg        nmie;
+always @ (posedge mclk or posedge puc)
+  if (puc)          nmie  <=  1'b0;
+  else if (nmi_acc) nmie  <=  1'b0; 
+  else if (ie1_wr)  nmie  <=  ie1_nxt[4];    
+
+reg        wdtie;
+always @ (posedge mclk or posedge puc)
+  if (puc)           wdtie <=  1'b0;
+  else if (ie1_wr)   wdtie <=  ie1_nxt[0];    
+
+assign  ie1 = {3'b000, nmie, 3'b000, wdtie};
+
+
+// IFG1 Register
+//---------------
+wire [7:0] ifg1;
+wire       ifg1_wr  = IFG1[0] ? reg_hi_wr[IFG1/2] : reg_lo_wr[IFG1/2];
+wire [7:0] ifg1_nxt = IFG1[0] ? per_din[15:8]     : per_din[7:0];
+
+reg        nmiifg;
+always @ (posedge mclk or posedge puc)
+  if (puc)           nmiifg <=  1'b0;
+  else if (nmi_acc)  nmiifg <=  1'b1;
+  else if (ifg1_wr)  nmiifg <=  ifg1_nxt[4];
+
+reg        wdtifg;
+always @ (posedge mclk or posedge por)
+  if (por)                        wdtifg <=  1'b0;
+  else if (wdtifg_set)            wdtifg <=  1'b1;
+  else if (wdttmsel & wdtifg_clr) wdtifg <=  1'b0;
+  else if (ifg1_wr)               wdtifg <=  ifg1_nxt[0];
+
+assign  ifg1 = {3'b000, nmiifg, 3'b000, wdtifg};
+
+
+//============================================================================
+// 4) DATA OUTPUT GENERATION
+//============================================================================
+
+// Data output mux
+wire [15:0] ie1_rd   = (ie1  & {8{reg_rd[IE1/2]}})  << (8 & {4{IE1[0]}});
+wire [15:0] ifg1_rd  = (ifg1 & {8{reg_rd[IFG1/2]}}) << (8 & {4{IFG1[0]}});
+
+wire [15:0] per_dout =  ie1_rd   |
+                        ifg1_rd;
+
+
+//=============================================================================
+// 5)  WATCHDOG INTERRUPT & RESET
+//=============================================================================
+
+// Watchdog interrupt generation
+//---------------------------------
+wire    wdt_irq      = wdttmsel & wdtifg & wdtie;
+
+   
+// Watchdog reset generation
+//-----------------------------
+reg     wdt_reset;
+
+always @ (posedge mclk or posedge por)
+  if (por) wdt_reset <= 1'b0;
+  else     wdt_reset <= wdtpw_error | (wdtifg_set & ~wdttmsel);
+
+
+endmodule // omsp_sfr
+
+`include "openMSP430_undefines.v"
diff --git a/omsp_watchdog.v b/omsp_watchdog.v
new file mode 100644 (file)
index 0000000..5e97595
--- /dev/null
@@ -0,0 +1,217 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2001 Authors
+//
+// This source file may be used and distributed without restriction provided
+// that this copyright statement is not removed from the file and that any
+// derivative work contains the original copyright notice and the associated
+// disclaimer.
+//
+// This source file is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// This source is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+// License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this source; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+//----------------------------------------------------------------------------
+//
+// *File Name: omsp_watchdog.v
+// 
+// *Module Description:
+//                       Watchdog Timer
+//
+// *Author(s):
+//              - Olivier Girard,    olgirard@gmail.com
+//
+//----------------------------------------------------------------------------
+// $Rev: 34 $
+// $LastChangedBy: olivier.girard $
+// $LastChangedDate: 2009-12-29 20:10:34 +0100 (Tue, 29 Dec 2009) $
+//----------------------------------------------------------------------------
+`include "timescale.v"
+`include "openMSP430_defines.v"
+
+module  omsp_watchdog (
+
+// OUTPUTs
+    nmi_evt,                        // NMI Event
+    per_dout,                       // Peripheral data output
+    wdtifg_set,                     // Set Watchdog-timer interrupt flag
+    wdtpw_error,                    // Watchdog-timer password error
+    wdttmsel,                       // Watchdog-timer mode select
+
+// INPUTs
+    aclk_en,                        // ACLK enable
+    dbg_freeze,                     // Freeze Watchdog counter
+    mclk,                           // Main system clock
+    nmi,                            // Non-maskable interrupt (asynchronous)
+    nmie,                           // Non-maskable interrupt enable
+    per_addr,                       // Peripheral address
+    per_din,                        // Peripheral data input
+    per_en,                         // Peripheral enable (high active)
+    per_wen,                        // Peripheral write enable (high active)
+    puc,                            // Main system reset
+    smclk_en,                       // SMCLK enable
+    wdtie                           // Watchdog timer interrupt enable
+);
+
+// OUTPUTs
+//=========
+output              nmi_evt;        // NMI Event
+output       [15:0] per_dout;       // Peripheral data output
+output              wdtifg_set;     // Set Watchdog-timer interrupt flag
+output              wdtpw_error;    // Watchdog-timer password error
+output              wdttmsel;       // Watchdog-timer mode select
+
+// INPUTs
+//=========
+input               aclk_en;        // ACLK enable
+input               dbg_freeze;     // Freeze Watchdog counter
+input               mclk;           // Main system clock
+input               nmi;            // Non-maskable interrupt (asynchronous)
+input               nmie;           // Non-maskable interrupt enable
+input         [7:0] per_addr;       // Peripheral address
+input        [15:0] per_din;        // Peripheral data input
+input               per_en;         // Peripheral enable (high active)
+input         [1:0] per_wen;        // Peripheral write enable (high active)
+input               puc;            // Main system reset
+input               smclk_en;       // SMCLK enable
+input               wdtie;          // Watchdog timer interrupt enable
+
+
+//=============================================================================
+// 1)  PARAMETER DECLARATION
+//=============================================================================
+
+// Register addresses
+parameter           WDTCTL     = 9'h120;
+
+
+// Register one-hot decoder
+parameter           WDTCTL_D   = (512'h1 << WDTCTL);
+
+
+//============================================================================
+// 2)  REGISTER DECODER
+//============================================================================
+
+// Register address decode
+reg  [511:0]  reg_dec; 
+always @(per_addr)
+  case ({per_addr,1'b0})
+    WDTCTL :     reg_dec  =  WDTCTL_D;
+    default:     reg_dec  =  {512{1'b0}};
+  endcase
+
+// Read/Write probes
+wire reg_write =  |per_wen   & per_en;
+wire reg_read  = ~|per_wen   & per_en;
+
+// Read/Write vectors
+wire [511:0] reg_wr    = reg_dec & {512{reg_write}};
+wire [511:0] reg_rd    = reg_dec & {512{reg_read}};
+
+
+//============================================================================
+// 3) REGISTERS
+//============================================================================
+
+// WDTCTL Register
+//-----------------
+// WDTNMI & WDTSSEL are not implemented and therefore masked
+   
+reg  [7:0] wdtctl;
+
+wire       wdtctl_wr = reg_wr[WDTCTL];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            wdtctl <=  8'h00;
+  else if (wdtctl_wr) wdtctl <=  per_din[7:0] & 8'hd7;
+
+wire       wdtpw_error = wdtctl_wr & (per_din[15:8]!=8'h5a);
+wire       wdttmsel    = wdtctl[4];
+
+
+//============================================================================
+// 3) REGISTERS
+//============================================================================
+
+// Data output mux
+wire [15:0] wdtctl_rd  = {8'h69, wdtctl}  & {16{reg_rd[WDTCTL]}};
+
+wire [15:0] per_dout   =  wdtctl_rd;
+
+
+//=============================================================================
+// 4)  NMI GENERATION
+//=============================================================================
+
+// Synchronization state
+reg [2:0] nmi_sync;
+always @ (posedge mclk or posedge puc)
+  if (puc)  nmi_sync <= 3'h0;
+  else      nmi_sync <= {nmi_sync[1:0], nmi};
+
+// Edge detection
+wire        nmi_re    = ~nmi_sync[2] &  nmi_sync[0] & nmie;
+wire        nmi_fe    =  nmi_sync[2] & ~nmi_sync[0] & nmie;
+
+// NMI event
+wire        nmi_evt   = wdtctl[6] ? nmi_fe : nmi_re;
+
+
+//=============================================================================
+// 5)  WATCHDOG TIMER
+//=============================================================================
+
+// Watchdog clock source selection
+//---------------------------------
+wire  clk_src_en = wdtctl[2] ? aclk_en : smclk_en;
+
+
+// Watchdog 16 bit counter
+//--------------------------
+reg [15:0] wdtcnt;
+
+wire       wdtcnt_clr = (wdtctl_wr & per_din[3]) | wdtifg_set;
+
+always @ (posedge mclk or posedge puc)
+  if (puc)                                        wdtcnt <= 16'h0000;
+  else if (wdtcnt_clr)                            wdtcnt <= 16'h0000;
+  else if (~wdtctl[7] & clk_src_en & ~dbg_freeze) wdtcnt <= wdtcnt+16'h0001;
+
+   
+// Interval selection mux
+//--------------------------
+reg        wdtqn;
+
+always @(wdtctl or wdtcnt)
+    case(wdtctl[1:0])
+      2'b00  : wdtqn =  wdtcnt[15];
+      2'b01  : wdtqn =  wdtcnt[13];
+      2'b10  : wdtqn =  wdtcnt[9];
+      default: wdtqn =  wdtcnt[6];
+    endcase
+
+
+// Watchdog event detection
+//-----------------------------
+reg        wdtqn_dly;
+
+always @ (posedge mclk or posedge puc)
+  if (puc) wdtqn_dly <= 1'b0;
+  else     wdtqn_dly <= wdtqn;
+
+wire       wdtifg_set =  (~wdtqn_dly & wdtqn) | wdtpw_error;
+
+
+endmodule // omsp_watchdog
+
+`include "openMSP430_undefines.v"
diff --git a/openMSP430.v b/openMSP430.v
new file mode 100644 (file)
index 0000000..2ee0881
--- /dev/null
@@ -0,0 +1,463 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2001 Authors
+//
+// This source file may be used and distributed without restriction provided
+// that this copyright statement is not removed from the file and that any
+// derivative work contains the original copyright notice and the associated
+// disclaimer.
+//
+// This source file is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// This source is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+// License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this source; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+//----------------------------------------------------------------------------
+//
+// *File Name: openMSP430.v
+// 
+// *Module Description:
+//                       openMSP430 Top level file
+//
+// *Author(s):
+//              - Olivier Girard,    olgirard@gmail.com
+//
+//----------------------------------------------------------------------------
+// $Rev: 67 $
+// $LastChangedBy: olivier.girard $
+// $LastChangedDate: 2010-03-07 12:59:38 +0100 (Sun, 07 Mar 2010) $
+//----------------------------------------------------------------------------
+`include "timescale.v"
+`include "openMSP430_defines.v"
+
+module  openMSP430 (
+
+// OUTPUTs
+    aclk_en,                       // ACLK enable
+    dbg_freeze,                    // Freeze peripherals
+    dbg_uart_txd,                  // Debug interface: UART TXD
+    dmem_addr,                     // Data Memory address
+    dmem_cen,                      // Data Memory chip enable (low active)
+    dmem_din,                      // Data Memory data input
+    dmem_wen,                      // Data Memory write enable (low active)
+    irq_acc,                       // Interrupt request accepted (one-hot signal)
+    mclk,                          // Main system clock
+    per_addr,                      // Peripheral address
+    per_din,                       // Peripheral data input
+    per_wen,                       // Peripheral write enable (high active)
+    per_en,                        // Peripheral enable (high active)
+    pmem_addr,                     // Program Memory address
+    pmem_cen,                      // Program Memory chip enable (low active)
+    pmem_din,                      // Program Memory data input (optional)
+    pmem_wen,                      // Program Memory write enable (low active) (optional)
+    puc,                           // Main system reset
+    smclk_en,                      // SMCLK enable
+
+// INPUTs
+    dbg_uart_rxd,                  // Debug interface: UART RXD
+    dco_clk,                       // Fast oscillator (fast clock)
+    dmem_dout,                     // Data Memory data output
+    irq,                           // Maskable interrupts
+    lfxt_clk,                      // Low frequency oscillator (typ 32kHz)
+    nmi,                           // Non-maskable interrupt (asynchronous)
+    per_dout,                      // Peripheral data output
+    pmem_dout,                     // Program Memory data output
+    reset_n                        // Reset Pin (low active)
+);
+
+// OUTPUTs
+//=========
+output               aclk_en;      // ACLK enable
+output               dbg_freeze;   // Freeze peripherals
+output               dbg_uart_txd; // Debug interface: UART TXD
+output [`DMEM_MSB:0] dmem_addr;    // Data Memory address
+output               dmem_cen;     // Data Memory chip enable (low active)
+output        [15:0] dmem_din;     // Data Memory data input
+output         [1:0] dmem_wen;     // Data Memory write enable (low active)
+output        [13:0] irq_acc;      // Interrupt request accepted (one-hot signal)
+output               mclk;         // Main system clock
+output         [7:0] per_addr;     // Peripheral address
+output        [15:0] per_din;      // Peripheral data input
+output         [1:0] per_wen;      // Peripheral write enable (high active)
+output               per_en;       // Peripheral enable (high active)
+output [`PMEM_MSB:0] pmem_addr;    // Program Memory address
+output               pmem_cen;     // Program Memory chip enable (low active)
+output        [15:0] pmem_din;     // Program Memory data input (optional)
+output         [1:0] pmem_wen;     // Program Memory write enable (low active) (optional)
+output               puc;          // Main system reset
+output               smclk_en;     // SMCLK enable
+
+
+// INPUTs
+//=========
+input                dbg_uart_rxd; // Debug interface: UART RXD
+input                dco_clk;      // Fast oscillator (fast clock)
+input         [15:0] dmem_dout;    // Data Memory data output
+input                [13:0] irq;          // Maskable interrupts
+input                lfxt_clk;     // Low frequency oscillator (typ 32kHz)
+input                       nmi;          // Non-maskable interrupt (asynchronous)
+input         [15:0] per_dout;     // Peripheral data output
+input         [15:0] pmem_dout;    // Program Memory data output
+input                reset_n;      // Reset Pin (active low)
+
+
+
+//=============================================================================
+// 1)  INTERNAL WIRES/REGISTERS/PARAMETERS DECLARATION
+//=============================================================================
+
+wire          [7:0] inst_ad;
+wire          [7:0] inst_as;
+wire         [11:0] inst_alu;
+wire                inst_bw;
+wire         [15:0] inst_dest;
+wire         [15:0] inst_dext;
+wire         [15:0] inst_sext;
+wire          [7:0] inst_so;
+wire         [15:0] inst_src;
+wire          [2:0] inst_type;
+wire          [3:0] e_state;
+wire                exec_done;
+
+wire         [15:0] eu_mab;
+wire         [15:0] eu_mdb_in;
+wire         [15:0] eu_mdb_out;
+wire          [1:0] eu_mb_wr;
+wire         [15:0] fe_mab;
+wire         [15:0] fe_mdb_in;
+
+wire         [15:0] pc_sw;
+wire          [7:0] inst_jmp;
+wire         [15:0] pc;
+wire         [15:0] pc_nxt;
+
+wire         [15:0] dbg_mem_addr;
+wire         [15:0] dbg_mem_dout;
+wire         [15:0] dbg_mem_din;
+wire         [15:0] dbg_reg_din;
+wire          [1:0] dbg_mem_wr;
+
+wire         [15:0] per_dout_or;
+wire         [15:0] per_dout_sfr;
+wire         [15:0] per_dout_wdog;
+wire         [15:0] per_dout_mpy;
+wire         [15:0] per_dout_clk;
+
+   
+//=============================================================================
+// 2)  GLOBAL CLOCK & RESET MANAGEMENT
+//=============================================================================
+
+omsp_clock_module clock_module_0 (
+
+// OUTPUTs
+    .aclk_en      (aclk_en),       // ACLK enablex
+    .mclk         (mclk),          // Main system clock
+    .per_dout     (per_dout_clk),  // Peripheral data output
+    .por          (por),           // Power-on reset
+    .puc          (puc),           // Main system reset
+    .smclk_en     (smclk_en),      // SMCLK enable
+            
+// INPUTs
+    .dbg_reset    (dbg_reset),     // Reset CPU from debug interface
+    .dco_clk      (dco_clk),       // Fast oscillator (fast clock)
+    .lfxt_clk     (lfxt_clk),      // Low frequency oscillator (typ 32kHz)
+    .oscoff       (oscoff),        // Turns off LFXT1 clock input
+    .per_addr     (per_addr),      // Peripheral address
+    .per_din      (per_din),       // Peripheral data input
+    .per_en       (per_en),        // Peripheral enable (high active)
+    .per_wen      (per_wen),       // Peripheral write enable (high active)
+    .reset_n      (reset_n),       // Reset Pin (low active)
+    .scg1         (scg1),          // System clock generator 1. Turns off the SMCLK
+    .wdt_reset    (wdt_reset)      // Watchdog-timer reset
+);
+
+   
+//=============================================================================
+// 3)  FRONTEND (<=> FETCH & DECODE)
+//=============================================================================
+
+omsp_frontend frontend_0 (
+
+// OUTPUTs
+    .dbg_halt_st  (dbg_halt_st),   // Halt/Run status from CPU
+    .decode_noirq (decode_noirq),  // Frontend decode instruction
+    .e_state      (e_state),       // Execution state
+    .exec_done    (exec_done),     // Execution completed
+    .inst_ad      (inst_ad),       // Decoded Inst: destination addressing mode
+    .inst_as      (inst_as),       // Decoded Inst: source addressing mode
+    .inst_alu     (inst_alu),      // ALU control signals
+    .inst_bw      (inst_bw),       // Decoded Inst: byte width
+    .inst_dest    (inst_dest),     // Decoded Inst: destination (one hot)
+    .inst_dext    (inst_dext),     // Decoded Inst: destination extended instruction word
+    .inst_irq_rst (inst_irq_rst),  // Decoded Inst: Reset interrupt
+    .inst_jmp     (inst_jmp),      // Decoded Inst: Conditional jump
+    .inst_sext    (inst_sext),     // Decoded Inst: source extended instruction word
+    .inst_so      (inst_so),       // Decoded Inst: Single-operand arithmetic
+    .inst_src     (inst_src),      // Decoded Inst: source (one hot)
+    .inst_type    (inst_type),     // Decoded Instruction type
+    .irq_acc      (irq_acc),       // Interrupt request accepted
+    .mab          (fe_mab),        // Frontend Memory address bus
+    .mb_en        (fe_mb_en),      // Frontend Memory bus enable
+    .nmi_acc      (nmi_acc),       // Non-Maskable interrupt request accepted
+    .pc           (pc),            // Program counter
+    .pc_nxt       (pc_nxt),        // Next PC value (for CALL & IRQ)
+                            
+// INPUTs
+    .cpuoff       (cpuoff),        // Turns off the CPU
+    .dbg_halt_cmd (dbg_halt_cmd),  // Halt CPU command
+    .dbg_reg_sel  (dbg_mem_addr[3:0]), // Debug selected register for rd/wr access
+    .fe_pmem_wait (fe_pmem_wait),  // Frontend wait for Instruction fetch
+    .gie          (gie),           // General interrupt enable
+    .irq          (irq),           // Maskable interrupts
+    .mclk         (mclk),          // Main system clock
+    .mdb_in       (fe_mdb_in),     // Frontend Memory data bus input
+    .nmi_evt      (nmi_evt),       // Non-maskable interrupt event
+    .pc_sw        (pc_sw),         // Program counter software value
+    .pc_sw_wr     (pc_sw_wr),      // Program counter software write
+    .puc          (puc),           // Main system reset
+    .wdt_irq      (wdt_irq)        // Watchdog-timer interrupt
+);
+
+
+//=============================================================================
+// 4)  EXECUTION UNIT
+//=============================================================================
+
+omsp_execution_unit execution_unit_0 (
+
+// OUTPUTs
+    .cpuoff       (cpuoff),        // Turns off the CPU
+    .dbg_reg_din  (dbg_reg_din),   // Debug unit CPU register data input
+    .mab          (eu_mab),        // Memory address bus
+    .mb_en        (eu_mb_en),      // Memory bus enable
+    .mb_wr        (eu_mb_wr),      // Memory bus write transfer
+    .mdb_out      (eu_mdb_out),    // Memory data bus output
+    .oscoff       (oscoff),        // Turns off LFXT1 clock input
+    .pc_sw        (pc_sw),         // Program counter software value
+    .pc_sw_wr     (pc_sw_wr),      // Program counter software write
+    .scg1         (scg1),          // System clock generator 1. Turns off the SMCLK
+
+// INPUTs
+    .dbg_halt_st  (dbg_halt_st),   // Halt/Run status from CPU
+    .dbg_mem_dout (dbg_mem_dout),  // Debug unit data output
+    .dbg_reg_wr   (dbg_reg_wr),    // Debug unit CPU register write
+    .e_state      (e_state),       // Execution state
+    .exec_done    (exec_done),     // Execution completed
+    .gie          (gie),           // General interrupt enable
+    .inst_ad      (inst_ad),       // Decoded Inst: destination addressing mode
+    .inst_as      (inst_as),       // Decoded Inst: source addressing mode
+    .inst_alu     (inst_alu),      // ALU control signals
+    .inst_bw      (inst_bw),       // Decoded Inst: byte width
+    .inst_dest    (inst_dest),     // Decoded Inst: destination (one hot)
+    .inst_dext    (inst_dext),     // Decoded Inst: destination extended instruction word
+    .inst_irq_rst (inst_irq_rst),  // Decoded Inst: reset interrupt
+    .inst_jmp     (inst_jmp),      // Decoded Inst: Conditional jump
+    .inst_sext    (inst_sext),     // Decoded Inst: source extended instruction word
+    .inst_so      (inst_so),       // Decoded Inst: Single-operand arithmetic
+    .inst_src     (inst_src),      // Decoded Inst: source (one hot)
+    .inst_type    (inst_type),     // Decoded Instruction type
+    .mclk         (mclk),          // Main system clock
+    .mdb_in       (eu_mdb_in),     // Memory data bus input
+    .pc           (pc),            // Program counter
+    .pc_nxt       (pc_nxt),        // Next PC value (for CALL & IRQ)
+    .puc          (puc)            // Main system reset
+);
+
+
+//=============================================================================
+// 5)  MEMORY BACKBONE
+//=============================================================================
+
+omsp_mem_backbone mem_backbone_0 (
+
+// OUTPUTs
+    .dbg_mem_din  (dbg_mem_din),   // Debug unit Memory data input
+    .dmem_addr    (dmem_addr),     // Data Memory address
+    .dmem_cen     (dmem_cen),      // Data Memory chip enable (low active)
+    .dmem_din     (dmem_din),      // Data Memory data input
+    .dmem_wen     (dmem_wen),      // Data Memory write enable (low active)
+    .eu_mdb_in    (eu_mdb_in),     // Execution Unit Memory data bus input
+    .fe_mdb_in    (fe_mdb_in),     // Frontend Memory data bus input
+    .fe_pmem_wait (fe_pmem_wait),  // Frontend wait for Instruction fetch
+    .per_addr     (per_addr),      // Peripheral address
+    .per_din      (per_din),       // Peripheral data input
+    .per_wen      (per_wen),       // Peripheral write enable (high active)
+    .per_en       (per_en),        // Peripheral enable (high active)
+    .pmem_addr    (pmem_addr),     // Program Memory address
+    .pmem_cen     (pmem_cen),      // Program Memory chip enable (low active)
+    .pmem_din     (pmem_din),      // Program Memory data input (optional)
+    .pmem_wen     (pmem_wen),      // Program Memory write enable (low active) (optional)
+                            
+// INPUTs
+    .dbg_halt_st  (dbg_halt_st),   // Halt/Run status from CPU
+    .dbg_mem_addr (dbg_mem_addr),  // Debug address for rd/wr access
+    .dbg_mem_dout (dbg_mem_dout),  // Debug unit data output
+    .dbg_mem_en   (dbg_mem_en),    // Debug unit memory enable
+    .dbg_mem_wr   (dbg_mem_wr),    // Debug unit memory write
+    .dmem_dout    (dmem_dout),     // Data Memory data output
+    .eu_mab       (eu_mab[15:1]),  // Execution Unit Memory address bus
+    .eu_mb_en     (eu_mb_en),      // Execution Unit Memory bus enable
+    .eu_mb_wr     (eu_mb_wr),      // Execution Unit Memory bus write transfer
+    .eu_mdb_out   (eu_mdb_out),    // Execution Unit Memory data bus output
+    .fe_mab       (fe_mab[15:1]),  // Frontend Memory address bus
+    .fe_mb_en     (fe_mb_en),      // Frontend Memory bus enable
+    .mclk         (mclk),          // Main system clock
+    .per_dout     (per_dout_or),   // Peripheral data output
+    .pmem_dout    (pmem_dout),     // Program Memory data output
+    .puc          (puc)            // Main system reset
+);
+
+
+//=============================================================================
+// 6)  SPECIAL FUNCTION REGISTERS
+//=============================================================================
+
+omsp_sfr sfr_0 (
+
+// OUTPUTs
+    .nmie         (nmie),          // Non-maskable interrupt enable
+    .per_dout     (per_dout_sfr),  // Peripheral data output
+    .wdt_irq      (wdt_irq),       // Watchdog-timer interrupt
+    .wdt_reset    (wdt_reset),     // Watchdog-timer reset
+    .wdtie        (wdtie),         // Watchdog-timer interrupt enable
+                            
+// INPUTs
+    .mclk         (mclk),          // Main system clock
+    .nmi_acc      (nmi_acc),       // Non-Maskable interrupt request accepted
+    .per_addr     (per_addr),      // Peripheral address
+    .per_din      (per_din),       // Peripheral data input
+    .per_en       (per_en),        // Peripheral enable (high active)
+    .per_wen      (per_wen),       // Peripheral write enable (high active)
+    .por          (por),           // Power-on reset
+    .puc          (puc),           // Main system reset
+    .wdtifg_clr   (irq_acc[10]),   // Clear Watchdog-timer interrupt flag
+    .wdtifg_set   (wdtifg_set),    // Set Watchdog-timer interrupt flag
+    .wdtpw_error  (wdtpw_error),   // Watchdog-timer password error
+    .wdttmsel     (wdttmsel)       // Watchdog-timer mode select
+);
+
+
+//=============================================================================
+// 7)  WATCHDOG TIMER
+//=============================================================================
+
+omsp_watchdog watchdog_0 (
+
+// OUTPUTs
+    .nmi_evt      (nmi_evt),       // NMI Event
+    .per_dout     (per_dout_wdog), // Peripheral data output
+    .wdtifg_set   (wdtifg_set),    // Set Watchdog-timer interrupt flag
+    .wdtpw_error  (wdtpw_error),   // Watchdog-timer password error
+    .wdttmsel     (wdttmsel),      // Watchdog-timer mode select
+                            
+// INPUTs
+    .aclk_en      (aclk_en),       // ACLK enable
+    .dbg_freeze   (dbg_freeze),    // Freeze Watchdog counter
+    .mclk         (mclk),          // Main system clock
+    .nmi          (nmi),           // Non-maskable interrupt (asynchronous)
+    .nmie         (nmie),          // Non-maskable interrupt enable
+    .per_addr     (per_addr),      // Peripheral address
+    .per_din      (per_din),       // Peripheral data input
+    .per_en       (per_en),        // Peripheral enable (high active)
+    .per_wen      (per_wen),       // Peripheral write enable (high active)
+    .puc          (puc),           // Main system reset
+    .smclk_en     (smclk_en),      // SMCLK enable
+    .wdtie        (wdtie)          // Watchdog-timer interrupt enable
+);
+
+
+//=============================================================================
+// 8)  HARDWARE MULTIPLIER
+//=============================================================================
+`ifdef MULTIPLIER
+omsp_multiplier multiplier_0 (
+
+// OUTPUTs
+    .per_dout     (per_dout_mpy),  // Peripheral data output
+                            
+// INPUTs
+    .mclk         (mclk),          // Main system clock
+    .per_addr     (per_addr),      // Peripheral address
+    .per_din      (per_din),       // Peripheral data input
+    .per_en       (per_en),        // Peripheral enable (high active)
+    .per_wen      (per_wen),       // Peripheral write enable (high active)
+    .puc          (puc)            // Main system reset
+);
+`else
+assign per_dout_mpy = 16'h0000;
+`endif
+   
+//=============================================================================
+// 9)  PERIPHERALS' OUTPUT BUS
+//=============================================================================
+
+assign  per_dout_or  =  per_dout      |
+                        per_dout_clk  |
+                        per_dout_sfr  |
+                        per_dout_wdog |
+                        per_dout_mpy;
+
+   
+//=============================================================================
+// 10)  DEBUG INTERFACE
+//=============================================================================
+
+`ifdef DBG_EN
+omsp_dbg dbg_0 (
+
+// OUTPUTs
+    .dbg_freeze   (dbg_freeze),    // Freeze peripherals
+    .dbg_halt_cmd (dbg_halt_cmd),  // Halt CPU command
+    .dbg_mem_addr (dbg_mem_addr),  // Debug address for rd/wr access
+    .dbg_mem_dout (dbg_mem_dout),  // Debug unit data output
+    .dbg_mem_en   (dbg_mem_en),    // Debug unit memory enable
+    .dbg_mem_wr   (dbg_mem_wr),    // Debug unit memory write
+    .dbg_reg_wr   (dbg_reg_wr),    // Debug unit CPU register write
+    .dbg_reset    (dbg_reset),     // Reset CPU from debug interface
+    .dbg_uart_txd (dbg_uart_txd),  // Debug interface: UART TXD
+                            
+// INPUTs
+    .dbg_halt_st  (dbg_halt_st),   // Halt/Run status from CPU
+    .dbg_mem_din  (dbg_mem_din),   // Debug unit Memory data input
+    .dbg_reg_din  (dbg_reg_din),   // Debug unit CPU register data input
+    .dbg_uart_rxd (dbg_uart_rxd),  // Debug interface: UART RXD
+    .decode_noirq (decode_noirq),  // Frontend decode instruction
+    .eu_mab       (eu_mab),        // Execution-Unit Memory address bus
+    .eu_mb_en     (eu_mb_en),      // Execution-Unit Memory bus enable
+    .eu_mb_wr     (eu_mb_wr),      // Execution-Unit Memory bus write transfer
+    .eu_mdb_in    (eu_mdb_in),     // Memory data bus input
+    .eu_mdb_out   (eu_mdb_out),    // Memory data bus output
+    .exec_done    (exec_done),     // Execution completed
+    .fe_mb_en     (fe_mb_en),      // Frontend Memory bus enable
+    .fe_mdb_in    (fe_mdb_in),     // Frontend Memory data bus input
+    .mclk         (mclk),          // Main system clock
+    .pc           (pc),            // Program counter
+    .por          (por),           // Power on reset
+    .puc          (puc)            // Main system reset
+);
+
+`else
+assign dbg_freeze   =  1'b0;
+assign dbg_halt_cmd =  1'b0;
+assign dbg_mem_addr = 16'h0000;
+assign dbg_mem_dout = 16'h0000;
+assign dbg_mem_en   =  1'b0;
+assign dbg_mem_wr   =  2'b00;
+assign dbg_reg_wr   =  1'b0;
+assign dbg_reset    =  1'b0;
+assign dbg_uart_txd =  1'b0;
+`endif
+
+   
+endmodule // openMSP430
+
+`include "openMSP430_undefines.v"
diff --git a/openMSP430_defines.v b/openMSP430_defines.v
new file mode 100644 (file)
index 0000000..0a71c10
--- /dev/null
@@ -0,0 +1,447 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2001 Authors
+//
+// This source file may be used and distributed without restriction provided
+// that this copyright statement is not removed from the file and that any
+// derivative work contains the original copyright notice and the associated
+// disclaimer.
+//
+// This source file is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// This source is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+// License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this source; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+//----------------------------------------------------------------------------
+// 
+// *File Name: openMSP430_defines.v
+// 
+// *Module Description:
+//                      openMSP430 Configuration file
+//
+// *Author(s):
+//              - Olivier Girard,    olgirard@gmail.com
+//
+//----------------------------------------------------------------------------
+// $Rev: 74 $
+// $LastChangedBy: olivier.girard $
+// $LastChangedDate: 2010-08-28 21:53:08 +0200 (Sat, 28 Aug 2010) $
+//----------------------------------------------------------------------------
+`include "openMSP430_undefines.v"
+
+//----------------------------------------------------------------------------
+// SYSTEM CONFIGURATION
+//----------------------------------------------------------------------------
+//
+// Note: the sum of both program and data memories should not exceed 63.5 kB
+//
+
+// Program Memory Size:
+//                     Uncomment the required memory size
+//-------------------------------------------------------
+//`define PMEM_SIZE_59_KB
+//`define PMEM_SIZE_55_KB
+//`define PMEM_SIZE_54_KB
+//`define PMEM_SIZE_51_KB
+//`define PMEM_SIZE_48_KB
+//`define PMEM_SIZE_41_KB
+//`define PMEM_SIZE_32_KB
+//`define PMEM_SIZE_24_KB
+//`define PMEM_SIZE_16_KB
+//`define PMEM_SIZE_12_KB
+//`define PMEM_SIZE_8_KB
+//`define PMEM_SIZE_4_KB
+`define PMEM_SIZE_2_KB
+//`define PMEM_SIZE_1_KB
+
+// Data Memory Size:
+//                     Uncomment the required memory size
+//-------------------------------------------------------
+//`define DMEM_SIZE_32_KB
+//`define DMEM_SIZE_24_KB
+//`define DMEM_SIZE_16_KB
+//`define DMEM_SIZE_10_KB
+//`define DMEM_SIZE_8_KB
+//`define DMEM_SIZE_5_KB
+//`define DMEM_SIZE_4_KB
+//`define DMEM_SIZE_2p5_KB
+//`define DMEM_SIZE_2_KB
+//`define DMEM_SIZE_1_KB
+//`define DMEM_SIZE_512_B
+//`define DMEM_SIZE_256_B
+`define DMEM_SIZE_128_B
+
+  
+// Include/Exclude Hardware Multiplier
+`define MULTIPLIER
+
+
+//----------------------------------------------------------------------------
+// REMOTE DEBUGGING INTERFACE CONFIGURATION
+//----------------------------------------------------------------------------
+
+// Include Debug interface
+`define DBG_EN
+
+// Debug interface selection
+//             `define DBG_UART -> Enable UART (8N1) debug interface
+//             `define DBG_JTAG -> DON'T UNCOMMENT, NOT SUPPORTED
+//
+`define DBG_UART
+//`define DBG_JTAG
+
+// Number of hardware breakpoints (each unit contains 2 hw address breakpoints)
+//             `define DBG_HWBRK_0 -> Include hardware breakpoints unit 0
+//             `define DBG_HWBRK_1 -> Include hardware breakpoints unit 1
+//             `define DBG_HWBRK_2 -> Include hardware breakpoints unit 2
+//             `define DBG_HWBRK_3 -> Include hardware breakpoints unit 3
+//
+`define  DBG_HWBRK_0
+`define  DBG_HWBRK_1
+`define  DBG_HWBRK_2
+`define  DBG_HWBRK_3
+
+
+//==========================================================================//
+//==========================================================================//
+//==========================================================================//
+//==========================================================================//
+//=====        SYSTEM CONSTANTS --- !!!!!!!! DO NOT EDIT !!!!!!!!      =====//
+//==========================================================================//
+//==========================================================================//
+//==========================================================================//
+//==========================================================================//
+
+//
+// PROGRAM & DATA MEMORY CONFIGURATION
+//======================================
+
+// Program Memory Size
+`ifdef PMEM_SIZE_59_KB
+  `define PMEM_AWIDTH      15
+  `define PMEM_SIZE     60416
+`endif
+`ifdef PMEM_SIZE_55_KB
+  `define PMEM_AWIDTH      15
+  `define PMEM_SIZE     56320
+`endif
+`ifdef PMEM_SIZE_54_KB
+  `define PMEM_AWIDTH      15
+  `define PMEM_SIZE     55296
+`endif
+`ifdef PMEM_SIZE_51_KB
+  `define PMEM_AWIDTH      15
+  `define PMEM_SIZE     52224
+`endif
+`ifdef PMEM_SIZE_48_KB
+  `define PMEM_AWIDTH      15
+  `define PMEM_SIZE     49152
+`endif
+`ifdef PMEM_SIZE_41_KB
+  `define PMEM_AWIDTH      15
+  `define PMEM_SIZE     41984
+`endif
+`ifdef PMEM_SIZE_32_KB
+  `define PMEM_AWIDTH      14
+  `define PMEM_SIZE     32768
+`endif
+`ifdef PMEM_SIZE_24_KB
+  `define PMEM_AWIDTH      14
+  `define PMEM_SIZE     24576
+`endif
+`ifdef PMEM_SIZE_16_KB
+  `define PMEM_AWIDTH      13
+  `define PMEM_SIZE     16384
+`endif
+`ifdef PMEM_SIZE_12_KB
+  `define PMEM_AWIDTH      13
+  `define PMEM_SIZE     12288
+`endif
+`ifdef PMEM_SIZE_8_KB
+  `define PMEM_AWIDTH      12
+  `define PMEM_SIZE      8192
+`endif
+`ifdef PMEM_SIZE_4_KB
+  `define PMEM_AWIDTH      11
+  `define PMEM_SIZE      4096
+`endif
+`ifdef PMEM_SIZE_2_KB
+  `define PMEM_AWIDTH      10
+  `define PMEM_SIZE      2048
+`endif
+`ifdef PMEM_SIZE_1_KB
+  `define PMEM_AWIDTH       9
+  `define PMEM_SIZE      1024
+`endif
+
+// Data Memory Size
+`ifdef DMEM_SIZE_32_KB
+  `define DMEM_AWIDTH       14
+  `define DMEM_SIZE      32768
+`endif
+`ifdef DMEM_SIZE_24_KB
+  `define DMEM_AWIDTH       14
+  `define DMEM_SIZE      24576
+`endif
+`ifdef DMEM_SIZE_16_KB
+  `define DMEM_AWIDTH       13
+  `define DMEM_SIZE      16384
+`endif
+`ifdef DMEM_SIZE_10_KB
+  `define DMEM_AWIDTH       13
+  `define DMEM_SIZE      10240
+`endif
+`ifdef DMEM_SIZE_8_KB
+  `define DMEM_AWIDTH       12
+  `define DMEM_SIZE       8192
+`endif
+`ifdef DMEM_SIZE_5_KB
+  `define DMEM_AWIDTH       12
+  `define DMEM_SIZE       5120
+`endif
+`ifdef DMEM_SIZE_4_KB
+  `define DMEM_AWIDTH       11
+  `define DMEM_SIZE       4096
+`endif
+`ifdef DMEM_SIZE_2p5_KB
+  `define DMEM_AWIDTH       11
+  `define DMEM_SIZE       2560
+`endif
+`ifdef DMEM_SIZE_2_KB
+  `define DMEM_AWIDTH       10
+  `define DMEM_SIZE       2048
+`endif
+`ifdef DMEM_SIZE_1_KB
+  `define DMEM_AWIDTH        9
+  `define DMEM_SIZE       1024
+`endif
+`ifdef DMEM_SIZE_512_B
+  `define DMEM_AWIDTH        8
+  `define DMEM_SIZE        512
+`endif
+`ifdef DMEM_SIZE_256_B
+  `define DMEM_AWIDTH        7
+  `define DMEM_SIZE        256
+`endif
+`ifdef DMEM_SIZE_128_B
+  `define DMEM_AWIDTH        6
+  `define DMEM_SIZE        128
+`endif
+
+// Data Memory Base Adresses
+`define DMEM_BASE  16'h0200
+
+// Program & Data Memory most significant address bit (for 16 bit words)
+`define PMEM_MSB   `PMEM_AWIDTH-1
+`define DMEM_MSB   `DMEM_AWIDTH-1
+
+//
+// STATES, REGISTER FIELDS, ...
+//======================================
+
+// Instructions type
+`define INST_SO  0
+`define INST_JMP 1
+`define INST_TO  2
+
+// Single-operand arithmetic
+`define RRC    0
+`define SWPB   1
+`define RRA    2
+`define SXT    3
+`define PUSH   4
+`define CALL   5
+`define RETI   6
+`define IRQ    7
+
+// Conditional jump
+`define JNE    0
+`define JEQ    1
+`define JNC    2
+`define JC     3
+`define JN     4
+`define JGE    5
+`define JL     6
+`define JMP    7
+
+// Two-operand arithmetic
+`define MOV    0
+`define ADD    1
+`define ADDC   2
+`define SUBC   3
+`define SUB    4
+`define CMP    5
+`define DADD   6
+`define BIT    7
+`define BIC    8
+`define BIS    9
+`define XOR   10
+`define AND   11
+
+// Addressing modes
+`define DIR      0
+`define IDX      1
+`define INDIR    2
+`define INDIR_I  3
+`define SYMB     4
+`define IMM      5
+`define ABS      6
+`define CONST    7
+
+// Execution state machine
+`define E_IRQ_0    4'h0
+`define E_IRQ_1    4'h1
+`define E_IRQ_2    4'h2
+`define E_IRQ_3    4'h3
+`define E_IRQ_4    4'h4
+`define E_SRC_AD   4'h5
+`define E_SRC_RD   4'h6
+`define E_SRC_WR   4'h7
+`define E_DST_AD   4'h8
+`define E_DST_RD   4'h9
+`define E_DST_WR   4'hA
+`define E_EXEC     4'hB
+`define E_JUMP     4'hC
+`define E_IDLE     4'hD
+
+// ALU control signals
+`define ALU_SRC_INV   0
+`define ALU_INC       1
+`define ALU_INC_C     2
+`define ALU_ADD       3
+`define ALU_AND       4
+`define ALU_OR        5
+`define ALU_XOR       6
+`define ALU_DADD      7
+`define ALU_STAT_7    8
+`define ALU_STAT_F    9
+`define ALU_SHIFT    10
+`define EXEC_NO_WR   11
+
+// Debug interface
+`define DBG_UART_WR   18
+`define DBG_UART_BW   17
+`define DBG_UART_ADDR 16:11
+
+// Debug interface CPU_CTL register
+`define HALT        0
+`define RUN         1
+`define ISTEP       2
+`define SW_BRK_EN   3
+`define FRZ_BRK_EN  4
+`define RST_BRK_EN  5
+`define CPU_RST     6
+
+// Debug interface CPU_STAT register
+`define HALT_RUN    0
+`define PUC_PND     1
+`define SWBRK_PND   3
+`define HWBRK0_PND  4
+`define HWBRK1_PND  5
+
+// Debug interface BRKx_CTL register
+`define BRK_MODE_RD 0
+`define BRK_MODE_WR 1
+`define BRK_MODE    1:0
+`define BRK_EN      2
+`define BRK_I_EN    3
+`define BRK_RANGE   4
+
+// Basic clock module: BCSCTL1 Control Register
+`define DIVAx       5:4
+
+// Basic clock module: BCSCTL2 Control Register
+`define SELS        3
+`define DIVSx       2:1
+
+// Timer A: TACTL Control Register
+`define TASSELx     9:8
+`define TAIDx       7:6
+`define TAMCx       5:4
+`define TACLR       2
+`define TAIE        1
+`define TAIFG       0
+
+// Timer A: TACCTLx Capture/Compare Control Register
+`define TACMx      15:14
+`define TACCISx    13:12
+`define TASCS      11
+`define TASCCI     10
+`define TACAP       8
+`define TAOUTMODx   7:5
+`define TACCIE      4
+`define TACCI       3
+`define TAOUT       2
+`define TACOV       1
+`define TACCIFG     0
+
+
+//
+// DEBUG INTERFACE EXTRA CONFIGURATION
+//======================================
+
+// Debug interface: Software breakpoint opcode
+`define DBG_SWBRK_OP 16'h4343
+
+// Debug UART interface auto data synchronization
+// If the following define is commented out, then
+// the DBG_UART_BAUD and DBG_DCO_FREQ need to be properly
+// defined.
+`define DBG_UART_AUTO_SYNC
+
+// Debug UART interface data rate
+//      In order to properly setup the UART debug interface, you
+//      need to specify the DCO_CLK frequency (DBG_DCO_FREQ) and
+//      the chosen BAUD rate from the UART interface.
+//
+//`define DBG_UART_BAUD    9600
+//`define DBG_UART_BAUD   19200
+//`define DBG_UART_BAUD   38400
+//`define DBG_UART_BAUD   57600
+//`define DBG_UART_BAUD  115200
+//`define DBG_UART_BAUD  230400
+//`define DBG_UART_BAUD  460800
+//`define DBG_UART_BAUD  576000
+//`define DBG_UART_BAUD  921600
+`define DBG_UART_BAUD 2000000
+`define DBG_DCO_FREQ  20000000
+`define DBG_UART_CNT ((`DBG_DCO_FREQ/`DBG_UART_BAUD)-1)
+
+// Enable/Disable the hardware breakpoint RANGE mode
+`define HWBRK_RANGE 1'b0
+
+// Counter width for the debug interface UART
+`define DBG_UART_XFER_CNT_W 16
+
+// Check configuration
+`ifdef DBG_EN
+ `ifdef DBG_UART
+   `ifdef DBG_JTAG
+CONFIGURATION ERROR: JTAG AND UART DEBUG INTERFACE ARE BOTH ENABLED
+   `endif
+ `else
+   `ifdef DBG_JTAG
+CONFIGURATION ERROR: JTAG INTERFACE NOT SUPPORTED
+   `else
+CONFIGURATION ERROR: JTAG OR UART DEBUG INTERFACE SHOULD BE ENABLED
+   `endif
+ `endif
+`endif
+
+//
+// MULTIPLIER CONFIGURATION
+//======================================
+
+// If uncommented, the following define selects
+// the 16x16 multiplier (1 cycle) instead of the
+// default 16x8 multplier (2 cycles)
+//`define MPY_16x16
+  
\ No newline at end of file
diff --git a/openMSP430_undefines.v b/openMSP430_undefines.v
new file mode 100644 (file)
index 0000000..806ae5b
--- /dev/null
@@ -0,0 +1,598 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2001 Authors
+//
+// This source file may be used and distributed without restriction provided
+// that this copyright statement is not removed from the file and that any
+// derivative work contains the original copyright notice and the associated
+// disclaimer.
+//
+// This source file is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// This source is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+// License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this source; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+//----------------------------------------------------------------------------
+// 
+// *File Name: openMSP430_undefines.v
+// 
+// *Module Description:
+//                      openMSP430 Verilog `undef file
+//
+// *Author(s):
+//              - Olivier Girard,    olgirard@gmail.com
+//
+//----------------------------------------------------------------------------
+// $Rev: 23 $
+// $LastChangedBy: olivier.girard $
+// $LastChangedDate: 2009-08-30 18:39:26 +0200 (Sun, 30 Aug 2009) $
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// SYSTEM CONFIGURATION
+//----------------------------------------------------------------------------
+
+// Program Memory Size:
+`ifdef PMEM_AWIDTH
+`undef PMEM_AWIDTH
+`endif
+
+// Data Memory Size:
+`ifdef DMEM_AWIDTH
+`undef DMEM_AWIDTH
+`endif
+
+// Include/Exclude Hardware Multiplier
+`ifdef MULTIPLIER
+`undef MULTIPLIER
+`endif
+
+//----------------------------------------------------------------------------
+// REMOTE DEBUGGING INTERFACE CONFIGURATION
+//----------------------------------------------------------------------------
+
+// Include Debug interface
+`ifdef DBG_EN
+`undef DBG_EN
+`endif
+
+// Debug interface selection
+`ifdef DBG_UART
+`undef DBG_UART
+`endif
+`ifdef DBG_JTAG
+`undef DBG_JTAG
+`endif
+
+// Number of hardware breakpoints
+`ifdef DBG_HWBRK_0
+`undef DBG_HWBRK_0
+`endif
+`ifdef DBG_HWBRK_1
+`undef DBG_HWBRK_1
+`endif
+`ifdef DBG_HWBRK_2
+`undef DBG_HWBRK_2
+`endif
+`ifdef DBG_HWBRK_3
+`undef DBG_HWBRK_3
+`endif
+
+
+//==========================================================================//
+//==========================================================================//
+//==========================================================================//
+//==========================================================================//
+//=====        SYSTEM CONSTANTS --- !!!!!!!! DO NOT EDIT !!!!!!!!      =====//
+//==========================================================================//
+//==========================================================================//
+//==========================================================================//
+//==========================================================================//
+
+// Program and Data Memory sizes
+`ifdef PMEM_SIZE_59_KB
+`undef PMEM_SIZE_59_KB
+`endif
+`ifdef PMEM_SIZE_55_KB
+`undef PMEM_SIZE_55_KB
+`endif
+`ifdef PMEM_SIZE_54_KB
+`undef PMEM_SIZE_54_KB
+`endif
+`ifdef PMEM_SIZE_51_KB
+`undef PMEM_SIZE_51_KB
+`endif
+`ifdef PMEM_SIZE_48_KB
+`undef PMEM_SIZE_48_KB
+`endif
+`ifdef PMEM_SIZE_41_KB
+`undef PMEM_SIZE_41_KB
+`endif
+`ifdef PMEM_SIZE_32_KB
+`undef PMEM_SIZE_32_KB
+`endif
+`ifdef PMEM_SIZE_24_KB
+`undef PMEM_SIZE_24_KB
+`endif
+`ifdef PMEM_SIZE_16_KB
+`undef PMEM_SIZE_16_KB
+`endif
+`ifdef PMEM_SIZE_12_KB
+`undef PMEM_SIZE_12_KB
+`endif
+`ifdef PMEM_SIZE_8_KB
+`undef PMEM_SIZE_8_KB
+`endif
+`ifdef PMEM_SIZE_4_KB
+`undef PMEM_SIZE_4_KB
+`endif
+`ifdef PMEM_SIZE_2_KB
+`undef PMEM_SIZE_2_KB
+`endif
+`ifdef PMEM_SIZE_1_KB
+`undef PMEM_SIZE_1_KB
+`endif
+`ifdef DMEM_SIZE_32_KB
+`undef DMEM_SIZE_32_KB
+`endif
+`ifdef DMEM_SIZE_24_KB
+`undef DMEM_SIZE_24_KB
+`endif
+`ifdef DMEM_SIZE_16_KB
+`undef DMEM_SIZE_16_KB
+`endif
+`ifdef DMEM_SIZE_10_KB
+`undef DMEM_SIZE_10_KB
+`endif
+`ifdef DMEM_SIZE_8_KB
+`undef DMEM_SIZE_8_KB
+`endif
+`ifdef DMEM_SIZE_5_KB
+`undef DMEM_SIZE_5_KB
+`endif
+`ifdef DMEM_SIZE_4_KB
+`undef DMEM_SIZE_4_KB
+`endif
+`ifdef DMEM_SIZE_2p5_KB
+`undef DMEM_SIZE_2p5_KB
+`endif
+`ifdef DMEM_SIZE_2_KB
+`undef DMEM_SIZE_2_KB
+`endif
+`ifdef DMEM_SIZE_1_KB
+`undef DMEM_SIZE_1_KB
+`endif
+`ifdef DMEM_SIZE_512_B
+`undef DMEM_SIZE_512_B
+`endif
+`ifdef DMEM_SIZE_256_B
+`undef DMEM_SIZE_256_B
+`endif
+`ifdef DMEM_SIZE_128_B
+`undef DMEM_SIZE_128_B
+`endif
+`ifdef PMEM_SIZE
+`undef PMEM_SIZE
+`endif
+`ifdef PMEM_AWIDTH
+`undef PMEM_AWIDTH
+`endif
+`ifdef DMEM_SIZE
+`undef DMEM_SIZE
+`endif
+`ifdef DMEM_AWIDTH
+`undef DMEM_AWIDTH
+`endif
+
+// Data Memory Base Adresses
+`ifdef DMEM_BASE
+`undef DMEM_BASE
+`endif
+
+// Program & Data Memory most significant address bit (for 16 bit words)
+`ifdef PMEM_MSB
+`undef PMEM_MSB
+`endif
+`ifdef DMEM_MSB
+`undef DMEM_MSB
+`endif
+
+
+// Instructions type
+`ifdef INST_SO
+`undef INST_SO
+`endif
+`ifdef INST_JMP
+`undef INST_JMP
+`endif
+`ifdef INST_TO
+`undef INST_TO
+`endif
+
+// Single-operand arithmetic
+`ifdef RRC
+`undef RRC
+`endif
+`ifdef SWPB
+`undef SWPB
+`endif
+`ifdef RRA
+`undef RRA
+`endif
+`ifdef SXT
+`undef SXT
+`endif
+`ifdef PUSH
+`undef PUSH
+`endif
+`ifdef CALL
+`undef CALL
+`endif
+`ifdef RETI
+`undef RETI
+`endif
+`ifdef IRQ
+`undef IRQ
+`endif
+
+// Conditional jump
+`ifdef JNE
+`undef JNE
+`endif
+`ifdef JEQ
+`undef JEQ
+`endif
+`ifdef JNC
+`undef JNC
+`endif
+`ifdef JC
+`undef JC
+`endif
+`ifdef JN
+`undef JN
+`endif
+`ifdef JGE
+`undef JGE
+`endif
+`ifdef JL
+`undef JL
+`endif
+`ifdef JMP
+`undef JMP
+`endif
+
+// Two-operand arithmetic
+`ifdef MOV
+`undef MOV
+`endif
+`ifdef ADD
+`undef ADD
+`endif
+`ifdef ADDC
+`undef ADDC
+`endif
+`ifdef SUBC
+`undef SUBC
+`endif
+`ifdef SUB
+`undef SUB
+`endif
+`ifdef CMP
+`undef CMP
+`endif
+`ifdef DADD
+`undef DADD
+`endif
+`ifdef BIT
+`undef BIT
+`endif
+`ifdef BIC
+`undef BIC
+`endif
+`ifdef BIS
+`undef BIS
+`endif
+`ifdef XOR
+`undef XOR
+`endif
+`ifdef AND
+`undef AND
+`endif
+
+// Addressing modes
+`ifdef DIR
+`undef DIR
+`endif
+`ifdef IDX
+`undef IDX
+`endif
+`ifdef INDIR
+`undef INDIR
+`endif
+`ifdef INDIR_I
+`undef INDIR_I
+`endif
+`ifdef SYMB
+`undef SYMB
+`endif
+`ifdef IMM
+`undef IMM
+`endif
+`ifdef ABS
+`undef ABS
+`endif
+`ifdef CONST
+`undef CONST
+`endif
+
+// Execution state machine
+`ifdef E_IRQ_0
+`undef E_IRQ_0
+`endif
+`ifdef E_IRQ_1
+`undef E_IRQ_1
+`endif
+`ifdef E_IRQ_2
+`undef E_IRQ_2
+`endif
+`ifdef E_IRQ_3
+`undef E_IRQ_3
+`endif
+`ifdef E_IRQ_4
+`undef E_IRQ_4
+`endif
+`ifdef E_SRC_AD
+`undef E_SRC_AD
+`endif
+`ifdef E_SRC_RD
+`undef E_SRC_RD
+`endif
+`ifdef E_SRC_WR
+`undef E_SRC_WR
+`endif
+`ifdef E_DST_AD
+`undef E_DST_AD
+`endif
+`ifdef E_DST_RD
+`undef E_DST_RD
+`endif
+`ifdef E_DST_WR
+`undef E_DST_WR
+`endif
+`ifdef E_EXEC
+`undef E_EXEC
+`endif
+`ifdef E_JUMP
+`undef E_JUMP
+`endif
+`ifdef E_IDLE
+`undef E_IDLE
+`endif
+
+// ALU control signals
+`ifdef ALU_SRC_INV
+`undef ALU_SRC_INV
+`endif
+`ifdef ALU_INC
+`undef ALU_INC
+`endif
+`ifdef ALU_INC_C
+`undef ALU_INC_C
+`endif
+`ifdef ALU_ADD
+`undef ALU_ADD
+`endif
+`ifdef ALU_AND
+`undef ALU_AND
+`endif
+`ifdef ALU_OR
+`undef ALU_OR
+`endif
+`ifdef ALU_XOR
+`undef ALU_XOR
+`endif
+`ifdef ALU_DADD
+`undef ALU_DADD
+`endif
+`ifdef ALU_STAT_7
+`undef ALU_STAT_7
+`endif
+`ifdef ALU_STAT_F
+`undef ALU_STAT_F
+`endif
+`ifdef ALU_SHIFT
+`undef ALU_SHIFT
+`endif
+`ifdef EXEC_NO_WR
+`undef EXEC_NO_WR
+`endif
+
+// Debug interface
+`ifdef DBG_UART_WR
+`undef DBG_UART_WR
+`endif
+`ifdef DBG_UART_BW
+`undef DBG_UART_BW
+`endif
+`ifdef DBG_UART_ADDR
+`undef DBG_UART_ADDR
+`endif
+
+// Debug interface CPU_CTL register
+`ifdef HALT
+`undef HALT
+`endif
+`ifdef RUN
+`undef RUN
+`endif
+`ifdef ISTEP
+`undef ISTEP
+`endif
+`ifdef SW_BRK_EN
+`undef SW_BRK_EN
+`endif
+`ifdef FRZ_BRK_EN
+`undef FRZ_BRK_EN
+`endif
+`ifdef RST_BRK_EN
+`undef RST_BRK_EN
+`endif
+`ifdef CPU_RST
+`undef CPU_RST
+`endif
+
+// Debug interface CPU_STAT register
+`ifdef HALT_RUN
+`undef HALT_RUN
+`endif
+`ifdef PUC_PND
+`undef PUC_PND
+`endif
+`ifdef SWBRK_PND
+`undef SWBRK_PND
+`endif
+`ifdef HWBRK0_PND
+`undef HWBRK0_PND
+`endif
+`ifdef HWBRK1_PND
+`undef HWBRK1_PND
+`endif
+
+// Debug interface BRKx_CTL register
+`ifdef BRK_MODE_RD
+`undef BRK_MODE_RD
+`endif
+`ifdef BRK_MODE_WR
+`undef BRK_MODE_WR
+`endif
+`ifdef BRK_MODE
+`undef BRK_MODE
+`endif
+`ifdef BRK_EN
+`undef BRK_EN
+`endif
+`ifdef BRK_I_EN
+`undef BRK_I_EN
+`endif
+`ifdef BRK_RANGE
+`undef BRK_RANGE
+`endif
+
+// Basic clock module: BCSCTL1 Control Register
+`ifdef DIVAx
+`undef DIVAx
+`endif
+
+// Basic clock module: BCSCTL2 Control Register
+`ifdef SELS
+`undef SELS
+`endif
+`ifdef DIVSx
+`undef DIVSx
+`endif
+
+// Timer A: TACTL Control Register
+`ifdef TASSELx
+`undef TASSELx
+`endif
+`ifdef TAIDx
+`undef TAIDx
+`endif
+`ifdef TAMCx
+`undef TAMCx
+`endif
+`ifdef TACLR
+`undef TACLR
+`endif
+`ifdef TAIE
+`undef TAIE
+`endif
+`ifdef TAIFG
+`undef TAIFG
+`endif
+
+// Timer A: TACCTLx Capture/Compare Control Register
+`ifdef TACMx
+`undef TACMx
+`endif
+`ifdef TACCISx
+`undef TACCISx
+`endif
+`ifdef TASCS
+`undef TASCS
+`endif
+`ifdef TASCCI
+`undef TASCCI
+`endif
+`ifdef TACAP
+`undef TACAP
+`endif
+`ifdef TAOUTMODx
+`undef TAOUTMODx
+`endif
+`ifdef TACCIE
+`undef TACCIE
+`endif
+`ifdef TACCI
+`undef TACCI
+`endif
+`ifdef TAOUT
+`undef TAOUT
+`endif
+`ifdef TACOV
+`undef TACOV
+`endif
+`ifdef TACCIFG
+`undef TACCIFG
+`endif
+
+//
+// DEBUG INTERFACE EXTRA CONFIGURATION
+//======================================
+
+// Debug interface: Software breakpoint opcode
+`ifdef DBG_SWBRK_OP
+`undef DBG_SWBRK_OP
+`endif
+
+// Debug UART interface auto data synchronization
+`ifdef DBG_UART_AUTO_SYNC
+`undef DBG_UART_AUTO_SYNC
+`endif
+
+// Debug UART interface data rate
+`ifdef DBG_UART_BAUD
+`undef DBG_UART_BAUD
+`endif
+`ifdef DBG_DCO_FREQ
+`undef DBG_DCO_FREQ
+`endif
+`ifdef DBG_UART_CNT
+`undef DBG_UART_CNT
+`endif
+
+// Enable/Disable the hardware breakpoint RANGE mode
+`ifdef HWBRK_RANGE
+`undef HWBRK_RANGE
+`endif
+
+// Counter width for the debug interface UART
+`ifdef DBG_UART_XFER_CNT_W
+`undef DBG_UART_XFER_CNT_W
+`endif
+
+//
+// MULTIPLIER CONFIGURATION
+//======================================
+
+`ifdef MPY_16x16
+`undef MPY_16x16
+`endif
diff --git a/periph/omsp_gpio.v b/periph/omsp_gpio.v
new file mode 100644 (file)
index 0000000..2101447
--- /dev/null
@@ -0,0 +1,828 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2001 Authors
+//
+// This source file may be used and distributed without restriction provided
+// that this copyright statement is not removed from the file and that any
+// derivative work contains the original copyright notice and the associated
+// disclaimer.
+//
+// This source file is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// This source is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+// License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this source; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+//----------------------------------------------------------------------------
+//
+// *File Name: omsp_gpio.v
+// 
+// *Module Description:
+//                       Digital I/O interface
+//
+// *Author(s):
+//              - Olivier Girard,    olgirard@gmail.com
+//
+//----------------------------------------------------------------------------
+// $Rev: 79 $
+// $LastChangedBy: olivier.girard $
+// $LastChangedDate: 2010-11-23 20:36:16 +0100 (Tue, 23 Nov 2010) $
+//----------------------------------------------------------------------------
+`include "timescale.v"
+`include "openMSP430_defines.v"
+
+module  omsp_gpio (
+
+// OUTPUTs
+    irq_port1,                      // Port 1 interrupt
+    irq_port2,                      // Port 2 interrupt
+    p1_dout,                        // Port 1 data output
+    p1_dout_en,                     // Port 1 data output enable
+    p1_sel,                         // Port 1 function select
+    p2_dout,                        // Port 2 data output
+    p2_dout_en,                     // Port 2 data output enable
+    p2_sel,                         // Port 2 function select
+    p3_dout,                        // Port 3 data output
+    p3_dout_en,                     // Port 3 data output enable
+    p3_sel,                         // Port 3 function select
+    p4_dout,                        // Port 4 data output
+    p4_dout_en,                     // Port 4 data output enable
+    p4_sel,                         // Port 4 function select
+    p5_dout,                        // Port 5 data output
+    p5_dout_en,                     // Port 5 data output enable
+    p5_sel,                         // Port 5 function select
+    p6_dout,                        // Port 6 data output
+    p6_dout_en,                     // Port 6 data output enable
+    p6_sel,                         // Port 6 function select
+    per_dout,                       // Peripheral data output
+
+// INPUTs
+    mclk,                           // Main system clock
+    p1_din,                         // Port 1 data input
+    p2_din,                         // Port 2 data input
+    p3_din,                         // Port 3 data input
+    p4_din,                         // Port 4 data input
+    p5_din,                         // Port 5 data input
+    p6_din,                         // Port 6 data input
+    per_addr,                       // Peripheral address
+    per_din,                        // Peripheral data input
+    per_en,                         // Peripheral enable (high active)
+    per_wen,                        // Peripheral write enable (high active)
+    puc                             // Main system reset
+);
+
+// PARAMETERs
+//============
+parameter           P1_EN = 1'b1;   // Enable Port 1
+parameter           P2_EN = 1'b1;   // Enable Port 2
+parameter           P3_EN = 1'b0;   // Enable Port 3
+parameter           P4_EN = 1'b0;   // Enable Port 4
+parameter           P5_EN = 1'b0;   // Enable Port 5
+parameter           P6_EN = 1'b0;   // Enable Port 6
+
+
+// OUTPUTs
+//=========
+output              irq_port1;      // Port 1 interrupt
+output              irq_port2;      // Port 2 interrupt
+output        [7:0] p1_dout;        // Port 1 data output
+output        [7:0] p1_dout_en;     // Port 1 data output enable
+output        [7:0] p1_sel;         // Port 1 function select
+output        [7:0] p2_dout;        // Port 2 data output
+output        [7:0] p2_dout_en;     // Port 2 data output enable
+output        [7:0] p2_sel;         // Port 2 function select
+output        [7:0] p3_dout;        // Port 3 data output
+output        [7:0] p3_dout_en;     // Port 3 data output enable
+output        [7:0] p3_sel;         // Port 3 function select
+output        [7:0] p4_dout;        // Port 4 data output
+output        [7:0] p4_dout_en;     // Port 4 data output enable
+output        [7:0] p4_sel;         // Port 4 function select
+output        [7:0] p5_dout;        // Port 5 data output
+output        [7:0] p5_dout_en;     // Port 5 data output enable
+output        [7:0] p5_sel;         // Port 5 function select
+output        [7:0] p6_dout;        // Port 6 data output
+output        [7:0] p6_dout_en;     // Port 6 data output enable
+output        [7:0] p6_sel;         // Port 6 function select
+output       [15:0] per_dout;       // Peripheral data output
+
+// INPUTs
+//=========
+input               mclk;           // Main system clock
+input         [7:0] p1_din;         // Port 1 data input
+input         [7:0] p2_din;         // Port 2 data input
+input         [7:0] p3_din;         // Port 3 data input
+input         [7:0] p4_din;         // Port 4 data input
+input         [7:0] p5_din;         // Port 5 data input
+input         [7:0] p6_din;         // Port 6 data input
+input         [7:0] per_addr;       // Peripheral address
+input        [15:0] per_din;        // Peripheral data input
+input               per_en;         // Peripheral enable (high active)
+input         [1:0] per_wen;        // Peripheral write enable (high active)
+input               puc;            // Main system reset
+
+
+//=============================================================================
+// 1)  PARAMETER DECLARATION
+//=============================================================================
+
+// Masks
+parameter           P1_EN_MSK   = {8{P1_EN[0]}};
+parameter           P2_EN_MSK   = {8{P2_EN[0]}};
+parameter           P3_EN_MSK   = {8{P3_EN[0]}};
+parameter           P4_EN_MSK   = {8{P4_EN[0]}};
+parameter           P5_EN_MSK   = {8{P5_EN[0]}};
+parameter           P6_EN_MSK   = {8{P6_EN[0]}};
+
+// Register addresses
+parameter           P1IN        = 9'h020;                  // Port 1
+parameter           P1OUT       = 9'h021;
+parameter           P1DIR       = 9'h022;
+parameter           P1IFG       = 9'h023;
+parameter           P1IES       = 9'h024;
+parameter           P1IE        = 9'h025;
+parameter           P1SEL       = 9'h026;
+parameter           P2IN        = 9'h028;                  // Port 2
+parameter           P2OUT       = 9'h029;
+parameter           P2DIR       = 9'h02A;
+parameter           P2IFG       = 9'h02B;
+parameter           P2IES       = 9'h02C;
+parameter           P2IE        = 9'h02D;
+parameter           P2SEL       = 9'h02E;
+parameter           P3IN        = 9'h018;                  // Port 3
+parameter           P3OUT       = 9'h019;
+parameter           P3DIR       = 9'h01A;
+parameter           P3SEL       = 9'h01B;
+parameter           P4IN        = 9'h01C;                  // Port 4
+parameter           P4OUT       = 9'h01D;
+parameter           P4DIR       = 9'h01E;
+parameter           P4SEL       = 9'h01F;
+parameter           P5IN        = 9'h030;                  // Port 5
+parameter           P5OUT       = 9'h031;
+parameter           P5DIR       = 9'h032;
+parameter           P5SEL       = 9'h033;
+parameter           P6IN        = 9'h034;                  // Port 6
+parameter           P6OUT       = 9'h035;
+parameter           P6DIR       = 9'h036;
+parameter           P6SEL       = 9'h037;
+
+   
+// Register one-hot decoder
+parameter           P1IN_D      = (256'h1 << (P1IN  /2));  // Port 1
+parameter           P1OUT_D     = (256'h1 << (P1OUT /2)); 
+parameter           P1DIR_D     = (256'h1 << (P1DIR /2)); 
+parameter           P1IFG_D     = (256'h1 << (P1IFG /2)); 
+parameter           P1IES_D     = (256'h1 << (P1IES /2)); 
+parameter           P1IE_D      = (256'h1 << (P1IE  /2)); 
+parameter           P1SEL_D     = (256'h1 << (P1SEL /2)); 
+parameter           P2IN_D      = (256'h1 << (P2IN  /2));  // Port 2
+parameter           P2OUT_D     = (256'h1 << (P2OUT /2)); 
+parameter           P2DIR_D     = (256'h1 << (P2DIR /2)); 
+parameter           P2IFG_D     = (256'h1 << (P2IFG /2)); 
+parameter           P2IES_D     = (256'h1 << (P2IES /2)); 
+parameter           P2IE_D      = (256'h1 << (P2IE  /2)); 
+parameter           P2SEL_D     = (256'h1 << (P2SEL /2)); 
+parameter           P3IN_D      = (256'h1 << (P3IN  /2));  // Port 3
+parameter           P3OUT_D     = (256'h1 << (P3OUT /2)); 
+parameter           P3DIR_D     = (256'h1 << (P3DIR /2)); 
+parameter           P3SEL_D     = (256'h1 << (P3SEL /2)); 
+parameter           P4IN_D      = (256'h1 << (P4IN  /2));  // Port 4
+parameter           P4OUT_D     = (256'h1 << (P4OUT /2)); 
+parameter           P4DIR_D     = (256'h1 << (P4DIR /2)); 
+parameter           P4SEL_D     = (256'h1 << (P4SEL /2)); 
+parameter           P5IN_D      = (256'h1 << (P5IN  /2));  // Port 5
+parameter           P5OUT_D     = (256'h1 << (P5OUT /2)); 
+parameter           P5DIR_D     = (256'h1 << (P5DIR /2)); 
+parameter           P5SEL_D     = (256'h1 << (P5SEL /2)); 
+parameter           P6IN_D      = (256'h1 << (P6IN  /2));  // Port 6
+parameter           P6OUT_D     = (256'h1 << (P6OUT /2)); 
+parameter           P6DIR_D     = (256'h1 << (P6DIR /2)); 
+parameter           P6SEL_D     = (256'h1 << (P6SEL /2)); 
+
+
+//============================================================================
+// 2)  REGISTER DECODER
+//============================================================================
+
+// Register address decode
+reg  [255:0]  reg_dec; 
+always @(per_addr)
+  case (per_addr)
+    (P1IN  /2):   reg_dec  =  P1IN_D   & {256{P1_EN[0]}};
+    (P1OUT /2):   reg_dec  =  P1OUT_D  & {256{P1_EN[0]}};
+    (P1DIR /2):   reg_dec  =  P1DIR_D  & {256{P1_EN[0]}};
+    (P1IFG /2):   reg_dec  =  P1IFG_D  & {256{P1_EN[0]}};
+    (P1IES /2):   reg_dec  =  P1IES_D  & {256{P1_EN[0]}};
+    (P1IE  /2):   reg_dec  =  P1IE_D   & {256{P1_EN[0]}};
+    (P1SEL /2):   reg_dec  =  P1SEL_D  & {256{P1_EN[0]}};
+    (P2IN  /2):   reg_dec  =  P2IN_D   & {256{P2_EN[0]}};
+    (P2OUT /2):   reg_dec  =  P2OUT_D  & {256{P2_EN[0]}};
+    (P2DIR /2):   reg_dec  =  P2DIR_D  & {256{P2_EN[0]}};
+    (P2IFG /2):   reg_dec  =  P2IFG_D  & {256{P2_EN[0]}};
+    (P2IES /2):   reg_dec  =  P2IES_D  & {256{P2_EN[0]}};
+    (P2IE  /2):   reg_dec  =  P2IE_D   & {256{P2_EN[0]}};
+    (P2SEL /2):   reg_dec  =  P2SEL_D  & {256{P2_EN[0]}};
+    (P3IN  /2):   reg_dec  =  P3IN_D   & {256{P3_EN[0]}};
+    (P3OUT /2):   reg_dec  =  P3OUT_D  & {256{P3_EN[0]}};
+    (P3DIR /2):   reg_dec  =  P3DIR_D  & {256{P3_EN[0]}};
+    (P3SEL /2):   reg_dec  =  P3SEL_D  & {256{P3_EN[0]}};
+    (P4IN  /2):   reg_dec  =  P4IN_D   & {256{P4_EN[0]}};
+    (P4OUT /2):   reg_dec  =  P4OUT_D  & {256{P4_EN[0]}};
+    (P4DIR /2):   reg_dec  =  P4DIR_D  & {256{P4_EN[0]}};
+    (P4SEL /2):   reg_dec  =  P4SEL_D  & {256{P4_EN[0]}};
+    (P5IN  /2):   reg_dec  =  P5IN_D   & {256{P5_EN[0]}};
+    (P5OUT /2):   reg_dec  =  P5OUT_D  & {256{P5_EN[0]}};
+    (P5DIR /2):   reg_dec  =  P5DIR_D  & {256{P5_EN[0]}};
+    (P5SEL /2):   reg_dec  =  P5SEL_D  & {256{P5_EN[0]}};
+    (P6IN  /2):   reg_dec  =  P6IN_D   & {256{P6_EN[0]}};
+    (P6OUT /2):   reg_dec  =  P6OUT_D  & {256{P6_EN[0]}};
+    (P6DIR /2):   reg_dec  =  P6DIR_D  & {256{P6_EN[0]}};
+    (P6SEL /2):   reg_dec  =  P6SEL_D  & {256{P6_EN[0]}};
+    default   :   reg_dec  =  {256{1'b0}};
+  endcase
+
+// Read/Write probes
+wire         reg_lo_write =  per_wen[0] & per_en;
+wire         reg_hi_write =  per_wen[1] & per_en;
+wire         reg_read     = ~|per_wen   & per_en;
+
+// Read/Write vectors
+wire [255:0] reg_hi_wr    = reg_dec & {256{reg_hi_write}};
+wire [255:0] reg_lo_wr    = reg_dec & {256{reg_lo_write}};
+wire [255:0] reg_rd       = reg_dec & {256{reg_read}};
+
+
+//============================================================================
+// 3) REGISTERS
+//============================================================================
+
+// P1IN Register
+//---------------
+reg  [7:0] p1in_s;
+reg  [7:0] p1in;
+
+always @ (posedge mclk or posedge puc)
+  if (puc)
+    begin
+       p1in_s <=  8'h00;
+       p1in   <=  8'h00;
+    end
+  else
+    begin
+       p1in_s <=  p1_din & P1_EN_MSK;
+       p1in   <=  p1in_s & P1_EN_MSK;
+    end
+
+
+// P1OUT Register
+//----------------
+reg  [7:0] p1out;
+
+wire       p1out_wr  = P1OUT[0] ? reg_hi_wr[P1OUT/2] : reg_lo_wr[P1OUT/2];
+wire [7:0] p1out_nxt = P1OUT[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            p1out <=  8'h00;
+  else if (p1out_wr)  p1out <=  p1out_nxt & P1_EN_MSK;
+
+assign p1_dout = p1out;
+
+
+// P1DIR Register
+//----------------
+reg  [7:0] p1dir;
+
+wire       p1dir_wr  = P1DIR[0] ? reg_hi_wr[P1DIR/2] : reg_lo_wr[P1DIR/2];
+wire [7:0] p1dir_nxt = P1DIR[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            p1dir <=  8'h00;
+  else if (p1dir_wr)  p1dir <=  p1dir_nxt & P1_EN_MSK;
+
+assign p1_dout_en = p1dir;
+
+   
+// P1IFG Register
+//----------------
+reg  [7:0] p1ifg;
+
+wire       p1ifg_wr  = P1IFG[0] ? reg_hi_wr[P1IFG/2] : reg_lo_wr[P1IFG/2];
+wire [7:0] p1ifg_nxt = P1IFG[0] ? per_din[15:8]      : per_din[7:0];
+wire [7:0] p1ifg_set;
+       
+always @ (posedge mclk or posedge puc)
+  if (puc)            p1ifg <=  8'h00;
+  else if (p1ifg_wr)  p1ifg <=  (p1ifg_nxt | p1ifg_set) & P1_EN_MSK;
+  else                p1ifg <=  (p1ifg     | p1ifg_set) & P1_EN_MSK;
+
+// P1IES Register
+//----------------
+reg  [7:0] p1ies;
+
+wire       p1ies_wr  = P1IES[0] ? reg_hi_wr[P1IES/2] : reg_lo_wr[P1IES/2];
+wire [7:0] p1ies_nxt = P1IES[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            p1ies <=  8'h00;
+  else if (p1ies_wr)  p1ies <=  p1ies_nxt & P1_EN_MSK;
+
+   
+// P1IE Register
+//----------------
+reg  [7:0] p1ie;
+
+wire       p1ie_wr  = P1IE[0] ? reg_hi_wr[P1IE/2] : reg_lo_wr[P1IE/2];
+wire [7:0] p1ie_nxt = P1IE[0] ? per_din[15:8]     : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)           p1ie <=  8'h00;
+  else if (p1ie_wr)  p1ie <=  p1ie_nxt & P1_EN_MSK;
+
+
+// P1SEL Register
+//----------------
+reg  [7:0] p1sel;
+
+wire       p1sel_wr  = P1SEL[0] ? reg_hi_wr[P1SEL/2] : reg_lo_wr[P1SEL/2];
+wire [7:0] p1sel_nxt = P1SEL[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)           p1sel <=  8'h00;
+  else if (p1sel_wr) p1sel <=  p1sel_nxt & P1_EN_MSK;
+
+assign p1_sel = p1sel;
+
+   
+// P2IN Register
+//---------------
+reg  [7:0] p2in_s;
+reg  [7:0] p2in;
+
+always @ (posedge mclk or posedge puc)
+  if (puc)
+    begin
+       p2in_s <=  8'h00;
+       p2in   <=  8'h00;
+    end
+  else
+    begin
+       p2in_s <=  p2_din & P2_EN_MSK;
+       p2in   <=  p2in_s & P2_EN_MSK;
+    end
+
+
+// P2OUT Register
+//----------------
+reg  [7:0] p2out;
+
+wire       p2out_wr  = P2OUT[0] ? reg_hi_wr[P2OUT/2] : reg_lo_wr[P2OUT/2];
+wire [7:0] p2out_nxt = P2OUT[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            p2out <=  8'h00;
+  else if (p2out_wr)  p2out <=  p2out_nxt & P2_EN_MSK;
+
+assign p2_dout = p2out;
+
+
+// P2DIR Register
+//----------------
+reg  [7:0] p2dir;
+
+wire       p2dir_wr  = P2DIR[0] ? reg_hi_wr[P2DIR/2] : reg_lo_wr[P2DIR/2];
+wire [7:0] p2dir_nxt = P2DIR[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            p2dir <=  8'h00;
+  else if (p2dir_wr)  p2dir <=  p2dir_nxt & P2_EN_MSK;
+
+assign p2_dout_en = p2dir;
+
+   
+// P2IFG Register
+//----------------
+reg  [7:0] p2ifg;
+
+wire       p2ifg_wr  = P2IFG[0] ? reg_hi_wr[P2IFG/2] : reg_lo_wr[P2IFG/2];
+wire [7:0] p2ifg_nxt = P2IFG[0] ? per_din[15:8]      : per_din[7:0];
+wire [7:0] p2ifg_set;
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            p2ifg <=  8'h00;
+  else if (p2ifg_wr)  p2ifg <=  (p2ifg_nxt | p2ifg_set) & P2_EN_MSK;
+  else                p2ifg <=  (p2ifg     | p2ifg_set) & P2_EN_MSK;
+
+   
+// P2IES Register
+//----------------
+reg  [7:0] p2ies;
+
+wire       p2ies_wr  = P2IES[0] ? reg_hi_wr[P2IES/2] : reg_lo_wr[P2IES/2];
+wire [7:0] p2ies_nxt = P2IES[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            p2ies <=  8'h00;
+  else if (p2ies_wr)  p2ies <=  p2ies_nxt & P2_EN_MSK;
+
+   
+// P2IE Register
+//----------------
+reg  [7:0] p2ie;
+
+wire       p2ie_wr  = P2IE[0] ? reg_hi_wr[P2IE/2] : reg_lo_wr[P2IE/2];
+wire [7:0] p2ie_nxt = P2IE[0] ? per_din[15:8]     : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)           p2ie <=  8'h00;
+  else if (p2ie_wr)  p2ie <=  p2ie_nxt & P2_EN_MSK;
+
+   
+// P2SEL Register
+//----------------
+reg  [7:0] p2sel;
+
+wire       p2sel_wr  = P2SEL[0] ? reg_hi_wr[P2SEL/2] : reg_lo_wr[P2SEL/2];
+wire [7:0] p2sel_nxt = P2SEL[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)           p2sel <=  8'h00;
+  else if (p2sel_wr) p2sel <=  p2sel_nxt & P2_EN_MSK;
+
+assign p2_sel = p2sel;
+
+   
+// P3IN Register
+//---------------
+reg  [7:0] p3in_s;
+reg  [7:0] p3in;
+
+always @ (posedge mclk or posedge puc)
+  if (puc)
+    begin
+       p3in_s <=  8'h00;
+       p3in   <=  8'h00;
+    end
+  else
+    begin
+       p3in_s <=  p3_din & P3_EN_MSK;
+       p3in   <=  p3in_s & P3_EN_MSK;
+    end
+
+
+// P3OUT Register
+//----------------
+reg  [7:0] p3out;
+
+wire       p3out_wr  = P3OUT[0] ? reg_hi_wr[P3OUT/2] : reg_lo_wr[P3OUT/2];
+wire [7:0] p3out_nxt = P3OUT[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            p3out <=  8'h00;
+  else if (p3out_wr)  p3out <=  p3out_nxt & P3_EN_MSK;
+
+assign p3_dout = p3out;
+
+
+// P3DIR Register
+//----------------
+reg  [7:0] p3dir;
+
+wire       p3dir_wr  = P3DIR[0] ? reg_hi_wr[P3DIR/2] : reg_lo_wr[P3DIR/2];
+wire [7:0] p3dir_nxt = P3DIR[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            p3dir <=  8'h00;
+  else if (p3dir_wr)  p3dir <=  p3dir_nxt & P3_EN_MSK;
+
+assign p3_dout_en = p3dir;
+
+
+// P3SEL Register
+//----------------
+reg  [7:0] p3sel;
+
+wire       p3sel_wr  = P3SEL[0] ? reg_hi_wr[P3SEL/2] : reg_lo_wr[P3SEL/2];
+wire [7:0] p3sel_nxt = P3SEL[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)           p3sel <=  8'h00;
+  else if (p3sel_wr) p3sel <=  p3sel_nxt & P3_EN_MSK;
+
+assign p3_sel = p3sel;
+
+   
+// P4IN Register
+//---------------
+reg  [7:0] p4in_s;
+reg  [7:0] p4in;
+
+always @ (posedge mclk or posedge puc)
+  if (puc)
+    begin
+       p4in_s <=  8'h00;
+       p4in   <=  8'h00;
+    end
+  else
+    begin
+       p4in_s <=  p4_din & P4_EN_MSK;
+       p4in   <=  p4in_s & P4_EN_MSK;
+    end
+
+
+// P4OUT Register
+//----------------
+reg  [7:0] p4out;
+
+wire       p4out_wr  = P4OUT[0] ? reg_hi_wr[P4OUT/2] : reg_lo_wr[P4OUT/2];
+wire [7:0] p4out_nxt = P4OUT[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            p4out <=  8'h00;
+  else if (p4out_wr)  p4out <=  p4out_nxt & P4_EN_MSK;
+
+assign p4_dout = p4out;
+
+
+// P4DIR Register
+//----------------
+reg  [7:0] p4dir;
+
+wire       p4dir_wr  = P4DIR[0] ? reg_hi_wr[P4DIR/2] : reg_lo_wr[P4DIR/2];
+wire [7:0] p4dir_nxt = P4DIR[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            p4dir <=  8'h00;
+  else if (p4dir_wr)  p4dir <=  p4dir_nxt & P4_EN_MSK;
+
+assign p4_dout_en = p4dir;
+
+
+// P4SEL Register
+//----------------
+reg  [7:0] p4sel;
+
+wire       p4sel_wr  = P4SEL[0] ? reg_hi_wr[P4SEL/2] : reg_lo_wr[P4SEL/2];
+wire [7:0] p4sel_nxt = P4SEL[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)           p4sel <=  8'h00;
+  else if (p4sel_wr) p4sel <=  p4sel_nxt & P4_EN_MSK;
+
+assign p4_sel = p4sel;
+
+   
+// P5IN Register
+//---------------
+reg  [7:0] p5in_s;
+reg  [7:0] p5in;
+
+always @ (posedge mclk or posedge puc)
+  if (puc)
+    begin
+       p5in_s <=  8'h00;
+       p5in   <=  8'h00;
+    end
+  else
+    begin
+       p5in_s <=  p5_din & P5_EN_MSK;
+       p5in   <=  p5in_s & P5_EN_MSK;
+    end
+
+
+// P5OUT Register
+//----------------
+reg  [7:0] p5out;
+
+wire       p5out_wr  = P5OUT[0] ? reg_hi_wr[P5OUT/2] : reg_lo_wr[P5OUT/2];
+wire [7:0] p5out_nxt = P5OUT[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            p5out <=  8'h00;
+  else if (p5out_wr)  p5out <=  p5out_nxt & P5_EN_MSK;
+
+assign p5_dout = p5out;
+
+
+// P5DIR Register
+//----------------
+reg  [7:0] p5dir;
+
+wire       p5dir_wr  = P5DIR[0] ? reg_hi_wr[P5DIR/2] : reg_lo_wr[P5DIR/2];
+wire [7:0] p5dir_nxt = P5DIR[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            p5dir <=  8'h00;
+  else if (p5dir_wr)  p5dir <=  p5dir_nxt & P5_EN_MSK;
+
+assign p5_dout_en = p5dir;
+
+   
+// P5SEL Register
+//----------------
+reg  [7:0] p5sel;
+
+wire       p5sel_wr  = P5SEL[0] ? reg_hi_wr[P5SEL/2] : reg_lo_wr[P5SEL/2];
+wire [7:0] p5sel_nxt = P5SEL[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)           p5sel <=  8'h00;
+  else if (p5sel_wr) p5sel <=  p5sel_nxt & P5_EN_MSK;
+
+assign p5_sel = p5sel;
+
+   
+// P6IN Register
+//---------------
+reg  [7:0] p6in_s;
+reg  [7:0] p6in;
+
+always @ (posedge mclk or posedge puc)
+  if (puc)
+    begin
+       p6in_s <=  8'h00;
+       p6in   <=  8'h00;
+    end
+  else
+    begin
+       p6in_s <=  p6_din & P6_EN_MSK;
+       p6in   <=  p6in_s & P6_EN_MSK;
+    end
+
+
+// P6OUT Register
+//----------------
+reg  [7:0] p6out;
+
+wire       p6out_wr  = P6OUT[0] ? reg_hi_wr[P6OUT/2] : reg_lo_wr[P6OUT/2];
+wire [7:0] p6out_nxt = P6OUT[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            p6out <=  8'h00;
+  else if (p6out_wr)  p6out <=  p6out_nxt & P6_EN_MSK;
+
+assign p6_dout = p6out;
+
+
+// P6DIR Register
+//----------------
+reg  [7:0] p6dir;
+
+wire       p6dir_wr  = P6DIR[0] ? reg_hi_wr[P6DIR/2] : reg_lo_wr[P6DIR/2];
+wire [7:0] p6dir_nxt = P6DIR[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            p6dir <=  8'h00;
+  else if (p6dir_wr)  p6dir <=  p6dir_nxt & P6_EN_MSK;
+
+assign p6_dout_en = p6dir;
+
+   
+// P6SEL Register
+//----------------
+reg  [7:0] p6sel;
+
+wire       p6sel_wr  = P6SEL[0] ? reg_hi_wr[P6SEL/2] : reg_lo_wr[P6SEL/2];
+wire [7:0] p6sel_nxt = P6SEL[0] ? per_din[15:8]      : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)           p6sel <=  8'h00;
+  else if (p6sel_wr) p6sel <=  p6sel_nxt & P6_EN_MSK;
+
+assign p6_sel = p6sel;
+
+   
+
+//============================================================================
+// 4) INTERRUPT GENERATION
+//============================================================================
+
+// Port 1 interrupt
+//------------------
+
+// Delay input
+reg    [7:0] p1in_dly;
+always @ (posedge mclk or posedge puc)
+  if (puc)      p1in_dly <=  8'h00;
+  else          p1in_dly <=  p1in & P1_EN_MSK;    
+
+// Edge detection
+wire   [7:0] p1in_re   =   p1in & ~p1in_dly;
+wire   [7:0] p1in_fe   =  ~p1in &  p1in_dly;
+
+// Set interrupt flag
+assign       p1ifg_set = {p1ies[7] ? p1in_fe[7] : p1in_re[7],
+                          p1ies[6] ? p1in_fe[6] : p1in_re[6],
+                          p1ies[5] ? p1in_fe[5] : p1in_re[5],
+                          p1ies[4] ? p1in_fe[4] : p1in_re[4],
+                          p1ies[3] ? p1in_fe[3] : p1in_re[3],
+                          p1ies[2] ? p1in_fe[2] : p1in_re[2],
+                          p1ies[1] ? p1in_fe[1] : p1in_re[1],
+                          p1ies[0] ? p1in_fe[0] : p1in_re[0]} & P1_EN_MSK;
+
+// Generate CPU interrupt
+assign       irq_port1 = |(p1ie & p1ifg) & P1_EN[0];
+
+
+// Port 1 interrupt
+//------------------
+
+// Delay input
+reg    [7:0] p2in_dly;
+always @ (posedge mclk or posedge puc)
+  if (puc)      p2in_dly <=  8'h00;
+  else          p2in_dly <=  p2in & P2_EN_MSK;    
+
+// Edge detection
+wire   [7:0] p2in_re   =   p2in & ~p2in_dly;
+wire   [7:0] p2in_fe   =  ~p2in &  p2in_dly;
+
+// Set interrupt flag
+assign       p2ifg_set = {p2ies[7] ? p2in_fe[7] : p2in_re[7],
+                          p2ies[6] ? p2in_fe[6] : p2in_re[6],
+                          p2ies[5] ? p2in_fe[5] : p2in_re[5],
+                          p2ies[4] ? p2in_fe[4] : p2in_re[4],
+                          p2ies[3] ? p2in_fe[3] : p2in_re[3],
+                          p2ies[2] ? p2in_fe[2] : p2in_re[2],
+                          p2ies[1] ? p2in_fe[1] : p2in_re[1],
+                          p2ies[0] ? p2in_fe[0] : p2in_re[0]} & P2_EN_MSK;
+
+// Generate CPU interrupt
+assign      irq_port2 = |(p2ie & p2ifg) & P2_EN[0];
+
+
+//============================================================================
+// 5) DATA OUTPUT GENERATION
+//============================================================================
+
+// Data output mux
+wire [15:0] p1in_rd   = (p1in  & {8{reg_rd[P1IN/2]}})  << (8 & {4{P1IN[0]}});
+wire [15:0] p1out_rd  = (p1out & {8{reg_rd[P1OUT/2]}}) << (8 & {4{P1OUT[0]}});
+wire [15:0] p1dir_rd  = (p1dir & {8{reg_rd[P1DIR/2]}}) << (8 & {4{P1DIR[0]}});
+wire [15:0] p1ifg_rd  = (p1ifg & {8{reg_rd[P1IFG/2]}}) << (8 & {4{P1IFG[0]}});
+wire [15:0] p1ies_rd  = (p1ies & {8{reg_rd[P1IES/2]}}) << (8 & {4{P1IES[0]}});
+wire [15:0] p1ie_rd   = (p1ie  & {8{reg_rd[P1IE/2]}})  << (8 & {4{P1IE[0]}});
+wire [15:0] p1sel_rd  = (p1sel & {8{reg_rd[P1SEL/2]}}) << (8 & {4{P1SEL[0]}});
+wire [15:0] p2in_rd   = (p2in  & {8{reg_rd[P2IN/2]}})  << (8 & {4{P2IN[0]}});
+wire [15:0] p2out_rd  = (p2out & {8{reg_rd[P2OUT/2]}}) << (8 & {4{P2OUT[0]}});
+wire [15:0] p2dir_rd  = (p2dir & {8{reg_rd[P2DIR/2]}}) << (8 & {4{P2DIR[0]}});
+wire [15:0] p2ifg_rd  = (p2ifg & {8{reg_rd[P2IFG/2]}}) << (8 & {4{P2IFG[0]}});
+wire [15:0] p2ies_rd  = (p2ies & {8{reg_rd[P2IES/2]}}) << (8 & {4{P2IES[0]}});
+wire [15:0] p2ie_rd   = (p2ie  & {8{reg_rd[P2IE/2]}})  << (8 & {4{P2IE[0]}});
+wire [15:0] p2sel_rd  = (p2sel & {8{reg_rd[P2SEL/2]}}) << (8 & {4{P2SEL[0]}});
+wire [15:0] p3in_rd   = (p3in  & {8{reg_rd[P3IN/2]}})  << (8 & {4{P3IN[0]}});
+wire [15:0] p3out_rd  = (p3out & {8{reg_rd[P3OUT/2]}}) << (8 & {4{P3OUT[0]}});
+wire [15:0] p3dir_rd  = (p3dir & {8{reg_rd[P3DIR/2]}}) << (8 & {4{P3DIR[0]}});
+wire [15:0] p3sel_rd  = (p3sel & {8{reg_rd[P3SEL/2]}}) << (8 & {4{P3SEL[0]}});
+wire [15:0] p4in_rd   = (p4in  & {8{reg_rd[P4IN/2]}})  << (8 & {4{P4IN[0]}});
+wire [15:0] p4out_rd  = (p4out & {8{reg_rd[P4OUT/2]}}) << (8 & {4{P4OUT[0]}});
+wire [15:0] p4dir_rd  = (p4dir & {8{reg_rd[P4DIR/2]}}) << (8 & {4{P4DIR[0]}});
+wire [15:0] p4sel_rd  = (p4sel & {8{reg_rd[P4SEL/2]}}) << (8 & {4{P4SEL[0]}});
+wire [15:0] p5in_rd   = (p5in  & {8{reg_rd[P5IN/2]}})  << (8 & {4{P5IN[0]}});
+wire [15:0] p5out_rd  = (p5out & {8{reg_rd[P5OUT/2]}}) << (8 & {4{P5OUT[0]}});
+wire [15:0] p5dir_rd  = (p5dir & {8{reg_rd[P5DIR/2]}}) << (8 & {4{P5DIR[0]}});
+wire [15:0] p5sel_rd  = (p5sel & {8{reg_rd[P5SEL/2]}}) << (8 & {4{P5SEL[0]}});
+wire [15:0] p6in_rd   = (p6in  & {8{reg_rd[P6IN/2]}})  << (8 & {4{P6IN[0]}});
+wire [15:0] p6out_rd  = (p6out & {8{reg_rd[P6OUT/2]}}) << (8 & {4{P6OUT[0]}});
+wire [15:0] p6dir_rd  = (p6dir & {8{reg_rd[P6DIR/2]}}) << (8 & {4{P6DIR[0]}});
+wire [15:0] p6sel_rd  = (p6sel & {8{reg_rd[P6SEL/2]}}) << (8 & {4{P6SEL[0]}});
+
+wire [15:0] per_dout  =  p1in_rd   |
+                         p1out_rd  |
+                         p1dir_rd  |
+                         p1ifg_rd  |
+                         p1ies_rd  |
+                         p1ie_rd   |
+                         p1sel_rd  |
+                         p2in_rd   |
+                         p2out_rd  |
+                         p2dir_rd  |
+                         p2ifg_rd  |
+                         p2ies_rd  |
+                         p2ie_rd   |
+                         p2sel_rd  |
+                         p3in_rd   |
+                         p3out_rd  |
+                         p3dir_rd  |
+                         p3sel_rd  |
+                         p4in_rd   |
+                         p4out_rd  |
+                         p4dir_rd  |
+                         p4sel_rd  |
+                         p5in_rd   |
+                         p5out_rd  |
+                         p5dir_rd  |
+                         p5sel_rd  |
+                         p6in_rd   |
+                         p6out_rd  |
+                         p6dir_rd  |
+                         p6sel_rd;
+
+endmodule // omsp_gpio
+
+`include "openMSP430_undefines.v"
diff --git a/periph/omsp_timerA.v b/periph/omsp_timerA.v
new file mode 100644 (file)
index 0000000..6f6d841
--- /dev/null
@@ -0,0 +1,689 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2001 Authors
+//
+// This source file may be used and distributed without restriction provided
+// that this copyright statement is not removed from the file and that any
+// derivative work contains the original copyright notice and the associated
+// disclaimer.
+//
+// This source file is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// This source is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+// License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this source; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+//----------------------------------------------------------------------------
+//
+// *File Name: omsp_timerA.v
+// 
+// *Module Description:
+//                       Timer A top-level
+//
+// *Author(s):
+//              - Olivier Girard,    olgirard@gmail.com
+//
+//----------------------------------------------------------------------------
+// $Rev: 34 $
+// $LastChangedBy: olivier.girard $
+// $LastChangedDate: 2009-12-29 20:10:34 +0100 (Tue, 29 Dec 2009) $
+//----------------------------------------------------------------------------
+`include "timescale.v"
+`include "openMSP430_defines.v"
+
+module  omsp_timerA (
+
+// OUTPUTs
+    irq_ta0,                        // Timer A interrupt: TACCR0
+    irq_ta1,                        // Timer A interrupt: TAIV, TACCR1, TACCR2
+    per_dout,                       // Peripheral data output
+    ta_out0,                        // Timer A output 0
+    ta_out0_en,                     // Timer A output 0 enable
+    ta_out1,                        // Timer A output 1
+    ta_out1_en,                     // Timer A output 1 enable
+    ta_out2,                        // Timer A output 2
+    ta_out2_en,                     // Timer A output 2 enable
+
+// INPUTs
+    aclk_en,                        // ACLK enable (from CPU)
+    dbg_freeze,                     // Freeze Timer A counter
+    inclk,                          // INCLK external timer clock (SLOW)
+    irq_ta0_acc,                    // Interrupt request TACCR0 accepted
+    mclk,                           // Main system clock
+    per_addr,                       // Peripheral address
+    per_din,                        // Peripheral data input
+    per_en,                         // Peripheral enable (high active)
+    per_wen,                        // Peripheral write enable (high active)
+    puc,                            // Main system reset
+    smclk_en,                       // SMCLK enable (from CPU)
+    ta_cci0a,                       // Timer A capture 0 input A
+    ta_cci0b,                       // Timer A capture 0 input B
+    ta_cci1a,                       // Timer A capture 1 input A
+    ta_cci1b,                       // Timer A capture 1 input B
+    ta_cci2a,                       // Timer A capture 2 input A
+    ta_cci2b,                       // Timer A capture 2 input B
+    taclk                           // TACLK external timer clock (SLOW)
+);
+
+// OUTPUTs
+//=========
+output              irq_ta0;        // Timer A interrupt: TACCR0
+output              irq_ta1;        // Timer A interrupt: TAIV, TACCR1, TACCR2
+output       [15:0] per_dout;       // Peripheral data output
+output              ta_out0;        // Timer A output 0
+output              ta_out0_en;     // Timer A output 0 enable
+output              ta_out1;        // Timer A output 1
+output              ta_out1_en;     // Timer A output 1 enable
+output              ta_out2;        // Timer A output 2
+output              ta_out2_en;     // Timer A output 2 enable
+
+// INPUTs
+//=========
+input               aclk_en;        // ACLK enable (from CPU)
+input               dbg_freeze;     // Freeze Timer A counter
+input               inclk;          // INCLK external timer clock (SLOW)
+input               irq_ta0_acc;    // Interrupt request TACCR0 accepted
+input               mclk;           // Main system clock
+input         [7:0] per_addr;       // Peripheral address
+input        [15:0] per_din;        // Peripheral data input
+input               per_en;         // Peripheral enable (high active)
+input         [1:0] per_wen;        // Peripheral write enable (high active)
+input               puc;            // Main system reset
+input               smclk_en;       // SMCLK enable (from CPU)
+input               ta_cci0a;       // Timer A capture 0 input A
+input               ta_cci0b;       // Timer A capture 0 input B
+input               ta_cci1a;       // Timer A capture 1 input A
+input               ta_cci1b;       // Timer A capture 1 input B
+input               ta_cci2a;       // Timer A capture 2 input A
+input               ta_cci2b;       // Timer A capture 2 input B
+input               taclk;          // TACLK external timer clock (SLOW)
+
+
+//=============================================================================
+// 1)  PARAMETER DECLARATION
+//=============================================================================
+
+// Register addresses
+parameter           TACTL      = 9'h160;
+parameter           TAR        = 9'h170;
+parameter           TACCTL0    = 9'h162;
+parameter           TACCR0     = 9'h172;
+parameter           TACCTL1    = 9'h164;
+parameter           TACCR1     = 9'h174;
+parameter           TACCTL2    = 9'h166;
+parameter           TACCR2     = 9'h176;
+parameter           TAIV       = 9'h12E;
+
+
+// Register one-hot decoder
+parameter           TACTL_D    = (512'h1 << TACTL);
+parameter           TAR_D      = (512'h1 << TAR);
+parameter           TACCTL0_D  = (512'h1 << TACCTL0);
+parameter           TACCR0_D   = (512'h1 << TACCR0);
+parameter           TACCTL1_D  = (512'h1 << TACCTL1);
+parameter           TACCR1_D   = (512'h1 << TACCR1);
+parameter           TACCTL2_D  = (512'h1 << TACCTL2);
+parameter           TACCR2_D   = (512'h1 << TACCR2);
+parameter           TAIV_D     = (512'h1 << TAIV);
+
+
+//============================================================================
+// 2)  REGISTER DECODER
+//============================================================================
+
+// Register address decode
+reg  [511:0]  reg_dec; 
+always @(per_addr)
+  case ({per_addr,1'b0})
+    TACTL  :     reg_dec  =  TACTL_D;
+    TAR    :     reg_dec  =  TAR_D;
+    TACCTL0:     reg_dec  =  TACCTL0_D;
+    TACCR0 :     reg_dec  =  TACCR0_D;
+    TACCTL1:     reg_dec  =  TACCTL1_D;
+    TACCR1 :     reg_dec  =  TACCR1_D;
+    TACCTL2:     reg_dec  =  TACCTL2_D;
+    TACCR2 :     reg_dec  =  TACCR2_D;
+    TAIV   :     reg_dec  =  TAIV_D;
+    default:     reg_dec  =  {512{1'b0}};
+  endcase
+
+// Read/Write probes
+wire         reg_write =  |per_wen   & per_en;
+wire         reg_read  = ~|per_wen   & per_en;
+
+// Read/Write vectors
+wire [511:0] reg_wr    = reg_dec & {512{reg_write}};
+wire [511:0] reg_rd    = reg_dec & {512{reg_read}};
+
+
+//============================================================================
+// 3) REGISTERS
+//============================================================================
+
+// TACTL Register
+//-----------------   
+reg   [9:0] tactl;
+
+wire        tactl_wr = reg_wr[TACTL];
+wire        taclr    = tactl_wr & per_din[`TACLR];
+wire        taifg_set;
+wire        taifg_clr;
+   
+always @ (posedge mclk or posedge puc)
+  if (puc)           tactl <=  10'h000;
+  else if (tactl_wr) tactl <=  ((per_din[9:0] & 10'h3f3) | {9'h000, taifg_set}) & {9'h1ff, ~taifg_clr};
+  else               tactl <=  (tactl                    | {9'h000, taifg_set}) & {9'h1ff, ~taifg_clr};
+
+
+// TAR Register
+//-----------------   
+reg  [15:0] tar;
+
+wire        tar_wr = reg_wr[TAR];
+
+wire        tar_clk;
+wire        tar_clr;
+wire        tar_inc;
+wire        tar_dec;
+wire [15:0] tar_add  = tar_inc ? 16'h0001 :
+                       tar_dec ? 16'hffff : 16'h0000;
+wire [15:0] tar_nxt  = tar_clr ? 16'h0000 : (tar+tar_add);
+  
+always @ (posedge mclk or posedge puc)
+  if (puc)                         tar <=  16'h0000;
+  else if  (tar_wr)                tar <=  per_din;
+  else if  (taclr)                 tar <=  16'h0000;
+  else if  (tar_clk & ~dbg_freeze) tar <=  tar_nxt;
+
+
+// TACCTL0 Register
+//------------------   
+reg  [15:0] tacctl0;
+
+wire        tacctl0_wr = reg_wr[TACCTL0];
+wire        ccifg0_set;
+wire        cov0_set;   
+
+always @ (posedge mclk or posedge puc)
+  if (puc)             tacctl0  <=  16'h0000;
+  else if (tacctl0_wr) tacctl0  <=  ((per_din & 16'hf9f7) | {14'h0000, cov0_set, ccifg0_set}) & {15'h7fff, ~irq_ta0_acc};
+  else                 tacctl0  <=  (tacctl0              | {14'h0000, cov0_set, ccifg0_set}) & {15'h7fff, ~irq_ta0_acc};
+
+wire        cci0;
+reg         scci0;
+wire [15:0] tacctl0_full = tacctl0 | {5'h00, scci0, 6'h00, cci0, 3'h0};
+
+   
+// TACCR0 Register
+//------------------   
+reg  [15:0] taccr0;
+
+wire        taccr0_wr = reg_wr[TACCR0];
+wire        cci0_cap;
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            taccr0 <=  16'h0000;
+  else if (taccr0_wr) taccr0 <=  per_din;
+  else if (cci0_cap)  taccr0 <=  tar;
+
+   
+// TACCTL1 Register
+//------------------   
+reg  [15:0] tacctl1;
+
+wire        tacctl1_wr = reg_wr[TACCTL1];
+wire        ccifg1_set;
+wire        ccifg1_clr;
+wire        cov1_set;   
+   
+always @ (posedge mclk or posedge puc)
+  if (puc)             tacctl1 <=  16'h0000;
+  else if (tacctl1_wr) tacctl1 <=  ((per_din & 16'hf9f7) | {14'h0000, cov1_set, ccifg1_set}) & {15'h7fff, ~ccifg1_clr};
+  else                 tacctl1 <=  (tacctl1              | {14'h0000, cov1_set, ccifg1_set}) & {15'h7fff, ~ccifg1_clr};
+
+wire        cci1;
+reg         scci1;
+wire [15:0] tacctl1_full = tacctl1 | {5'h00, scci1, 6'h00, cci1, 3'h0};
+
+   
+// TACCR1 Register
+//------------------   
+reg  [15:0] taccr1;
+
+wire        taccr1_wr = reg_wr[TACCR1];
+wire        cci1_cap;
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            taccr1 <=  16'h0000;
+  else if (taccr1_wr) taccr1 <=  per_din;
+  else if (cci1_cap)  taccr1 <=  tar;
+
+
+// TACCTL2 Register
+//------------------   
+reg  [15:0] tacctl2;
+
+wire        tacctl2_wr = reg_wr[TACCTL2];
+wire        ccifg2_set;
+wire        ccifg2_clr;
+wire        cov2_set;   
+   
+always @ (posedge mclk or posedge puc)
+  if (puc)             tacctl2 <=  16'h0000;
+  else if (tacctl2_wr) tacctl2 <=  ((per_din & 16'hf9f7) | {14'h0000, cov2_set, ccifg2_set}) & {15'h7fff, ~ccifg2_clr};
+  else                 tacctl2 <=  (tacctl2              | {14'h0000, cov2_set, ccifg2_set}) & {15'h7fff, ~ccifg2_clr};
+
+wire        cci2;
+reg         scci2;
+wire [15:0] tacctl2_full = tacctl2 | {5'h00, scci2, 6'h00, cci2, 3'h0};
+
+   
+// TACCR2 Register
+//------------------   
+reg  [15:0] taccr2;
+
+wire        taccr2_wr = reg_wr[TACCR2];
+wire        cci2_cap;
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            taccr2 <=  16'h0000;
+  else if (taccr2_wr) taccr2 <=  per_din;
+  else if (cci2_cap)  taccr2 <=  tar;
+
+   
+// TAIV Register
+//------------------   
+
+wire [3:0] taiv = (tacctl1[`TACCIFG] & tacctl1[`TACCIE]) ? 4'h2 : 
+                  (tacctl2[`TACCIFG] & tacctl2[`TACCIE]) ? 4'h4 : 
+                  (tactl[`TAIFG]     & tactl[`TAIE])     ? 4'hA : 
+                                                           4'h0;
+
+assign     ccifg1_clr = (reg_rd[TAIV] | reg_wr[TAIV]) & (taiv==4'h2);
+assign     ccifg2_clr = (reg_rd[TAIV] | reg_wr[TAIV]) & (taiv==4'h4);
+assign     taifg_clr  = (reg_rd[TAIV] | reg_wr[TAIV]) & (taiv==4'hA);
+
+
+//============================================================================
+// 4) DATA OUTPUT GENERATION
+//============================================================================
+
+// Data output mux
+wire [15:0] tactl_rd   = {6'h00, tactl}  & {16{reg_rd[TACTL]}};
+wire [15:0] tar_rd     = tar             & {16{reg_rd[TAR]}};
+wire [15:0] tacctl0_rd = tacctl0_full    & {16{reg_rd[TACCTL0]}};
+wire [15:0] taccr0_rd  = taccr0          & {16{reg_rd[TACCR0]}};
+wire [15:0] tacctl1_rd = tacctl1_full    & {16{reg_rd[TACCTL1]}};
+wire [15:0] taccr1_rd  = taccr1          & {16{reg_rd[TACCR1]}};
+wire [15:0] tacctl2_rd = tacctl2_full    & {16{reg_rd[TACCTL2]}};
+wire [15:0] taccr2_rd  = taccr2          & {16{reg_rd[TACCR2]}};
+wire [15:0] taiv_rd    = {12'h000, taiv} & {16{reg_rd[TAIV]}};
+
+wire [15:0] per_dout   =  tactl_rd   |
+                          tar_rd     |
+                          tacctl0_rd |
+                          taccr0_rd  |
+                          tacctl1_rd |
+                          taccr1_rd  |
+                          tacctl2_rd |
+                          taccr2_rd  |
+                          taiv_rd;
+
+   
+//============================================================================
+// 5) Timer A counter control
+//============================================================================
+
+// Clock input synchronization (TACLK & INCLK)
+//-----------------------------------------------------------
+reg  [2:0] taclk_s;
+   
+always @ (posedge mclk or posedge puc)
+  if (puc) taclk_s <=  3'b000;
+  else     taclk_s <=  {taclk_s[1:0], taclk};    
+
+wire taclk_en = taclk_s[1] & ~taclk_s[2];
+
+   
+reg  [2:0] inclk_s;
+   
+always @ (posedge mclk or posedge puc)
+  if (puc) inclk_s <=  3'b000;
+  else     inclk_s <=  {inclk_s[1:0], inclk};    
+
+wire inclk_en = inclk_s[1] & ~inclk_s[2];
+
+   
+// Timer clock input mux
+//-----------------------------------------------------------
+
+wire sel_clk = (tactl[`TASSELx]==2'b00) ? taclk_en :
+               (tactl[`TASSELx]==2'b01) ?  aclk_en :
+               (tactl[`TASSELx]==2'b10) ? smclk_en : inclk_en;
+
+     
+// Generate update pluse for the counter (<=> divided clock)
+//-----------------------------------------------------------
+reg [2:0] clk_div;
+
+assign    tar_clk = sel_clk & ((tactl[`TAIDx]==2'b00) ?  1'b1         :
+                               (tactl[`TAIDx]==2'b01) ?  clk_div[0]   :
+                               (tactl[`TAIDx]==2'b10) ? &clk_div[1:0] :
+                                                        &clk_div[2:0]);
+         
+always @ (posedge mclk or posedge puc)
+  if (puc)                                   clk_div <=  3'h0;
+  else if  (tar_clk | taclr)                 clk_div <=  3'h0;
+  else if ((tactl[`TAMCx]!=2'b00) & sel_clk) clk_div <=  clk_div+3'h1;
+
+  
+// Time counter control signals
+//-----------------------------------------------------------
+
+assign  tar_clr   = ((tactl[`TAMCx]==2'b01) & (tar>=taccr0))         |
+                    ((tactl[`TAMCx]==2'b11) & (taccr0==16'h0000));
+
+assign  tar_inc   =  (tactl[`TAMCx]==2'b01) | (tactl[`TAMCx]==2'b10) | 
+                    ((tactl[`TAMCx]==2'b11) & ~tar_dec);
+
+reg tar_dir;
+always @ (posedge mclk or posedge puc)
+  if (puc)                            tar_dir <=  1'b0;
+  else if (taclr)                     tar_dir <=  1'b0;
+  else if (tactl[`TAMCx]==2'b11)
+    begin
+       if (tar_clk & (tar==16'h0001)) tar_dir <=  1'b0;
+       else if       (tar>=taccr0)    tar_dir <=  1'b1;
+    end
+  else                                tar_dir <=  1'b0;
+   
+assign tar_dec = tar_dir | ((tactl[`TAMCx]==2'b11) & (tar>=taccr0));
+
+   
+//============================================================================
+// 6) Timer A comparator
+//============================================================================
+
+wire equ0 = (tar_nxt==taccr0) & (tar!=taccr0);
+wire equ1 = (tar_nxt==taccr1) & (tar!=taccr1);
+wire equ2 = (tar_nxt==taccr2) & (tar!=taccr2);
+
+
+//============================================================================
+// 7) Timer A capture logic
+//============================================================================
+
+// Input selection
+//------------------
+assign cci0 = (tacctl0[`TACCISx]==2'b00) ? ta_cci0a :
+              (tacctl0[`TACCISx]==2'b01) ? ta_cci0b :
+              (tacctl0[`TACCISx]==2'b10) ?     1'b0 : 1'b1;
+
+assign cci1 = (tacctl1[`TACCISx]==2'b00) ? ta_cci1a :
+              (tacctl1[`TACCISx]==2'b01) ? ta_cci1b :
+              (tacctl1[`TACCISx]==2'b10) ?     1'b0 : 1'b1;
+
+assign cci2 = (tacctl2[`TACCISx]==2'b00) ? ta_cci2a :
+              (tacctl2[`TACCISx]==2'b01) ? ta_cci2b :
+              (tacctl2[`TACCISx]==2'b10) ?     1'b0 : 1'b1;
+
+// Register CCIx for synchronization and edge detection
+reg [2:0] cci_s;
+always @ (posedge mclk or posedge puc)
+  if (puc) cci_s <=  3'h0;
+  else     cci_s <=  {cci2, cci1, cci0};
+reg [2:0] cci_ss;
+always @ (posedge mclk or posedge puc)
+  if (puc) cci_ss <=  3'h0;
+  else     cci_ss <=  cci_s;
+reg [2:0] cci_sss;
+always @ (posedge mclk or posedge puc)
+  if (puc) cci_sss <=  3'h0;
+  else     cci_sss <=  cci_ss;
+
+   
+// Generate SCCIx
+//------------------
+
+always @ (posedge mclk or posedge puc)
+  if (puc)                 scci0 <=  1'b0;
+  else if (tar_clk & equ0) scci0 <=  cci_ss[0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)                 scci1 <=  1'b0;
+  else if (tar_clk & equ1) scci1 <=  cci_ss[1];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)                 scci2 <=  1'b0;
+  else if (tar_clk & equ2) scci2 <=  cci_ss[2];
+
+
+// Capture mode
+//------------------
+wire cci0_evt = (tacctl0[`TACMx]==2'b00) ? 1'b0                  :
+                (tacctl0[`TACMx]==2'b01) ? ( cci_ss[0] & ~cci_sss[0]) :   // Rising edge
+                (tacctl0[`TACMx]==2'b10) ? (~cci_ss[0] &  cci_sss[0]) :   // Falling edge
+                                           ( cci_ss[0] ^  cci_sss[0]);    // Both edges
+
+wire cci1_evt = (tacctl1[`TACMx]==2'b00) ? 1'b0                  :
+                (tacctl1[`TACMx]==2'b01) ? ( cci_ss[1] & ~cci_sss[1]) :   // Rising edge
+                (tacctl1[`TACMx]==2'b10) ? (~cci_ss[1] &  cci_sss[1]) :   // Falling edge
+                                           ( cci_ss[1] ^  cci_sss[1]);    // Both edges
+
+wire cci2_evt = (tacctl2[`TACMx]==2'b00) ? 1'b0                  :
+                (tacctl2[`TACMx]==2'b01) ? ( cci_ss[2] & ~cci_sss[2]) :   // Rising edge
+                (tacctl2[`TACMx]==2'b10) ? (~cci_ss[2] &  cci_sss[2]) :   // Falling edge
+                                           ( cci_ss[2] ^  cci_sss[2]);    // Both edges
+
+// Event Synchronization
+//-----------------------
+
+reg cci0_evt_s;
+always @ (posedge mclk or posedge puc)
+  if (puc)           cci0_evt_s <=  1'b0;
+  else if (tar_clk)  cci0_evt_s <=  1'b0;
+  else if (cci0_evt) cci0_evt_s <=  1'b1;
+
+reg cci1_evt_s;
+always @ (posedge mclk or posedge puc)
+  if (puc)           cci1_evt_s <=  1'b0;
+  else if (tar_clk)  cci1_evt_s <=  1'b0;
+  else if (cci1_evt) cci1_evt_s <=  1'b1;
+
+reg cci2_evt_s;
+always @ (posedge mclk or posedge puc)
+  if (puc)           cci2_evt_s <=  1'b0;
+  else if (tar_clk)  cci2_evt_s <=  1'b0;
+  else if (cci2_evt) cci2_evt_s <=  1'b1;
+
+reg cci0_sync;
+always @ (posedge mclk or posedge puc)
+  if (puc) cci0_sync <=  1'b0;
+  else     cci0_sync <=  (tar_clk & cci0_evt_s) | (tar_clk & cci0_evt & ~cci0_evt_s);
+
+reg cci1_sync;
+always @ (posedge mclk or posedge puc)
+  if (puc) cci1_sync <=  1'b0;
+  else     cci1_sync <=  (tar_clk & cci1_evt_s) | (tar_clk & cci1_evt & ~cci1_evt_s);
+
+reg cci2_sync;
+always @ (posedge mclk or posedge puc)
+  if (puc) cci2_sync <=  1'b0;
+  else     cci2_sync <=  (tar_clk & cci2_evt_s) | (tar_clk & cci2_evt & ~cci2_evt_s);
+
+   
+// Generate final capture command
+//-----------------------------------
+
+assign cci0_cap  = tacctl0[`TASCS] ? cci0_sync : cci0_evt;
+assign cci1_cap  = tacctl1[`TASCS] ? cci1_sync : cci1_evt;
+assign cci2_cap  = tacctl2[`TASCS] ? cci2_sync : cci2_evt;
+
+   
+// Generate capture overflow flag
+//-----------------------------------
+
+reg  cap0_taken;
+wire cap0_taken_clr = reg_rd[TACCR0] | (tacctl0_wr & tacctl0[`TACOV] & ~per_din[`TACOV]);
+always @ (posedge mclk or posedge puc)
+  if (puc)                 cap0_taken <=  1'b0;
+  else if (cci0_cap)       cap0_taken <=  1'b1;
+  else if (cap0_taken_clr) cap0_taken <=  1'b0;
+   
+reg  cap1_taken;
+wire cap1_taken_clr = reg_rd[TACCR1] | (tacctl1_wr & tacctl1[`TACOV] & ~per_din[`TACOV]);
+always @ (posedge mclk or posedge puc)
+  if (puc)                 cap1_taken <=  1'b0;
+  else if (cci1_cap)       cap1_taken <=  1'b1;
+  else if (cap1_taken_clr) cap1_taken <=  1'b0;
+      
+reg  cap2_taken;
+wire cap2_taken_clr = reg_rd[TACCR2] | (tacctl2_wr & tacctl2[`TACOV] & ~per_din[`TACOV]);
+always @ (posedge mclk or posedge puc)
+  if (puc)                 cap2_taken <=  1'b0;
+  else if (cci2_cap)       cap2_taken <=  1'b1;
+  else if (cap2_taken_clr) cap2_taken <=  1'b0;
+
+   
+assign cov0_set = cap0_taken & cci0_cap & ~reg_rd[TACCR0];
+assign cov1_set = cap1_taken & cci1_cap & ~reg_rd[TACCR1];   
+assign cov2_set = cap2_taken & cci2_cap & ~reg_rd[TACCR2];
+  
+      
+//============================================================================
+// 8) Timer A output unit
+//============================================================================
+
+// Output unit 0
+//-------------------
+reg  ta_out0;
+
+wire ta_out0_mode0 = tacctl0[`TAOUT];                // Output
+wire ta_out0_mode1 = equ0 ?  1'b1    : ta_out0;      // Set
+wire ta_out0_mode2 = equ0 ? ~ta_out0 :               // Toggle/Reset
+                     equ0 ?  1'b0    : ta_out0;
+wire ta_out0_mode3 = equ0 ?  1'b1    :               // Set/Reset
+                     equ0 ?  1'b0    : ta_out0;
+wire ta_out0_mode4 = equ0 ? ~ta_out0 : ta_out0;      // Toggle
+wire ta_out0_mode5 = equ0 ?  1'b0    : ta_out0;      // Reset
+wire ta_out0_mode6 = equ0 ? ~ta_out0 :               // Toggle/Set
+                     equ0 ?  1'b1    : ta_out0;
+wire ta_out0_mode7 = equ0 ?  1'b0    :               // Reset/Set
+                     equ0 ?  1'b1    : ta_out0;
+
+wire ta_out0_nxt   = (tacctl0[`TAOUTMODx]==3'b000) ? ta_out0_mode0 :
+                     (tacctl0[`TAOUTMODx]==3'b001) ? ta_out0_mode1 :
+                     (tacctl0[`TAOUTMODx]==3'b010) ? ta_out0_mode2 :
+                     (tacctl0[`TAOUTMODx]==3'b011) ? ta_out0_mode3 :
+                     (tacctl0[`TAOUTMODx]==3'b100) ? ta_out0_mode4 :
+                     (tacctl0[`TAOUTMODx]==3'b101) ? ta_out0_mode5 :
+                     (tacctl0[`TAOUTMODx]==3'b110) ? ta_out0_mode6 :
+                                                     ta_out0_mode7;
+
+always @ (posedge mclk or posedge puc)
+  if (puc)                                         ta_out0 <=  1'b0;
+  else if ((tacctl0[`TAOUTMODx]==3'b001) & taclr)  ta_out0 <=  1'b0;
+  else if (tar_clk)                                ta_out0 <=  ta_out0_nxt;
+
+assign  ta_out0_en = ~tacctl0[`TACAP];
+
+   
+// Output unit 1
+//-------------------
+reg  ta_out1;
+
+wire ta_out1_mode0 = tacctl1[`TAOUT];                // Output
+wire ta_out1_mode1 = equ1 ?  1'b1    : ta_out1;      // Set
+wire ta_out1_mode2 = equ1 ? ~ta_out1 :               // Toggle/Reset
+                     equ0 ?  1'b0    : ta_out1;
+wire ta_out1_mode3 = equ1 ?  1'b1    :               // Set/Reset
+                     equ0 ?  1'b0    : ta_out1;
+wire ta_out1_mode4 = equ1 ? ~ta_out1 : ta_out1;      // Toggle
+wire ta_out1_mode5 = equ1 ?  1'b0    : ta_out1;      // Reset
+wire ta_out1_mode6 = equ1 ? ~ta_out1 :               // Toggle/Set
+                     equ0 ?  1'b1    : ta_out1;
+wire ta_out1_mode7 = equ1 ?  1'b0    :               // Reset/Set
+                     equ0 ?  1'b1    : ta_out1;
+
+wire ta_out1_nxt   = (tacctl1[`TAOUTMODx]==3'b000) ? ta_out1_mode0 :
+                     (tacctl1[`TAOUTMODx]==3'b001) ? ta_out1_mode1 :
+                     (tacctl1[`TAOUTMODx]==3'b010) ? ta_out1_mode2 :
+                     (tacctl1[`TAOUTMODx]==3'b011) ? ta_out1_mode3 :
+                     (tacctl1[`TAOUTMODx]==3'b100) ? ta_out1_mode4 :
+                     (tacctl1[`TAOUTMODx]==3'b101) ? ta_out1_mode5 :
+                     (tacctl1[`TAOUTMODx]==3'b110) ? ta_out1_mode6 :
+                                                     ta_out1_mode7;
+
+always @ (posedge mclk or posedge puc)
+  if (puc)                                         ta_out1 <=  1'b0;
+  else if ((tacctl1[`TAOUTMODx]==3'b001) & taclr)  ta_out1 <=  1'b0;
+  else if (tar_clk)                                ta_out1 <=  ta_out1_nxt;
+
+assign  ta_out1_en = ~tacctl1[`TACAP];
+
+   
+// Output unit 2
+//-------------------
+reg  ta_out2;
+
+wire ta_out2_mode0 = tacctl2[`TAOUT];                // Output
+wire ta_out2_mode1 = equ2 ?  1'b1    : ta_out2;      // Set
+wire ta_out2_mode2 = equ2 ? ~ta_out2 :               // Toggle/Reset
+                     equ0 ?  1'b0    : ta_out2;
+wire ta_out2_mode3 = equ2 ?  1'b1    :               // Set/Reset
+                     equ0 ?  1'b0    : ta_out2;
+wire ta_out2_mode4 = equ2 ? ~ta_out2 : ta_out2;      // Toggle
+wire ta_out2_mode5 = equ2 ?  1'b0    : ta_out2;      // Reset
+wire ta_out2_mode6 = equ2 ? ~ta_out2 :               // Toggle/Set
+                     equ0 ?  1'b1    : ta_out2;
+wire ta_out2_mode7 = equ2 ?  1'b0    :               // Reset/Set
+                     equ0 ?  1'b1    : ta_out2;
+
+wire ta_out2_nxt   = (tacctl2[`TAOUTMODx]==3'b000) ? ta_out2_mode0 :
+                     (tacctl2[`TAOUTMODx]==3'b001) ? ta_out2_mode1 :
+                     (tacctl2[`TAOUTMODx]==3'b010) ? ta_out2_mode2 :
+                     (tacctl2[`TAOUTMODx]==3'b011) ? ta_out2_mode3 :
+                     (tacctl2[`TAOUTMODx]==3'b100) ? ta_out2_mode4 :
+                     (tacctl2[`TAOUTMODx]==3'b101) ? ta_out2_mode5 :
+                     (tacctl2[`TAOUTMODx]==3'b110) ? ta_out2_mode6 :
+                                                     ta_out2_mode7;
+
+always @ (posedge mclk or posedge puc)
+  if (puc)                                         ta_out2 <=  1'b0;
+  else if ((tacctl2[`TAOUTMODx]==3'b001) & taclr)  ta_out2 <=  1'b0;
+  else if (tar_clk)                                ta_out2 <=  ta_out2_nxt;
+
+assign  ta_out2_en = ~tacctl2[`TACAP];
+
+   
+//============================================================================
+// 9) Timer A interrupt generation
+//============================================================================
+
+
+assign   taifg_set   = tar_clk & (((tactl[`TAMCx]==2'b01) & (tar==taccr0))                  |
+                                  ((tactl[`TAMCx]==2'b10) & (tar==16'hffff))                |
+                                  ((tactl[`TAMCx]==2'b11) & (tar_nxt==16'h0000) & tar_dec));
+
+assign   ccifg0_set  = tacctl0[`TACAP] ? cci0_cap : (tar_clk &  ((tactl[`TAMCx]!=2'b00) & equ0));
+assign   ccifg1_set  = tacctl1[`TACAP] ? cci1_cap : (tar_clk &  ((tactl[`TAMCx]!=2'b00) & equ1));
+assign   ccifg2_set  = tacctl2[`TACAP] ? cci2_cap : (tar_clk &  ((tactl[`TAMCx]!=2'b00) & equ2));
+
+  
+wire     irq_ta0    = (tacctl0[`TACCIFG] & tacctl0[`TACCIE]);
+
+wire     irq_ta1    = (tactl[`TAIFG]     & tactl[`TAIE])     |
+                      (tacctl1[`TACCIFG] & tacctl1[`TACCIE]) |
+                      (tacctl2[`TACCIFG] & tacctl2[`TACCIE]);
+   
+
+endmodule // omsp_timerA
+
+`include "openMSP430_undefines.v"
diff --git a/periph/template_periph_16b.v b/periph/template_periph_16b.v
new file mode 100644 (file)
index 0000000..a402c78
--- /dev/null
@@ -0,0 +1,182 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2001 Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of the authors nor the names of its contributors
+//       may be used to endorse or promote products derived from this software
+//       without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE
+//
+//----------------------------------------------------------------------------
+//
+// *File Name: template_periph_16b.v
+// 
+// *Module Description:
+//                       16 bit peripheral template.
+//
+// *Author(s):
+//              - Olivier Girard,    olgirard@gmail.com
+//
+//----------------------------------------------------------------------------
+// $Rev: 66 $
+// $LastChangedBy: olivier.girard $
+// $LastChangedDate: 2010-03-07 09:09:38 +0100 (Sun, 07 Mar 2010) $
+//----------------------------------------------------------------------------
+`include "timescale.v"
+`include "openMSP430_defines.v"
+
+module  template_periph_16b (
+
+// OUTPUTs
+    per_dout,                       // Peripheral data output
+
+// INPUTs
+    mclk,                           // Main system clock
+    per_addr,                       // Peripheral address
+    per_din,                        // Peripheral data input
+    per_en,                         // Peripheral enable (high active)
+    per_wen,                        // Peripheral write enable (high active)
+    puc                             // Main system reset
+);
+
+// OUTPUTs
+//=========
+output       [15:0] per_dout;       // Peripheral data output
+
+// INPUTs
+//=========
+input               mclk;           // Main system clock
+input         [7:0] per_addr;       // Peripheral address
+input        [15:0] per_din;        // Peripheral data input
+input               per_en;         // Peripheral enable (high active)
+input         [1:0] per_wen;        // Peripheral write enable (high active)
+input               puc;            // Main system reset
+
+
+//=============================================================================
+// 1)  PARAMETER DECLARATION
+//=============================================================================
+
+// Register addresses
+parameter           CNTRL1     = 9'h190;
+parameter           CNTRL2     = 9'h192;
+parameter           CNTRL3     = 9'h194;
+parameter           CNTRL4     = 9'h196;
+
+
+// Register one-hot decoder
+parameter           CNTRL1_D   = (512'h1 << CNTRL1);
+parameter           CNTRL2_D   = (512'h1 << CNTRL2);
+parameter           CNTRL3_D   = (512'h1 << CNTRL3);
+parameter           CNTRL4_D   = (512'h1 << CNTRL4);
+
+
+//============================================================================
+// 2)  REGISTER DECODER
+//============================================================================
+
+// Register address decode
+reg  [511:0]  reg_dec; 
+always @(per_addr)
+  case ({per_addr,1'b0})
+    CNTRL1 :     reg_dec  =  CNTRL1_D;
+    CNTRL2 :     reg_dec  =  CNTRL2_D;
+    CNTRL3 :     reg_dec  =  CNTRL3_D;
+    CNTRL4 :     reg_dec  =  CNTRL4_D;
+    default:     reg_dec  =  {512{1'b0}};
+  endcase
+
+// Read/Write probes
+wire         reg_write =  |per_wen   & per_en;
+wire         reg_read  = ~|per_wen   & per_en;
+
+// Read/Write vectors
+wire [511:0] reg_wr    = reg_dec & {512{reg_write}};
+wire [511:0] reg_rd    = reg_dec & {512{reg_read}};
+
+
+//============================================================================
+// 3) REGISTERS
+//============================================================================
+
+// CNTRL1 Register
+//-----------------   
+reg  [15:0] cntrl1;
+
+wire        cntrl1_wr = reg_wr[CNTRL1];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            cntrl1 <=  16'h0000;
+  else if (cntrl1_wr) cntrl1 <=  per_din;
+
+   
+// CNTRL2 Register
+//-----------------   
+reg  [15:0] cntrl2;
+
+wire        cntrl2_wr = reg_wr[CNTRL2];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            cntrl2 <=  16'h0000;
+  else if (cntrl2_wr) cntrl2 <=  per_din;
+
+   
+// CNTRL3 Register
+//-----------------   
+reg  [15:0] cntrl3;
+
+wire        cntrl3_wr = reg_wr[CNTRL3];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            cntrl3 <=  16'h0000;
+  else if (cntrl3_wr) cntrl3 <=  per_din;
+
+   
+// CNTRL4 Register
+//-----------------   
+reg  [15:0] cntrl4;
+
+wire        cntrl4_wr = reg_wr[CNTRL4];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            cntrl4 <=  16'h0000;
+  else if (cntrl4_wr) cntrl4 <=  per_din;
+
+
+//============================================================================
+// 4) DATA OUTPUT GENERATION
+//============================================================================
+
+// Data output mux
+wire [15:0] cntrl1_rd  = cntrl1  & {16{reg_rd[CNTRL1]}};
+wire [15:0] cntrl2_rd  = cntrl2  & {16{reg_rd[CNTRL2]}};
+wire [15:0] cntrl3_rd  = cntrl3  & {16{reg_rd[CNTRL3]}};
+wire [15:0] cntrl4_rd  = cntrl4  & {16{reg_rd[CNTRL4]}};
+
+wire [15:0] per_dout   =  cntrl1_rd  |
+                          cntrl2_rd  |
+                          cntrl3_rd  |
+                          cntrl4_rd;
+
+
+endmodule // template_periph_16b
+
+`include "openMSP430_undefines.v"
diff --git a/periph/template_periph_8b.v b/periph/template_periph_8b.v
new file mode 100644 (file)
index 0000000..e41ac16
--- /dev/null
@@ -0,0 +1,189 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2009 Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of the authors nor the names of its contributors
+//       may be used to endorse or promote products derived from this software
+//       without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE
+//
+//----------------------------------------------------------------------------
+//
+// *File Name: template_periph_8b.v
+// 
+// *Module Description:
+//                       8 bit peripheral template.
+//
+// *Author(s):
+//              - Olivier Girard,    olgirard@gmail.com
+//
+//----------------------------------------------------------------------------
+// $Rev: 66 $
+// $LastChangedBy: olivier.girard $
+// $LastChangedDate: 2010-03-07 09:09:38 +0100 (Sun, 07 Mar 2010) $
+//----------------------------------------------------------------------------
+`include "timescale.v"
+`include "openMSP430_defines.v"
+
+module  template_periph_8b (
+
+// OUTPUTs
+    per_dout,                       // Peripheral data output
+
+// INPUTs
+    mclk,                           // Main system clock
+    per_addr,                       // Peripheral address
+    per_din,                        // Peripheral data input
+    per_en,                         // Peripheral enable (high active)
+    per_wen,                        // Peripheral write enable (high active)
+    puc                             // Main system reset
+);
+
+// OUTPUTs
+//=========
+output      [15:0] per_dout;        // Peripheral data output
+
+// INPUTs
+//=========
+input              mclk;            // Main system clock
+input        [7:0] per_addr;        // Peripheral address
+input       [15:0] per_din;         // Peripheral data input
+input              per_en;          // Peripheral enable (high active)
+input        [1:0] per_wen;         // Peripheral write enable (high active)
+input              puc;             // Main system reset
+
+
+//=============================================================================
+// 1)  PARAMETER DECLARATION
+//=============================================================================
+
+// Register addresses
+parameter          CNTRL1    = 9'h090;
+parameter          CNTRL2    = 9'h091;
+parameter          CNTRL3    = 9'h092;
+parameter          CNTRL4    = 9'h093;
+
+   
+// Register one-hot decoder
+parameter          CNTRL1_D  = (256'h1 << (CNTRL1 /2));
+parameter          CNTRL2_D  = (256'h1 << (CNTRL2 /2)); 
+parameter          CNTRL3_D  = (256'h1 << (CNTRL3 /2)); 
+parameter          CNTRL4_D  = (256'h1 << (CNTRL4 /2)); 
+
+
+//============================================================================
+// 2)  REGISTER DECODER
+//============================================================================
+
+// Register address decode
+reg  [255:0]  reg_dec; 
+always @(per_addr)
+  case (per_addr)
+    (CNTRL1 /2):   reg_dec   = CNTRL1_D;
+    (CNTRL2 /2):   reg_dec   = CNTRL2_D;
+    (CNTRL3 /2):   reg_dec   = CNTRL3_D;
+    (CNTRL4 /2):   reg_dec   = CNTRL4_D;
+    default    :   reg_dec   = {256{1'b0}};
+  endcase
+
+// Read/Write probes
+wire         reg_lo_write =  per_wen[0] & per_en;
+wire         reg_hi_write =  per_wen[1] & per_en;
+wire         reg_read     = ~|per_wen   & per_en;
+
+// Read/Write vectors
+wire [255:0] reg_hi_wr    = reg_dec & {256{reg_hi_write}};
+wire [255:0] reg_lo_wr    = reg_dec & {256{reg_lo_write}};
+wire [255:0] reg_rd       = reg_dec & {256{reg_read}};
+
+
+//============================================================================
+// 3) REGISTERS
+//============================================================================
+
+// CNTRL1 Register
+//-----------------
+reg  [7:0] cntrl1;
+
+wire       cntrl1_wr  = CNTRL1[0] ? reg_hi_wr[CNTRL1/2] : reg_lo_wr[CNTRL1/2];
+wire [7:0] cntrl1_nxt = CNTRL1[0] ? per_din[15:8]       : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            cntrl1 <=  8'h00;
+  else if (cntrl1_wr) cntrl1 <=  cntrl1_nxt;
+
+   
+// CNTRL2 Register
+//-----------------
+reg  [7:0] cntrl2;
+
+wire       cntrl2_wr  = CNTRL2[0] ? reg_hi_wr[CNTRL2/2] : reg_lo_wr[CNTRL2/2];
+wire [7:0] cntrl2_nxt = CNTRL2[0] ? per_din[15:8]       : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            cntrl2 <=  8'h00;
+  else if (cntrl2_wr) cntrl2 <=  cntrl2_nxt;
+
+   
+// CNTRL3 Register
+//-----------------
+reg  [7:0] cntrl3;
+
+wire       cntrl3_wr  = CNTRL3[0] ? reg_hi_wr[CNTRL3/2] : reg_lo_wr[CNTRL3/2];
+wire [7:0] cntrl3_nxt = CNTRL3[0] ? per_din[15:8]       : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            cntrl3 <=  8'h00;
+  else if (cntrl3_wr) cntrl3 <=  cntrl3_nxt;
+
+   
+// CNTRL4 Register
+//-----------------
+reg  [7:0] cntrl4;
+
+wire       cntrl4_wr  = CNTRL4[0] ? reg_hi_wr[CNTRL4/2] : reg_lo_wr[CNTRL4/2];
+wire [7:0] cntrl4_nxt = CNTRL4[0] ? per_din[15:8]       : per_din[7:0];
+
+always @ (posedge mclk or posedge puc)
+  if (puc)            cntrl4 <=  8'h00;
+  else if (cntrl4_wr) cntrl4 <=  cntrl4_nxt;
+
+
+
+//============================================================================
+// 4) DATA OUTPUT GENERATION
+//============================================================================
+
+// Data output mux
+wire [15:0] cntrl1_rd   = (cntrl1  & {8{reg_rd[CNTRL1/2]}})  << (8 & {4{CNTRL1[0]}});
+wire [15:0] cntrl2_rd   = (cntrl2  & {8{reg_rd[CNTRL2/2]}})  << (8 & {4{CNTRL2[0]}});
+wire [15:0] cntrl3_rd   = (cntrl3  & {8{reg_rd[CNTRL3/2]}})  << (8 & {4{CNTRL3[0]}});
+wire [15:0] cntrl4_rd   = (cntrl4  & {8{reg_rd[CNTRL4/2]}})  << (8 & {4{CNTRL4[0]}});
+
+wire [15:0] per_dout  =  cntrl1_rd  |
+                         cntrl2_rd  |
+                         cntrl3_rd  |
+                         cntrl4_rd;
+
+   
+endmodule // template_periph_8b
+
+`include "openMSP430_undefines.v"
diff --git a/timescale.v b/timescale.v
new file mode 100644 (file)
index 0000000..cbc3c49
--- /dev/null
@@ -0,0 +1 @@
+`timescale 1ns / 100ps