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 |