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

Subversion Repositories openmsp430

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openmsp430/trunk/core/rtl/verilog
    from Rev 132 to Rev 134
    Reverse comparison

Rev 132 → Rev 134

/omsp_scan_mux.v
0,0 → 1,75
//----------------------------------------------------------------------------
// Copyright (C) 2009 , Olivier Girard
//
// 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: omsp_scan_mux.v
//
// *Module Description:
// Generic mux for scan mode
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev: 103 $
// $LastChangedBy: olivier.girard $
// $LastChangedDate: 2011-03-05 15:44:48 +0100 (Sat, 05 Mar 2011) $
//----------------------------------------------------------------------------
 
module omsp_scan_mux (
 
// OUTPUTs
data_out, // Scan mux data output
 
// INPUTs
data_in_scan, // Selected data input for scan mode
data_in_func, // Selected data input for functional mode
scan_mode // Scan mode
);
 
// OUTPUTs
//=========
output data_out; // Scan mux data output
 
// INPUTs
//=========
input data_in_scan; // Selected data input for scan mode
input data_in_func; // Selected data input for functional mode
input scan_mode; // Scan mode
 
 
//=============================================================================
// 1) SCAN MUX
//=============================================================================
 
assign data_out = scan_mode ? data_in_scan : data_in_func;
 
 
endmodule // omsp_scan_mux
 
 
omsp_scan_mux.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: omsp_sync_reset.v =================================================================== --- omsp_sync_reset.v (nonexistent) +++ omsp_sync_reset.v (revision 134) @@ -0,0 +1,78 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// 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: omsp_sync_reset.v +// +// *Module Description: +// Generic reset synchronizer for the openMSP430 +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 103 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2011-03-05 15:44:48 +0100 (Sat, 05 Mar 2011) $ +//---------------------------------------------------------------------------- + +module omsp_sync_reset ( + +// OUTPUTs + rst_s, // Synchronized reset + +// INPUTs + clk, // Receiving clock + rst_a // Asynchronous reset +); + +// OUTPUTs +//========= +output rst_s; // Synchronized reset + +// INPUTs +//========= +input clk; // Receiving clock +input rst_a; // Asynchronous reset + + +//============================================================================= +// 1) SYNCHRONIZER +//============================================================================= + +reg [1:0] data_sync; + +always @(posedge clk or posedge rst_a) + if (rst_a) data_sync <= 2'b11; + else data_sync <= {data_sync[0], 1'b0}; + +assign rst_s = data_sync[1]; + + +endmodule // omsp_sync_reset +
omsp_sync_reset.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: omsp_frontend.v =================================================================== --- omsp_frontend.v (revision 132) +++ omsp_frontend.v (revision 134) @@ -68,6 +68,8 @@ irq_acc, // Interrupt request accepted (one-hot signal) mab, // Frontend Memory address bus mb_en, // Frontend Memory bus enable + mclk_enable, // Main System Clock enable + mclk_wkup, // Main System Clock wake-up (asynchronous) nmi_acc, // Non-Maskable interrupt request accepted pc, // Program counter pc_nxt, // Next PC value (for CALL & IRQ) @@ -82,11 +84,15 @@ irq, // Maskable interrupts mclk, // Main system clock mdb_in, // Frontend Memory data bus input - nmi_evt, // Non-maskable interrupt event + nmi_pnd, // Non-maskable interrupt pending + nmi_wkup, // NMI Wakeup pc_sw, // Program counter software value pc_sw_wr, // Program counter software write puc_rst, // Main system reset - wdt_irq // Watchdog-timer interrupt + scan_enable, // Scan enable (active during scan shifting) + wdt_irq, // Watchdog-timer interrupt + wdt_wkup, // Watchdog Wakeup + wkup // System Wake-up (asynchronous) ); // OUTPUTs @@ -111,6 +117,8 @@ 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 mclk_enable; // Main System Clock enable +output mclk_wkup; // Main System Clock wake-up (asynchronous) 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) @@ -122,15 +130,19 @@ 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 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 nmi_pnd; // Non-maskable interrupt pending +input nmi_wkup; // NMI Wakeup input [15:0] pc_sw; // Program counter software value input pc_sw_wr; // Program counter software write input puc_rst; // Main system reset +input scan_enable; // Scan enable (active during scan shifting) input wdt_irq; // Watchdog-timer interrupt +input wdt_wkup; // Watchdog Wakeup +input wkup; // System Wake-up (asynchronous) //============================================================================= @@ -157,7 +169,7 @@ //============================================================================= -// 2) Parameter definitions +// 2) PARAMETER DEFINITIONS //============================================================================= // @@ -206,7 +218,7 @@ wire is_const; reg [15:0] sconst_nxt; reg [3:0] e_state_nxt; - + // CPU on/off through the debug interface or cpu_en port wire cpu_halt_cmd = dbg_halt_cmd | ~cpu_en_s; @@ -222,13 +234,14 @@ (cpuoff | cpu_halt_cmd) & exec_done ? I_IDLE : cpu_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 + ~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 : + I_EXT1 : i_state_nxt = 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; + I_EXT2 : i_state_nxt = I_DEC; + // pragma coverage off default : i_state_nxt = I_IRQ_FETCH; + // pragma coverage on endcase // State machine @@ -249,17 +262,13 @@ //============================================================================= -// 4) INTERRUPT HANDLING +// 4) INTERRUPT HANDLING & SYSTEM WAKEUP //============================================================================= -// Detect nmi interrupt -reg inst_nmi; -always @(posedge mclk or posedge puc_rst) - if (puc_rst) inst_nmi <= 1'b0; - else if (nmi_evt) inst_nmi <= 1'b1; - else if (i_state==I_IRQ_DONE) inst_nmi <= 1'b0; +// +// 4.1) INTERRUPT HANDLING +//----------------------------------------- - // Detect reset interrupt reg inst_irq_rst; always @(posedge mclk or posedge puc_rst) @@ -267,13 +276,25 @@ else if (exec_done) inst_irq_rst <= 1'b0; // Detect other interrupts -assign irq_detect = (inst_nmi | ((|irq | wdt_irq) & gie)) & ~cpu_halt_cmd & ~dbg_halt_st & (exec_done | (i_state==I_IDLE)); +assign irq_detect = (nmi_pnd | ((|irq | wdt_irq) & gie)) & ~cpu_halt_cmd & ~dbg_halt_st & (exec_done | (i_state==I_IDLE)); +`ifdef CLOCK_GATING +wire mclk_irq_num; +omsp_clock_gate clock_gate_irq_num (.gclk(mclk_irq_num), + .clk (mclk), .enable(irq_detect), .scan_enable(scan_enable)); +`else +wire mclk_irq_num = mclk; +`endif + // Select interrupt vector reg [3:0] irq_num; -always @(posedge mclk or posedge puc_rst) +always @(posedge mclk_irq_num or posedge puc_rst) if (puc_rst) irq_num <= 4'hf; - else if (irq_detect) irq_num <= inst_nmi ? 4'he : +`ifdef CLOCK_GATING + else irq_num <= nmi_pnd ? 4'he : +`else + else if (irq_detect) irq_num <= nmi_pnd ? 4'he : +`endif irq[13] ? 4'hd : irq[12] ? 4'hc : irq[11] ? 4'hb : @@ -296,7 +317,35 @@ wire [13:0] irq_acc = irq_acc_all[13:0]; wire nmi_acc = irq_acc_all[14]; +// +// 4.2) SYSTEM WAKEUP +//----------------------------------------- +`ifdef CPUOFF_EN +// Generate the main system clock enable signal + // Keep the clock running if: +wire mclk_enable = inst_irq_rst ? cpu_en_s : // - the RESET interrupt is currently executing + // and if the CPU is enabled + // otherwise if: + ~((cpuoff | ~cpu_en_s) & // - the CPUOFF flag, cpu_en command, instruction + (i_state==I_IDLE) & // and execution state machines are all two + (e_state==E_IDLE)); // not idle. + + +// Wakeup condition from maskable interrupts +wire mirq_wkup; +omsp_and_gate and_mirq_wkup (.y(mirq_wkup), .a(wkup | wdt_wkup), .b(gie)); + +// Combined asynchronous wakeup detection from nmi & irq (masked if the cpu is disabled) +omsp_and_gate and_mclk_wkup (.y(mclk_wkup), .a(nmi_wkup | mirq_wkup), .b(cpu_en_s)); + +`else + +// In the CPUOFF feature is disabled, the wake-up and enable signals are always 1 +assign mclk_wkup = 1'b1; +assign mclk_enable = 1'b1; +`endif + //============================================================================= // 5) FETCH INSTRUCTION //============================================================================= @@ -314,7 +363,19 @@ (i_state==I_IRQ_FETCH) ? irq_addr : (i_state==I_IRQ_DONE) ? mdb_in : pc_incr; -always @(posedge mclk or posedge puc_rst) +`ifdef CLOCK_GATING +wire pc_en = fetch | + pc_sw_wr | + (i_state==I_IRQ_FETCH) | + (i_state==I_IRQ_DONE); +wire mclk_pc; +omsp_clock_gate clock_gate_pc (.gclk(mclk_pc), + .clk (mclk), .enable(pc_en), .scan_enable(scan_enable)); +`else +wire mclk_pc = mclk; +`endif + +always @(posedge mclk_pc or posedge puc_rst) if (puc_rst) pc <= 16'h0000; else pc <= pc_nxt; @@ -339,9 +400,6 @@ // 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]) | @@ -353,11 +411,27 @@ // Store source extension word reg [15:0] inst_sext; -always @(posedge mclk or posedge puc_rst) + +`ifdef CLOCK_GATING +wire inst_sext_en = (decode & is_const) | + (decode & inst_type_nxt[`INST_JMP]) | + ((i_state==I_EXT1) & is_sext); +wire mclk_inst_sext; +omsp_clock_gate clock_gate_inst_sext (.gclk(mclk_inst_sext), + .clk (mclk), .enable(inst_sext_en), .scan_enable(scan_enable)); +`else +wire mclk_inst_sext = mclk; +`endif + +always @(posedge mclk_inst_sext or posedge puc_rst) if (puc_rst) 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}; +`ifdef CLOCK_GATING + else inst_sext <= ext_nxt; +`else else if ((i_state==I_EXT1) & is_sext) inst_sext <= ext_nxt; +`endif // Source extension word is ready wire inst_sext_rdy = (i_state==I_EXT1) & is_sext; @@ -365,10 +439,25 @@ // Store destination extension word reg [15:0] inst_dext; -always @(posedge mclk or posedge puc_rst) + +`ifdef CLOCK_GATING +wire inst_dext_en = ((i_state==I_EXT1) & ~is_sext) | + (i_state==I_EXT2); +wire mclk_inst_dext; +omsp_clock_gate clock_gate_inst_dext (.gclk(mclk_inst_dext), + .clk (mclk), .enable(inst_dext_en), .scan_enable(scan_enable)); +`else +wire mclk_inst_dext = mclk; +`endif + +always @(posedge mclk_inst_dext or posedge puc_rst) if (puc_rst) inst_dext <= 16'h0000; else if ((i_state==I_EXT1) & ~is_sext) inst_dext <= ext_nxt; +`ifdef CLOCK_GATING + else inst_dext <= ext_nxt; +`else else if (i_state==I_EXT2) inst_dext <= ext_nxt; +`endif // Destination extension word is ready wire inst_dext_rdy = (((i_state==I_EXT1) & ~is_sext) | (i_state==I_EXT2)); @@ -378,6 +467,14 @@ // 6) DECODE INSTRUCTION //============================================================================= +`ifdef CLOCK_GATING +wire mclk_decode; +omsp_clock_gate clock_gate_decode (.gclk(mclk_decode), + .clk (mclk), .enable(decode), .scan_enable(scan_enable)); +`else +wire mclk_decode = mclk; +`endif + // // 6.1) OPCODE: INSTRUCTION TYPE //---------------------------------------- @@ -392,9 +489,13 @@ (ir[15:13]==3'b001), (ir[15:13]==3'b000)} & {3{~irq_detect}}; -always @(posedge mclk or posedge puc_rst) +always @(posedge mclk_decode or posedge puc_rst) if (puc_rst) inst_type <= 3'b000; +`ifdef CLOCK_GATING + else inst_type <= inst_type_nxt; +`else else if (decode) inst_type <= inst_type_nxt; +`endif // // 6.2) OPCODE: SINGLE-OPERAND ARITHMETIC @@ -413,9 +514,13 @@ reg [7:0] inst_so; wire [7:0] inst_so_nxt = irq_detect ? 8'h80 : (one_hot8(ir[9:7]) & {8{inst_type_nxt[`INST_SO]}}); -always @(posedge mclk or posedge puc_rst) +always @(posedge mclk_decode or posedge puc_rst) if (puc_rst) inst_so <= 8'h00; +`ifdef CLOCK_GATING + else inst_so <= inst_so_nxt; +`else else if (decode) inst_so <= inst_so_nxt; +`endif // // 6.3) OPCODE: CONDITIONAL JUMP @@ -432,9 +537,13 @@ // 8'b10000000: JMP reg [2:0] inst_jmp_bin; -always @(posedge mclk or posedge puc_rst) +always @(posedge mclk_decode or posedge puc_rst) if (puc_rst) inst_jmp_bin <= 3'h0; +`ifdef CLOCK_GATING + else inst_jmp_bin <= ir[12:10]; +`else else if (decode) inst_jmp_bin <= ir[12:10]; +`endif wire [7:0] inst_jmp = one_hot8(inst_jmp_bin) & {8{inst_type[`INST_JMP]}}; @@ -461,9 +570,13 @@ wire [11:0] inst_to_nxt = inst_to_1hot[15:4]; reg inst_mov; -always @(posedge mclk or posedge puc_rst) +always @(posedge mclk_decode or posedge puc_rst) if (puc_rst) inst_mov <= 1'b0; +`ifdef CLOCK_GATING + else inst_mov <= inst_to_nxt[`MOV]; +`else else if (decode) inst_mov <= inst_to_nxt[`MOV]; +`endif // @@ -472,9 +585,13 @@ // Destination register reg [3:0] inst_dest_bin; -always @(posedge mclk or posedge puc_rst) +always @(posedge mclk_decode or posedge puc_rst) if (puc_rst) inst_dest_bin <= 4'h0; +`ifdef CLOCK_GATING + else inst_dest_bin <= ir[3:0]; +`else else if (decode) inst_dest_bin <= ir[3:0]; +`endif wire [15:0] inst_dest = dbg_halt_st ? one_hot16(dbg_reg_sel) : inst_type[`INST_JMP] ? 16'h0001 : @@ -486,9 +603,13 @@ // Source register reg [3:0] inst_src_bin; -always @(posedge mclk or posedge puc_rst) +always @(posedge mclk_decode or posedge puc_rst) if (puc_rst) inst_src_bin <= 4'h0; +`ifdef CLOCK_GATING + else inst_src_bin <= ir[11:8]; +`else else if (decode) inst_src_bin <= ir[11:8]; +`endif wire [15:0] inst_src = inst_type[`INST_TO] ? one_hot16(inst_src_bin) : inst_so[`RETI] ? 16'h0002 : @@ -525,39 +646,43 @@ 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; + 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; + 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; + 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; + 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_rst) +always @(posedge mclk_decode or posedge puc_rst) if (puc_rst) inst_as <= 8'h00; +`ifdef CLOCK_GATING + else inst_as <= {is_const, inst_as_nxt[6:0]}; +`else else if (decode) inst_as <= {is_const, inst_as_nxt[6:0]}; +`endif // 13'b0000010000000: Constant 4. @@ -598,25 +723,29 @@ 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; + 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]) - 1'b1 : inst_ad_nxt = 8'b00010000; - default: inst_ad_nxt = 8'b00000001; + 1'b1 : inst_ad_nxt = 8'b00010000; + default: inst_ad_nxt = 8'b00000001; endcase else // General Addressing mode case (ir[7]) - 1'b1 : inst_ad_nxt = 8'b00000010; - default: inst_ad_nxt = 8'b00000001; + 1'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_rst) +always @(posedge mclk_decode or posedge puc_rst) if (puc_rst) inst_ad <= 8'h00; +`ifdef CLOCK_GATING + else inst_ad <= inst_ad_nxt; +`else else if (decode) inst_ad <= inst_ad_nxt; +`endif // @@ -632,9 +761,13 @@ // 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_rst) +always @(posedge mclk_decode or posedge puc_rst) if (puc_rst) inst_sz <= 2'b00; +`ifdef CLOCK_GATING + else inst_sz <= inst_sz_nxt; +`else else if (decode) inst_sz <= inst_sz_nxt; +`endif //============================================================================= @@ -723,7 +856,9 @@ 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; + // pragma coverage off default : e_state_nxt = E_IRQ_0; + // pragma coverage on endcase // State machine @@ -801,20 +936,26 @@ wire exec_no_wr = inst_to_nxt[`CMP] | inst_to_nxt[`BIT]; -always @(posedge mclk or posedge puc_rst) +wire [11:0] inst_alu_nxt = {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}; + +always @(posedge mclk_decode or posedge puc_rst) if (puc_rst) 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}; +`ifdef CLOCK_GATING + else inst_alu <= inst_alu_nxt; +`else + else if (decode) inst_alu <= inst_alu_nxt; +`endif endmodule // omsp_frontend
/omsp_alu.v
93,13 → 93,13
 
input [3:0] X;
input [3:0] Y;
input C;
input C_;
 
reg [4:0] Z;
reg [4:0] Z_;
begin
Z = {1'b0,X}+{1'b0,Y}+{4'b0,C};
if (Z<5'd10) bcd_add = Z;
else bcd_add = Z+5'd6;
Z_ = {1'b0,X}+{1'b0,Y}+{4'b0,C_};
if (Z_<5'd10) bcd_add = Z_;
else bcd_add = Z_+5'd6;
end
 
endfunction
/omsp_register_file.v
55,6 → 55,7
pc_sw_wr, // Program counter software write
reg_dest, // Selected register destination content
reg_src, // Selected register source content
scg0, // System clock generator 1. Turns off the DCO
scg1, // System clock generator 1. Turns off the SMCLK
status, // R2 Status {V,N,Z,C}
 
74,7 → 75,8
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
reg_incr, // Increment source register
scan_enable // Scan enable (active during scan shifting)
);
 
// OUTPUTs
86,6 → 88,7
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 scg0; // System clock generator 1. Turns off the DCO
output scg1; // System clock generator 1. Turns off the SMCLK
output [3:0] status; // R2 Status {V,N,Z,C}
 
107,6 → 110,7
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
input scan_enable; // Scan enable (active during scan shifting)
 
 
//=============================================================================
145,11 → 149,24
wire r1_wr = inst_dest[1] & reg_dest_wr;
wire r1_inc = inst_src_in[1] & reg_incr;
 
always @(posedge mclk or posedge puc_rst)
`ifdef CLOCK_GATING
wire r1_en = r1_wr | reg_sp_wr | r1_inc;
wire mclk_r1;
omsp_clock_gate clock_gate_r1 (.gclk(mclk_r1),
.clk (mclk), .enable(r1_en), .scan_enable(scan_enable));
`else
wire mclk_r1 = mclk;
`endif
 
always @(posedge mclk_r1 or posedge puc_rst)
if (puc_rst) 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;
`ifdef CLOCK_GATING
else r1 <= reg_incr_val & 16'hfffe;
`else
else if (r1_inc) r1 <= reg_incr_val & 16'hfffe;
`endif
 
 
// R2: Status register
157,43 → 174,108
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
`ifdef CLOCK_GATING // -- WITH CLOCK GATING --
wire r2_c = alu_stat_wr[0] ? alu_stat[0] : reg_dest_val_in[0]; // C
 
wire r2_z = alu_stat_wr[1] ? alu_stat[1] :
r2_wr ? reg_dest_val_in[1] : r2[1]; // Z
wire r2_z = alu_stat_wr[1] ? alu_stat[1] : reg_dest_val_in[1]; // Z
 
wire r2_n = alu_stat_wr[2] ? alu_stat[2] :
r2_wr ? reg_dest_val_in[2] : r2[2]; // N
wire r2_n = alu_stat_wr[2] ? alu_stat[2] : reg_dest_val_in[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
wire r2_v = alu_stat_wr[3] ? alu_stat[3] : reg_dest_val_in[8]; // V
 
wire r2_en = |alu_stat_wr | r2_wr | reg_sr_clr;
wire mclk_r2;
omsp_clock_gate clock_gate_r2 (.gclk(mclk_r2),
.clk (mclk), .enable(r2_en), .scan_enable(scan_enable));
 
always @(posedge mclk or posedge puc_rst)
`else // -- WITHOUT CLOCK GATING --
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
 
 
wire mclk_r2 = mclk;
`endif
 
`ifdef ASIC
`ifdef CPUOFF_EN
wire [15:0] cpuoff_mask = 16'h0010;
`else
wire [15:0] cpuoff_mask = 16'h0000;
`endif
`ifdef OSCOFF_EN
wire [15:0] oscoff_mask = 16'h0020;
`else
wire [15:0] oscoff_mask = 16'h0000;
`endif
`ifdef SCG0_EN
wire [15:0] scg0_mask = 16'h0040;
`else
wire [15:0] scg0_mask = 16'h0000;
`endif
`ifdef SCG1_EN
wire [15:0] scg1_mask = 16'h0080;
`else
wire [15:0] scg1_mask = 16'h0000;
`endif
`else
wire [15:0] cpuoff_mask = 16'h0010; // For the FPGA version: - the CPUOFF mode is emulated
wire [15:0] oscoff_mask = 16'h0020; // - the SCG1 mode is emulated
wire [15:0] scg0_mask = 16'h0000; // - the SCG0 is not supported
wire [15:0] scg1_mask = 16'h0080; // - the SCG1 mode is emulated
`endif
wire [15:0] r2_mask = cpuoff_mask | oscoff_mask | scg0_mask | scg1_mask | 16'h010f;
always @(posedge mclk_r2 or posedge puc_rst)
if (puc_rst) 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};
else r2 <= {7'h00, r2_v, r2_nxt, r2_n, r2_z, r2_c} & r2_mask;
 
assign status = {r2[8], r2[2:0]};
assign gie = r2[3];
assign cpuoff = r2[4] | (r2_nxt[4] & r2_wr);
assign cpuoff = r2[4] | (r2_nxt[4] & r2_wr & cpuoff_mask[4]);
assign oscoff = r2[5];
assign scg0 = r2[6];
assign scg1 = r2[7];
 
 
// R3: Constant generator
//------------------------
//-------------------------------------------------------------
// Note: the auto-increment feature is not implemented for R3
// because the @R3+ addressing mode is used for constant
// generation (#-1).
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_rst)
`ifdef CLOCK_GATING
wire r3_en = r3_wr;
wire mclk_r3;
omsp_clock_gate clock_gate_r3 (.gclk(mclk_r3),
.clk (mclk), .enable(r3_en), .scan_enable(scan_enable));
`else
wire mclk_r3 = mclk;
`endif
 
always @(posedge mclk_r3 or posedge puc_rst)
if (puc_rst) r3 <= 16'h0000;
`ifdef CLOCK_GATING
else r3 <= reg_dest_val_in;
`else
else if (r3_wr) r3 <= reg_dest_val_in;
else if (r3_inc) r3 <= reg_incr_val;
`endif
 
 
//=============================================================================
201,112 → 283,292
//=============================================================================
 
// 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_rst)
 
`ifdef CLOCK_GATING
wire r4_en = r4_wr | r4_inc;
wire mclk_r4;
omsp_clock_gate clock_gate_r4 (.gclk(mclk_r4),
.clk (mclk), .enable(r4_en), .scan_enable(scan_enable));
`else
wire mclk_r4 = mclk;
`endif
 
always @(posedge mclk_r4 or posedge puc_rst)
if (puc_rst) r4 <= 16'h0000;
else if (r4_wr) r4 <= reg_dest_val_in;
`ifdef CLOCK_GATING
else r4 <= reg_incr_val;
`else
else if (r4_inc) r4 <= reg_incr_val;
`endif
 
// 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_rst)
 
`ifdef CLOCK_GATING
wire r5_en = r5_wr | r5_inc;
wire mclk_r5;
omsp_clock_gate clock_gate_r5 (.gclk(mclk_r5),
.clk (mclk), .enable(r5_en), .scan_enable(scan_enable));
`else
wire mclk_r5 = mclk;
`endif
 
always @(posedge mclk_r5 or posedge puc_rst)
if (puc_rst) r5 <= 16'h0000;
else if (r5_wr) r5 <= reg_dest_val_in;
`ifdef CLOCK_GATING
else r5 <= reg_incr_val;
`else
else if (r5_inc) r5 <= reg_incr_val;
`endif
 
// 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_rst)
 
`ifdef CLOCK_GATING
wire r6_en = r6_wr | r6_inc;
wire mclk_r6;
omsp_clock_gate clock_gate_r6 (.gclk(mclk_r6),
.clk (mclk), .enable(r6_en), .scan_enable(scan_enable));
`else
wire mclk_r6 = mclk;
`endif
 
always @(posedge mclk_r6 or posedge puc_rst)
if (puc_rst) r6 <= 16'h0000;
else if (r6_wr) r6 <= reg_dest_val_in;
`ifdef CLOCK_GATING
else r6 <= reg_incr_val;
`else
else if (r6_inc) r6 <= reg_incr_val;
`endif
 
// 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_rst)
 
`ifdef CLOCK_GATING
wire r7_en = r7_wr | r7_inc;
wire mclk_r7;
omsp_clock_gate clock_gate_r7 (.gclk(mclk_r7),
.clk (mclk), .enable(r7_en), .scan_enable(scan_enable));
`else
wire mclk_r7 = mclk;
`endif
 
always @(posedge mclk_r7 or posedge puc_rst)
if (puc_rst) r7 <= 16'h0000;
else if (r7_wr) r7 <= reg_dest_val_in;
`ifdef CLOCK_GATING
else r7 <= reg_incr_val;
`else
else if (r7_inc) r7 <= reg_incr_val;
`endif
 
// 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_rst)
 
`ifdef CLOCK_GATING
wire r8_en = r8_wr | r8_inc;
wire mclk_r8;
omsp_clock_gate clock_gate_r8 (.gclk(mclk_r8),
.clk (mclk), .enable(r8_en), .scan_enable(scan_enable));
`else
wire mclk_r8 = mclk;
`endif
 
always @(posedge mclk_r8 or posedge puc_rst)
if (puc_rst) r8 <= 16'h0000;
else if (r8_wr) r8 <= reg_dest_val_in;
`ifdef CLOCK_GATING
else r8 <= reg_incr_val;
`else
else if (r8_inc) r8 <= reg_incr_val;
`endif
 
// 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_rst)
 
`ifdef CLOCK_GATING
wire r9_en = r9_wr | r9_inc;
wire mclk_r9;
omsp_clock_gate clock_gate_r9 (.gclk(mclk_r9),
.clk (mclk), .enable(r9_en), .scan_enable(scan_enable));
`else
wire mclk_r9 = mclk;
`endif
 
always @(posedge mclk_r9 or posedge puc_rst)
if (puc_rst) r9 <= 16'h0000;
else if (r9_wr) r9 <= reg_dest_val_in;
`ifdef CLOCK_GATING
else r9 <= reg_incr_val;
`else
else if (r9_inc) r9 <= reg_incr_val;
`endif
 
// 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_rst)
 
`ifdef CLOCK_GATING
wire r10_en = r10_wr | r10_inc;
wire mclk_r10;
omsp_clock_gate clock_gate_r10 (.gclk(mclk_r10),
.clk (mclk), .enable(r10_en), .scan_enable(scan_enable));
`else
wire mclk_r10 = mclk;
`endif
 
always @(posedge mclk_r10 or posedge puc_rst)
if (puc_rst) r10 <= 16'h0000;
else if (r10_wr) r10 <= reg_dest_val_in;
`ifdef CLOCK_GATING
else r10 <= reg_incr_val;
`else
else if (r10_inc) r10 <= reg_incr_val;
`endif
 
// 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_rst)
 
`ifdef CLOCK_GATING
wire r11_en = r11_wr | r11_inc;
wire mclk_r11;
omsp_clock_gate clock_gate_r11 (.gclk(mclk_r11),
.clk (mclk), .enable(r11_en), .scan_enable(scan_enable));
`else
wire mclk_r11 = mclk;
`endif
 
always @(posedge mclk_r11 or posedge puc_rst)
if (puc_rst) r11 <= 16'h0000;
else if (r11_wr) r11 <= reg_dest_val_in;
`ifdef CLOCK_GATING
else r11 <= reg_incr_val;
`else
else if (r11_inc) r11 <= reg_incr_val;
`endif
 
// 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_rst)
 
`ifdef CLOCK_GATING
wire r12_en = r12_wr | r12_inc;
wire mclk_r12;
omsp_clock_gate clock_gate_r12 (.gclk(mclk_r12),
.clk (mclk), .enable(r12_en), .scan_enable(scan_enable));
`else
wire mclk_r12 = mclk;
`endif
 
always @(posedge mclk_r12 or posedge puc_rst)
if (puc_rst) r12 <= 16'h0000;
else if (r12_wr) r12 <= reg_dest_val_in;
`ifdef CLOCK_GATING
else r12 <= reg_incr_val;
`else
else if (r12_inc) r12 <= reg_incr_val;
`endif
 
// 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_rst)
 
`ifdef CLOCK_GATING
wire r13_en = r13_wr | r13_inc;
wire mclk_r13;
omsp_clock_gate clock_gate_r13 (.gclk(mclk_r13),
.clk (mclk), .enable(r13_en), .scan_enable(scan_enable));
`else
wire mclk_r13 = mclk;
`endif
 
always @(posedge mclk_r13 or posedge puc_rst)
if (puc_rst) r13 <= 16'h0000;
else if (r13_wr) r13 <= reg_dest_val_in;
`ifdef CLOCK_GATING
else r13 <= reg_incr_val;
`else
else if (r13_inc) r13 <= reg_incr_val;
`endif
 
// 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_rst)
 
`ifdef CLOCK_GATING
wire r14_en = r14_wr | r14_inc;
wire mclk_r14;
omsp_clock_gate clock_gate_r14 (.gclk(mclk_r14),
.clk (mclk), .enable(r14_en), .scan_enable(scan_enable));
`else
wire mclk_r14 = mclk;
`endif
 
always @(posedge mclk_r14 or posedge puc_rst)
if (puc_rst) r14 <= 16'h0000;
else if (r14_wr) r14 <= reg_dest_val_in;
`ifdef CLOCK_GATING
else r14 <= reg_incr_val;
`else
else if (r14_inc) r14 <= reg_incr_val;
`endif
 
// 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_rst)
 
`ifdef CLOCK_GATING
wire r15_en = r15_wr | r15_inc;
wire mclk_r15;
omsp_clock_gate clock_gate_r15 (.gclk(mclk_r15),
.clk (mclk), .enable(r15_en), .scan_enable(scan_enable));
`else
wire mclk_r15 = mclk;
`endif
 
always @(posedge mclk_r15 or posedge puc_rst)
if (puc_rst) r15 <= 16'h0000;
else if (r15_wr) r15 <= reg_dest_val_in;
else if (r15_inc) r15 <= reg_incr_val;
`ifdef CLOCK_GATING
else r15 <= reg_incr_val;
`else
else if (r15_inc) r15 <= reg_incr_val;
`endif
 
 
//=============================================================================
/omsp_clock_mux.v
0,0 → 1,192
//----------------------------------------------------------------------------
// Copyright (C) 2009 , Olivier Girard
//
// 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: omsp_clock_mux.v
//
// *Module Description:
// Standard clock mux for the openMSP430
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev: 103 $
// $LastChangedBy: olivier.girard $
// $LastChangedDate: 2011-03-05 15:44:48 +0100 (Sat, 05 Mar 2011) $
//----------------------------------------------------------------------------
 
module omsp_clock_mux (
 
// OUTPUTs
clk_out, // Clock output
 
// INPUTs
clk_in0, // Clock input 0
clk_in1, // Clock input 1
reset, // Reset
scan_mode, // Scan mode (clk_in0 is selected in scan mode)
select // Clock selection
);
 
// OUTPUTs
//=========
output clk_out; // Clock output
 
// INPUTs
//=========
input clk_in0; // Clock input 0
input clk_in1; // Clock input 1
input reset; // Reset
input scan_mode; // Scan mode (clk_in0 is selected in scan mode)
input select; // Clock selection
 
 
//===========================================================================================================================//
// 1) CLOCK MUX //
//===========================================================================================================================//
// //
// The following (glitch free) clock mux is implemented as following: //
// //
// //
// //
// //
// +-----. +--------+ +--------+ //
// select >>----+-------------O| \ | | | | +-----. //
// | | |---| D Q |---| D Q |--+-------| \ //
// | +-------O| / | | | | | | |O-+ //
// | | +-----' | | | | | +--O| / | //
// | | | /\ | | /\ | | | +-----' | //
// | | +--+--+--+ +--+--+--+ | | | //
// | | O | | | | //
// | | | | | | | +-----. //
// clk_in0 >>----------------------------------+------------+-----------+ +--| \ //
// | | | | |----<< clk_out //
// | | +---------------------------------------+ +--| / //
// | | | | +-----' //
// | +---------------------------------------------+ | //
// | | | | //
// | | +-----. +--------+ +--------+ | | //
// | +-O| \ | | | | | +-----. | //
// | | |---| D Q |---| D Q |--+-------| \ | //
// +--------------| / | | | | | |O-+ //
// +-----' | | | | +--O| / //
// | /\ | | /\ | | +-----' //
// +--+--+--+ +--+--+--+ | //
// O | | //
// | | | //
// clk_in1 >>----------------------------------+------------+-----------+ //
// //
// //
//===========================================================================================================================//
 
//-----------------------------------------------------------------------------
// Wire declarations
//-----------------------------------------------------------------------------
wire in0_select;
reg in0_select_s;
reg in0_select_ss;
wire in0_enable;
 
wire in1_select;
reg in1_select_s;
reg in1_select_ss;
wire in1_enable;
 
wire clk_in0_inv;
wire clk_in1_inv;
wire gated_clk_in0;
wire gated_clk_in1;
 
 
//-----------------------------------------------------------------------------
// CLK_IN0 Selection
//-----------------------------------------------------------------------------
assign in0_select = ~select & ~in1_select_ss;
always @ (posedge clk_in0_inv or posedge reset)
if (reset) in0_select_s <= 1'b1;
else in0_select_s <= in0_select;
 
always @ (posedge clk_in0 or posedge reset)
if (reset) in0_select_ss <= 1'b1;
else in0_select_ss <= in0_select_s;
 
assign in0_enable = in0_select_ss | scan_mode;
 
 
//-----------------------------------------------------------------------------
// CLK_IN1 Selection
//-----------------------------------------------------------------------------
assign in1_select = select & ~in0_select_ss;
always @ (posedge clk_in1_inv or posedge reset)
if (reset) in1_select_s <= 1'b0;
else in1_select_s <= in1_select;
 
always @ (posedge clk_in1 or posedge reset)
if (reset) in1_select_ss <= 1'b0;
else in1_select_ss <= in1_select_s;
 
assign in1_enable = in1_select_ss & ~scan_mode;
 
//-----------------------------------------------------------------------------
// Clock MUX
//-----------------------------------------------------------------------------
//
// IMPORTANT NOTE:
// Because the clock network is a critical part of the design,
// the following combinatorial logic should be replaced with
// direct instanciation of standard cells from target library.
// Don't forget the "dont_touch" attribute to make sure
// synthesis won't mess it up.
//
 
// Replace with standard cell INVERTER
assign clk_in0_inv = ~clk_in0;
assign clk_in1_inv = ~clk_in1;
 
 
// Replace with standard cell NAND2
assign gated_clk_in0 = ~(clk_in0_inv & in0_enable);
assign gated_clk_in1 = ~(clk_in1_inv & in1_enable);
 
// Replace with standard cell AND2
assign clk_out = (gated_clk_in0 & gated_clk_in1);
 
 
 
endmodule // omsp_clock_gate
 
 
 
omsp_clock_mux.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: periph/template_periph_8b.v =================================================================== --- periph/template_periph_8b.v (revision 132) +++ periph/template_periph_8b.v (revision 134) @@ -87,7 +87,7 @@ // Register one-hot decoder utilities -parameter DEC_SZ = 2**DEC_WD; +parameter DEC_SZ = (1 << DEC_WD); parameter [DEC_SZ-1:0] BASE_REG = {{DEC_SZ-1{1'b0}}, 1'b1}; // Register one-hot decoder
/periph/omsp_gpio.v
182,7 → 182,7
P6SEL = 'h37;
 
// Register one-hot decoder utilities
parameter DEC_SZ = 2**DEC_WD;
parameter DEC_SZ = (1 << DEC_WD);
parameter [DEC_SZ-1:0] BASE_REG = {{DEC_SZ-1{1'b0}}, 1'b1};
 
// Register one-hot decoder
278,14 → 278,14
//---------------
wire [7:0] p1in;
 
omsp_sync_cell sync_cell_p1in_0 (.data_out(p1in[0]), .clk(mclk), .data_in(p1_din[0] & P1_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p1in_1 (.data_out(p1in[1]), .clk(mclk), .data_in(p1_din[1] & P1_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p1in_2 (.data_out(p1in[2]), .clk(mclk), .data_in(p1_din[2] & P1_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p1in_3 (.data_out(p1in[3]), .clk(mclk), .data_in(p1_din[3] & P1_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p1in_4 (.data_out(p1in[4]), .clk(mclk), .data_in(p1_din[4] & P1_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p1in_5 (.data_out(p1in[5]), .clk(mclk), .data_in(p1_din[5] & P1_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p1in_6 (.data_out(p1in[6]), .clk(mclk), .data_in(p1_din[6] & P1_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p1in_7 (.data_out(p1in[7]), .clk(mclk), .data_in(p1_din[7] & P1_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p1in_0 (.data_out(p1in[0]), .data_in(p1_din[0] & P1_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p1in_1 (.data_out(p1in[1]), .data_in(p1_din[1] & P1_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p1in_2 (.data_out(p1in[2]), .data_in(p1_din[2] & P1_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p1in_3 (.data_out(p1in[3]), .data_in(p1_din[3] & P1_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p1in_4 (.data_out(p1in[4]), .data_in(p1_din[4] & P1_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p1in_5 (.data_out(p1in[5]), .data_in(p1_din[5] & P1_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p1in_6 (.data_out(p1in[6]), .data_in(p1_din[6] & P1_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p1in_7 (.data_out(p1in[7]), .data_in(p1_din[7] & P1_EN[0]), .clk(mclk), .rst(puc_rst));
 
 
// P1OUT Register
371,14 → 371,14
//---------------
wire [7:0] p2in;
 
omsp_sync_cell sync_cell_p2in_0 (.data_out(p2in[0]), .clk(mclk), .data_in(p2_din[0] & P2_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p2in_1 (.data_out(p2in[1]), .clk(mclk), .data_in(p2_din[1] & P2_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p2in_2 (.data_out(p2in[2]), .clk(mclk), .data_in(p2_din[2] & P2_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p2in_3 (.data_out(p2in[3]), .clk(mclk), .data_in(p2_din[3] & P2_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p2in_4 (.data_out(p2in[4]), .clk(mclk), .data_in(p2_din[4] & P2_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p2in_5 (.data_out(p2in[5]), .clk(mclk), .data_in(p2_din[5] & P2_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p2in_6 (.data_out(p2in[6]), .clk(mclk), .data_in(p2_din[6] & P2_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p2in_7 (.data_out(p2in[7]), .clk(mclk), .data_in(p2_din[7] & P2_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p2in_0 (.data_out(p2in[0]), .data_in(p2_din[0] & P2_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p2in_1 (.data_out(p2in[1]), .data_in(p2_din[1] & P2_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p2in_2 (.data_out(p2in[2]), .data_in(p2_din[2] & P2_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p2in_3 (.data_out(p2in[3]), .data_in(p2_din[3] & P2_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p2in_4 (.data_out(p2in[4]), .data_in(p2_din[4] & P2_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p2in_5 (.data_out(p2in[5]), .data_in(p2_din[5] & P2_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p2in_6 (.data_out(p2in[6]), .data_in(p2_din[6] & P2_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p2in_7 (.data_out(p2in[7]), .data_in(p2_din[7] & P2_EN[0]), .clk(mclk), .rst(puc_rst));
 
 
// P2OUT Register
465,14 → 465,14
//---------------
wire [7:0] p3in;
 
omsp_sync_cell sync_cell_p3in_0 (.data_out(p3in[0]), .clk(mclk), .data_in(p3_din[0] & P3_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p3in_1 (.data_out(p3in[1]), .clk(mclk), .data_in(p3_din[1] & P3_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p3in_2 (.data_out(p3in[2]), .clk(mclk), .data_in(p3_din[2] & P3_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p3in_3 (.data_out(p3in[3]), .clk(mclk), .data_in(p3_din[3] & P3_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p3in_4 (.data_out(p3in[4]), .clk(mclk), .data_in(p3_din[4] & P3_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p3in_5 (.data_out(p3in[5]), .clk(mclk), .data_in(p3_din[5] & P3_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p3in_6 (.data_out(p3in[6]), .clk(mclk), .data_in(p3_din[6] & P3_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p3in_7 (.data_out(p3in[7]), .clk(mclk), .data_in(p3_din[7] & P3_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p3in_0 (.data_out(p3in[0]), .data_in(p3_din[0] & P3_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p3in_1 (.data_out(p3in[1]), .data_in(p3_din[1] & P3_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p3in_2 (.data_out(p3in[2]), .data_in(p3_din[2] & P3_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p3in_3 (.data_out(p3in[3]), .data_in(p3_din[3] & P3_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p3in_4 (.data_out(p3in[4]), .data_in(p3_din[4] & P3_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p3in_5 (.data_out(p3in[5]), .data_in(p3_din[5] & P3_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p3in_6 (.data_out(p3in[6]), .data_in(p3_din[6] & P3_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p3in_7 (.data_out(p3in[7]), .data_in(p3_din[7] & P3_EN[0]), .clk(mclk), .rst(puc_rst));
 
 
// P3OUT Register
521,14 → 521,14
//---------------
wire [7:0] p4in;
 
omsp_sync_cell sync_cell_p4in_0 (.data_out(p4in[0]), .clk(mclk), .data_in(p4_din[0] & P4_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p4in_1 (.data_out(p4in[1]), .clk(mclk), .data_in(p4_din[1] & P4_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p4in_2 (.data_out(p4in[2]), .clk(mclk), .data_in(p4_din[2] & P4_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p4in_3 (.data_out(p4in[3]), .clk(mclk), .data_in(p4_din[3] & P4_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p4in_4 (.data_out(p4in[4]), .clk(mclk), .data_in(p4_din[4] & P4_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p4in_5 (.data_out(p4in[5]), .clk(mclk), .data_in(p4_din[5] & P4_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p4in_6 (.data_out(p4in[6]), .clk(mclk), .data_in(p4_din[6] & P4_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p4in_7 (.data_out(p4in[7]), .clk(mclk), .data_in(p4_din[7] & P4_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p4in_0 (.data_out(p4in[0]), .data_in(p4_din[0] & P4_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p4in_1 (.data_out(p4in[1]), .data_in(p4_din[1] & P4_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p4in_2 (.data_out(p4in[2]), .data_in(p4_din[2] & P4_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p4in_3 (.data_out(p4in[3]), .data_in(p4_din[3] & P4_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p4in_4 (.data_out(p4in[4]), .data_in(p4_din[4] & P4_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p4in_5 (.data_out(p4in[5]), .data_in(p4_din[5] & P4_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p4in_6 (.data_out(p4in[6]), .data_in(p4_din[6] & P4_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p4in_7 (.data_out(p4in[7]), .data_in(p4_din[7] & P4_EN[0]), .clk(mclk), .rst(puc_rst));
 
 
// P4OUT Register
577,14 → 577,14
//---------------
wire [7:0] p5in;
 
omsp_sync_cell sync_cell_p5in_0 (.data_out(p5in[0]), .clk(mclk), .data_in(p5_din[0] & P5_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p5in_1 (.data_out(p5in[1]), .clk(mclk), .data_in(p5_din[1] & P5_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p5in_2 (.data_out(p5in[2]), .clk(mclk), .data_in(p5_din[2] & P5_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p5in_3 (.data_out(p5in[3]), .clk(mclk), .data_in(p5_din[3] & P5_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p5in_4 (.data_out(p5in[4]), .clk(mclk), .data_in(p5_din[4] & P5_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p5in_5 (.data_out(p5in[5]), .clk(mclk), .data_in(p5_din[5] & P5_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p5in_6 (.data_out(p5in[6]), .clk(mclk), .data_in(p5_din[6] & P5_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p5in_7 (.data_out(p5in[7]), .clk(mclk), .data_in(p5_din[7] & P5_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p5in_0 (.data_out(p5in[0]), .data_in(p5_din[0] & P5_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p5in_1 (.data_out(p5in[1]), .data_in(p5_din[1] & P5_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p5in_2 (.data_out(p5in[2]), .data_in(p5_din[2] & P5_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p5in_3 (.data_out(p5in[3]), .data_in(p5_din[3] & P5_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p5in_4 (.data_out(p5in[4]), .data_in(p5_din[4] & P5_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p5in_5 (.data_out(p5in[5]), .data_in(p5_din[5] & P5_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p5in_6 (.data_out(p5in[6]), .data_in(p5_din[6] & P5_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p5in_7 (.data_out(p5in[7]), .data_in(p5_din[7] & P5_EN[0]), .clk(mclk), .rst(puc_rst));
 
 
// P5OUT Register
633,14 → 633,14
//---------------
wire [7:0] p6in;
 
omsp_sync_cell sync_cell_p6in_0 (.data_out(p6in[0]), .clk(mclk), .data_in(p6_din[0] & P6_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p6in_1 (.data_out(p6in[1]), .clk(mclk), .data_in(p6_din[1] & P6_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p6in_2 (.data_out(p6in[2]), .clk(mclk), .data_in(p6_din[2] & P6_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p6in_3 (.data_out(p6in[3]), .clk(mclk), .data_in(p6_din[3] & P6_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p6in_4 (.data_out(p6in[4]), .clk(mclk), .data_in(p6_din[4] & P6_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p6in_5 (.data_out(p6in[5]), .clk(mclk), .data_in(p6_din[5] & P6_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p6in_6 (.data_out(p6in[6]), .clk(mclk), .data_in(p6_din[6] & P6_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p6in_7 (.data_out(p6in[7]), .clk(mclk), .data_in(p6_din[7] & P6_EN[0]), .rst(puc_rst));
omsp_sync_cell sync_cell_p6in_0 (.data_out(p6in[0]), .data_in(p6_din[0] & P6_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p6in_1 (.data_out(p6in[1]), .data_in(p6_din[1] & P6_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p6in_2 (.data_out(p6in[2]), .data_in(p6_din[2] & P6_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p6in_3 (.data_out(p6in[3]), .data_in(p6_din[3] & P6_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p6in_4 (.data_out(p6in[4]), .data_in(p6_din[4] & P6_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p6in_5 (.data_out(p6in[5]), .data_in(p6_din[5] & P6_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p6in_6 (.data_out(p6in[6]), .data_in(p6_din[6] & P6_EN[0]), .clk(mclk), .rst(puc_rst));
omsp_sync_cell sync_cell_p6in_7 (.data_out(p6in[7]), .data_in(p6_din[7] & P6_EN[0]), .clk(mclk), .rst(puc_rst));
 
 
// P6OUT Register
/periph/omsp_timerA.v
135,7 → 135,7
TAIV = 'h2E;
 
// Register one-hot decoder utilities
parameter DEC_SZ = 2**DEC_WD;
parameter DEC_SZ = (1 << DEC_WD);
parameter [DEC_SZ-1:0] BASE_REG = {{DEC_SZ-1{1'b0}}, 1'b1};
 
// Register one-hot decoder
364,17 → 364,17
wire inclk_s;
 
omsp_sync_cell sync_cell_taclk (
.data_out (taclk_s),
.clk (mclk),
.data_in (taclk),
.rst (puc_rst)
.data_out (taclk_s),
.data_in (taclk),
.clk (mclk),
.rst (puc_rst)
);
 
omsp_sync_cell sync_cell_inclk (
.data_out (inclk_s),
.clk (mclk),
.data_in (inclk),
.rst (puc_rst)
.data_out (inclk_s),
.data_in (inclk),
.clk (mclk),
.rst (puc_rst)
);
 
 
479,20 → 479,20
 
omsp_sync_cell sync_cell_cci0 (
.data_out (cci0_s),
.data_in (cci0),
.clk (mclk),
.data_in (cci0),
.rst (puc_rst)
);
omsp_sync_cell sync_cell_cci1 (
.data_out (cci1_s),
.data_in (cci1),
.clk (mclk),
.data_in (cci1),
.rst (puc_rst)
);
omsp_sync_cell sync_cell_cci2 (
.data_out (cci2_s),
.data_in (cci2),
.clk (mclk),
.data_in (cci2),
.rst (puc_rst)
);
 
/periph/template_periph_16b.v
86,7 → 86,7
CNTRL4 = 'h6;
 
// Register one-hot decoder utilities
parameter DEC_SZ = 2**DEC_WD;
parameter DEC_SZ = (1 << DEC_WD);
parameter [DEC_SZ-1:0] BASE_REG = {{DEC_SZ-1{1'b0}}, 1'b1};
 
// Register one-hot decoder
/omsp_multiplier.v
56,7 → 56,8
per_din, // Peripheral data input
per_en, // Peripheral enable (high active)
per_we, // Peripheral write enable (high active)
puc_rst // Main system reset
puc_rst, // Main system reset
scan_enable // Scan enable (active during scan shifting)
);
 
// OUTPUTs
71,6 → 72,7
input per_en; // Peripheral enable (high active)
input [1:0] per_we; // Peripheral write enable (high active)
input puc_rst; // Main system reset
input scan_enable; // Scan enable (active during scan shifting)
 
 
//=============================================================================
94,7 → 96,7
SUMEXT = 'hE;
 
// Register one-hot decoder utilities
parameter DEC_SZ = 2**DEC_WD;
parameter DEC_SZ = (1 << DEC_WD);
parameter [DEC_SZ-1:0] BASE_REG = {{DEC_SZ-1{1'b0}}, 1'b1};
 
// Register one-hot decoder
156,10 → 158,22
reg_wr[OP1_MAC] |
reg_wr[OP1_MACS];
 
always @ (posedge mclk or posedge puc_rst)
`ifdef CLOCK_GATING
wire mclk_op1;
omsp_clock_gate clock_gate_op1 (.gclk(mclk_op1),
.clk (mclk), .enable(op1_wr), .scan_enable(scan_enable));
`else
wire mclk_op1 = mclk;
`endif
 
always @ (posedge mclk_op1 or posedge puc_rst)
if (puc_rst) op1 <= 16'h0000;
`ifdef CLOCK_GATING
else op1 <= per_din;
`else
else if (op1_wr) op1 <= per_din;
`endif
 
wire [15:0] op1_rd = op1;
 
169,9 → 183,21
 
wire op2_wr = reg_wr[OP2];
 
always @ (posedge mclk or posedge puc_rst)
`ifdef CLOCK_GATING
wire mclk_op2;
omsp_clock_gate clock_gate_op2 (.gclk(mclk_op2),
.clk (mclk), .enable(op2_wr), .scan_enable(scan_enable));
`else
wire mclk_op2 = mclk;
`endif
 
always @ (posedge mclk_op2 or posedge puc_rst)
if (puc_rst) op2 <= 16'h0000;
`ifdef CLOCK_GATING
else op2 <= per_din;
`else
else if (op2_wr) op2 <= per_din;
`endif
 
wire [15:0] op2_rd = op2;
 
183,11 → 209,24
wire [15:0] reslo_nxt;
wire reslo_wr = reg_wr[RESLO];
 
always @ (posedge mclk or posedge puc_rst)
`ifdef CLOCK_GATING
wire reslo_en = reslo_wr | result_clr | result_wr;
wire mclk_reslo;
omsp_clock_gate clock_gate_reslo (.gclk(mclk_reslo),
.clk (mclk), .enable(reslo_en), .scan_enable(scan_enable));
`else
wire mclk_reslo = mclk;
`endif
 
always @ (posedge mclk_reslo or posedge puc_rst)
if (puc_rst) reslo <= 16'h0000;
else if (reslo_wr) reslo <= per_din;
else if (result_clr) reslo <= 16'h0000;
`ifdef CLOCK_GATING
else reslo <= reslo_nxt;
`else
else if (result_wr) reslo <= reslo_nxt;
`endif
 
wire [15:0] reslo_rd = early_read ? reslo_nxt : reslo;
 
199,11 → 238,24
wire [15:0] reshi_nxt;
wire reshi_wr = reg_wr[RESHI];
 
always @ (posedge mclk or posedge puc_rst)
`ifdef CLOCK_GATING
wire reshi_en = reshi_wr | result_clr | result_wr;
wire mclk_reshi;
omsp_clock_gate clock_gate_reshi (.gclk(mclk_reshi),
.clk (mclk), .enable(reshi_en), .scan_enable(scan_enable));
`else
wire mclk_reshi = mclk;
`endif
 
always @ (posedge mclk_reshi or posedge puc_rst)
if (puc_rst) reshi <= 16'h0000;
else if (reshi_wr) reshi <= per_din;
else if (result_clr) reshi <= 16'h0000;
`ifdef CLOCK_GATING
else reshi <= reshi_nxt;
`else
else if (result_wr) reshi <= reshi_nxt;
`endif
 
wire [15:0] reshi_rd = early_read ? reshi_nxt : reshi;
 
254,16 → 306,24
 
// Detect signed mode
reg sign_sel;
always @ (posedge mclk or posedge puc_rst)
always @ (posedge mclk_op1 or posedge puc_rst)
if (puc_rst) sign_sel <= 1'b0;
`ifdef CLOCK_GATING
else sign_sel <= reg_wr[OP1_MPYS] | reg_wr[OP1_MACS];
`else
else if (op1_wr) sign_sel <= reg_wr[OP1_MPYS] | reg_wr[OP1_MACS];
`endif
 
 
// Detect accumulate mode
reg acc_sel;
always @ (posedge mclk or posedge puc_rst)
always @ (posedge mclk_op1 or posedge puc_rst)
if (puc_rst) acc_sel <= 1'b0;
`ifdef CLOCK_GATING
else acc_sel <= reg_wr[OP1_MAC] | reg_wr[OP1_MACS];
`else
else if (op1_wr) acc_sel <= reg_wr[OP1_MAC] | reg_wr[OP1_MACS];
`endif
 
 
// Detect whenever the RESHI and RESLO registers should be cleared
/omsp_dbg_uart.v
100,10 → 100,10
wire uart_rxd_n;
 
omsp_sync_cell sync_cell_uart_rxd (
.data_out (uart_rxd_n),
.clk (dbg_clk),
.data_in (~dbg_uart_rxd),
.rst (dbg_rst)
.data_out (uart_rxd_n),
.data_in (~dbg_uart_rxd),
.clk (dbg_clk),
.rst (dbg_rst)
);
wire uart_rxd = ~uart_rxd_n;
`else
121,19 → 121,18
//------------------------
reg rxd_maj;
 
wire [1:0] rxd_maj_cnt = {1'b0, uart_rxd} +
{1'b0, rxd_buf[0]} +
{1'b0, rxd_buf[1]};
wire rxd_maj_nxt = (rxd_maj_cnt>=2'b10);
wire rxd_maj_nxt = (uart_rxd & rxd_buf[0]) |
(uart_rxd & rxd_buf[1]) |
(rxd_buf[0] & rxd_buf[1]);
always @ (posedge dbg_clk or posedge dbg_rst)
if (dbg_rst) rxd_maj <= 1'b0;
if (dbg_rst) rxd_maj <= 1'b1;
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;
 
wire rxd_s = rxd_maj;
wire rxd_fe = rxd_maj & ~rxd_maj_nxt;
wire rxd_re = ~rxd_maj & rxd_maj_nxt;
wire rxd_edge = rxd_maj ^ rxd_maj_nxt;
//=============================================================================
// 2) UART STATE MACHINE
141,12 → 140,13
 
// Receive state
//------------------------
reg [2:0] uart_state;
reg [2:0] uart_state_nxt;
reg [2:0] uart_state;
reg [2:0] uart_state_nxt;
 
wire sync_done;
wire xfer_done;
reg [19:0] xfer_buf;
wire sync_done;
wire xfer_done;
reg [19:0] xfer_buf;
wire [19:0] xfer_buf_nxt;
 
// State machine definition
parameter RX_SYNC = 3'h0;
157,7 → 157,7
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)
always @(uart_state or xfer_buf_nxt 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 ?
164,9 → 164,9
(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));
(xfer_buf_nxt[`DBG_UART_WR] ?
(xfer_buf_nxt[`DBG_UART_BW] ? RX_DATA2 : RX_DATA1) :
(xfer_buf_nxt[`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) :
175,7 → 175,9
TX_DATA2 : uart_state_nxt = (mem_burst & ~mem_burst_end) ?
(mem_bw ? TX_DATA2 : TX_DATA1) :
RX_CMD;
// pragma coverage off
default : uart_state_nxt = RX_CMD;
// pragma coverage on
endcase
// State machine
186,6 → 188,7
 
// Utility signals
wire cmd_valid = (uart_state==RX_CMD) & xfer_done;
wire rx_active = (uart_state==RX_DATA1) | (uart_state==RX_DATA2) | (uart_state==RX_CMD);
wire tx_active = (uart_state==TX_DATA1) | (uart_state==TX_DATA2);
 
208,8 → 211,8
 
reg [`DBG_UART_XFER_CNT_W+2:0] sync_cnt;
always @ (posedge dbg_clk or posedge dbg_rst)
if (dbg_rst) 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};
if (dbg_rst) sync_cnt <= {{`DBG_UART_XFER_CNT_W{1'b1}}, 3'b000};
else if (sync_busy | (~sync_busy & sync_cnt[2])) 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
229,7 → 232,7
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);
assign xfer_done = rx_active ? (xfer_bit==4'ha) : (xfer_bit==4'hb);
always @ (posedge dbg_clk or posedge dbg_rst)
if (dbg_rst) xfer_bit <= 4'h0;
239,14 → 242,14
 
always @ (posedge dbg_clk or posedge dbg_rst)
if (dbg_rst) 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 (rx_active & rxd_edge) 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}};
else if (|xfer_cnt) 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]};
assign xfer_buf_nxt = {rxd_s, xfer_buf[19:1]};
 
always @ (posedge dbg_clk or posedge dbg_rst)
if (dbg_rst) xfer_buf <= 20'h00000;
270,20 → 273,20
reg [5:0] dbg_addr;
always @ (posedge dbg_clk or posedge dbg_rst)
if (dbg_rst) dbg_addr <= 6'h00;
else if (cmd_valid) dbg_addr <= xfer_buf[`DBG_UART_ADDR];
else if (cmd_valid) dbg_addr <= xfer_buf_nxt[`DBG_UART_ADDR];
 
reg dbg_bw;
always @ (posedge dbg_clk or posedge dbg_rst)
if (dbg_rst) dbg_bw <= 1'b0;
else if (cmd_valid) dbg_bw <= xfer_buf[`DBG_UART_BW];
else if (cmd_valid) dbg_bw <= xfer_buf_nxt[`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 [15:0] dbg_din = dbg_din_bw ? {8'h00, xfer_buf_nxt[18:11]} :
{xfer_buf_nxt[18:11], xfer_buf_nxt[9:2]};
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;
(cmd_valid & ~xfer_buf_nxt[`DBG_UART_WR]) | mem_burst_rd;
 
/omsp_sfr.v
31,6 → 31,7
//
// *Module Description:
// Processor Special function register
// Non-Maskable Interrupt generation
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
48,49 → 49,51
module omsp_sfr (
 
// OUTPUTs
nmie, // Non-maskable interrupt enable
cpu_id, // CPU ID
nmi_pnd, // NMI Pending
nmi_wkup, // NMI Wakeup
per_dout, // Peripheral data output
wdt_irq, // Watchdog-timer interrupt
wdt_reset, // Watchdog-timer reset
wdtie, // Watchdog-timer interrupt enable
wdtifg_sw_clr, // Watchdog-timer interrupt flag software clear
wdtifg_sw_set, // Watchdog-timer interrupt flag software set
 
// INPUTs
mclk, // Main system clock
nmi, // Non-maskable interrupt (asynchronous)
nmi_acc, // Non-Maskable interrupt request accepted
per_addr, // Peripheral address
per_din, // Peripheral data input
per_en, // Peripheral enable (high active)
per_we, // Peripheral write enable (high active)
por, // Power-on reset
puc_rst, // 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
scan_mode, // Scan mode
wdtifg, // Watchdog-timer interrupt flag
wdtnmies // Watchdog-timer NMI edge selection
);
 
// OUTPUTs
//=========
output nmie; // Non-maskable interrupt enable
output [31:0] cpu_id; // CPU ID
output nmi_pnd; // NMI Pending
output nmi_wkup; // NMI Wakeup
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
output wdtifg_sw_clr;// Watchdog-timer interrupt flag software clear
output wdtifg_sw_set;// Watchdog-timer interrupt flag software set
 
// INPUTs
//=========
input mclk; // Main system clock
input nmi; // Non-maskable interrupt (asynchronous)
input nmi_acc; // Non-Maskable interrupt request accepted
input [13:0] per_addr; // Peripheral address
input [15:0] per_din; // Peripheral data input
input per_en; // Peripheral enable (high active)
input [1:0] per_we; // Peripheral write enable (high active)
input por; // Power-on reset
input puc_rst; // 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
input scan_mode; // Scan mode
input wdtifg; // Watchdog-timer interrupt flag
input wdtnmies; // Watchdog-timer NMI edge selection
 
 
//=============================================================================
101,19 → 104,23
parameter [14:0] BASE_ADDR = 15'h0000;
 
// Decoder bit width (defines how many bits are considered for address decoding)
parameter DEC_WD = 2;
parameter DEC_WD = 3;
 
// Register addresses offset
parameter [DEC_WD-1:0] IE1 = 'h0,
IFG1 = 'h2;
IFG1 = 'h2,
CPU_ID_LO = 'h4,
CPU_ID_HI = 'h6;
 
// Register one-hot decoder utilities
parameter DEC_SZ = 2**DEC_WD;
parameter DEC_SZ = (1 << DEC_WD);
parameter [DEC_SZ-1:0] BASE_REG = {{DEC_SZ-1{1'b0}}, 1'b1};
 
// Register one-hot decoder
parameter [DEC_SZ-1:0] IE1_D = (BASE_REG << IE1),
IFG1_D = (BASE_REG << IFG1);
IFG1_D = (BASE_REG << IFG1),
CPU_ID_LO_D = (BASE_REG << CPU_ID_LO),
CPU_ID_HI_D = (BASE_REG << CPU_ID_HI);
 
 
//============================================================================
127,8 → 134,10
wire [DEC_WD-1:0] reg_addr = {1'b0, per_addr[DEC_WD-2:0]};
 
// Register address decode
wire [DEC_SZ-1:0] reg_dec = (IE1_D & {DEC_SZ{(reg_addr==(IE1 >>1))}}) |
(IFG1_D & {DEC_SZ{(reg_addr==(IFG1 >>1))}});
wire [DEC_SZ-1:0] reg_dec = (IE1_D & {DEC_SZ{(reg_addr==(IE1 >>1))}}) |
(IFG1_D & {DEC_SZ{(reg_addr==(IFG1 >>1))}}) |
(CPU_ID_LO_D & {DEC_SZ{(reg_addr==(CPU_ID_LO >>1))}}) |
(CPU_ID_HI_D & {DEC_SZ{(reg_addr==(CPU_ID_HI >>1))}});
 
// Read/Write probes
wire reg_lo_write = per_we[0] & reg_sel;
151,16 → 160,24
wire ie1_wr = IE1[0] ? reg_hi_wr[IE1] : reg_lo_wr[IE1];
wire [7:0] ie1_nxt = IE1[0] ? per_din[15:8] : per_din[7:0];
 
`ifdef NMI
reg nmie;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) nmie <= 1'b0;
else if (nmi_acc) nmie <= 1'b0;
else if (ie1_wr) nmie <= ie1_nxt[4];
`else
wire nmie = 1'b0;
`endif
 
`ifdef WATCHDOG
reg wdtie;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) wdtie <= 1'b0;
else if (ie1_wr) wdtie <= ie1_nxt[0];
`else
wire wdtie = 1'b0;
`endif
 
assign ie1 = {3'b000, nmie, 3'b000, wdtie};
 
168,55 → 185,166
// IFG1 Register
//---------------
wire [7:0] ifg1;
 
wire ifg1_wr = IFG1[0] ? reg_hi_wr[IFG1] : reg_lo_wr[IFG1];
wire [7:0] ifg1_nxt = IFG1[0] ? per_din[15:8] : per_din[7:0];
 
`ifdef NMI
reg nmiifg;
wire nmi_edge;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) nmiifg <= 1'b0;
else if (nmi_acc) nmiifg <= 1'b1;
else if (nmi_edge) nmiifg <= 1'b1;
else if (ifg1_wr) nmiifg <= ifg1_nxt[4];
`else
wire nmiifg = 1'b0;
`endif
 
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];
`ifdef WATCHDOG
assign wdtifg_sw_clr = ifg1_wr & ~ifg1_nxt[0];
assign wdtifg_sw_set = ifg1_wr & ifg1_nxt[0];
`else
assign wdtifg_sw_clr = 1'b0;
assign wdtifg_sw_set = 1'b0;
`endif
 
assign ifg1 = {3'b000, nmiifg, 3'b000, wdtifg};
 
 
// CPU_ID Register (READ ONLY)
//-----------------------------
// -------------------------------------------------------------------
// CPU_ID_LO: | 15 14 13 12 11 10 9 | 8 7 6 5 4 | 3 | 2 1 0 |
// |----------------------------+-----------------+------+-------------|
// | PER_SPACE | USER_VERSION | ASIC | CPU_VERSION |
// --------------------------------------------------------------------
// CPU_ID_HI: | 15 14 13 12 11 10 | 9 8 7 6 5 4 3 2 1 | 0 |
// |----------------------------+-------------------------------+------|
// | PMEM_SIZE | DMEM_SIZE | MPY |
// -------------------------------------------------------------------
 
wire [2:0] cpu_version = `CPU_VERSION;
`ifdef ASIC
wire cpu_asic = 1'b1;
`else
wire cpu_asic = 1'b0;
`endif
wire [4:0] user_version = `USER_VERSION;
wire [6:0] per_space = (`PER_SIZE >> 9); // cpu_id_per * 512 = peripheral space size
`ifdef MULTIPLIER
wire mpy_info = 1'b1;
`else
wire mpy_info = 1'b0;
`endif
wire [8:0] dmem_size = (`DMEM_SIZE >> 7); // cpu_id_dmem * 128 = data memory size
wire [5:0] pmem_size = (`PMEM_SIZE >> 10); // cpu_id_pmem * 1024 = program memory size
 
assign cpu_id = {pmem_size,
dmem_size,
mpy_info,
per_space,
user_version,
cpu_asic,
cpu_version};
 
 
//============================================================================
// 4) DATA OUTPUT GENERATION
//============================================================================
 
// Data output mux
wire [15:0] ie1_rd = {8'h00, (ie1 & {8{reg_rd[IE1]}})} << (8 & {4{IE1[0]}});
wire [15:0] ifg1_rd = {8'h00, (ifg1 & {8{reg_rd[IFG1]}})} << (8 & {4{IFG1[0]}});
wire [15:0] ie1_rd = {8'h00, (ie1 & {8{reg_rd[IE1]}})} << (8 & {4{IE1[0]}});
wire [15:0] ifg1_rd = {8'h00, (ifg1 & {8{reg_rd[IFG1]}})} << (8 & {4{IFG1[0]}});
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] per_dout = ie1_rd |
ifg1_rd;
wire [15:0] per_dout = ie1_rd |
ifg1_rd |
cpu_id_lo_rd |
cpu_id_hi_rd;
 
 
//=============================================================================
// 5) WATCHDOG INTERRUPT & RESET
// 5) NMI GENERATION
//=============================================================================
// NOTE THAT THE NMI INPUT IS ASSUMED TO BE NON-GLITCHY
`ifdef NMI
 
// Watchdog interrupt generation
//---------------------------------
wire wdt_irq = wdttmsel & wdtifg & wdtie;
//-----------------------------------
// Edge selection
//-----------------------------------
wire nmi_pol = nmi ^ wdtnmies;
 
// Watchdog reset generation
//-----------------------------
reg wdt_reset;
//-----------------------------------
// Pulse capture and synchronization
//-----------------------------------
`ifdef SYNC_NMI
`ifdef ASIC
// Glitch free reset for the event capture
reg nmi_capture_rst;
always @(posedge mclk or posedge puc_rst)
if (puc_rst) nmi_capture_rst <= 1'b1;
else nmi_capture_rst <= ifg1_wr & ~ifg1_nxt[4];
// NMI event capture
wire nmi_capture;
omsp_wakeup_cell wakeup_cell_nmi (
.wkup_out (nmi_capture), // Wakup signal (asynchronous)
.scan_clk (mclk), // Scan clock
.scan_mode (scan_mode), // Scan mode
.scan_rst (puc_rst), // Scan reset
.wkup_clear (nmi_capture_rst), // Glitch free wakeup event clear
.wkup_event (nmi_pol) // Glitch free asynchronous wakeup event
);
`else
wire nmi_capture = nmi_pol;
`endif
 
always @ (posedge mclk or posedge por)
if (por) wdt_reset <= 1'b0;
else wdt_reset <= wdtpw_error | (wdtifg_set & ~wdttmsel);
// Synchronization
wire nmi_s;
omsp_sync_cell sync_cell_nmi (
.data_out (nmi_s),
.data_in (nmi_capture),
.clk (mclk),
.rst (puc_rst)
);
 
`else
wire nmi_capture = nmi_pol;
wire nmi_s = nmi_pol;
`endif
 
//-----------------------------------
// NMI Pending flag
//-----------------------------------
 
// Delay
reg nmi_dly;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) nmi_dly <= 1'b0;
else nmi_dly <= nmi_s;
 
// Edge detection
assign nmi_edge = ~nmi_dly & nmi_s;
 
// NMI pending
wire nmi_pnd = nmiifg & nmie;
 
// NMI wakeup
`ifdef ASIC
wire nmi_wkup;
omsp_and_gate and_nmi_wkup (.y(nmi_wkup), .a(nmi_capture ^ nmi_dly), .b(nmie));
`else
wire nmi_wkup = 1'b0;
`endif
 
`else
 
wire nmi_pnd = 1'b0;
wire nmi_wkup = 1'b0;
 
`endif
 
endmodule // omsp_sfr
 
`ifdef OMSP_NO_INCLUDE
/omsp_wakeup_cell.v
0,0 → 1,108
//----------------------------------------------------------------------------
// Copyright (C) 2009 , Olivier Girard
//
// 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: omsp_wakeup_cell.v
//
// *Module Description:
// Generic Wakeup cell
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev: 103 $
// $LastChangedBy: olivier.girard $
// $LastChangedDate: 2011-03-05 15:44:48 +0100 (Sat, 05 Mar 2011) $
//----------------------------------------------------------------------------
 
module omsp_wakeup_cell (
 
// OUTPUTs
wkup_out, // Wakup signal (asynchronous)
 
// INPUTs
scan_clk, // Scan clock
scan_mode, // Scan mode
scan_rst, // Scan reset
wkup_clear, // Glitch free wakeup event clear
wkup_event // Glitch free asynchronous wakeup event
);
 
// OUTPUTs
//=========
output wkup_out; // Wakup signal (asynchronous)
 
// INPUTs
//=========
input scan_clk; // Scan clock
input scan_mode; // Scan mode
input scan_rst; // Scan reset
input wkup_clear; // Glitch free wakeup event clear
input wkup_event; // Glitch free asynchronous wakeup event
 
 
//=============================================================================
// 1) AND GATE
//=============================================================================
 
// Scan stuff for the ASIC mode
`ifdef ASIC
wire wkup_rst;
omsp_scan_mux scan_mux_rst (
.scan_mode (scan_mode),
.data_in_scan (scan_rst),
.data_in_func (wkup_clear),
.data_out (wkup_rst)
);
 
wire wkup_clk;
omsp_scan_mux scan_mux_clk (
.scan_mode (scan_mode),
.data_in_scan (scan_clk),
.data_in_func (wkup_event),
.data_out (wkup_clk)
);
 
`else
wire wkup_rst = wkup_clear;
wire wkup_clk = wkup_event;
`endif
 
// Wakeup capture
reg wkup_out;
always @(posedge wkup_clk or posedge wkup_rst)
if (wkup_rst) wkup_out <= 1'b0;
else wkup_out <= 1'b1;
 
 
endmodule // omsp_wakeup_cell
 
 
 
 
omsp_wakeup_cell.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: omsp_clock_gate.v =================================================================== --- omsp_clock_gate.v (nonexistent) +++ omsp_clock_gate.v (revision 134) @@ -0,0 +1,86 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2009 , Olivier Girard +// +// 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: omsp_clock_gate.v +// +// *Module Description: +// Generic clock gate cell for the openMSP430 +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev: 103 $ +// $LastChangedBy: olivier.girard $ +// $LastChangedDate: 2011-03-05 15:44:48 +0100 (Sat, 05 Mar 2011) $ +//---------------------------------------------------------------------------- + +module omsp_clock_gate ( + +// OUTPUTs + gclk, // Gated clock + +// INPUTs + clk, // Clock + enable, // Clock enable + scan_enable // Scan enable (active during scan shifting) +); + +// OUTPUTs +//========= +output gclk; // Gated clock + +// INPUTs +//========= +input clk; // Clock +input enable; // Clock enable +input scan_enable; // Scan enable (active during scan shifting) + + +//============================================================================= +// CLOCK GATE: LATCH + AND +//============================================================================= + +// Enable clock gate during scan shift +// (the gate itself is checked with the scan capture cycle) +wire enable_in = (enable | scan_enable); + +// LATCH the enable signal +reg enable_latch; +always @(clk or enable_in) + if (~clk) + enable_latch <= enable_in; + +// AND gate +assign gclk = (clk & enable_latch); + + +endmodule // omsp_clock_gate + +
omsp_clock_gate.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: omsp_dbg.v =================================================================== --- omsp_dbg.v (revision 132) +++ omsp_dbg.v (revision 134) @@ -60,6 +60,7 @@ // INPUTs cpu_en_s, // Enable CPU code execution (synchronous) + cpu_id, // CPU ID dbg_clk, // Debug unit clock dbg_en_s, // Debug interface enable (synchronous) dbg_halt_st, // Halt/Run status from CPU @@ -77,7 +78,7 @@ fe_mb_en, // Frontend Memory bus enable fe_mdb_in, // Frontend Memory data bus input pc, // Program counter - puc_rst // Main system reset + puc_pnd_set // PUC pending set for the serial debug interface ); // OUTPUTs @@ -95,6 +96,7 @@ // INPUTs //========= input cpu_en_s; // Enable CPU code execution (synchronous) +input [31:0] cpu_id; // CPU ID input dbg_clk; // Debug unit clock input dbg_en_s; // Debug interface enable (synchronous) input dbg_halt_st; // Halt/Run status from CPU @@ -112,7 +114,7 @@ input fe_mb_en; // Frontend Memory bus enable input [15:0] fe_mdb_in; // Frontend Memory data bus input input [15:0] pc; // Program counter -input puc_rst; // Main system reset +input puc_pnd_set; // PUC pending set for the serial debug interface //============================================================================= @@ -145,6 +147,9 @@ wire brk3_pnd; wire [15:0] brk3_dout; +// Number of registers +parameter NR_REG = 24; + // Register addresses parameter CPU_ID_LO = 6'h00; parameter CPU_ID_HI = 6'h01; @@ -180,47 +185,41 @@ `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); +parameter BASE_D = {{NR_REG-1{1'b0}}, 1'b1}; +parameter CPU_ID_LO_D = (BASE_D << CPU_ID_LO); +parameter CPU_ID_HI_D = (BASE_D << CPU_ID_HI); +parameter CPU_CTL_D = (BASE_D << CPU_CTL); +parameter CPU_STAT_D = (BASE_D << CPU_STAT); +parameter MEM_CTL_D = (BASE_D << MEM_CTL); +parameter MEM_ADDR_D = (BASE_D << MEM_ADDR); +parameter MEM_DATA_D = (BASE_D << MEM_DATA); +parameter MEM_CNT_D = (BASE_D << 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); +parameter BRK0_CTL_D = (BASE_D << BRK0_CTL); +parameter BRK0_STAT_D = (BASE_D << BRK0_STAT); +parameter BRK0_ADDR0_D = (BASE_D << BRK0_ADDR0); +parameter BRK0_ADDR1_D = (BASE_D << 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); +parameter BRK1_CTL_D = (BASE_D << BRK1_CTL); +parameter BRK1_STAT_D = (BASE_D << BRK1_STAT); +parameter BRK1_ADDR0_D = (BASE_D << BRK1_ADDR0); +parameter BRK1_ADDR1_D = (BASE_D << 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); +parameter BRK2_CTL_D = (BASE_D << BRK2_CTL); +parameter BRK2_STAT_D = (BASE_D << BRK2_STAT); +parameter BRK2_ADDR0_D = (BASE_D << BRK2_ADDR0); +parameter BRK2_ADDR1_D = (BASE_D << 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); +parameter BRK3_CTL_D = (BASE_D << BRK3_CTL); +parameter BRK3_STAT_D = (BASE_D << BRK3_STAT); +parameter BRK3_ADDR0_D = (BASE_D << BRK3_ADDR0); +parameter BRK3_ADDR1_D = (BASE_D << BRK3_ADDR1); `endif -// PUC is localy used as a data. -reg [1:0] puc_sync; -always @ (posedge dbg_clk or posedge dbg_rst) - if (dbg_rst) puc_sync <= 2'b11; - else puc_sync <= {puc_sync[0] , puc_rst}; -wire puc_s = puc_sync[1]; - //============================================================================ // 2) REGISTER DECODER //============================================================================ @@ -229,7 +228,7 @@ wire [5:0] dbg_addr_in = mem_burst ? MEM_DATA : dbg_addr; // Register address decode -reg [63:0] reg_dec; +reg [NR_REG-1:0] reg_dec; always @(dbg_addr_in) case (dbg_addr_in) CPU_ID_LO : reg_dec = CPU_ID_LO_D; @@ -264,16 +263,18 @@ BRK3_ADDR0: reg_dec = BRK3_ADDR0_D; BRK3_ADDR1: reg_dec = BRK3_ADDR1_D; `endif - default: reg_dec = {64{1'b0}}; + // pragma coverage off + default: reg_dec = {NR_REG{1'b0}}; + // pragma coverage on endcase // Read/Write probes -wire reg_write = dbg_wr; -wire reg_read = 1'b1; +wire reg_write = dbg_wr; +wire reg_read = 1'b1; // Read/Write vectors -wire [63:0] reg_wr = reg_dec & {64{reg_write}}; -wire [63:0] reg_rd = reg_dec & {64{reg_read}}; +wire [NR_REG-1:0] reg_wr = reg_dec & {NR_REG{reg_write}}; +wire [NR_REG-1:0] reg_rd = reg_dec & {NR_REG{reg_read}}; //============================================================================= @@ -292,31 +293,9 @@ // | PMEM_SIZE | DMEM_SIZE | MPY | // ------------------------------------------------------------------- -wire [2:0] cpu_version = `CPU_VERSION; -`ifdef ASIC -wire cpu_asic = 1'b1; -`else -wire cpu_asic = 1'b0; -`endif -wire [4:0] user_version = `USER_VERSION; -wire [6:0] per_space = (`PER_SIZE >> 9); // cpu_id_per * 512 = peripheral space size -`ifdef MULTIPLIER -wire mpy_info = 1'b1; -`else -wire mpy_info = 1'b0; -`endif -wire [8:0] dmem_size = (`DMEM_SIZE >> 7); // cpu_id_dmem * 128 = data memory size -wire [5:0] pmem_size = (`PMEM_SIZE >> 10); // cpu_id_pmem * 1024 = program memory size +// This register is assigned in the SFR module -wire [31:0] cpu_id = {pmem_size, - dmem_size, - mpy_info, - per_space, - user_version, - cpu_asic, - cpu_version}; - // CPU_CTL Register //----------------------------------------------------------------------------- // 7 6 5 4 3 2 1 0 @@ -328,9 +307,9 @@ always @ (posedge dbg_clk or posedge dbg_rst) `ifdef DBG_RST_BRK_EN - if (dbg_rst) cpu_ctl <= 4'h4; + if (dbg_rst) cpu_ctl <= 4'h6; `else - if (dbg_rst) cpu_ctl <= 4'h0; + if (dbg_rst) cpu_ctl <= 4'h2; `endif else if (cpu_ctl_wr) cpu_ctl <= dbg_din[6:3]; @@ -349,7 +328,7 @@ reg [3:2] cpu_stat; wire cpu_stat_wr = reg_wr[CPU_STAT]; -wire [3:2] cpu_stat_set = {dbg_swbrk, puc_s}; +wire [3:2] cpu_stat_set = {dbg_swbrk, puc_pnd_set}; wire [3:2] cpu_stat_clr = ~dbg_din[3:2]; always @ (posedge dbg_clk or posedge dbg_rst) @@ -667,7 +646,7 @@ // Break after reset //-------------------------- -wire halt_rst = cpu_ctl[`RST_BRK_EN] & dbg_en_s & puc_s; +wire halt_rst = cpu_ctl[`RST_BRK_EN] & dbg_en_s & puc_pnd_set; // Freeze peripherals @@ -757,7 +736,9 @@ 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; + // pragma coverage off default : mem_state_nxt = M_IDLE; + // pragma coverage on endcase // State machine
/omsp_clock_module.v
31,10 → 31,6
//
// *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
52,23 → 48,33
module omsp_clock_module (
 
// OUTPUTs
aclk, // ACLK
aclk_en, // ACLK enable
cpu_en_s, // Enable CPU code execution (synchronous)
dbg_clk, // Debug unit clock
dbg_en_s, // Debug interface enable (synchronous)
dbg_rst, // Debug unit reset
dco_enable, // Fast oscillator enable
dco_wkup, // Fast oscillator wake-up (asynchronous)
lfxt_enable, // Low frequency oscillator enable
lfxt_wkup, // Low frequency oscillator wake-up (asynchronous)
mclk, // Main system clock
per_dout, // Peripheral data output
por, // Power-on reset
puc_pnd_set, // PUC pending set for the serial debug interface
puc_rst, // Main system reset
smclk, // SMCLK
smclk_en, // SMCLK enable
// INPUTs
cpu_en, // Enable CPU code execution (asynchronous)
cpuoff, // Turns off the CPU
dbg_cpu_reset, // Reset CPU from debug interface
dbg_en, // Debug interface enable (asynchronous)
dco_clk, // Fast oscillator (fast clock)
lfxt_clk, // Low frequency oscillator (typ 32kHz)
mclk_enable, // Main System Clock enable
mclk_wkup, // Main System Clock wake-up (asynchronous)
oscoff, // Turns off LFXT1 clock input
per_addr, // Peripheral address
per_din, // Peripheral data input
75,6 → 81,9
per_en, // Peripheral enable (high active)
per_we, // Peripheral write enable (high active)
reset_n, // Reset Pin (low active, asynchronous)
scan_enable, // Scan enable (active during scan shifting)
scan_mode, // Scan mode
scg0, // System clock generator 1. Turns off the DCO
scg1, // System clock generator 1. Turns off the SMCLK
wdt_reset // Watchdog-timer reset
);
81,24 → 90,34
 
// OUTPUTs
//=========
output aclk; // ACLK
output aclk_en; // ACLK enable
output cpu_en_s; // Enable CPU code execution (synchronous)
output dbg_clk; // Debug unit clock
output dbg_en_s; // Debug unit enable (synchronous)
output dbg_rst; // Debug unit reset
output dco_enable; // Fast oscillator enable
output dco_wkup; // Fast oscillator wake-up (asynchronous)
output lfxt_enable; // Low frequency oscillator enable
output lfxt_wkup; // Low frequency oscillator wake-up (asynchronous)
output mclk; // Main system clock
output [15:0] per_dout; // Peripheral data output
output por; // Power-on reset
output puc_pnd_set; // PUC pending set for the serial debug interface
output puc_rst; // Main system reset
output smclk; // SMCLK
output smclk_en; // SMCLK enable
 
// INPUTs
//=========
input cpu_en; // Enable CPU code execution (asynchronous)
input cpuoff; // Turns off the CPU
input dbg_cpu_reset;// Reset CPU from debug interface
input dbg_en; // Debug interface enable (asynchronous)
input dco_clk; // Fast oscillator (fast clock)
input lfxt_clk; // Low frequency oscillator (typ 32kHz)
input mclk_enable; // Main System Clock enable
input mclk_wkup; // Main System Clock wake-up (asynchronous)
input oscoff; // Turns off LFXT1 clock input
input [13:0] per_addr; // Peripheral address
input [15:0] per_din; // Peripheral data input
105,12 → 124,15
input per_en; // Peripheral enable (high active)
input [1:0] per_we; // Peripheral write enable (high active)
input reset_n; // Reset Pin (low active, asynchronous)
input scan_enable; // Scan enable (active during scan shifting)
input scan_mode; // Scan mode
input scg0; // System clock generator 1. Turns off the DCO
input scg1; // System clock generator 1. Turns off the SMCLK
input wdt_reset; // Watchdog-timer reset
 
 
//=============================================================================
// 1) PARAMETER DECLARATION
// 1) WIRES & PARAMETER DECLARATION
//=============================================================================
 
// Register base address (must be aligned to decoder bit width)
124,7 → 146,7
BCSCTL2 = 'h8;
 
// Register one-hot decoder utilities
parameter DEC_SZ = 2**DEC_WD;
parameter DEC_SZ = (1 << DEC_WD);
parameter [DEC_SZ-1:0] BASE_REG = {{DEC_SZ-1{1'b0}}, 1'b1};
 
// Register one-hot decoder
131,7 → 153,12
parameter [DEC_SZ-1:0] BCSCTL1_D = (BASE_REG << BCSCTL1),
BCSCTL2_D = (BASE_REG << BCSCTL2);
 
// Local wire declarations
wire nodiv_mclk;
wire nodiv_mclk_n;
wire nodiv_smclk;
 
 
//============================================================================
// 2) REGISTER DECODER
//============================================================================
167,20 → 194,57
wire bcsctl1_wr = BCSCTL1[0] ? reg_hi_wr[BCSCTL1] : reg_lo_wr[BCSCTL1];
wire [7:0] bcsctl1_nxt = BCSCTL1[0] ? per_din[15:8] : per_din[7:0];
 
`ifdef ASIC
`ifdef ACLK_DIVIDER
wire [7:0] divax_mask = 8'h30;
`else
wire [7:0] divax_mask = 8'h00;
`endif
`else
wire [7:0] divax_mask = 8'h30;
`endif
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) bcsctl1 <= 8'h00;
else if (bcsctl1_wr) bcsctl1 <= bcsctl1_nxt & 8'h30; // Mask unused bits
else if (bcsctl1_wr) bcsctl1 <= bcsctl1_nxt & divax_mask; // Mask unused bits
 
 
// BCSCTL2 Register
//--------------
reg [7:0] bcsctl2;
wire bcsctl2_wr = BCSCTL2[0] ? reg_hi_wr[BCSCTL2] : reg_lo_wr[BCSCTL2];
wire [7:0] bcsctl2_nxt = BCSCTL2[0] ? per_din[15:8] : per_din[7:0];
wire bcsctl2_wr = BCSCTL2[0] ? reg_hi_wr[BCSCTL2] : reg_lo_wr[BCSCTL2];
wire [7:0] bcsctl2_nxt = BCSCTL2[0] ? per_din[15:8] : per_din[7:0];
 
`ifdef MCLK_MUX
wire [7:0] selmx_mask = 8'h80;
`else
wire [7:0] selmx_mask = 8'h00;
`endif
`ifdef MCLK_DIVIDER
wire [7:0] divmx_mask = 8'h30;
`else
wire [7:0] divmx_mask = 8'h00;
`endif
`ifdef ASIC
`ifdef SMCLK_MUX
wire [7:0] sels_mask = 8'h08;
`else
wire [7:0] sels_mask = 8'h00;
`endif
`ifdef SMCLK_DIVIDER
wire [7:0] divsx_mask = 8'h06;
`else
wire [7:0] divsx_mask = 8'h00;
`endif
`else
wire [7:0] sels_mask = 8'h08;
wire [7:0] divsx_mask = 8'h06;
`endif
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) bcsctl2 <= 8'h00;
else if (bcsctl2_wr) bcsctl2 <= bcsctl2_nxt & 8'h0e; // Mask unused bits
else if (bcsctl2_wr) bcsctl2 <= bcsctl2_nxt & ( sels_mask | divsx_mask |
selmx_mask | divmx_mask); // Mask unused bits
 
 
//============================================================================
196,31 → 260,213
 
 
//=============================================================================
// 5) CLOCK GENERATION
// 5) DCO_CLK / LFXT_CLK INTERFACES (WAKEUP, ENABLE, ...)
//=============================================================================
 
// Synchronize CPU_EN signal
//---------------------------------------
`ifdef SYNC_CPU_EN
omsp_sync_cell sync_cell_cpu_en (
.data_out (cpu_en_s),
.clk (mclk),
.data_in (cpu_en),
.rst (por)
);
`ifdef ASIC
wire cpuoff_and_mclk_enable;
omsp_and_gate and_cpuoff_mclk_en (.y(cpuoff_and_mclk_enable), .a(cpuoff), .b(mclk_enable));
`endif
 
//-----------------------------------------------------------
// 5.1) HIGH SPEED SYSTEM CLOCK GENERATOR (DCO_CLK)
//-----------------------------------------------------------
// Note1: switching off the DCO osillator is only
// supported in ASIC mode with SCG0 low power mode
//
// Note2: unlike the original MSP430 specification,
// we allow to switch off the DCO even
// if it is selected by MCLK or SMCLK.
 
wire por_a;
wire dco_wkup;
wire cpu_en_wkup;
 
`ifdef SCG0_EN
 
// The DCO oscillator is synchronously disabled if:
// - the cpu pin is disabled (in that case, wait for mclk_enable==0)
// - the debug interface is disabled
// - SCG0 is set (in that case, wait for the mclk_enable==0 if selected by SELMx)
//
// Note that we make extensive use of the AND gate module in order
// to prevent glitch propagation on the wakeup logic cone.
wire cpu_enabled_with_dco;
wire dco_not_enabled_by_dbg;
wire dco_disable_by_scg0;
wire dco_disable_by_cpu_en;
wire dco_enable_nxt;
omsp_and_gate and_dco_dis1 (.y(cpu_enabled_with_dco), .a(~bcsctl2[`SELMx]), .b(cpuoff_and_mclk_enable));
omsp_and_gate and_dco_dis2 (.y(dco_not_enabled_by_dbg), .a(~dbg_en_s), .b(~cpu_enabled_with_dco));
omsp_and_gate and_dco_dis3 (.y(dco_disable_by_scg0), .a(scg0), .b(dco_not_enabled_by_dbg));
omsp_and_gate and_dco_dis4 (.y(dco_disable_by_cpu_en), .a(~cpu_en_s), .b(~mclk_enable));
omsp_and_gate and_dco_dis5 (.y(dco_enable_nxt), .a(~dco_disable_by_scg0), .b(~dco_disable_by_cpu_en));
 
// Register to prevent glitch propagation
reg dco_disable;
always @(posedge nodiv_mclk_n or posedge por)
if (por) dco_disable <= 1'b1;
else dco_disable <= ~dco_enable_nxt;
 
// Note that a synchronizer is required if the MCLK mux is included
wire dco_clk_n = ~dco_clk;
`ifdef MCLK_MUX
omsp_sync_cell sync_cell_dco_disable (
.data_out (dco_enable),
.data_in (~dco_disable),
.clk (dco_clk_n),
.rst (por)
);
`else
 
assign dco_enable = ~dco_disable;
`endif
 
// The DCO oscillator will get an asynchronous wakeup if:
// - the MCLK generates a wakeup (only if the MCLK mux selects dco_clk)
// - if the DCO wants to be synchronously enabled (i.e dco_enable_nxt=1)
wire dco_mclk_wkup;
wire dco_en_wkup;
omsp_and_gate and_dco_mclk_wkup (.y(dco_mclk_wkup), .a(mclk_wkup), .b(~bcsctl2[`SELMx]));
omsp_and_gate and_dco_en_wkup (.y(dco_en_wkup), .a(~dco_enable), .b(dco_enable_nxt));
 
wire dco_wkup_set = dco_mclk_wkup | dco_en_wkup | cpu_en_wkup;
 
// Scan MUX for the asynchronous SET
wire dco_wkup_set_scan;
omsp_scan_mux scan_mux_dco_wkup (
.scan_mode (scan_mode),
.data_in_scan (por_a),
.data_in_func (dco_wkup_set | por),
.data_out (dco_wkup_set_scan)
);
 
// Scan MUX to increase coverage
wire dco_wkup_clear;
omsp_scan_mux scan_mux_dco_wkup_clear (
.scan_mode (scan_mode),
.data_in_scan (dco_wkup_set),
.data_in_func (1'b1),
.data_out (dco_wkup_clear)
);
 
// The wakeup is asynchronously set, synchronously released
wire dco_wkup_n;
omsp_sync_cell sync_cell_dco_wkup (
.data_out (dco_wkup_n),
.data_in (dco_wkup_clear),
.clk (dco_clk_n),
.rst (dco_wkup_set_scan)
);
 
omsp_and_gate and_dco_wkup (.y(dco_wkup), .a(~dco_wkup_n), .b(cpu_en));
 
`else
assign cpu_en_s = cpu_en;
assign dco_enable = 1'b1;
assign dco_wkup = 1'b1;
`endif
 
 
//-----------------------------------------------------------
// 5.2) LOW FREQUENCY CRYSTAL CLOCK GENERATOR (LFXT_CLK)
//-----------------------------------------------------------
 
// ASIC MODE
//------------------------------------------------
// Note: unlike the original MSP430 specification,
// we allow to switch off the LFXT even
// if it is selected by MCLK or SMCLK.
`ifdef ASIC
 
`ifdef OSCOFF_EN
 
// The LFXT is synchronously disabled if:
// - the cpu pin is disabled (in that case, wait for mclk_enable==0)
// - the debug interface is disabled
// - OSCOFF is set (in that case, wait for the mclk_enable==0 if selected by SELMx)
wire cpu_enabled_with_lfxt;
wire lfxt_not_enabled_by_dbg;
wire lfxt_disable_by_oscoff;
wire lfxt_disable_by_cpu_en;
wire lfxt_enable_nxt;
omsp_and_gate and_lfxt_dis1 (.y(cpu_enabled_with_lfxt), .a(bcsctl2[`SELMx]), .b(cpuoff_and_mclk_enable));
omsp_and_gate and_lfxt_dis2 (.y(lfxt_not_enabled_by_dbg), .a(~dbg_en_s), .b(~cpu_enabled_with_lfxt));
omsp_and_gate and_lfxt_dis3 (.y(lfxt_disable_by_oscoff), .a(oscoff), .b(lfxt_not_enabled_by_dbg));
omsp_and_gate and_lfxt_dis4 (.y(lfxt_disable_by_cpu_en), .a(~cpu_en_s), .b(~mclk_enable));
omsp_and_gate and_lfxt_dis5 (.y(lfxt_enable_nxt), .a(~lfxt_disable_by_oscoff), .b(~lfxt_disable_by_cpu_en));
 
// Register to prevent glitch propagation
reg lfxt_disable;
always @(posedge nodiv_mclk_n or posedge por)
if (por) lfxt_disable <= 1'b1;
else lfxt_disable <= ~lfxt_enable_nxt;
 
// Synchronize the OSCOFF control signal to the LFXT clock domain
wire lfxt_clk_n = ~lfxt_clk;
omsp_sync_cell sync_cell_lfxt_disable (
.data_out (lfxt_enable),
.data_in (~lfxt_disable),
.clk (lfxt_clk_n),
.rst (por)
);
 
// The LFXT will get an asynchronous wakeup if:
// - the MCLK generates a wakeup (only if the MCLK mux selects lfxt_clk)
// - if the LFXT wants to be synchronously enabled (i.e lfxt_enable_nxt=1)
wire lfxt_mclk_wkup;
wire lfxt_en_wkup;
omsp_and_gate and_lfxt_mclk_wkup (.y(lfxt_mclk_wkup), .a(mclk_wkup), .b(bcsctl2[`SELMx]));
omsp_and_gate and_lfxt_en_wkup (.y(lfxt_en_wkup), .a(~lfxt_enable), .b(lfxt_enable_nxt));
 
wire lfxt_wkup_set = lfxt_mclk_wkup | lfxt_en_wkup | cpu_en_wkup;
 
// Scan MUX for the asynchronous SET
wire lfxt_wkup_set_scan;
omsp_scan_mux scan_mux_lfxt_wkup (
.scan_mode (scan_mode),
.data_in_scan (por_a),
.data_in_func (lfxt_wkup_set | por),
.data_out (lfxt_wkup_set_scan)
);
 
// Scan MUX to increase coverage
wire lfxt_wkup_clear;
omsp_scan_mux scan_mux_lfxt_wkup_clear (
.scan_mode (scan_mode),
.data_in_scan (lfxt_wkup_set),
.data_in_func (1'b1),
.data_out (lfxt_wkup_clear)
);
 
// The wakeup is asynchronously set, synchronously released
wire lfxt_wkup_n;
omsp_sync_cell sync_cell_lfxt_wkup (
.data_out (lfxt_wkup_n),
.data_in (lfxt_wkup_clear),
.clk (lfxt_clk_n),
.rst (lfxt_wkup_set_scan)
);
 
omsp_and_gate and_lfxt_wkup (.y(lfxt_wkup), .a(~lfxt_wkup_n), .b(cpu_en));
 
`else
assign lfxt_enable = 1'b1;
assign lfxt_wkup = 1'b0;
`endif
 
 
// FPGA MODE
//---------------------------------------
// Synchronize LFXT_CLK & edge detection
//---------------------------------------
`else
 
wire lfxt_clk_s;
 
omsp_sync_cell sync_cell_lfxt_clk (
.data_out (lfxt_clk_s),
.clk (mclk),
.data_in (lfxt_clk),
.rst (por)
.data_out (lfxt_clk_s),
.data_in (lfxt_clk),
.clk (mclk),
.rst (por)
);
 
reg lfxt_clk_dly;
229,39 → 475,395
if (por) lfxt_clk_dly <= 1'b0;
else lfxt_clk_dly <= lfxt_clk_s;
 
wire lfxt_clk_en = (lfxt_clk_s & ~lfxt_clk_dly) & ~(oscoff & ~bcsctl2[`SELS]);
wire lfxt_clk_en = (lfxt_clk_s & ~lfxt_clk_dly) & ~(oscoff & ~bcsctl2[`SELS]);
assign lfxt_enable = 1'b1;
assign lfxt_wkup = 1'b0;
`endif
 
//=============================================================================
// 6) CLOCK GENERATION
//=============================================================================
 
//-----------------------------------------------------------
// 6.1) GLOBAL CPU ENABLE
//-----------------------------------------------------------
// ACLK and SMCLK are directly switched-off
// with the cpu_en pin (after synchronization).
// MCLK will be switched off once the CPU reaches
// its IDLE state (through the mclk_enable signal)
 
 
// Synchronize CPU_EN signal to the MCLK domain
//----------------------------------------------
`ifdef SYNC_CPU_EN
omsp_sync_cell sync_cell_cpu_en (
.data_out (cpu_en_s),
.data_in (cpu_en),
.clk (nodiv_mclk),
.rst (por)
);
omsp_and_gate and_cpu_en_wkup (.y(cpu_en_wkup), .a(cpu_en), .b(~cpu_en_s));
`else
assign cpu_en_s = cpu_en;
assign cpu_en_wkup = 1'b0;
`endif
 
// Synchronize CPU_EN signal to the ACLK domain
//----------------------------------------------
`ifdef LFXT_DOMAIN
wire cpu_en_aux_s;
omsp_sync_cell sync_cell_cpu_aux_en (
.data_out (cpu_en_aux_s),
.data_in (cpu_en),
.clk (lfxt_clk),
.rst (por)
);
`else
wire cpu_en_aux_s = cpu_en_s;
`endif
 
// Synchronize CPU_EN signal to the SMCLK domain
//----------------------------------------------
// Note: the synchronizer is only required if there is a SMCLK_MUX
`ifdef ASIC
`ifdef SMCLK_MUX
wire cpu_en_sm_s;
omsp_sync_cell sync_cell_cpu_sm_en (
.data_out (cpu_en_sm_s),
.data_in (cpu_en),
.clk (nodiv_smclk),
.rst (por)
);
`else
wire cpu_en_sm_s = cpu_en_s;
`endif
`endif
 
 
//-----------------------------------------------------------
// 6.2) MCLK GENERATION
//-----------------------------------------------------------
 
// Clock MUX
//----------------------------
`ifdef MCLK_MUX
omsp_clock_mux clock_mux_mclk (
.clk_out (nodiv_mclk),
.clk_in0 (dco_clk),
.clk_in1 (lfxt_clk),
.reset (por),
.scan_mode (scan_mode),
.select (bcsctl2[`SELMx])
);
`else
assign nodiv_mclk = dco_clk;
`endif
assign nodiv_mclk_n = ~nodiv_mclk;
 
// Wakeup synchronizer
//----------------------------
wire mclk_wkup_s;
 
`ifdef CPUOFF_EN
omsp_sync_cell sync_cell_mclk_wkup (
.data_out (mclk_wkup_s),
.data_in (mclk_wkup),
.clk (nodiv_mclk),
.rst (puc_rst)
);
`else
assign mclk_wkup_s = 1'b0;
`endif
 
 
// Clock Divider
//----------------------------
// No need for extra synchronizer as bcsctl2
// comes from the same clock domain.
 
`ifdef CPUOFF_EN
wire mclk_active = mclk_enable | mclk_wkup_s | (dbg_en_s & cpu_en_s);
`else
wire mclk_active = 1'b1;
`endif
`ifdef MCLK_DIVIDER
reg [2:0] mclk_div;
always @ (posedge nodiv_mclk or posedge puc_rst)
if (puc_rst) mclk_div <= 3'h0;
else if ((bcsctl2[`DIVMx]!=2'b00)) mclk_div <= mclk_div+3'h1;
 
wire mclk_div_en = mclk_active & ((bcsctl2[`DIVMx]==2'b00) ? 1'b1 :
(bcsctl2[`DIVMx]==2'b01) ? mclk_div[0] :
(bcsctl2[`DIVMx]==2'b10) ? &mclk_div[1:0] :
&mclk_div[2:0]);
`else
wire mclk_div_en = mclk_active;
`endif
 
 
// Generate main system clock
//----------------------------
`ifdef MCLK_CGATE
 
wire mclk = dco_clk;
wire mclk_n = !dco_clk;
omsp_clock_gate clock_gate_mclk (
.gclk (mclk),
.clk (nodiv_mclk),
.enable (mclk_div_en),
.scan_enable (scan_enable)
);
`else
assign mclk = nodiv_mclk;
`endif
 
 
// Generate ACLK
//-----------------------------------------------------------
// 6.3) ACLK GENERATION
//-----------------------------------------------------------
 
// ASIC MODE
//----------------------------
`ifdef ASIC
 
reg aclk_en;
reg [2:0] aclk_div;
`ifdef ACLK_DIVIDER
`ifdef LFXT_DOMAIN
 
wire aclk_en_nxt = 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]);
wire nodiv_aclk = lfxt_clk;
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) aclk_en <= 1'b0;
else aclk_en <= aclk_en_nxt & cpu_en_s;
// Local Reset synchronizer
wire puc_lfxt_rst;
wire puc_lfxt_noscan_n;
omsp_sync_cell sync_cell_puc_lfxt (
.data_out (puc_lfxt_noscan_n),
.data_in (1'b1),
.clk (nodiv_aclk),
.rst (puc_rst)
);
omsp_scan_mux scan_mux_puc_lfxt (
.scan_mode (scan_mode),
.data_in_scan (por_a),
.data_in_func (~puc_lfxt_noscan_n),
.data_out (puc_lfxt_rst)
);
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) aclk_div <= 3'h0;
else if ((bcsctl1[`DIVAx]!=2'b00) & lfxt_clk_en) aclk_div <= aclk_div+3'h1;
// Local synchronizer for the bcsctl1.DIVAx configuration
// (note that we can live with a full bus synchronizer as
// it won't hurt if we get a wrong DIVAx value for a single clock cycle)
reg [1:0] divax_s;
reg [1:0] divax_ss;
always @ (posedge nodiv_aclk or posedge puc_lfxt_rst)
if (puc_lfxt_rst)
begin
divax_s <= 2'h0;
divax_ss <= 2'h0;
end
else
begin
divax_s <= bcsctl1[`DIVAx];
divax_ss <= divax_s;
end
 
// If the OSCOFF mode is enabled synchronize OSCOFF signal
wire oscoff_s;
`ifdef OSCOFF_EN
omsp_sync_cell sync_cell_oscoff (
.data_out (oscoff_s),
.data_in (oscoff),
.clk (nodiv_aclk),
.rst (puc_lfxt_rst)
);
`else
assign oscoff_s = 1'b0;
`endif
`else
wire puc_lfxt_rst = puc_rst;
wire nodiv_aclk = dco_clk;
wire [1:0] divax_ss = bcsctl1[`DIVAx];
wire oscoff_s = oscoff;
`endif
 
// Generate SMCLK
// Divider
reg [2:0] aclk_div;
always @ (posedge nodiv_aclk or posedge puc_lfxt_rst)
if (puc_lfxt_rst) aclk_div <= 3'h0;
else if ((divax_ss!=2'b00)) aclk_div <= aclk_div+3'h1;
 
wire aclk_div_en = cpu_en_aux_s & ~oscoff_s & ((divax_ss==2'b00) ? 1'b1 :
(divax_ss==2'b01) ? aclk_div[0] :
(divax_ss==2'b10) ? &aclk_div[1:0] :
&aclk_div[2:0]);
 
// Clock gate
omsp_clock_gate clock_gate_aclk (
.gclk (aclk),
.clk (nodiv_aclk),
.enable (aclk_div_en),
.scan_enable (scan_enable)
);
 
`else
`ifdef LFXT_DOMAIN
assign aclk = lfxt_clk;
`else
assign aclk = dco_clk;
`endif
`endif
 
assign aclk_en = 1'b1;
 
 
// FPGA MODE
//----------------------------
`else
reg aclk_en;
reg [2:0] aclk_div;
wire aclk_en_nxt = 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_rst)
if (puc_rst) aclk_div <= 3'h0;
else if ((bcsctl1[`DIVAx]!=2'b00) & lfxt_clk_en) aclk_div <= aclk_div+3'h1;
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) aclk_en <= 1'b0;
else aclk_en <= aclk_en_nxt & cpu_en_s;
 
assign aclk = mclk;
`endif
//-----------------------------------------------------------
// 6.4) SMCLK GENERATION
//-----------------------------------------------------------
 
// Clock MUX
//----------------------------
`ifdef SMCLK_MUX
omsp_clock_mux clock_mux_smclk (
.clk_out (nodiv_smclk),
.clk_in0 (dco_clk),
.clk_in1 (lfxt_clk),
.reset (por),
.scan_mode (scan_mode),
.select (bcsctl2[`SELS])
);
`else
assign nodiv_smclk = dco_clk;
`endif
 
 
// ASIC MODE
//----------------------------
`ifdef ASIC
`ifdef SMCLK_MUX
 
// Synchronizers
//------------------------------------------------------
// When the SMCLK MUX is enabled, the reset and DIVSx
// and SCG1 signals must be synchronized, otherwise not.
// Local Reset synchronizer
wire puc_sm_noscan_n;
wire puc_sm_rst;
omsp_sync_cell sync_cell_puc_sm (
.data_out (puc_sm_noscan_n),
.data_in (1'b1),
.clk (nodiv_smclk),
.rst (puc_rst)
);
omsp_scan_mux scan_mux_puc_sm (
.scan_mode (scan_mode),
.data_in_scan (por_a),
.data_in_func (~puc_sm_noscan_n),
.data_out (puc_sm_rst)
);
 
// SCG1 synchronizer
`ifdef SCG1_EN
wire scg1_s;
omsp_sync_cell sync_cell_scg1 (
.data_out (scg1_s),
.data_in (scg1),
.clk (nodiv_smclk),
.rst (puc_sm_rst)
);
`else
wire scg1_s = 1'b0;
`endif
 
`ifdef SMCLK_DIVIDER
// Local synchronizer for the bcsctl2.DIVSx configuration
// (note that we can live with a full bus synchronizer as
// it won't hurt if we get a wrong DIVSx value for a single clock cycle)
reg [1:0] divsx_s;
reg [1:0] divsx_ss;
always @ (posedge nodiv_smclk or posedge puc_sm_rst)
if (puc_sm_rst)
begin
divsx_s <= 2'h0;
divsx_ss <= 2'h0;
end
else
begin
divsx_s <= bcsctl2[`DIVSx];
divsx_ss <= divsx_s;
end
`endif
`else
wire puc_sm_rst = puc_rst;
wire [1:0] divsx_ss = bcsctl2[`DIVSx];
wire scg1_s = scg1;
`endif
 
// Clock Divider
//----------------------------
`ifdef SMCLK_DIVIDER
 
reg [2:0] smclk_div;
always @ (posedge nodiv_smclk or posedge puc_sm_rst)
if (puc_sm_rst) smclk_div <= 3'h0;
else if ((divsx_ss!=2'b00)) smclk_div <= smclk_div+3'h1;
 
wire smclk_div_en = cpu_en_sm_s & ~scg1_s & ((divsx_ss==2'b00) ? 1'b1 :
(divsx_ss==2'b01) ? smclk_div[0] :
(divsx_ss==2'b10) ? &smclk_div[1:0] :
&smclk_div[2:0]);
`else
`ifdef SCG1_EN
wire smclk_div_en = cpu_en_sm_s & ~scg1_s;
`else
wire smclk_div_en = cpu_en_sm_s;
`endif
`endif
 
// Generate sub-system clock
//----------------------------
`ifdef SMCLK_CGATE
omsp_clock_gate clock_gate_smclk (
.gclk (smclk),
.clk (nodiv_smclk),
.enable (smclk_div_en),
.scan_enable (scan_enable)
);
`else
assign smclk = nodiv_smclk;
`endif
assign smclk_en = 1'b1;
 
 
// FPGA MODE
//----------------------------
`else
reg smclk_en;
reg [2:0] smclk_div;
 
280,62 → 882,174
if (puc_rst) smclk_div <= 3'h0;
else if ((bcsctl2[`DIVSx]!=2'b00) & smclk_in) smclk_div <= smclk_div+3'h1;
 
wire smclk = mclk;
 
// Generate DBG_CLK
//----------------------------
`endif
 
assign dbg_clk = mclk;
//-----------------------------------------------------------
// 6.5) DEBUG INTERFACE CLOCK GENERATION (DBG_CLK)
//-----------------------------------------------------------
 
// Synchronize DBG_EN signal to MCLK domain
//------------------------------------------
`ifdef DBG_EN
`ifdef SYNC_DBG_EN
wire dbg_en_n_s;
omsp_sync_cell sync_cell_dbg_en (
.data_out (dbg_en_n_s),
.data_in (~dbg_en),
.clk (mclk),
.rst (por)
);
assign dbg_en_s = ~dbg_en_n_s;
wire dbg_rst_nxt = dbg_en_n_s;
`else
assign dbg_en_s = dbg_en;
wire dbg_rst_nxt = ~dbg_en;
`endif
`else
assign dbg_en_s = 1'b0;
wire dbg_rst_nxt = 1'b0;
`endif
 
 
// Serial Debug Interface Clock gate
//------------------------------------------------
`ifdef DBG_EN
`ifdef ASIC
omsp_clock_gate clock_gate_dbg_clk (
.gclk (dbg_clk),
.clk (mclk),
.enable (dbg_en_s),
.scan_enable (scan_enable)
);
`else
assign dbg_clk = dco_clk;
`endif
`else
assign dbg_clk = 1'b0;
`endif
 
 
//=============================================================================
// 6) RESET GENERATION
// 7) RESET GENERATION
//=============================================================================
//
// Whenever the reset pin (reset_n) is deasserted, the internal resets of the
// openMSP430 will be released in the following order:
// 1- POR
// 2- DBG_RST (if the sdi interface is enabled, i.e. dbg_en=1)
// 3- PUC
//
// Note: releasing the DBG_RST before PUC is particularly important in order
// to allow the sdi interface to halt the cpu immediately after a PUC.
//
// Generate synchronized POR to MCLK domain
//------------------------------------------
 
// Generate synchronized POR
wire por_n;
wire por_reset_a = !reset_n;
// Asynchronous reset source
assign por_a = !reset_n;
wire por_noscan;
 
omsp_sync_cell sync_cell_por (
.data_out (por_n),
.clk (mclk),
.data_in (1'b1),
.rst (por_reset_a)
// Reset Synchronizer
omsp_sync_reset sync_reset_por (
.rst_s (por_noscan),
.clk (nodiv_mclk),
.rst_a (por_a)
);
 
wire por = ~por_n;
// Scan Reset Mux
`ifdef ASIC
omsp_scan_mux scan_mux_por (
.scan_mode (scan_mode),
.data_in_scan (por_a),
.data_in_func (por_noscan),
.data_out (por)
);
`else
assign por = por_noscan;
`endif
 
// Generate synchronized reset for the SDI
//------------------------------------------
`ifdef DBG_EN
 
// Generate main system reset
wire puc_rst_comb = por | wdt_reset | dbg_cpu_reset;
reg puc_rst;
always @(posedge mclk or posedge puc_rst_comb)
if (puc_rst_comb) puc_rst <= 1'b1;
else puc_rst <= 1'b0;
// Reset Generation
reg dbg_rst_noscan;
always @ (posedge mclk or posedge por)
if (por) dbg_rst_noscan <= 1'b1;
else dbg_rst_noscan <= dbg_rst_nxt;
 
 
// Generate debug unit reset
`ifdef DBG_EN
wire dbg_rst_n;
 
`ifdef SYNC_DBG_EN
omsp_sync_cell sync_cell_dbg_en (
.data_out (dbg_rst_n),
.clk (mclk),
.data_in (dbg_en),
.rst (por)
);
// Scan Reset Mux
`ifdef ASIC
omsp_scan_mux scan_mux_dbg_rst (
.scan_mode (scan_mode),
.data_in_scan (por_a),
.data_in_func (dbg_rst_noscan),
.data_out (dbg_rst)
);
`else
assign dbg_rst_n = dbg_en;
assign dbg_rst = dbg_rst_noscan;
`endif
 
`else
wire dbg_rst_n = 1'b0;
wire dbg_rst_noscan = 1'b1;
assign dbg_rst = 1'b1;
`endif
 
wire dbg_en_s = dbg_rst_n;
wire dbg_rst = ~dbg_rst_n;
 
// Generate main system reset (PUC_RST)
//--------------------------------------
wire puc_noscan_n;
wire puc_a_scan;
 
// Asynchronous PUC reset
wire puc_a = por | wdt_reset;
 
// Synchronous PUC reset
wire puc_s = dbg_cpu_reset | // With the debug interface command
 
(dbg_en_s & dbg_rst_noscan & ~puc_noscan_n); // Sequencing making sure PUC is released
// after DBG_RST if the debug interface is
// enabled at power-on-reset time
// Scan Reset Mux
`ifdef ASIC
omsp_scan_mux scan_mux_puc_rst_a (
.scan_mode (scan_mode),
.data_in_scan (por_a),
.data_in_func (puc_a),
.data_out (puc_a_scan)
);
`else
assign puc_a_scan = puc_a;
`endif
 
// Reset Synchronizer
// (required because of the asynchronous watchdog reset)
omsp_sync_cell sync_cell_puc (
.data_out (puc_noscan_n),
.data_in (~puc_s),
.clk (mclk),
.rst (puc_a_scan)
);
 
// Scan Reset Mux
`ifdef ASIC
omsp_scan_mux scan_mux_puc_rst (
.scan_mode (scan_mode),
.data_in_scan (por_a),
.data_in_func (~puc_noscan_n),
.data_out (puc_rst)
);
`else
assign puc_rst = ~puc_noscan_n;
`endif
 
// PUC pending set the serial debug interface
assign puc_pnd_set = ~puc_noscan_n;
 
 
endmodule // omsp_clock_module
 
`ifdef OMSP_NO_INCLUDE
/omsp_watchdog.v
48,49 → 48,63
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
wdt_irq, // Watchdog-timer interrupt
wdt_reset, // Watchdog-timer reset
wdt_wkup, // Watchdog Wakeup
wdtifg, // Watchdog-timer interrupt flag
wdtnmies, // Watchdog-timer NMI edge selection
 
// INPUTs
aclk, // ACLK
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_we, // Peripheral write enable (high active)
por, // Power-on reset
puc_rst, // Main system reset
scan_enable, // Scan enable (active during scan shifting)
scan_mode, // Scan mode
smclk, // SMCLK
smclk_en, // SMCLK enable
wdtie // Watchdog timer interrupt enable
wdtie, // Watchdog timer interrupt enable
wdtifg_irq_clr, // Watchdog-timer interrupt flag irq accepted clear
wdtifg_sw_clr, // Watchdog-timer interrupt flag software clear
wdtifg_sw_set // Watchdog-timer interrupt flag software set
);
 
// 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
output wdt_irq; // Watchdog-timer interrupt
output wdt_reset; // Watchdog-timer reset
output wdt_wkup; // Watchdog Wakeup
output wdtifg; // Watchdog-timer interrupt flag
output wdtnmies; // Watchdog-timer NMI edge selection
 
// INPUTs
//=========
input aclk; // ACLK
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 [13:0] per_addr; // Peripheral address
input [15:0] per_din; // Peripheral data input
input per_en; // Peripheral enable (high active)
input [1:0] per_we; // Peripheral write enable (high active)
input por; // Power-on reset
input puc_rst; // Main system reset
input scan_enable; // Scan enable (active during scan shifting)
input scan_mode; // Scan mode
input smclk; // SMCLK
input smclk_en; // SMCLK enable
input wdtie; // Watchdog timer interrupt enable
input wdtifg_irq_clr; // Clear Watchdog-timer interrupt flag
input wdtifg_sw_clr; // Watchdog-timer interrupt flag software clear
input wdtifg_sw_set; // Watchdog-timer interrupt flag software set
 
 
//=============================================================================
107,7 → 121,7
parameter [DEC_WD-1:0] WDTCTL = 'h0;
 
// Register one-hot decoder utilities
parameter DEC_SZ = 2**DEC_WD;
parameter DEC_SZ = (1 << DEC_WD);
parameter [DEC_SZ-1:0] BASE_REG = {{DEC_SZ-1{1'b0}}, 1'b1};
 
// Register one-hot decoder
142,64 → 156,326
 
// WDTCTL Register
//-----------------
// WDTNMI & WDTSSEL are not implemented and therefore masked
// WDTNMI is not implemented and therefore masked
reg [7:0] wdtctl;
 
wire wdtctl_wr = reg_wr[WDTCTL];
 
always @ (posedge mclk or posedge puc_rst)
`ifdef CLOCK_GATING
wire mclk_wdtctl;
omsp_clock_gate clock_gate_wdtctl (.gclk(mclk_wdtctl),
.clk (mclk), .enable(wdtctl_wr), .scan_enable(scan_enable));
`else
wire mclk_wdtctl = mclk;
`endif
 
`ifdef NMI
parameter [7:0] WDTNMIES_MASK = 8'h40;
`else
parameter [7:0] WDTNMIES_MASK = 8'h00;
`endif
 
`ifdef ASIC
`ifdef WATCHDOG_MUX
parameter [7:0] WDTSSEL_MASK = 8'h04;
`else
parameter [7:0] WDTSSEL_MASK = 8'h00;
`endif
`else
parameter [7:0] WDTSSEL_MASK = 8'h04;
`endif
 
parameter [7:0] WDTCTL_MASK = (8'b1001_0011 | WDTSSEL_MASK | WDTNMIES_MASK);
always @ (posedge mclk_wdtctl or posedge puc_rst)
if (puc_rst) wdtctl <= 8'h00;
else if (wdtctl_wr) wdtctl <= per_din[7:0] & 8'hd7;
`ifdef CLOCK_GATING
else wdtctl <= per_din[7:0] & WDTCTL_MASK;
`else
else if (wdtctl_wr) wdtctl <= per_din[7:0] & WDTCTL_MASK;
`endif
 
wire wdtpw_error = wdtctl_wr & (per_din[15:8]!=8'h5a);
wire wdttmsel = wdtctl[4];
wire wdtnmies = wdtctl[6];
 
 
//============================================================================
// 3) REGISTERS
// 4) DATA OUTPUT GENERATION
//============================================================================
 
`ifdef NMI
parameter [7:0] WDTNMI_RD_MASK = 8'h20;
`else
parameter [7:0] WDTNMI_RD_MASK = 8'h00;
`endif
`ifdef WATCHDOG_MUX
parameter [7:0] WDTSSEL_RD_MASK = 8'h00;
`else
`ifdef WATCHDOG_NOMUX_ACLK
parameter [7:0] WDTSSEL_RD_MASK = 8'h04;
`else
parameter [7:0] WDTSSEL_RD_MASK = 8'h00;
`endif
`endif
parameter [7:0] WDTCTL_RD_MASK = WDTNMI_RD_MASK | WDTSSEL_RD_MASK;
 
// Data output mux
wire [15:0] wdtctl_rd = {8'h69, wdtctl} & {16{reg_rd[WDTCTL]}};
 
wire [15:0] wdtctl_rd = {8'h69, wdtctl | WDTCTL_RD_MASK} & {16{reg_rd[WDTCTL]}};
wire [15:0] per_dout = wdtctl_rd;
 
 
//=============================================================================
// 4) NMI GENERATION
// 5) WATCHDOG TIMER (ASIC IMPLEMENTATION)
//=============================================================================
`ifdef ASIC
 
// Synchronization
wire nmi_s;
`ifdef SYNC_NMI
omsp_sync_cell sync_cell_nmi (
.data_out (nmi_s),
.clk (mclk),
.data_in (nmi),
.rst (puc_rst)
// Watchdog clock source selection
//---------------------------------
wire wdt_clk;
 
`ifdef WATCHDOG_MUX
omsp_clock_mux clock_mux_watchdog (
.clk_out (wdt_clk),
.clk_in0 (smclk),
.clk_in1 (aclk),
.reset (puc_rst),
.scan_mode (scan_mode),
.select (wdtctl[2])
);
`else
assign nmi_s = nmi;
`ifdef WATCHDOG_NOMUX_ACLK
assign wdt_clk = aclk;
`else
assign wdt_clk = smclk;
`endif
`endif
 
// Reset synchronizer for the watchdog local clock domain
//--------------------------------------------------------
// Delay
reg nmi_dly;
wire wdt_rst_noscan;
wire wdt_rst;
 
// Reset Synchronizer
omsp_sync_reset sync_reset_por (
.rst_s (wdt_rst_noscan),
.clk (wdt_clk),
.rst_a (puc_rst)
);
 
// Scan Reset Mux
omsp_scan_mux scan_mux_wdt_rst (
.scan_mode (scan_mode),
.data_in_scan (puc_rst),
.data_in_func (wdt_rst_noscan),
.data_out (wdt_rst)
);
 
// Watchog counter clear (synchronization)
//-----------------------------------------
 
// Toggle bit whenever the watchog needs to be cleared
reg wdtcnt_clr_toggle;
wire wdtcnt_clr_detect = (wdtctl_wr & per_din[3]);
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) nmi_dly <= 1'b0;
else nmi_dly <= nmi_s;
if (puc_rst) wdtcnt_clr_toggle <= 1'b0;
else if (wdtcnt_clr_detect) wdtcnt_clr_toggle <= ~wdtcnt_clr_toggle;
 
// Synchronization
wire wdtcnt_clr_sync;
omsp_sync_cell sync_cell_wdtcnt_clr (
.data_out (wdtcnt_clr_sync),
.data_in (wdtcnt_clr_toggle),
.clk (wdt_clk),
.rst (wdt_rst)
);
 
// Edge detection
wire nmi_re = ~nmi_dly & nmi_s & nmie;
wire nmi_fe = nmi_dly & ~nmi_s & nmie;
reg wdtcnt_clr_sync_dly;
always @ (posedge wdt_clk or posedge wdt_rst)
if (wdt_rst) wdtcnt_clr_sync_dly <= 1'b0;
else wdtcnt_clr_sync_dly <= wdtcnt_clr_sync;
 
// NMI event
wire nmi_evt = wdtctl[6] ? nmi_fe : nmi_re;
wire wdtqn_edge;
wire wdtcnt_clr = (wdtcnt_clr_sync ^ wdtcnt_clr_sync_dly) | wdtqn_edge;
 
 
// Watchog counter increment (synchronization)
//----------------------------------------------
wire wdtcnt_incr;
 
omsp_sync_cell sync_cell_wdtcnt_incr (
.data_out (wdtcnt_incr),
.data_in (~wdtctl[7] & ~dbg_freeze),
.clk (wdt_clk),
.rst (wdt_rst)
);
 
 
// Watchdog 16 bit counter
//--------------------------
reg [15:0] wdtcnt;
 
wire [15:0] wdtcnt_nxt = wdtcnt+16'h0001;
 
`ifdef CLOCK_GATING
wire wdtcnt_en = wdtcnt_clr | wdtcnt_incr;
wire wdt_clk_cnt;
omsp_clock_gate clock_gate_wdtcnt (.gclk(wdt_clk_cnt),
.clk (wdt_clk), .enable(wdtcnt_en), .scan_enable(scan_enable));
`else
wire wdt_clk_cnt = wdt_clk;
`endif
 
always @ (posedge wdt_clk_cnt or posedge wdt_rst)
if (wdt_rst) wdtcnt <= 16'h0000;
else if (wdtcnt_clr) wdtcnt <= 16'h0000;
`ifdef CLOCK_GATING
else wdtcnt <= wdtcnt_nxt;
`else
else if (wdtcnt_incr) wdtcnt <= wdtcnt_nxt;
`endif
 
 
// Local synchronizer for the wdtctl.WDTISx
// configuration (note that we can live with
// a full bus synchronizer as it won't hurt
// if we get a wrong WDTISx value for a
// single clock cycle)
//--------------------------------------------
reg [1:0] wdtisx_s;
reg [1:0] wdtisx_ss;
always @ (posedge wdt_clk_cnt or posedge wdt_rst)
if (wdt_rst)
begin
wdtisx_s <= 2'h0;
wdtisx_ss <= 2'h0;
end
else
begin
wdtisx_s <= wdtctl[1:0];
wdtisx_ss <= wdtisx_s;
end
 
 
// Interval selection mux
//--------------------------
reg wdtqn;
 
always @(wdtisx_ss or wdtcnt_nxt)
case(wdtisx_ss)
2'b00 : wdtqn = wdtcnt_nxt[15];
2'b01 : wdtqn = wdtcnt_nxt[13];
2'b10 : wdtqn = wdtcnt_nxt[9];
default: wdtqn = wdtcnt_nxt[6];
endcase
 
 
// Watchdog event detection
//-----------------------------
 
// Interval end detection
assign wdtqn_edge = (wdtqn & wdtcnt_incr);
 
// Toggle bit for the transmition to the MCLK domain
reg wdt_evt_toggle;
always @ (posedge wdt_clk_cnt or posedge wdt_rst)
if (wdt_rst) wdt_evt_toggle <= 1'b0;
else if (wdtqn_edge) wdt_evt_toggle <= ~wdt_evt_toggle;
 
// Synchronize in the MCLK domain
wire wdt_evt_toggle_sync;
omsp_sync_cell sync_cell_wdt_evt (
.data_out (wdt_evt_toggle_sync),
.data_in (wdt_evt_toggle),
.clk (mclk),
.rst (puc_rst)
);
 
// Delay for edge detection of the toggle bit
reg wdt_evt_toggle_sync_dly;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) wdt_evt_toggle_sync_dly <= 1'b0;
else wdt_evt_toggle_sync_dly <= wdt_evt_toggle_sync;
 
wire wdtifg_evt = (wdt_evt_toggle_sync_dly ^ wdt_evt_toggle_sync) | wdtpw_error;
 
 
// Watchdog wakeup generation
//-------------------------------------------------------------
 
// Clear wakeup when the watchdog flag is cleared (glitch free)
reg wdtifg_clr_reg;
wire wdtifg_clr;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) wdtifg_clr_reg <= 1'b1;
else wdtifg_clr_reg <= wdtifg_clr;
 
// Set wakeup when the watchdog event is detected (glitch free)
reg wdtqn_edge_reg;
always @ (posedge wdt_clk_cnt or posedge wdt_rst)
if (wdt_rst) wdtqn_edge_reg <= 1'b0;
else wdtqn_edge_reg <= wdtqn_edge;
 
// Watchdog wakeup cell
wire wdt_wkup_pre;
omsp_wakeup_cell wakeup_cell_wdog (
.wkup_out (wdt_wkup_pre), // Wakup signal (asynchronous)
.scan_clk (mclk), // Scan clock
.scan_mode (scan_mode), // Scan mode
.scan_rst (puc_rst), // Scan reset
.wkup_clear (wdtifg_clr_reg), // Glitch free wakeup event clear
.wkup_event (wdtqn_edge_reg) // Glitch free asynchronous wakeup event
);
 
// When not in HOLD, the watchdog can generate a wakeup when:
// - in interval mode (if interrupts are enabled)
// - in reset mode (always)
reg wdt_wkup_en;
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) wdt_wkup_en <= 1'b0;
else wdt_wkup_en <= ~wdtctl[7] & (~wdttmsel | (wdttmsel & wdtie));
 
// Make wakeup when not enabled
wire wdt_wkup;
omsp_and_gate and_wdt_wkup (.y(wdt_wkup), .a(wdt_wkup_pre), .b(wdt_wkup_en));
 
 
// Watchdog interrupt flag
//------------------------------
reg wdtifg;
 
wire wdtifg_set = wdtifg_evt | wdtifg_sw_set;
assign wdtifg_clr = (wdtifg_irq_clr & wdttmsel) | wdtifg_sw_clr;
 
always @ (posedge mclk or posedge por)
if (por) wdtifg <= 1'b0;
else if (wdtifg_set) wdtifg <= 1'b1;
else if (wdtifg_clr) wdtifg <= 1'b0;
 
 
// 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);
 
 
 
//=============================================================================
// 5) WATCHDOG TIMER
// 6) WATCHDOG TIMER (FPGA IMPLEMENTATION)
//=============================================================================
`else
 
// Watchdog clock source selection
//---------------------------------
210,12 → 486,16
//--------------------------
reg [15:0] wdtcnt;
 
wire wdtcnt_clr = (wdtctl_wr & per_din[3]) | wdtifg_set;
wire wdtifg_evt;
wire wdtcnt_clr = (wdtctl_wr & per_din[3]) | wdtifg_evt;
wire wdtcnt_incr = ~wdtctl[7] & clk_src_en & ~dbg_freeze;
 
wire [15:0] wdtcnt_nxt = wdtcnt+16'h0001;
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) wdtcnt <= 16'h0000;
else if (wdtcnt_clr) wdtcnt <= 16'h0000;
else if (~wdtctl[7] & clk_src_en & ~dbg_freeze) wdtcnt <= wdtcnt+16'h0001;
if (puc_rst) wdtcnt <= 16'h0000;
else if (wdtcnt_clr) wdtcnt <= 16'h0000;
else if (wdtcnt_incr) wdtcnt <= wdtcnt_nxt;
 
// Interval selection mux
222,26 → 502,52
//--------------------------
reg wdtqn;
 
always @(wdtctl or wdtcnt)
always @(wdtctl or wdtcnt_nxt)
case(wdtctl[1:0])
2'b00 : wdtqn = wdtcnt[15];
2'b01 : wdtqn = wdtcnt[13];
2'b10 : wdtqn = wdtcnt[9];
default: wdtqn = wdtcnt[6];
2'b00 : wdtqn = wdtcnt_nxt[15];
2'b01 : wdtqn = wdtcnt_nxt[13];
2'b10 : wdtqn = wdtcnt_nxt[9];
default: wdtqn = wdtcnt_nxt[6];
endcase
 
 
// Watchdog event detection
//-----------------------------
reg wdtqn_dly;
 
always @ (posedge mclk or posedge puc_rst)
if (puc_rst) wdtqn_dly <= 1'b0;
else wdtqn_dly <= wdtqn;
assign wdtifg_evt = (wdtqn & wdtcnt_incr) | wdtpw_error;
 
wire wdtifg_set = (~wdtqn_dly & wdtqn) | wdtpw_error;
 
// Watchdog interrupt flag
//------------------------------
reg wdtifg;
 
wire wdtifg_set = wdtifg_evt | wdtifg_sw_set;
wire wdtifg_clr = (wdtifg_irq_clr & wdttmsel) | wdtifg_sw_clr;
 
always @ (posedge mclk or posedge por)
if (por) wdtifg <= 1'b0;
else if (wdtifg_set) wdtifg <= 1'b1;
else if (wdtifg_clr) wdtifg <= 1'b0;
 
 
// Watchdog interrupt generation
//---------------------------------
wire wdt_irq = wdttmsel & wdtifg & wdtie;
wire wdt_wkup = 1'b0;
 
 
// 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);
 
 
`endif
 
 
endmodule // omsp_watchdog
 
`ifdef OMSP_NO_INCLUDE
/omsp_mem_backbone.v
81,7 → 81,8
mclk, // Main system clock
per_dout, // Peripheral data output
pmem_dout, // Program Memory data output
puc_rst // Main system reset
puc_rst, // Main system reset
scan_enable // Scan enable (active during scan shifting)
);
 
// OUTPUTs
121,6 → 122,7
input [15:0] per_dout; // Peripheral data output
input [15:0] pmem_dout; // Program Memory data output
input puc_rst; // Main system reset
input scan_enable; // Scan enable (active during scan shifting)
 
 
//=============================================================================
205,11 → 207,23
 
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;
 
`ifdef CLOCK_GATING
wire mclk_bckup;
omsp_clock_gate clock_gate_bckup (.gclk(mclk_bckup),
.clk (mclk), .enable(fe_pmem_save), .scan_enable(scan_enable));
`else
wire mclk_bckup = mclk;
`endif
reg [15:0] pmem_dout_bckup;
always @(posedge mclk or posedge puc_rst)
always @(posedge mclk_bckup or posedge puc_rst)
if (puc_rst) pmem_dout_bckup <= 16'h0000;
`ifdef CLOCK_GATING
else pmem_dout_bckup <= pmem_dout;
`else
else if (fe_pmem_save) pmem_dout_bckup <= pmem_dout;
`endif
 
// Mux between the ROM data and the backup
reg pmem_dout_bckup_sel;
/omsp_execution_unit.v
58,6 → 58,7
oscoff, // Turns off LFXT1 clock input
pc_sw, // Program counter software value
pc_sw_wr, // Program counter software write
scg0, // System clock generator 1. Turns off the DCO
scg1, // System clock generator 1. Turns off the SMCLK
 
// INPUTs
83,7 → 84,8
mdb_in, // Memory data bus input
pc, // Program counter
pc_nxt, // Next PC value (for CALL & IRQ)
puc_rst // Main system reset
puc_rst, // Main system reset
scan_enable // Scan enable (active during scan shifting)
);
 
// OUTPUTs
98,6 → 100,7
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 scg0; // System clock generator 1. Turns off the DCO
output scg1; // System clock generator 1. Turns off the SMCLK
 
// INPUTs
125,6 → 128,7
input [15:0] pc; // Program counter
input [15:0] pc_nxt; // Next PC value (for CALL & IRQ)
input puc_rst; // Main system reset
input scan_enable; // Scan enable (active during scan shifting)
 
 
//=============================================================================
182,6 → 186,7
.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
.scg0 (scg0), // System clock generator 1. Turns off the DCO
.scg1 (scg1), // System clock generator 1. Turns off the SMCLK
.status (status), // R2 Status {V,N,Z,C}
 
201,7 → 206,8
.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
.reg_incr (reg_incr), // Increment source register
.scan_enable (scan_enable) // Scan enable (active during scan shifting)
);
 
 
340,11 → 346,27
 
// Memory data bus output
reg [15:0] mdb_out_nxt;
always @(posedge mclk or posedge puc_rst)
 
`ifdef CLOCK_GATING
wire mdb_out_nxt_en = (e_state==`E_DST_RD) |
(((e_state==`E_EXEC) & ~inst_so[`CALL]) |
(e_state==`E_IRQ_0) | (e_state==`E_IRQ_2));
wire mclk_mdb_out_nxt;
omsp_clock_gate clock_gate_mdb_out_nxt (.gclk(mclk_mdb_out_nxt),
.clk (mclk), .enable(mdb_out_nxt_en), .scan_enable(scan_enable));
`else
wire mclk_mdb_out_nxt = mclk;
`endif
 
always @(posedge mclk_mdb_out_nxt or posedge puc_rst)
if (puc_rst) mdb_out_nxt <= 16'h0000;
else if (e_state==`E_DST_RD) mdb_out_nxt <= pc_nxt;
`ifdef CLOCK_GATING
else mdb_out_nxt <= alu_out;
`else
else if ((e_state==`E_EXEC & ~inst_so[`CALL]) |
(e_state==`E_IRQ_0) | (e_state==`E_IRQ_2)) mdb_out_nxt <= alu_out;
`endif
 
assign mdb_out = inst_bw ? {2{mdb_out_nxt[7:0]}} : mdb_out_nxt;
 
370,9 → 392,22
else if (mdb_in_buf_en) mdb_in_buf_valid <= 1'b1;
 
reg [15:0] mdb_in_buf;
always @(posedge mclk or posedge puc_rst)
 
`ifdef CLOCK_GATING
wire mclk_mdb_in_buf;
omsp_clock_gate clock_gate_mdb_in_buf (.gclk(mclk_mdb_in_buf),
.clk (mclk), .enable(mdb_in_buf_en), .scan_enable(scan_enable));
`else
wire mclk_mdb_in_buf = mclk;
`endif
 
always @(posedge mclk_mdb_in_buf or posedge puc_rst)
if (puc_rst) mdb_in_buf <= 16'h0000;
`ifdef CLOCK_GATING
else mdb_in_buf <= mdb_in_bw;
`else
else if (mdb_in_buf_en) mdb_in_buf <= mdb_in_bw;
`endif
 
assign mdb_in_val = mdb_in_buf_valid ? mdb_in_buf : mdb_in_bw;
 
/omsp_and_gate.v
0,0 → 1,89
//----------------------------------------------------------------------------
// Copyright (C) 2009 , Olivier Girard
//
// 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: omsp_and_gate.v
//
// *Module Description:
// Generic AND gate cell for the openMSP430
//
// *Author(s):
// - Olivier Girard, olgirard@gmail.com
//
//----------------------------------------------------------------------------
// $Rev: 103 $
// $LastChangedBy: olivier.girard $
// $LastChangedDate: 2011-03-05 15:44:48 +0100 (Sat, 05 Mar 2011) $
//----------------------------------------------------------------------------
 
module omsp_and_gate (
 
// OUTPUTs
y, // AND gate output
 
// INPUTs
a, // AND gate input A
b // AND gate input B
);
 
// OUTPUTs
//=========
output y; // AND gate output
 
// INPUTs
//=========
input a; // AND gate input A
input b; // AND gate input B
 
 
//=============================================================================
// 1) SOME COMMENTS ON THIS MODULE
//=============================================================================
//
// In its ASIC version, some combinatorial pathes of the openMSP430 are
// sensitive to glitches, in particular the ones generating the wakeup
// signals.
// To prevent synthesis from optmizing combinatorial clouds into glitchy
// logic, this AND gate module has been instanciated in the critical places.
//
// Make sure that synthesis doesn't ungroup this module. As an alternative,
// a standard cell from the library could also be directly instanciated here
// (don't forget the "dont_touch" attribute)
//
//
//=============================================================================
// 2) AND GATE
//=============================================================================
 
assign y = a & b;
 
 
endmodule // omsp_and_gate
 
 
 
omsp_and_gate.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: openMSP430_defines.v =================================================================== --- openMSP430_defines.v (revision 132) +++ openMSP430_defines.v (revision 134) @@ -108,6 +108,56 @@ //============================================================================ //------------------------------------------------------- +// Custom user version number +//------------------------------------------------------- +// This 5 bit field can be freely used in order to allow +// custom identification of the system through the debug +// interface. +// (see CPU_ID.USER_VERSION field in the documentation) +//------------------------------------------------------- +`define USER_VERSION 5'b00000 + + +//------------------------------------------------------- +// Include/Exclude Watchdog timer +//------------------------------------------------------- +// When excluded, the following functionality will be +// lost: +// - Watchog (both interval and watchdog modes) +// - NMI interrupt edge selection +// - Possibility to generate a software PUC reset +//------------------------------------------------------- +`define WATCHDOG + + +///------------------------------------------------------- +// Include/Exclude Non-Maskable-Interrupt support +//------------------------------------------------------- +`define NMI + + +//------------------------------------------------------- +// Input synchronizers +//------------------------------------------------------- +// In some cases, the asynchronous input ports might +// already be synchronized externally. +// If an extensive CDC design review showed that this +// is really the case, the individual synchronizers +// can be disabled with the following defines. +// +// Notes: +// - all three signals are all sampled in the MCLK domain +// +// - the dbg_en signal reset the debug interface +// when 0. Therefore make sure it is glitch free. +// +//------------------------------------------------------- +`define SYNC_NMI +//`define SYNC_CPU_EN +//`define SYNC_DBG_EN + + +//------------------------------------------------------- // Peripheral Memory Space: //------------------------------------------------------- // The original MSP430 architecture map the peripherals @@ -132,24 +182,13 @@ // (CPU break on PUC reset) //------------------------------------------------------- // When defined, the CPU will automatically break after -// a PUC occurrence by default. This is typically usefull +// a PUC occurrence by default. This is typically useful // when the program memory can only be initialized through // the serial debug interface. //------------------------------------------------------- -//`define DBG_RST_BRK_EN +`define DBG_RST_BRK_EN -//------------------------------------------------------- -// Custom user version number -//------------------------------------------------------- -// This 5 bit field can be freely used in order to allow -// custom identification of the system through the debug -// interface. -// (see CPU_ID.USER_VERSION field in the documentation) -//------------------------------------------------------- -`define USER_VERSION 5'b00000 - - //============================================================================ //============================================================================ // EXPERT SYSTEM CONFIGURATION ( !!!! EXPERTS ONLY !!!! ) @@ -163,8 +202,9 @@ //============================================================================ //------------------------------------------------------- -// Number of hardware breakpoint units (each unit contains -// two hardware address breakpoints): +// Number of hardware breakpoint/watchpoint units +// (each unit contains two hardware addresses available +// for breakpoints or watchpoints): // - DBG_HWBRK_0 -> Include hardware breakpoints unit 0 // - DBG_HWBRK_1 -> Include hardware breakpoints unit 1 // - DBG_HWBRK_2 -> Include hardware breakpoints unit 2 @@ -173,7 +213,7 @@ // Please keep in mind that hardware breakpoints only // make sense whenever the program memory is not an SRAM // (i.e. Flash/OTP/ROM/...) or when you are interested -// in data breakpoints (btw. not supported by GDB). +// in data breakpoints. //------------------------------------------------------- //`define DBG_HWBRK_0 //`define DBG_HWBRK_1 @@ -193,28 +233,162 @@ //------------------------------------------------------- -// Input synchronizers +// ASIC version //------------------------------------------------------- -// In some cases, the asynchronous input ports might -// already be synchronized externally. -// If an extensive CDC design review showed that this -// is really the case, the individual synchronizers -// can be disabled with the following defines. +// When uncommented, this define will enable the +// ASIC system configuration section (see below) and +// will activate scan support for production test. // -// Notes: -// - the dbg_en signal will reset the debug interface -// when 0. Therefore make sure it is glitch free. -// -// - the dbg_uart_rxd synchronizer must be set to 1 -// when its reset is active. +// WARNING: if you target an FPGA, leave this define +// commented. //------------------------------------------------------- -`define SYNC_CPU_EN -`define SYNC_DBG_EN -`define SYNC_DBG_UART_RXD -`define SYNC_NMI +//`define ASIC +//============================================================================ +//============================================================================ +// ASIC SYSTEM CONFIGURATION ( !!!! EXPERTS/PROFESSIONALS ONLY !!!! ) +//============================================================================ +//============================================================================ +`ifdef ASIC +//=============================================================== +// FINE GRAINED CLOCK GATING +//=============================================================== + +//------------------------------------------------------- +// When uncommented, this define will enable the fine +// grained clock gating of all registers in the core. +//------------------------------------------------------- +`define CLOCK_GATING + + +//=============================================================== +// LFXT CLOCK DOMAIN +//=============================================================== + +//------------------------------------------------------- +// When uncommented, this define will enable the lfxt_clk +// clock domain. +// When commented out, the whole chip is clocked with dco_clk. +//------------------------------------------------------- +`define LFXT_DOMAIN + + +//=============================================================== +// CLOCK MUXES +//=============================================================== + +//------------------------------------------------------- +// MCLK: Clock Mux +//------------------------------------------------------- +// When uncommented, this define will enable the +// MCLK clock MUX allowing the selection between +// DCO_CLK and LFXT_CLK with the BCSCTL2.SELMx register. +// When commented, DCO_CLK is selected. +//------------------------------------------------------- +`define MCLK_MUX + +//------------------------------------------------------- +// SMCLK: Clock Mux +//------------------------------------------------------- +// When uncommented, this define will enable the +// SMCLK clock MUX allowing the selection between +// DCO_CLK and LFXT_CLK with the BCSCTL2.SELS register. +// When commented, DCO_CLK is selected. +//------------------------------------------------------- +`define SMCLK_MUX + +//------------------------------------------------------- +// WATCHDOG: Clock Mux +//------------------------------------------------------- +// When uncommented, this define will enable the +// Watchdog clock MUX allowing the selection between +// ACLK and SMCLK with the WDTCTL.WDTSSEL register. +// When commented out, ACLK is selected if the +// WATCHDOG_NOMUX_ACLK define is uncommented, SMCLK is +// selected otherwise. +//------------------------------------------------------- +`define WATCHDOG_MUX +//`define WATCHDOG_NOMUX_ACLK + + +//=============================================================== +// CLOCK DIVIDERS +//=============================================================== + +//------------------------------------------------------- +// MCLK: Clock divider +//------------------------------------------------------- +// When uncommented, this define will enable the +// MCLK clock divider (/1/2/4/8) +//------------------------------------------------------- +`define MCLK_DIVIDER + +//------------------------------------------------------- +// SMCLK: Clock divider (/1/2/4/8) +//------------------------------------------------------- +// When uncommented, this define will enable the +// SMCLK clock divider +//------------------------------------------------------- +`define SMCLK_DIVIDER + +//------------------------------------------------------- +// ACLK: Clock divider (/1/2/4/8) +//------------------------------------------------------- +// When uncommented, this define will enable the +// ACLK clock divider +//------------------------------------------------------- +`define ACLK_DIVIDER + + +//=============================================================== +// LOW POWER MODES +//=============================================================== + +//------------------------------------------------------- +// LOW POWER MODE: CPUOFF +//------------------------------------------------------- +// When uncommented, this define will include the +// clock gate allowing to switch off MCLK in +// all low power modes: LPM0, LPM1, LPM2, LPM3, LPM4 +//------------------------------------------------------- +`define CPUOFF_EN + +//------------------------------------------------------- +// LOW POWER MODE: SCG0 +//------------------------------------------------------- +// When uncommented, this define will enable the +// DCO_ENABLE/WKUP port control (always 1 when commented). +// This allows to switch off the DCO oscillator in the +// following low power modes: LPM1, LPM3, LPM4 +//------------------------------------------------------- +`define SCG0_EN + +//------------------------------------------------------- +// LOW POWER MODE: SCG1 +//------------------------------------------------------- +// When uncommented, this define will include the +// clock gate allowing to switch off SMCLK in +// the following low power modes: LPM2, LPM3, LPM4 +//------------------------------------------------------- +`define SCG1_EN + +//------------------------------------------------------- +// LOW POWER MODE: OSCOFF +//------------------------------------------------------- +// When uncommented, this define will include the +// LFXT_CLK clock gate and enable the LFXT_ENABLE/WKUP +// port control (always 1 when commented). +// This allows to switch off the low frequency oscillator +// in the following low power modes: LPM4 +//------------------------------------------------------- +`define OSCOFF_EN + + + +`endif + //==========================================================================// //==========================================================================// //==========================================================================// @@ -441,9 +615,10 @@ `define I_IDLE 3'h5 // Execution state machine -`define E_IRQ_0 4'h0 +// (swapped E_IRQ_0 and E_IRQ_2 values to suppress glitch generation warning from lint tool) +`define E_IRQ_0 4'h2 `define E_IRQ_1 4'h1 -`define E_IRQ_2 4'h2 +`define E_IRQ_2 4'h0 `define E_IRQ_3 4'h3 `define E_IRQ_4 4'h4 `define E_SRC_AD 4'h5 @@ -503,16 +678,35 @@ `define DIVAx 5:4 // Basic clock module: BCSCTL2 Control Register +`define SELMx 7 +`define DIVMx 5:4 `define SELS 3 `define DIVSx 2:1 +// MCLK Clock gate +`ifdef CPUOFF_EN + `define MCLK_CGATE +`else +`ifdef MCLK_DIVIDER + `define MCLK_CGATE +`endif +`endif +// SMCLK Clock gate +`ifdef SCG1_EN + `define SMCLK_CGATE +`else +`ifdef SMCLK_DIVIDER + `define SMCLK_CGATE +`endif +`endif + // // DEBUG INTERFACE EXTRA CONFIGURATION //====================================== // Debug interface: CPU version -`define CPU_VERSION 3'h1 +`define CPU_VERSION 3'h2 // Debug interface: Software breakpoint opcode `define DBG_SWBRK_OP 16'h4343 @@ -548,6 +742,9 @@ `define DBG_UART //`define DBG_JTAG +// Debug interface input synchronizer +`define SYNC_DBG_UART_RXD + // Enable/Disable the hardware breakpoint RANGE mode `ifdef DBG_HWBRK_RANGE `define HWBRK_RANGE 1'b1 @@ -581,4 +778,26 @@ // the 16x16 multiplier (1 cycle) instead of the // default 16x8 multplier (2 cycles) //`define MPY_16x16 - \ No newline at end of file + +//====================================== +// CONFIGURATION CHECKS +//====================================== +`ifdef LFXT_DOMAIN +`else + `ifdef MCLK_MUX +CONFIGURATION ERROR: THE MCLK_MUX CAN ONLY BE ENABLED IF THE LFXT_DOMAIN IS ENABLED AS WELL + `endif + `ifdef SMCLK_MUX +CONFIGURATION ERROR: THE SMCLK_MUX CAN ONLY BE ENABLED IF THE LFXT_DOMAIN IS ENABLED AS WELL + `endif + `ifdef WATCHDOG_MUX +CONFIGURATION ERROR: THE WATCHDOG_MUX CAN ONLY BE ENABLED IF THE LFXT_DOMAIN IS ENABLED AS WELL + `else + `ifdef WATCHDOG_NOMUX_ACLK +CONFIGURATION ERROR: THE WATCHDOG_NOMUX_ACLK CAN ONLY BE ENABLED IF THE LFXT_DOMAIN IS ENABLED AS WELL + `endif + `endif + `ifdef OSCOFF_EN +CONFIGURATION ERROR: THE OSCOFF LOW POWER MODE CAN ONLY BE ENABLED IF THE LFXT_DOMAIN IS ENABLED AS WELL + `endif +`endif
/openMSP430_undefines.v
178,7 → 178,16
`undef USER_VERSION
`endif
 
// Include/Exclude Watchdog timer
`ifdef WATCHDOG
`undef WATCHDOG
`endif
 
// Include/Exclude Non-Maskable-Interrupt support
`ifdef NMI
`undef NMI
`endif
 
//----------------------------------------------------------------------------
// EXPERT SYSTEM CONFIGURATION ( !!!! EXPERTS ONLY !!!! )
//----------------------------------------------------------------------------
216,7 → 225,77
`undef SYNC_NMI
`endif
 
// ASIC version
`ifdef ASIC
`undef ASIC
`endif
 
 
//----------------------------------------------------------------------------
// ASIC SYSTEM CONFIGURATION ( !!!! EXPERTS ONLY !!!! )
//----------------------------------------------------------------------------
 
// Fine grained clock gating
`ifdef CLOCK_GATING
`undef CLOCK_GATING
`endif
 
// LFXT clock domain
`ifdef LFXT_DOMAIN
`undef LFXT_DOMAIN
`endif
 
// MCLK: Clock Mux
`ifdef MCLK_MUX
`undef MCLK_MUX
`endif
 
// SMCLK: Clock Mux
`ifdef SMCLK_MUX
`undef SMCLK_MUX
`endif
 
// WATCHDOG: Clock Mux
`ifdef WATCHDOG_MUX
`undef WATCHDOG_MUX
`endif
 
// MCLK: Clock divider
`ifdef MCLK_DIVIDER
`undef MCLK_DIVIDER
`endif
 
// SMCLK: Clock divider (/1/2/4/8)
`ifdef SMCLK_DIVIDER
`undef SMCLK_DIVIDER
`endif
 
// ACLK: Clock divider (/1/2/4/8)
`ifdef ACLK_DIVIDER
`undef ACLK_DIVIDER
`endif
 
// LOW POWER MODE: CPUOFF
`ifdef CPUOFF_EN
`undef CPUOFF_EN
`endif
 
// LOW POWER MODE: OSCOFF
`ifdef OSCOFF_EN
`undef OSCOFF_EN
`endif
 
// LOW POWER MODE: SCG0
`ifdef SCG0_EN
`undef SCG0_EN
`endif
 
// LOW POWER MODE: SCG1
`ifdef SCG1_EN
`undef SCG1_EN
`endif
 
 
//==========================================================================//
//==========================================================================//
//==========================================================================//
573,6 → 652,12
`endif
 
// Basic clock module: BCSCTL2 Control Register
`ifdef SELMx
`undef SELMx
`endif
`ifdef DIVMx
`undef DIVMx
`endif
`ifdef SELS
`undef SELS
`endif
580,7 → 665,16
`undef DIVSx
`endif
 
// MCLK Clock gate
`ifdef MCLK_CGATE
`undef MCLK_CGATE
`endif
 
// SMCLK Clock gate
`ifdef SMCLK_CGATE
`undef SMCLK_CGATE
`endif
 
//
// DEBUG INTERFACE EXTRA CONFIGURATION
//======================================
/openMSP430.v
48,14 → 48,19
module openMSP430 (
 
// OUTPUTs
aclk_en, // ACLK enable
aclk, // ASIC ONLY: ACLK
aclk_en, // FPGA ONLY: ACLK enable
dbg_freeze, // Freeze peripherals
dbg_uart_txd, // Debug interface: UART TXD
dco_enable, // ASIC ONLY: Fast oscillator enable
dco_wkup, // ASIC ONLY: Fast oscillator wake-up (asynchronous)
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)
lfxt_enable, // ASIC ONLY: Low frequency oscillator enable
lfxt_wkup, // ASIC ONLY: Low frequency oscillator wake-up (asynchronous)
mclk, // Main system clock
per_addr, // Peripheral address
per_din, // Peripheral data input
66,11 → 71,12
pmem_din, // Program Memory data input (optional)
pmem_wen, // Program Memory write enable (low active) (optional)
puc_rst, // Main system reset
smclk_en, // SMCLK enable
smclk, // ASIC ONLY: SMCLK
smclk_en, // FPGA ONLY: SMCLK enable
 
// INPUTs
cpu_en, // Enable CPU code execution (asynchronous)
dbg_en, // Debug interface enable (asynchronous)
cpu_en, // Enable CPU code execution (asynchronous and non-glitchy)
dbg_en, // Debug interface enable (asynchronous and non-glitchy)
dbg_uart_rxd, // Debug interface: UART RXD (asynchronous)
dco_clk, // Fast oscillator (fast clock)
dmem_dout, // Data Memory data output
79,19 → 85,27
nmi, // Non-maskable interrupt (asynchronous)
per_dout, // Peripheral data output
pmem_dout, // Program Memory data output
reset_n // Reset Pin (low active, asynchronous)
reset_n, // Reset Pin (low active, asynchronous and non-glitchy)
scan_enable, // ASIC ONLY: Scan enable (active during scan shifting)
scan_mode, // ASIC ONLY: Scan mode
wkup // ASIC ONLY: System Wake-up (asynchronous and non-glitchy)
);
 
// OUTPUTs
//=========
output aclk_en; // ACLK enable
output aclk; // ASIC ONLY: ACLK
output aclk_en; // FPGA ONLY: ACLK enable
output dbg_freeze; // Freeze peripherals
output dbg_uart_txd; // Debug interface: UART TXD
output dco_enable; // ASIC ONLY: Fast oscillator enable
output dco_wkup; // ASIC ONLY: Fast oscillator wake-up (asynchronous)
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 lfxt_enable; // ASIC ONLY: Low frequency oscillator enable
output lfxt_wkup; // ASIC ONLY: Low frequency oscillator wake-up (asynchronous)
output mclk; // Main system clock
output [13:0] per_addr; // Peripheral address
output [15:0] per_din; // Peripheral data input
102,22 → 116,26
output [15:0] pmem_din; // Program Memory data input (optional)
output [1:0] pmem_wen; // Program Memory write enable (low active) (optional)
output puc_rst; // Main system reset
output smclk_en; // SMCLK enable
output smclk; // ASIC ONLY: SMCLK
output smclk_en; // FPGA ONLY: SMCLK enable
 
 
// INPUTs
//=========
input cpu_en; // Enable CPU code execution (asynchronous)
input dbg_en; // Debug interface enable (asynchronous)
input cpu_en; // Enable CPU code execution (asynchronous and non-glitchy)
input dbg_en; // Debug interface enable (asynchronous and non-glitchy)
input dbg_uart_rxd; // Debug interface: UART RXD (asynchronous)
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 nmi; // Non-maskable interrupt (asynchronous and non-glitchy)
input [15:0] per_dout; // Peripheral data output
input [15:0] pmem_dout; // Program Memory data output
input reset_n; // Reset Pin (active low, asynchronous)
input reset_n; // Reset Pin (active low, asynchronous and non-glitchy)
input scan_enable; // ASIC ONLY: Scan enable (active during scan shifting)
input scan_mode; // ASIC ONLY: Scan mode
input wkup; // ASIC ONLY: System Wake-up (asynchronous and non-glitchy)
 
 
 
144,9 → 162,13
wire cpu_en_s;
wire cpuoff;
wire oscoff;
wire scg0;
wire scg1;
wire por;
wire gie;
wire mclk_enable;
wire mclk_wkup;
wire [31:0] cpu_id;
 
wire [15:0] eu_mab;
wire [15:0] eu_mdb_in;
163,16 → 185,18
wire [15:0] pc;
wire [15:0] pc_nxt;
 
wire nmie;
wire nmi_acc;
wire nmi_evt;
wire nmi_pnd;
wire nmi_wkup;
 
wire wdtie;
wire wdtifg_set;
wire wdtpw_error;
wire wdttmsel;
wire wdtnmies;
wire wdtifg;
wire wdt_irq;
wire wdt_wkup;
wire wdt_reset;
wire wdtifg_sw_clr;
wire wdtifg_sw_set;
 
wire dbg_clk;
wire dbg_rst;
187,7 → 211,8
wire [15:0] dbg_mem_din;
wire [15:0] dbg_reg_din;
wire [1:0] dbg_mem_wr;
 
wire puc_pnd_set;
wire [15:0] per_dout_or;
wire [15:0] per_dout_sfr;
wire [15:0] per_dout_wdog;
202,23 → 227,33
omsp_clock_module clock_module_0 (
 
// OUTPUTs
.aclk (aclk), // ACLK
.aclk_en (aclk_en), // ACLK enablex
.cpu_en_s (cpu_en_s), // Enable CPU code execution (synchronous)
.dbg_clk (dbg_clk), // Debug unit clock
.dbg_en_s (dbg_en_s), // Debug interface enable (synchronous)
.dbg_rst (dbg_rst), // Debug unit reset
.dco_enable (dco_enable), // Fast oscillator enable
.dco_wkup (dco_wkup), // Fast oscillator wake-up (asynchronous)
.lfxt_enable (lfxt_enable), // Low frequency oscillator enable
.lfxt_wkup (lfxt_wkup), // Low frequency oscillator wake-up (asynchronous)
.mclk (mclk), // Main system clock
.per_dout (per_dout_clk), // Peripheral data output
.por (por), // Power-on reset
.puc_pnd_set (puc_pnd_set), // PUC pending set for the serial debug interface
.puc_rst (puc_rst), // Main system reset
.smclk (smclk), // SMCLK
.smclk_en (smclk_en), // SMCLK enable
// INPUTs
.cpu_en (cpu_en), // Enable CPU code execution (asynchronous)
.cpuoff (cpuoff), // Turns off the CPU
.dbg_cpu_reset(dbg_cpu_reset), // Reset CPU from debug interface
.dbg_en (dbg_en), // Debug interface enable (asynchronous)
.dco_clk (dco_clk), // Fast oscillator (fast clock)
.lfxt_clk (lfxt_clk), // Low frequency oscillator (typ 32kHz)
.mclk_enable (mclk_enable), // Main System Clock enable
.mclk_wkup (mclk_wkup), // Main System Clock wake-up (asynchronous)
.oscoff (oscoff), // Turns off LFXT1 clock input
.per_addr (per_addr), // Peripheral address
.per_din (per_din), // Peripheral data input
225,6 → 260,9
.per_en (per_en), // Peripheral enable (high active)
.per_we (per_we), // Peripheral write enable (high active)
.reset_n (reset_n), // Reset Pin (low active, asynchronous)
.scan_enable (scan_enable), // Scan enable (active during scan shifting)
.scan_mode (scan_mode), // Scan mode
.scg0 (scg0), // System clock generator 1. Turns off the DCO
.scg1 (scg1), // System clock generator 1. Turns off the SMCLK
.wdt_reset (wdt_reset) // Watchdog-timer reset
);
257,6 → 295,8
.irq_acc (irq_acc), // Interrupt request accepted
.mab (fe_mab), // Frontend Memory address bus
.mb_en (fe_mb_en), // Frontend Memory bus enable
.mclk_enable (mclk_enable), // Main System Clock enable
.mclk_wkup (mclk_wkup), // Main System Clock wake-up (asynchronous)
.nmi_acc (nmi_acc), // Non-Maskable interrupt request accepted
.pc (pc), // Program counter
.pc_nxt (pc_nxt), // Next PC value (for CALL & IRQ)
271,11 → 311,15
.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
.nmi_pnd (nmi_pnd), // Non-maskable interrupt pending
.nmi_wkup (nmi_wkup), // NMI Wakeup
.pc_sw (pc_sw), // Program counter software value
.pc_sw_wr (pc_sw_wr), // Program counter software write
.puc_rst (puc_rst), // Main system reset
.wdt_irq (wdt_irq) // Watchdog-timer interrupt
.scan_enable (scan_enable), // Scan enable (active during scan shifting)
.wdt_irq (wdt_irq), // Watchdog-timer interrupt
.wdt_wkup (wdt_wkup), // Watchdog Wakeup
.wkup (wkup) // System Wake-up (asynchronous)
);
 
 
295,6 → 339,7
.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
.scg0 (scg0), // System clock generator 1. Turns off the DCO
.scg1 (scg1), // System clock generator 1. Turns off the SMCLK
 
// INPUTs
321,7 → 366,8
.mdb_in (eu_mdb_in), // Memory data bus input
.pc (pc), // Program counter
.pc_nxt (pc_nxt), // Next PC value (for CALL & IRQ)
.puc_rst (puc_rst) // Main system reset
.puc_rst (puc_rst), // Main system reset
.scan_enable (scan_enable) // Scan enable (active during scan shifting)
);
 
 
365,7 → 411,8
.mclk (mclk), // Main system clock
.per_dout (per_dout_or), // Peripheral data output
.pmem_dout (pmem_dout), // Program Memory data output
.puc_rst (puc_rst) // Main system reset
.puc_rst (puc_rst), // Main system reset
.scan_enable (scan_enable) // Scan enable (active during scan shifting)
);
 
 
372,29 → 419,29
//=============================================================================
// 6) SPECIAL FUNCTION REGISTERS
//=============================================================================
 
omsp_sfr sfr_0 (
 
// OUTPUTs
.nmie (nmie), // Non-maskable interrupt enable
.cpu_id (cpu_id), // CPU ID
.nmi_pnd (nmi_pnd), // NMI Pending
.nmi_wkup (nmi_wkup), // NMI Wakeup
.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
.wdtifg_sw_clr(wdtifg_sw_clr), // Watchdog-timer interrupt flag software clear
.wdtifg_sw_set(wdtifg_sw_set), // Watchdog-timer interrupt flag software set
// INPUTs
.mclk (mclk), // Main system clock
.nmi (nmi), // Non-maskable interrupt (asynchronous)
.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_we (per_we), // Peripheral write enable (high active)
.por (por), // Power-on reset
.puc_rst (puc_rst), // 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
.scan_mode (scan_mode), // Scan mode
.wdtifg (wdtifg), // Watchdog-timer interrupt flag
.wdtnmies (wdtnmies) // Watchdog-timer NMI edge selection
);
 
 
401,30 → 448,45
//=============================================================================
// 7) WATCHDOG TIMER
//=============================================================================
 
`ifdef WATCHDOG
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
.per_dout (per_dout_wdog), // Peripheral data output
.wdt_irq (wdt_irq), // Watchdog-timer interrupt
.wdt_reset (wdt_reset), // Watchdog-timer reset
.wdt_wkup (wdt_wkup), // Watchdog Wakeup
.wdtifg (wdtifg), // Watchdog-timer interrupt flag
.wdtnmies (wdtnmies), // Watchdog-timer NMI edge selection
// 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_we (per_we), // Peripheral write enable (high active)
.puc_rst (puc_rst), // Main system reset
.smclk_en (smclk_en), // SMCLK enable
.wdtie (wdtie) // Watchdog-timer interrupt enable
.aclk (aclk), // ACLK
.aclk_en (aclk_en), // ACLK enable
.dbg_freeze (dbg_freeze), // Freeze Watchdog counter
.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_we (per_we), // Peripheral write enable (high active)
.por (por), // Power-on reset
.puc_rst (puc_rst), // Main system reset
.scan_enable (scan_enable), // Scan enable (active during scan shifting)
.scan_mode (scan_mode), // Scan mode
.smclk (smclk), // SMCLK
.smclk_en (smclk_en), // SMCLK enable
.wdtie (wdtie), // Watchdog-timer interrupt enable
.wdtifg_irq_clr (irq_acc[10]), // Clear Watchdog-timer interrupt flag
.wdtifg_sw_clr (wdtifg_sw_clr), // Watchdog-timer interrupt flag software clear
.wdtifg_sw_set (wdtifg_sw_set) // Watchdog-timer interrupt flag software set
);
`else
assign per_dout_wdog = 16'h0000;
assign wdt_irq = 1'b0;
assign wdt_reset = 1'b0;
assign wdt_wkup = 1'b0;
assign wdtifg = 1'b0;
assign wdtnmies = 1'b0;
`endif
 
 
//=============================================================================
442,7 → 504,8
.per_din (per_din), // Peripheral data input
.per_en (per_en), // Peripheral enable (high active)
.per_we (per_we), // Peripheral write enable (high active)
.puc_rst (puc_rst) // Main system reset
.puc_rst (puc_rst), // Main system reset
.scan_enable (scan_enable) // Scan enable (active during scan shifting)
);
`else
assign per_dout_mpy = 16'h0000;
479,6 → 542,7
// INPUTs
.cpu_en_s (cpu_en_s), // Enable CPU code execution (synchronous)
.cpu_id (cpu_id), // CPU ID
.dbg_clk (dbg_clk), // Debug unit clock
.dbg_en_s (dbg_en_s), // Debug interface enable (synchronous)
.dbg_halt_st (dbg_halt_st), // Halt/Run status from CPU
496,7 → 560,7
.fe_mb_en (fe_mb_en), // Frontend Memory bus enable
.fe_mdb_in (fe_mdb_in), // Frontend Memory data bus input
.pc (pc), // Program counter
.puc_rst (puc_rst) // Main system reset
.puc_pnd_set (puc_pnd_set) // PUC pending set for the serial debug interface
);
 
`else

powered by: WebSVN 2.1.0

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