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

Subversion Repositories openmsp430

Compare Revisions

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

Rev 33 → Rev 34

/sfr.v File deleted
sfr.v Property changes : Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Date Revision Author \ No newline at end of property Index: register_file.v =================================================================== --- register_file.v (revision 33) +++ register_file.v (nonexistent) @@ -1,345 +0,0 @@ -//---------------------------------------------------------------------------- -// Copyright (C) 2001 Authors -// -// This source file may be used and distributed without restriction provided -// that this copyright statement is not removed from the file and that any -// derivative work contains the original copyright notice and the associated -// disclaimer. -// -// This source file is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This source is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -// License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this source; if not, write to the Free Software Foundation, -// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -//---------------------------------------------------------------------------- -// -// *File Name: register_file.v -// -// *Module Description: -// openMSP430 Register files -// -// *Author(s): -// - Olivier Girard, olgirard@gmail.com -// -//---------------------------------------------------------------------------- -// $Rev$ -// $LastChangedBy$ -// $LastChangedDate$ -//---------------------------------------------------------------------------- -`include "timescale.v" -`include "openMSP430_defines.v" - -module register_file ( - -// OUTPUTs - cpuoff, // Turns off the CPU - gie, // General interrupt enable - oscoff, // Turns off LFXT1 clock input - pc_sw, // Program counter software value - pc_sw_wr, // Program counter software write - reg_dest, // Selected register destination content - reg_src, // Selected register source content - scg1, // System clock generator 1. Turns off the SMCLK - status, // R2 Status {V,N,Z,C} - -// INPUTs - alu_stat, // ALU Status {V,N,Z,C} - alu_stat_wr, // ALU Status write {V,N,Z,C} - inst_bw, // Decoded Inst: byte width - inst_dest, // Register destination selection - inst_src, // Register source selection - mclk, // Main system clock - pc, // Program counter - puc, // Main system reset - reg_dest_val, // Selected register destination value - reg_dest_wr, // Write selected register destination - reg_pc_call, // Trigger PC update for a CALL instruction - reg_sp_val, // Stack Pointer next value - reg_sp_wr, // Stack Pointer write - reg_sr_wr, // Status register update for RETI instruction - reg_sr_clr, // Status register clear for interrupts - reg_incr // Increment source register -); - -// OUTPUTs -//========= -output cpuoff; // Turns off the CPU -output gie; // General interrupt enable -output oscoff; // Turns off LFXT1 clock input -output [15:0] pc_sw; // Program counter software value -output pc_sw_wr; // Program counter software write -output [15:0] reg_dest; // Selected register destination content -output [15:0] reg_src; // Selected register source content -output scg1; // System clock generator 1. Turns off the SMCLK -output [3:0] status; // R2 Status {V,N,Z,C} - -// INPUTs -//========= -input [3:0] alu_stat; // ALU Status {V,N,Z,C} -input [3:0] alu_stat_wr; // ALU Status write {V,N,Z,C} -input inst_bw; // Decoded Inst: byte width -input [15:0] inst_dest; // Register destination selection -input [15:0] inst_src; // Register source selection -input mclk; // Main system clock -input [15:0] pc; // Program counter -input puc; // Main system reset -input [15:0] reg_dest_val; // Selected register destination value -input reg_dest_wr; // Write selected register destination -input reg_pc_call; // Trigger PC update for a CALL instruction -input [15:0] reg_sp_val; // Stack Pointer next value -input reg_sp_wr; // Stack Pointer write -input reg_sr_wr; // Status register update for RETI instruction -input reg_sr_clr; // Status register clear for interrupts -input reg_incr; // Increment source register - - -//============================================================================= -// 1) AUTOINCREMENT UNIT -//============================================================================= - -wire [15:0] incr_op = inst_bw ? 16'h0001 : 16'h0002; -wire [15:0] reg_incr_val = reg_src+incr_op; - -wire [15:0] reg_dest_val_in = inst_bw ? {8'h00,reg_dest_val[7:0]} : reg_dest_val; - - -//============================================================================= -// 2) SPECIAL REGISTERS (R1/R2/R3) -//============================================================================= - -// Source input selection mask (for interrupt support) -//----------------------------------------------------- - -wire [15:0] inst_src_in = reg_sr_clr ? 16'h0004 : inst_src; - - -// R0: Program counter -//--------------------- - -wire [15:0] r0 = pc; - -wire [15:0] pc_sw = reg_dest_val_in; -wire pc_sw_wr = (inst_dest[0] & reg_dest_wr) | reg_pc_call; - - -// R1: Stack pointer -//------------------- -reg [15:0] r1; -wire r1_wr = inst_dest[1] & reg_dest_wr; -wire r1_inc = inst_src_in[1] & reg_incr; - -always @(posedge mclk or posedge puc) - if (puc) r1 <= 16'h0000; - else if (r1_wr) r1 <= reg_dest_val_in & 16'hfffe; - else if (reg_sp_wr) r1 <= reg_sp_val & 16'hfffe; - else if (r1_inc) r1 <= reg_incr_val & 16'hfffe; - - -// R2: Status register -//--------------------- -reg [15:0] r2; -wire r2_wr = (inst_dest[2] & reg_dest_wr) | reg_sr_wr; - -wire r2_c = alu_stat_wr[0] ? alu_stat[0] : - r2_wr ? reg_dest_val_in[0] : r2[0]; // C - -wire r2_z = alu_stat_wr[1] ? alu_stat[1] : - r2_wr ? reg_dest_val_in[1] : r2[1]; // Z - -wire r2_n = alu_stat_wr[2] ? alu_stat[2] : - r2_wr ? reg_dest_val_in[2] : r2[2]; // N - -wire [7:3] r2_nxt = r2_wr ? reg_dest_val_in[7:3] : r2[7:3]; - -wire r2_v = alu_stat_wr[3] ? alu_stat[3] : - r2_wr ? reg_dest_val_in[8] : r2[8]; // V - - -always @(posedge mclk or posedge puc) - if (puc) r2 <= 16'h0000; - else if (reg_sr_clr) r2 <= 16'h0000; - else r2 <= {7'h00, r2_v, r2_nxt, r2_n, r2_z, r2_c}; - -assign status = {r2[8], r2[2:0]}; -assign gie = r2[3]; -assign cpuoff = r2[4] | (r2_nxt[4] & r2_wr); -assign oscoff = r2[5]; -assign scg1 = r2[7]; - - -// R3: Constant generator -//------------------------ -reg [15:0] r3; -wire r3_wr = inst_dest[3] & reg_dest_wr; -wire r3_inc = inst_src_in[3] & reg_incr; - -always @(posedge mclk or posedge puc) - if (puc) r3 <= 16'h0000; - else if (r3_wr) r3 <= reg_dest_val_in; - else if (r3_inc) r3 <= reg_incr_val; - - -//============================================================================= -// 4) GENERAL PURPOSE REGISTERS (R4...R15) -//============================================================================= - -// R4 -reg [15:0] r4; -wire r4_wr = inst_dest[4] & reg_dest_wr; -wire r4_inc = inst_src_in[4] & reg_incr; -always @(posedge mclk or posedge puc) - if (puc) r4 <= 16'h0000; - else if (r4_wr) r4 <= reg_dest_val_in; - else if (r4_inc) r4 <= reg_incr_val; - -// R5 -reg [15:0] r5; -wire r5_wr = inst_dest[5] & reg_dest_wr; -wire r5_inc = inst_src_in[5] & reg_incr; -always @(posedge mclk or posedge puc) - if (puc) r5 <= 16'h0000; - else if (r5_wr) r5 <= reg_dest_val_in; - else if (r5_inc) r5 <= reg_incr_val; - -// R6 -reg [15:0] r6; -wire r6_wr = inst_dest[6] & reg_dest_wr; -wire r6_inc = inst_src_in[6] & reg_incr; -always @(posedge mclk or posedge puc) - if (puc) r6 <= 16'h0000; - else if (r6_wr) r6 <= reg_dest_val_in; - else if (r6_inc) r6 <= reg_incr_val; - -// R7 -reg [15:0] r7; -wire r7_wr = inst_dest[7] & reg_dest_wr; -wire r7_inc = inst_src_in[7] & reg_incr; -always @(posedge mclk or posedge puc) - if (puc) r7 <= 16'h0000; - else if (r7_wr) r7 <= reg_dest_val_in; - else if (r7_inc) r7 <= reg_incr_val; - -// R8 -reg [15:0] r8; -wire r8_wr = inst_dest[8] & reg_dest_wr; -wire r8_inc = inst_src_in[8] & reg_incr; -always @(posedge mclk or posedge puc) - if (puc) r8 <= 16'h0000; - else if (r8_wr) r8 <= reg_dest_val_in; - else if (r8_inc) r8 <= reg_incr_val; - -// R9 -reg [15:0] r9; -wire r9_wr = inst_dest[9] & reg_dest_wr; -wire r9_inc = inst_src_in[9] & reg_incr; -always @(posedge mclk or posedge puc) - if (puc) r9 <= 16'h0000; - else if (r9_wr) r9 <= reg_dest_val_in; - else if (r9_inc) r9 <= reg_incr_val; - -// R10 -reg [15:0] r10; -wire r10_wr = inst_dest[10] & reg_dest_wr; -wire r10_inc = inst_src_in[10] & reg_incr; -always @(posedge mclk or posedge puc) - if (puc) r10 <= 16'h0000; - else if (r10_wr) r10 <= reg_dest_val_in; - else if (r10_inc) r10 <= reg_incr_val; - -// R11 -reg [15:0] r11; -wire r11_wr = inst_dest[11] & reg_dest_wr; -wire r11_inc = inst_src_in[11] & reg_incr; -always @(posedge mclk or posedge puc) - if (puc) r11 <= 16'h0000; - else if (r11_wr) r11 <= reg_dest_val_in; - else if (r11_inc) r11 <= reg_incr_val; - -// R12 -reg [15:0] r12; -wire r12_wr = inst_dest[12] & reg_dest_wr; -wire r12_inc = inst_src_in[12] & reg_incr; -always @(posedge mclk or posedge puc) - if (puc) r12 <= 16'h0000; - else if (r12_wr) r12 <= reg_dest_val_in; - else if (r12_inc) r12 <= reg_incr_val; - -// R13 -reg [15:0] r13; -wire r13_wr = inst_dest[13] & reg_dest_wr; -wire r13_inc = inst_src_in[13] & reg_incr; -always @(posedge mclk or posedge puc) - if (puc) r13 <= 16'h0000; - else if (r13_wr) r13 <= reg_dest_val_in; - else if (r13_inc) r13 <= reg_incr_val; - -// R14 -reg [15:0] r14; -wire r14_wr = inst_dest[14] & reg_dest_wr; -wire r14_inc = inst_src_in[14] & reg_incr; -always @(posedge mclk or posedge puc) - if (puc) r14 <= 16'h0000; - else if (r14_wr) r14 <= reg_dest_val_in; - else if (r14_inc) r14 <= reg_incr_val; - -// R15 -reg [15:0] r15; -wire r15_wr = inst_dest[15] & reg_dest_wr; -wire r15_inc = inst_src_in[15] & reg_incr; -always @(posedge mclk or posedge puc) - if (puc) r15 <= 16'h0000; - else if (r15_wr) r15 <= reg_dest_val_in; - else if (r15_inc) r15 <= reg_incr_val; - - -//============================================================================= -// 5) READ MUX -//============================================================================= - -assign reg_src = (r0 & {16{inst_src_in[0]}}) | - (r1 & {16{inst_src_in[1]}}) | - (r2 & {16{inst_src_in[2]}}) | - (r3 & {16{inst_src_in[3]}}) | - (r4 & {16{inst_src_in[4]}}) | - (r5 & {16{inst_src_in[5]}}) | - (r6 & {16{inst_src_in[6]}}) | - (r7 & {16{inst_src_in[7]}}) | - (r8 & {16{inst_src_in[8]}}) | - (r9 & {16{inst_src_in[9]}}) | - (r10 & {16{inst_src_in[10]}}) | - (r11 & {16{inst_src_in[11]}}) | - (r12 & {16{inst_src_in[12]}}) | - (r13 & {16{inst_src_in[13]}}) | - (r14 & {16{inst_src_in[14]}}) | - (r15 & {16{inst_src_in[15]}}); - -assign reg_dest = (r0 & {16{inst_dest[0]}}) | - (r1 & {16{inst_dest[1]}}) | - (r2 & {16{inst_dest[2]}}) | - (r3 & {16{inst_dest[3]}}) | - (r4 & {16{inst_dest[4]}}) | - (r5 & {16{inst_dest[5]}}) | - (r6 & {16{inst_dest[6]}}) | - (r7 & {16{inst_dest[7]}}) | - (r8 & {16{inst_dest[8]}}) | - (r9 & {16{inst_dest[9]}}) | - (r10 & {16{inst_dest[10]}}) | - (r11 & {16{inst_dest[11]}}) | - (r12 & {16{inst_dest[12]}}) | - (r13 & {16{inst_dest[13]}}) | - (r14 & {16{inst_dest[14]}}) | - (r15 & {16{inst_dest[15]}}); - - -endmodule // register_file - -`include "openMSP430_undefines.v"
register_file.v Property changes : Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Date Revision Author \ No newline at end of property Index: execution_unit.v =================================================================== --- execution_unit.v (revision 33) +++ execution_unit.v (nonexistent) @@ -1,367 +0,0 @@ -//---------------------------------------------------------------------------- -// Copyright (C) 2001 Authors -// -// This source file may be used and distributed without restriction provided -// that this copyright statement is not removed from the file and that any -// derivative work contains the original copyright notice and the associated -// disclaimer. -// -// This source file is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This source is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -// License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this source; if not, write to the Free Software Foundation, -// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -//---------------------------------------------------------------------------- -// -// *File Name: execution_unit.v -// -// *Module Description: -// openMSP430 Execution unit -// -// *Author(s): -// - Olivier Girard, olgirard@gmail.com -// -//---------------------------------------------------------------------------- -// $Rev$ -// $LastChangedBy$ -// $LastChangedDate$ -//---------------------------------------------------------------------------- -`include "timescale.v" -`include "openMSP430_defines.v" - -module execution_unit ( - -// OUTPUTs - cpuoff, // Turns off the CPU - dbg_reg_din, // Debug unit CPU register data input - gie, // General interrupt enable - mab, // Memory address bus - mb_en, // Memory bus enable - mb_wr, // Memory bus write transfer - mdb_out, // Memory data bus output - oscoff, // Turns off LFXT1 clock input - pc_sw, // Program counter software value - pc_sw_wr, // Program counter software write - scg1, // System clock generator 1. Turns off the SMCLK - -// INPUTs - dbg_halt_st, // Halt/Run status from CPU - dbg_mem_dout, // Debug unit data output - dbg_reg_wr, // Debug unit CPU register write - e_state, // Execution state - exec_done, // Execution completed - inst_ad, // Decoded Inst: destination addressing mode - inst_as, // Decoded Inst: source addressing mode - inst_alu, // ALU control signals - inst_bw, // Decoded Inst: byte width - inst_dest, // Decoded Inst: destination (one hot) - inst_dext, // Decoded Inst: destination extended instruction word - inst_irq_rst, // Decoded Inst: reset interrupt - inst_jmp, // Decoded Inst: Conditional jump - inst_sext, // Decoded Inst: source extended instruction word - inst_so, // Decoded Inst: Single-operand arithmetic - inst_src, // Decoded Inst: source (one hot) - inst_type, // Decoded Instruction type - mclk, // Main system clock - mdb_in, // Memory data bus input - pc, // Program counter - pc_nxt, // Next PC value (for CALL & IRQ) - puc // Main system reset -); - -// OUTPUTs -//========= -output cpuoff; // Turns off the CPU -output [15:0] dbg_reg_din; // Debug unit CPU register data input -output gie; // General interrupt enable -output [15:0] mab; // Memory address bus -output mb_en; // Memory bus enable -output [1:0] mb_wr; // Memory bus write transfer -output [15:0] mdb_out; // Memory data bus output -output oscoff; // Turns off LFXT1 clock input -output [15:0] pc_sw; // Program counter software value -output pc_sw_wr; // Program counter software write -output scg1; // System clock generator 1. Turns off the SMCLK - -// INPUTs -//========= -input dbg_halt_st; // Halt/Run status from CPU -input [15:0] dbg_mem_dout; // Debug unit data output -input dbg_reg_wr; // Debug unit CPU register write -input [3:0] e_state; // Execution state -input exec_done; // Execution completed -input [7:0] inst_ad; // Decoded Inst: destination addressing mode -input [7:0] inst_as; // Decoded Inst: source addressing mode -input [11:0] inst_alu; // ALU control signals -input inst_bw; // Decoded Inst: byte width -input [15:0] inst_dest; // Decoded Inst: destination (one hot) -input [15:0] inst_dext; // Decoded Inst: destination extended instruction word -input inst_irq_rst; // Decoded Inst: reset interrupt -input [7:0] inst_jmp; // Decoded Inst: Conditional jump -input [15:0] inst_sext; // Decoded Inst: source extended instruction word -input [7:0] inst_so; // Decoded Inst: Single-operand arithmetic -input [15:0] inst_src; // Decoded Inst: source (one hot) -input [2:0] inst_type; // Decoded Instruction type -input mclk; // Main system clock -input [15:0] mdb_in; // Memory data bus input -input [15:0] pc; // Program counter -input [15:0] pc_nxt; // Next PC value (for CALL & IRQ) -input puc; // Main system reset - - -//============================================================================= -// 1) INTERNAL WIRES/REGISTERS/PARAMETERS DECLARATION -//============================================================================= - -wire [15:0] alu_out; -wire [15:0] alu_out_add; -wire [3:0] alu_stat; -wire [3:0] alu_stat_wr; -wire [15:0] op_dst; -wire [15:0] op_src; -wire [15:0] reg_dest; -wire [15:0] reg_src; -wire [15:0] mdb_in_bw; -wire [15:0] mdb_in_val; -wire [3:0] status; - - -//============================================================================= -// 2) REGISTER FILE -//============================================================================= - -wire reg_dest_wr = ((e_state==`E_EXEC) & ( - (inst_type[`INST_TO] & inst_ad[`DIR] & ~inst_alu[`EXEC_NO_WR]) | - (inst_type[`INST_SO] & inst_as[`DIR] & ~(inst_so[`PUSH] | inst_so[`CALL] | inst_so[`RETI])) | - inst_type[`INST_JMP])) | dbg_reg_wr; - -wire reg_sp_wr = (((e_state==`E_IRQ_1) | (e_state==`E_IRQ_3)) & ~inst_irq_rst) | - ((e_state==`E_DST_RD) & (inst_so[`PUSH] | inst_so[`CALL])); - -wire reg_sr_wr = (e_state==`E_DST_RD) & inst_so[`RETI]; - -wire reg_sr_clr = (e_state==`E_IRQ_2); - -wire reg_pc_call = ((e_state==`E_EXEC) & inst_so[`CALL]) | - ((e_state==`E_DST_WR) & inst_so[`RETI]); - -wire reg_incr = (exec_done & inst_as[`INDIR_I]) | - ((e_state==`E_SRC_RD) & inst_so[`RETI]) | - ((e_state==`E_EXEC) & inst_so[`RETI]); - -assign dbg_reg_din = reg_dest; - - -register_file register_file_0 ( - -// OUTPUTs - .cpuoff (cpuoff), // Turns off the CPU - .gie (gie), // General interrupt enable - .oscoff (oscoff), // Turns off LFXT1 clock input - .pc_sw (pc_sw), // Program counter software value - .pc_sw_wr (pc_sw_wr), // Program counter software write - .reg_dest (reg_dest), // Selected register destination content - .reg_src (reg_src), // Selected register source content - .scg1 (scg1), // System clock generator 1. Turns off the SMCLK - .status (status), // R2 Status {V,N,Z,C} - -// INPUTs - .alu_stat (alu_stat), // ALU Status {V,N,Z,C} - .alu_stat_wr (alu_stat_wr), // ALU Status write {V,N,Z,C} - .inst_bw (inst_bw), // Decoded Inst: byte width - .inst_dest (inst_dest), // Register destination selection - .inst_src (inst_src), // Register source selection - .mclk (mclk), // Main system clock - .pc (pc), // Program counter - .puc (puc), // Main system reset - .reg_dest_val (alu_out), // Selected register destination value - .reg_dest_wr (reg_dest_wr), // Write selected register destination - .reg_pc_call (reg_pc_call), // Trigger PC update for a CALL instruction - .reg_sp_val (alu_out_add), // Stack Pointer next value - .reg_sp_wr (reg_sp_wr), // Stack Pointer write - .reg_sr_clr (reg_sr_clr), // Status register clear for interrupts - .reg_sr_wr (reg_sr_wr), // Status Register update for RETI instruction - .reg_incr (reg_incr) // Increment source register -); - - -//============================================================================= -// 3) SOURCE OPERAND MUXING -//============================================================================= -// inst_as[`DIR] : Register direct. -> Source is in register -// inst_as[`IDX] : Register indexed. -> Source is in memory, address is register+offset -// inst_as[`INDIR] : Register indirect. -// inst_as[`INDIR_I]: Register indirect autoincrement. -// inst_as[`SYMB] : Symbolic (operand is in memory at address PC+x). -// inst_as[`IMM] : Immediate (operand is next word in the instruction stream). -// inst_as[`ABS] : Absolute (operand is in memory at address x). -// inst_as[`CONST] : Constant. - -wire src_reg_src_sel = (e_state==`E_IRQ_0) | - (e_state==`E_IRQ_2) | - ((e_state==`E_SRC_RD) & ~inst_as[`ABS]) | - ((e_state==`E_SRC_WR) & ~inst_as[`ABS]) | - ((e_state==`E_EXEC) & inst_as[`DIR] & ~inst_type[`INST_JMP]); - -wire src_reg_dest_sel = (e_state==`E_IRQ_1) | - (e_state==`E_IRQ_3) | - ((e_state==`E_DST_RD) & (inst_so[`PUSH] | inst_so[`CALL])); - -wire src_mdb_in_val_sel = ((e_state==`E_DST_RD) & inst_so[`RETI]) | - ((e_state==`E_EXEC) & (inst_as[`INDIR] | inst_as[`INDIR_I] | - inst_as[`IDX] | inst_as[`SYMB] | - inst_as[`ABS])); - -wire src_inst_dext_sel = ((e_state==`E_DST_RD) & ~(inst_so[`PUSH] | inst_so[`CALL])) | - ((e_state==`E_DST_WR) & ~(inst_so[`PUSH] | inst_so[`CALL] | - inst_so[`RETI])); - -wire src_inst_sext_sel = ((e_state==`E_EXEC) & (inst_type[`INST_JMP] | inst_as[`IMM] | - inst_as[`CONST] | inst_so[`RETI])); - - -assign op_src = src_reg_src_sel ? reg_src : - src_reg_dest_sel ? reg_dest : - src_mdb_in_val_sel ? mdb_in_val : - src_inst_dext_sel ? inst_dext : - src_inst_sext_sel ? inst_sext : 16'h0000; - - -//============================================================================= -// 4) DESTINATION OPERAND MUXING -//============================================================================= -// inst_ad[`DIR] : Register direct. -// inst_ad[`IDX] : Register indexed. -// inst_ad[`SYMB] : Symbolic (operand is in memory at address PC+x). -// inst_ad[`ABS] : Absolute (operand is in memory at address x). - - -wire dst_inst_sext_sel = ((e_state==`E_SRC_RD) & (inst_as[`IDX] | inst_as[`SYMB] | - inst_as[`ABS])) | - ((e_state==`E_SRC_WR) & (inst_as[`IDX] | inst_as[`SYMB] | - inst_as[`ABS])); - -wire dst_mdb_in_bw_sel = ((e_state==`E_DST_WR) & inst_so[`RETI]) | - ((e_state==`E_EXEC) & ~(inst_ad[`DIR] | inst_type[`INST_JMP] | - inst_type[`INST_SO]) & ~inst_so[`RETI]); - -wire dst_fffe_sel = (e_state==`E_IRQ_0) | - (e_state==`E_IRQ_1) | - (e_state==`E_IRQ_3) | - ((e_state==`E_DST_RD) & (inst_so[`PUSH] | inst_so[`CALL]) & ~inst_so[`RETI]); - -wire dst_reg_dest_sel = ((e_state==`E_DST_RD) & ~(inst_so[`PUSH] | inst_so[`CALL] | inst_ad[`ABS] | inst_so[`RETI])) | - ((e_state==`E_DST_WR) & ~inst_ad[`ABS]) | - ((e_state==`E_EXEC) & (inst_ad[`DIR] | inst_type[`INST_JMP] | - inst_type[`INST_SO]) & ~inst_so[`RETI]); - - -assign op_dst = dbg_halt_st ? dbg_mem_dout : - dst_inst_sext_sel ? inst_sext : - dst_mdb_in_bw_sel ? mdb_in_bw : - dst_reg_dest_sel ? reg_dest : - dst_fffe_sel ? 16'hfffe : 16'h0000; - - -//============================================================================= -// 5) ALU -//============================================================================= - -wire exec_cycle = (e_state==`E_EXEC); - -alu alu_0 ( - -// OUTPUTs - .alu_out (alu_out), // ALU output value - .alu_out_add (alu_out_add), // ALU adder output value - .alu_stat (alu_stat), // ALU Status {V,N,Z,C} - .alu_stat_wr (alu_stat_wr), // ALU Status write {V,N,Z,C} - -// INPUTs - .dbg_halt_st (dbg_halt_st), // Halt/Run status from CPU - .exec_cycle (exec_cycle), // Instruction execution cycle - .inst_alu (inst_alu), // ALU control signals - .inst_bw (inst_bw), // Decoded Inst: byte width - .inst_jmp (inst_jmp), // Decoded Inst: Conditional jump - .inst_so (inst_so), // Single-operand arithmetic - .op_dst (op_dst), // Destination operand - .op_src (op_src), // Source operand - .status (status) // R2 Status {V,N,Z,C} -); - - -//============================================================================= -// 6) MEMORY INTERFACE -//============================================================================= - -// Detect memory read/write access -assign mb_en = ((e_state==`E_IRQ_1) & ~inst_irq_rst) | - ((e_state==`E_IRQ_3) & ~inst_irq_rst) | - ((e_state==`E_SRC_RD) & ~inst_as[`IMM]) | - (e_state==`E_SRC_WR) | - ((e_state==`E_EXEC) & inst_so[`RETI]) | - (e_state==`E_DST_RD) | - (e_state==`E_DST_WR); - -wire [1:0] mb_wr_msk = inst_alu[`EXEC_NO_WR] ? 2'b00 : - ~inst_bw ? 2'b11 : - alu_out_add[0] ? 2'b10 : 2'b01; -assign mb_wr = ({2{(e_state==`E_IRQ_1)}} | - {2{(e_state==`E_IRQ_3)}} | - {2{(e_state==`E_DST_WR)}} | - {2{(e_state==`E_SRC_WR)}}) & mb_wr_msk; - -// Memory address bus -assign mab = alu_out_add[15:0]; - -// Memory data bus output -reg [15:0] mdb_out_nxt; -always @(posedge mclk or posedge puc) - if (puc) mdb_out_nxt <= 16'h0000; - else if (e_state==`E_DST_RD) mdb_out_nxt <= pc_nxt; - else if ((e_state==`E_EXEC & ~inst_so[`CALL]) | - (e_state==`E_IRQ_0) | (e_state==`E_IRQ_2)) mdb_out_nxt <= alu_out; - -assign mdb_out = inst_bw ? {2{mdb_out_nxt[7:0]}} : mdb_out_nxt; - -// Format memory data bus input depending on BW -reg mab_lsb; -always @(posedge mclk or posedge puc) - if (puc) mab_lsb <= 1'b0; - else if (mb_en) mab_lsb <= alu_out_add[0]; - -assign mdb_in_bw = ~inst_bw ? mdb_in : - mab_lsb ? {2{mdb_in[15:8]}} : mdb_in; - -// Memory data bus input buffer (buffer after a source read) -reg mdb_in_buf_en; -always @(posedge mclk or posedge puc) - if (puc) mdb_in_buf_en <= 1'b0; - else mdb_in_buf_en <= (e_state==`E_SRC_RD); - -reg mdb_in_buf_valid; -always @(posedge mclk or posedge puc) - if (puc) mdb_in_buf_valid <= 1'b0; - else if (e_state==`E_EXEC) mdb_in_buf_valid <= 1'b0; - else if (mdb_in_buf_en) mdb_in_buf_valid <= 1'b1; - -reg [15:0] mdb_in_buf; -always @(posedge mclk or posedge puc) - if (puc) mdb_in_buf <= 16'h0000; - else if (mdb_in_buf_en) mdb_in_buf <= mdb_in_bw; - -assign mdb_in_val = mdb_in_buf_valid ? mdb_in_buf : mdb_in_bw; - - -endmodule // execution_unit - -`include "openMSP430_undefines.v"
execution_unit.v Property changes : Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Date Revision Author \ No newline at end of property Index: dbg_uart.v =================================================================== --- dbg_uart.v (revision 33) +++ dbg_uart.v (nonexistent) @@ -1,268 +0,0 @@ -//---------------------------------------------------------------------------- -// Copyright (C) 2001 Authors -// -// This source file may be used and distributed without restriction provided -// that this copyright statement is not removed from the file and that any -// derivative work contains the original copyright notice and the associated -// disclaimer. -// -// This source file is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This source is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -// License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this source; if not, write to the Free Software Foundation, -// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -//---------------------------------------------------------------------------- -// -// *File Name: dbg_uart.v -// -// *Module Description: -// Debug UART communication interface (8N1, Half-duplex) -// -// *Author(s): -// - Olivier Girard, olgirard@gmail.com -// -//---------------------------------------------------------------------------- -// $Rev$ -// $LastChangedBy$ -// $LastChangedDate$ -//---------------------------------------------------------------------------- -`include "timescale.v" -`include "openMSP430_defines.v" - -module dbg_uart ( - -// OUTPUTs - dbg_addr, // Debug register address - dbg_din, // Debug register data input - dbg_rd, // Debug register data read - dbg_uart_txd, // Debug interface: UART TXD - dbg_wr, // Debug register data write - -// INPUTs - dbg_dout, // Debug register data output - dbg_rd_rdy, // Debug register data is ready for read - dbg_uart_rxd, // Debug interface: UART RXD - mclk, // Main system clock - mem_burst, // Burst on going - mem_burst_end, // End TX/RX burst - mem_burst_rd, // Start TX burst - mem_burst_wr, // Start RX burst - mem_bw, // Burst byte width - por // Power on reset -); - -// OUTPUTs -//========= -output [5:0] dbg_addr; // Debug register address -output [15:0] dbg_din; // Debug register data input -output dbg_rd; // Debug register data read -output dbg_uart_txd; // Debug interface: UART TXD -output dbg_wr; // Debug register data write - -// INPUTs -//========= -input [15:0] dbg_dout; // Debug register data output -input dbg_rd_rdy; // Debug register data is ready for read -input dbg_uart_rxd; // Debug interface: UART RXD -input mclk; // Main system clock -input mem_burst; // Burst on going -input mem_burst_end; // End TX/RX burst -input mem_burst_rd; // Start TX burst -input mem_burst_wr; // Start RX burst -input mem_bw; // Burst byte width -input por; // Power on reset - - -//============================================================================= -// 1) UART RECEIVE LINE SYNCHRONIZTION & FILTERING -//============================================================================= - -// Synchronize RXD input & buffer -//-------------------------------- -reg [3:0] rxd_sync; -always @ (posedge mclk or posedge por) - if (por) rxd_sync <= 4'h0; - else rxd_sync <= {rxd_sync[2:0], dbg_uart_rxd}; - -// Majority decision -//------------------------ -reg rxd_maj; - -wire [1:0] rxd_maj_cnt = {1'b0, rxd_sync[1]} + - {1'b0, rxd_sync[2]} + - {1'b0, rxd_sync[3]}; -wire rxd_maj_nxt = (rxd_maj_cnt>=2'b10); - -always @ (posedge mclk or posedge por) - if (por) rxd_maj <= 1'b0; - else rxd_maj <= rxd_maj_nxt; - -wire rxd_s = rxd_maj; -wire rxd_fe = rxd_maj & ~rxd_maj_nxt; -wire rxd_re = ~rxd_maj & rxd_maj_nxt; - - -//============================================================================= -// 2) UART STATE MACHINE -//============================================================================= - -// Receive state -//------------------------ -reg [2:0] uart_state; -reg [2:0] uart_state_nxt; - -wire sync_done; -wire xfer_done; -reg [19:0] xfer_buf; - -// State machine definition -parameter RX_SYNC = 3'h0; -parameter RX_CMD = 3'h1; -parameter RX_DATA1 = 3'h2; -parameter RX_DATA2 = 3'h3; -parameter TX_DATA1 = 3'h4; -parameter TX_DATA2 = 3'h5; - -// State transition -always @(uart_state or xfer_buf or mem_burst or mem_burst_wr or mem_burst_rd or mem_burst_end or mem_bw) - case (uart_state) - RX_SYNC : uart_state_nxt = RX_CMD; - RX_CMD : uart_state_nxt = mem_burst_wr ? - (mem_bw ? RX_DATA2 : RX_DATA1) : - mem_burst_rd ? - (mem_bw ? TX_DATA2 : TX_DATA1) : - (xfer_buf[`DBG_UART_WR] ? - (xfer_buf[`DBG_UART_BW] ? RX_DATA2 : RX_DATA1) : - (xfer_buf[`DBG_UART_BW] ? TX_DATA2 : TX_DATA1)); - RX_DATA1 : uart_state_nxt = RX_DATA2; - RX_DATA2 : uart_state_nxt = (mem_burst & ~mem_burst_end) ? - (mem_bw ? RX_DATA2 : RX_DATA1) : - RX_CMD; - TX_DATA1 : uart_state_nxt = TX_DATA2; - TX_DATA2 : uart_state_nxt = (mem_burst & ~mem_burst_end) ? - (mem_bw ? TX_DATA2 : TX_DATA1) : - RX_CMD; - default : uart_state_nxt = RX_CMD; - endcase - -// State machine -always @(posedge mclk or posedge por) - if (por) uart_state <= RX_SYNC; - else if (xfer_done | sync_done | - mem_burst_wr | mem_burst_rd) uart_state <= uart_state_nxt; - -// Utility signals -wire cmd_valid = (uart_state==RX_CMD) & xfer_done; -wire tx_active = (uart_state==TX_DATA1) | (uart_state==TX_DATA2); - - -//============================================================================= -// 3) UART SYNCHRONIZATION -//============================================================================= -// After POR, the host needs to fist send a synchronization character (0x80) -// If this feature doesn't work properly, it is possible to disable it by -// commenting the DBG_UART_AUTO_SYNC define in the openMSP430.inc file. - -reg sync_busy; -always @ (posedge mclk or posedge por) - if (por) sync_busy <= 1'b0; - else if ((uart_state==RX_SYNC) & rxd_fe) sync_busy <= 1'b1; - else if ((uart_state==RX_SYNC) & rxd_re) sync_busy <= 1'b0; - -assign sync_done = (uart_state==RX_SYNC) & rxd_re & sync_busy; - -`ifdef DBG_UART_AUTO_SYNC - -reg [14:0] sync_cnt; -always @ (posedge mclk or posedge por) - if (por) sync_cnt <= 15'h7ff8; - else if (sync_busy) sync_cnt <= sync_cnt+15'h0001; - -wire [11:0] bit_cnt_max = sync_cnt[14:3]; -`else -wire [11:0] bit_cnt_max = `DBG_UART_CNT; -`endif - - -//============================================================================= -// 4) UART RECEIVE / TRANSMIT -//============================================================================= - -// Transfer counter -//------------------------ -reg [3:0] xfer_bit; -reg [11:0] xfer_cnt; - -wire txd_start = dbg_rd_rdy | (xfer_done & (uart_state==TX_DATA1)); -wire rxd_start = (xfer_bit==4'h0) & rxd_fe & ((uart_state!=RX_SYNC)); -wire xfer_bit_inc = (xfer_bit!=4'h0) & (xfer_cnt==12'h000); -assign xfer_done = (xfer_bit==4'hb); - -always @ (posedge mclk or posedge por) - if (por) xfer_bit <= 4'h0; - else if (txd_start | rxd_start) xfer_bit <= 4'h1; - else if (xfer_done) xfer_bit <= 4'h0; - else if (xfer_bit_inc) xfer_bit <= xfer_bit+4'h1; - -always @ (posedge mclk or posedge por) - if (por) xfer_cnt <= 12'h000; - else if (rxd_start) xfer_cnt <= {1'b0, bit_cnt_max[11:1]}; - else if (txd_start | xfer_bit_inc) xfer_cnt <= bit_cnt_max; - else xfer_cnt <= xfer_cnt+12'hfff; - - -// Receive/Transmit buffer -//------------------------- -wire [19:0] xfer_buf_nxt = {rxd_s, xfer_buf[19:1]}; - -always @ (posedge mclk or posedge por) - if (por) xfer_buf <= 18'h00000; - else if (dbg_rd_rdy) xfer_buf <= {1'b1, dbg_dout[15:8], 2'b01, dbg_dout[7:0], 1'b0}; - else if (xfer_bit_inc) xfer_buf <= xfer_buf_nxt; - - -// Generate TXD output -//------------------------ -reg dbg_uart_txd; - -always @ (posedge mclk or posedge por) - if (por) dbg_uart_txd <= 1'b1; - else if (xfer_bit_inc & tx_active) dbg_uart_txd <= xfer_buf[0]; - - -//============================================================================= -// 5) INTERFACE TO DEBUG REGISTERS -//============================================================================= - -reg [5:0] dbg_addr; - always @ (posedge mclk or posedge por) - if (por) dbg_addr <= 6'h00; - else if (cmd_valid) dbg_addr <= xfer_buf[`DBG_UART_ADDR]; - -reg dbg_bw; -always @ (posedge mclk or posedge por) - if (por) dbg_bw <= 1'b0; - else if (cmd_valid) dbg_bw <= xfer_buf[`DBG_UART_BW]; - -wire dbg_din_bw = mem_burst ? mem_bw : dbg_bw; - -wire [15:0] dbg_din = dbg_din_bw ? {8'h00, xfer_buf[18:11]} : - {xfer_buf[18:11], xfer_buf[8:1]}; -wire dbg_wr = (xfer_done & (uart_state==RX_DATA2)); -wire dbg_rd = mem_burst ? (xfer_done & (uart_state==TX_DATA2)) : - (cmd_valid & ~xfer_buf[`DBG_UART_WR]) | mem_burst_rd; - - - -endmodule // dbg_uart - -`include "openMSP430_undefines.v"
dbg_uart.v Property changes : Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Date Revision Author \ No newline at end of property Index: frontend.v =================================================================== --- frontend.v (revision 33) +++ frontend.v (nonexistent) @@ -1,758 +0,0 @@ -//---------------------------------------------------------------------------- -// Copyright (C) 2001 Authors -// -// This source file may be used and distributed without restriction provided -// that this copyright statement is not removed from the file and that any -// derivative work contains the original copyright notice and the associated -// disclaimer. -// -// This source file is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This source is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -// License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this source; if not, write to the Free Software Foundation, -// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -//---------------------------------------------------------------------------- -// -// *File Name: frontend.v -// -// *Module Description: -// openMSP430 Instruction fetch and decode unit -// -// *Author(s): -// - Olivier Girard, olgirard@gmail.com -// -//---------------------------------------------------------------------------- -// $Rev$ -// $LastChangedBy$ -// $LastChangedDate$ -//---------------------------------------------------------------------------- -`include "timescale.v" -`include "openMSP430_defines.v" - -module frontend ( - -// OUTPUTs - dbg_halt_st, // Halt/Run status from CPU - decode, // Frontend decode instruction - e_state, // Execution state - exec_done, // Execution completed - inst_ad, // Decoded Inst: destination addressing mode - inst_as, // Decoded Inst: source addressing mode - inst_alu, // ALU control signals - inst_bw, // Decoded Inst: byte width - inst_dest, // Decoded Inst: destination (one hot) - inst_dext, // Decoded Inst: destination extended instruction word - inst_irq_rst, // Decoded Inst: Reset interrupt - inst_jmp, // Decoded Inst: Conditional jump - inst_sext, // Decoded Inst: source extended instruction word - inst_so, // Decoded Inst: Single-operand arithmetic - inst_src, // Decoded Inst: source (one hot) - inst_type, // Decoded Instruction type - irq_acc, // Interrupt request accepted (one-hot signal) - mab, // Frontend Memory address bus - mb_en, // Frontend Memory bus enable - nmi_acc, // Non-Maskable interrupt request accepted - pc, // Program counter - pc_nxt, // Next PC value (for CALL & IRQ) - -// INPUTs - cpuoff, // Turns off the CPU - dbg_halt_cmd, // Halt CPU command - dbg_reg_sel, // Debug selected register for rd/wr access - fe_pmem_wait, // Frontend wait for Instruction fetch - gie, // General interrupt enable - irq, // Maskable interrupts - mclk, // Main system clock - mdb_in, // Frontend Memory data bus input - nmi_evt, // Non-maskable interrupt event - pc_sw, // Program counter software value - pc_sw_wr, // Program counter software write - puc, // Main system reset - wdt_irq // Watchdog-timer interrupt -); - -// OUTPUTs -//========= -output dbg_halt_st; // Halt/Run status from CPU -output decode; // Frontend decode instruction -output [3:0] e_state; // Execution state -output exec_done; // Execution completed -output [7:0] inst_ad; // Decoded Inst: destination addressing mode -output [7:0] inst_as; // Decoded Inst: source addressing mode -output [11:0] inst_alu; // ALU control signals -output inst_bw; // Decoded Inst: byte width -output [15:0] inst_dest; // Decoded Inst: destination (one hot) -output [15:0] inst_dext; // Decoded Inst: destination extended instruction word -output inst_irq_rst; // Decoded Inst: Reset interrupt -output [7:0] inst_jmp; // Decoded Inst: Conditional jump -output [15:0] inst_sext; // Decoded Inst: source extended instruction word -output [7:0] inst_so; // Decoded Inst: Single-operand arithmetic -output [15:0] inst_src; // Decoded Inst: source (one hot) -output [2:0] inst_type; // Decoded Instruction type -output [13:0] irq_acc; // Interrupt request accepted (one-hot signal) -output [15:0] mab; // Frontend Memory address bus -output mb_en; // Frontend Memory bus enable -output nmi_acc; // Non-Maskable interrupt request accepted -output [15:0] pc; // Program counter -output [15:0] pc_nxt; // Next PC value (for CALL & IRQ) - -// INPUTs -//========= -input cpuoff; // Turns off the CPU -input dbg_halt_cmd; // Halt CPU command -input [3:0] dbg_reg_sel; // Debug selected register for rd/wr access -input fe_pmem_wait; // Frontend wait for Instruction fetch -input gie; // General interrupt enable -input [13:0] irq; // Maskable interrupts -input mclk; // Main system clock -input [15:0] mdb_in; // Frontend Memory data bus input -input nmi_evt; // Non-maskable interrupt event -input [15:0] pc_sw; // Program counter software value -input pc_sw_wr; // Program counter software write -input puc; // Main system reset -input wdt_irq; // Watchdog-timer interrupt - - -//============================================================================= -// 1) FRONTEND STATE MACHINE -//============================================================================= - -// The wire "conv" is used as state bits to calculate the next response -reg [2:0] i_state; -reg [2:0] i_state_nxt; - -reg [1:0] inst_sz; -wire [1:0] inst_sz_nxt; -wire irq_detect; -wire [2:0] inst_type_nxt; -wire is_const; -reg [15:0] sconst_nxt; -reg [3:0] e_state_nxt; - -// State machine definitons -parameter I_IRQ_FETCH = 3'h0; -parameter I_IRQ_DONE = 3'h1; -parameter I_DEC = 3'h2; // New instruction ready for decode -parameter I_EXT1 = 3'h3; // 1st Extension word -parameter I_EXT2 = 3'h4; // 2nd Extension word -parameter I_IDLE = 3'h5; // CPU is in IDLE mode - -// States Transitions -always @(i_state or inst_sz or inst_sz_nxt or pc_sw_wr or exec_done or - exec_done or irq_detect or cpuoff or dbg_halt_cmd or e_state) - case(i_state) - I_IDLE : i_state_nxt = (irq_detect & ~dbg_halt_cmd) ? I_IRQ_FETCH : - (~cpuoff & ~dbg_halt_cmd) ? I_DEC : I_IDLE; - I_IRQ_FETCH: i_state_nxt = I_IRQ_DONE; - I_IRQ_DONE : i_state_nxt = I_DEC; - I_DEC : i_state_nxt = irq_detect ? I_IRQ_FETCH : - (cpuoff | dbg_halt_cmd) & exec_done ? I_IDLE : - dbg_halt_cmd & (e_state==`E_IDLE) ? I_IDLE : - pc_sw_wr ? I_DEC : - ~exec_done & ~(e_state==`E_IDLE) ? I_DEC : // Wait in decode state - (inst_sz_nxt!=2'b00) ? I_EXT1 : I_DEC; // until execution is completed - I_EXT1 : i_state_nxt = irq_detect ? I_IRQ_FETCH : - pc_sw_wr ? I_DEC : - (inst_sz!=2'b01) ? I_EXT2 : I_DEC; - I_EXT2 : i_state_nxt = irq_detect ? I_IRQ_FETCH : I_DEC; - default : i_state_nxt = I_IRQ_FETCH; - endcase - -// State machine -always @(posedge mclk or posedge puc) - if (puc) i_state <= I_IRQ_FETCH; - else i_state <= i_state_nxt; - -// Utility signals -wire decode = ((i_state==I_DEC) & (exec_done | (e_state==`E_IDLE))) | irq_detect; -wire fetch = ~((i_state==I_DEC) & ~(exec_done | (e_state==`E_IDLE))) & ~(e_state_nxt==`E_IDLE); - -// Debug interface cpu status -reg dbg_halt_st; -always @(posedge mclk or posedge puc) - if (puc) dbg_halt_st <= 1'b0; - else dbg_halt_st <= dbg_halt_cmd & (i_state_nxt==I_IDLE); - - -//============================================================================= -// 2) INTERRUPT HANDLING -//============================================================================= - -// Detect nmi interrupt -reg inst_nmi; -always @(posedge mclk or posedge puc) - if (puc) inst_nmi <= 1'b0; - else if (nmi_evt) inst_nmi <= 1'b1; - else if (i_state==I_IRQ_DONE) inst_nmi <= 1'b0; - - -// Detect reset interrupt -reg inst_irq_rst; -always @(posedge mclk or posedge puc) - if (puc) inst_irq_rst <= 1'b1; - else if (exec_done) inst_irq_rst <= 1'b0; - -// Detect other interrupts -assign irq_detect = (inst_nmi | ((|irq | wdt_irq) & gie)) & ~dbg_halt_cmd & (exec_done | (i_state==I_IDLE)); - -// Select interrupt vector -reg [3:0] irq_num; -always @(posedge mclk or posedge puc) - if (puc) irq_num <= 4'hf; - else if (irq_detect) irq_num <= inst_nmi ? 4'he : - irq[13] ? 4'hd : - irq[12] ? 4'hc : - irq[11] ? 4'hb : - (irq[10] | wdt_irq) ? 4'ha : - irq[9] ? 4'h9 : - irq[8] ? 4'h8 : - irq[7] ? 4'h7 : - irq[6] ? 4'h6 : - irq[5] ? 4'h5 : - irq[4] ? 4'h4 : - irq[3] ? 4'h3 : - irq[2] ? 4'h2 : - irq[1] ? 4'h1 : - irq[0] ? 4'h0 : 4'hf; - -wire [15:0] irq_addr = {11'h7ff, irq_num, 1'b0}; - -// Interrupt request accepted -wire [15:0] irq_acc_all = (16'h0001 << irq_num) & {16{(i_state==I_IRQ_FETCH)}}; -wire [13:0] irq_acc = irq_acc_all[13:0]; -wire nmi_acc = irq_acc_all[14]; - - -//============================================================================= -// 3) FETCH INSTRUCTION -//============================================================================= - -// -// 3.1) PROGRAM COUNTER & MEMORY INTERFACE -//----------------------------------------- - -// Program counter -reg [15:0] pc; - -// Detect if PC needs to be incremented -wire pc_inc = (~pc_sw_wr & fetch) & ~(i_state==I_IRQ_FETCH) & ~(i_state==I_IRQ_DONE); - -// Mux between software update and old PC -wire [15:0] pc_sel = pc_sw_wr ? pc_sw : - (i_state==I_IRQ_FETCH) ? irq_addr : - (i_state==I_IRQ_DONE) ? mdb_in : pc; - -// Compute next PC value -wire [15:0] pc_nxt = pc_sel + {14'h0000, pc_inc, 1'b0}; - -always @(posedge mclk or posedge puc) - if (puc) pc <= 16'h0000; - else pc <= pc_nxt; - -// Check if ROM has been busy in order to retry ROM access -reg pmem_busy; -always @(posedge mclk or posedge puc) - if (puc) pmem_busy <= 16'h0000; - else pmem_busy <= fe_pmem_wait; - -// Memory interface -wire [15:0] mab = pc_nxt; -wire mb_en = fetch | pc_sw_wr | (i_state==I_IRQ_FETCH) | pmem_busy | (dbg_halt_st & ~dbg_halt_cmd); - - -// -// 3.2) INSTRUCTION REGISTER -//-------------------------------- - -// Instruction register -wire [15:0] ir = mdb_in; - -// Detect if source extension word is required -wire is_sext = (inst_as[`IDX] | inst_as[`SYMB] | inst_as[`ABS] | inst_as[`IMM]); - -// Detect if destination extension word is required -wire is_dext = (inst_ad[`IDX] | inst_ad[`SYMB] | inst_ad[`ABS]); - -// For the Symbolic addressing mode, add -2 to the extension word in order -// to make up for the PC address -wire [15:0] ext_incr = ((i_state==I_EXT1) & inst_as[`SYMB]) | - ((i_state==I_EXT2) & inst_ad[`SYMB]) | - ((i_state==I_EXT1) & ~inst_as[`SYMB] & - ~(i_state_nxt==I_EXT2) & inst_ad[`SYMB]) ? 16'hfffe : 16'h0000; - -wire [15:0] ext_nxt = ir + ext_incr; - -// Store source extension word -reg [15:0] inst_sext; -always @(posedge mclk or posedge puc) - if (puc) inst_sext <= 16'h0000; - else if (decode & is_const) inst_sext <= sconst_nxt; - else if (decode & inst_type_nxt[`INST_JMP]) inst_sext <= {{5{ir[9]}},ir[9:0],1'b0}; - else if ((i_state==I_EXT1) & is_sext) inst_sext <= ext_nxt; - -// Source extension word is ready -wire inst_sext_rdy = (i_state==I_EXT1) & is_sext; - - -// Store destination extension word -reg [15:0] inst_dext; -always @(posedge mclk or posedge puc) - if (puc) inst_dext <= 16'h0000; - else if ((i_state==I_EXT1) & ~is_sext) inst_dext <= ext_nxt; - else if (i_state==I_EXT2) inst_dext <= ext_nxt; - -// Destination extension word is ready -wire inst_dext_rdy = (((i_state==I_EXT1) & ~is_sext) | (i_state==I_EXT2)); - - -//============================================================================= -// 4) DECODE INSTRUCTION -//============================================================================= - -// -// 4.1) OPCODE: INSTRUCTION TYPE -//---------------------------------------- -// Instructions type is encoded in a one hot fashion as following: -// -// 3'b001: Single-operand arithmetic -// 3'b010: Conditional jump -// 3'b100: Two-operand arithmetic - -reg [2:0] inst_type; -assign inst_type_nxt = {(ir[15:14]!=2'b00), - (ir[15:13]==3'b001), - (ir[15:13]==3'b000)} & {3{~irq_detect}}; - -always @(posedge mclk or posedge puc) - if (puc) inst_type <= 3'b000; - else if (decode) inst_type <= inst_type_nxt; - -// -// 4.2) OPCODE: SINGLE-OPERAND ARITHMETIC -//---------------------------------------- -// Instructions are encoded in a one hot fashion as following: -// -// 8'b00000001: RRC -// 8'b00000010: SWPB -// 8'b00000100: RRA -// 8'b00001000: SXT -// 8'b00010000: PUSH -// 8'b00100000: CALL -// 8'b01000000: RETI -// 8'b10000000: IRQ - -reg [7:0] inst_so; -wire [7:0] inst_so_nxt = irq_detect ? 8'h80 : ((8'h01<
frontend.v Property changes : Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Date Revision Author \ No newline at end of property Index: dbg.v =================================================================== --- dbg.v (revision 33) +++ dbg.v (nonexistent) @@ -1,792 +0,0 @@ -//---------------------------------------------------------------------------- -// Copyright (C) 2001 Authors -// -// This source file may be used and distributed without restriction provided -// that this copyright statement is not removed from the file and that any -// derivative work contains the original copyright notice and the associated -// disclaimer. -// -// This source file is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This source is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -// License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this source; if not, write to the Free Software Foundation, -// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -//---------------------------------------------------------------------------- -// -// *File Name: dbg.v -// -// *Module Description: -// Debug interface -// -// *Author(s): -// - Olivier Girard, olgirard@gmail.com -// -//---------------------------------------------------------------------------- -// $Rev$ -// $LastChangedBy$ -// $LastChangedDate$ -//---------------------------------------------------------------------------- -`include "timescale.v" -`include "openMSP430_defines.v" - -module dbg ( - -// OUTPUTs - dbg_freeze, // Freeze peripherals - dbg_halt_cmd, // Halt CPU command - dbg_mem_addr, // Debug address for rd/wr access - dbg_mem_dout, // Debug unit data output - dbg_mem_en, // Debug unit memory enable - dbg_mem_wr, // Debug unit memory write - dbg_reg_wr, // Debug unit CPU register write - dbg_reset, // Reset CPU from debug interface - dbg_uart_txd, // Debug interface: UART TXD - -// INPUTs - dbg_halt_st, // Halt/Run status from CPU - dbg_mem_din, // Debug unit Memory data input - dbg_reg_din, // Debug unit CPU register data input - dbg_uart_rxd, // Debug interface: UART RXD - decode, // Frontend decode instruction - eu_mab, // Execution-Unit Memory address bus - eu_mb_en, // Execution-Unit Memory bus enable - eu_mb_wr, // Execution-Unit Memory bus write transfer - eu_mdb_in, // Memory data bus input - eu_mdb_out, // Memory data bus output - exec_done, // Execution completed - fe_mb_en, // Frontend Memory bus enable - fe_mdb_in, // Frontend Memory data bus input - mclk, // Main system clock - pc, // Program counter - por, // Power on reset - puc // Main system reset -); - -// OUTPUTs -//========= -output dbg_freeze; // Freeze peripherals -output dbg_halt_cmd; // Halt CPU command -output [15:0] dbg_mem_addr; // Debug address for rd/wr access -output [15:0] dbg_mem_dout; // Debug unit data output -output dbg_mem_en; // Debug unit memory enable -output [1:0] dbg_mem_wr; // Debug unit memory write -output dbg_reg_wr; // Debug unit CPU register write -output dbg_reset; // Reset CPU from debug interface -output dbg_uart_txd; // Debug interface: UART TXD - -// INPUTs -//========= -input dbg_halt_st; // Halt/Run status from CPU -input [15:0] dbg_mem_din; // Debug unit Memory data input -input [15:0] dbg_reg_din; // Debug unit CPU register data input -input dbg_uart_rxd; // Debug interface: UART RXD -input decode; // Frontend decode instruction -input [15:0] eu_mab; // Execution-Unit Memory address bus -input eu_mb_en; // Execution-Unit Memory bus enable -input [1:0] eu_mb_wr; // Execution-Unit Memory bus write transfer -input [15:0] eu_mdb_in; // Memory data bus input -input [15:0] eu_mdb_out; // Memory data bus output -input exec_done; // Execution completed -input fe_mb_en; // Frontend Memory bus enable -input [15:0] fe_mdb_in; // Frontend Memory data bus input -input mclk; // Main system clock -input [15:0] pc; // Program counter -input por; // Power on reset -input puc; // Main system reset - - -//============================================================================= -// 1) WIRE & PARAMETER DECLARATION -//============================================================================= - -// Diverse wires and registers -wire [5:0] dbg_addr; -wire [15:0] dbg_din; -wire dbg_wr; -reg mem_burst; -wire dbg_reg_rd; -wire dbg_mem_rd; -reg dbg_mem_rd_dly; -wire dbg_swbrk; -wire dbg_rd; -reg dbg_rd_rdy; -wire mem_burst_rd; -wire mem_burst_wr; -wire brk0_halt; -wire brk0_pnd; -wire [15:0] brk0_dout; -wire brk1_halt; -wire brk1_pnd; -wire [15:0] brk1_dout; -wire brk2_halt; -wire brk2_pnd; -wire [15:0] brk2_dout; -wire brk3_halt; -wire brk3_pnd; -wire [15:0] brk3_dout; - -// Register addresses -parameter CPU_ID_LO = 6'h00; -parameter CPU_ID_HI = 6'h01; -parameter CPU_CTL = 6'h02; -parameter CPU_STAT = 6'h03; -parameter MEM_CTL = 6'h04; -parameter MEM_ADDR = 6'h05; -parameter MEM_DATA = 6'h06; -parameter MEM_CNT = 6'h07; -`ifdef DBG_HWBRK_0 -parameter BRK0_CTL = 6'h08; -parameter BRK0_STAT = 6'h09; -parameter BRK0_ADDR0 = 6'h0A; -parameter BRK0_ADDR1 = 6'h0B; -`endif -`ifdef DBG_HWBRK_1 -parameter BRK1_CTL = 6'h0C; -parameter BRK1_STAT = 6'h0D; -parameter BRK1_ADDR0 = 6'h0E; -parameter BRK1_ADDR1 = 6'h0F; -`endif -`ifdef DBG_HWBRK_2 -parameter BRK2_CTL = 6'h10; -parameter BRK2_STAT = 6'h11; -parameter BRK2_ADDR0 = 6'h12; -parameter BRK2_ADDR1 = 6'h13; -`endif -`ifdef DBG_HWBRK_3 -parameter BRK3_CTL = 6'h14; -parameter BRK3_STAT = 6'h15; -parameter BRK3_ADDR0 = 6'h16; -parameter BRK3_ADDR1 = 6'h17; -`endif - -// Register one-hot decoder -parameter CPU_ID_LO_D = (64'h1 << CPU_ID_LO); -parameter CPU_ID_HI_D = (64'h1 << CPU_ID_HI); -parameter CPU_CTL_D = (64'h1 << CPU_CTL); -parameter CPU_STAT_D = (64'h1 << CPU_STAT); -parameter MEM_CTL_D = (64'h1 << MEM_CTL); -parameter MEM_ADDR_D = (64'h1 << MEM_ADDR); -parameter MEM_DATA_D = (64'h1 << MEM_DATA); -parameter MEM_CNT_D = (64'h1 << MEM_CNT); -`ifdef DBG_HWBRK_0 -parameter BRK0_CTL_D = (64'h1 << BRK0_CTL); -parameter BRK0_STAT_D = (64'h1 << BRK0_STAT); -parameter BRK0_ADDR0_D = (64'h1 << BRK0_ADDR0); -parameter BRK0_ADDR1_D = (64'h1 << BRK0_ADDR1); -`endif -`ifdef DBG_HWBRK_1 -parameter BRK1_CTL_D = (64'h1 << BRK1_CTL); -parameter BRK1_STAT_D = (64'h1 << BRK1_STAT); -parameter BRK1_ADDR0_D = (64'h1 << BRK1_ADDR0); -parameter BRK1_ADDR1_D = (64'h1 << BRK1_ADDR1); -`endif -`ifdef DBG_HWBRK_2 -parameter BRK2_CTL_D = (64'h1 << BRK2_CTL); -parameter BRK2_STAT_D = (64'h1 << BRK2_STAT); -parameter BRK2_ADDR0_D = (64'h1 << BRK2_ADDR0); -parameter BRK2_ADDR1_D = (64'h1 << BRK2_ADDR1); -`endif -`ifdef DBG_HWBRK_3 -parameter BRK3_CTL_D = (64'h1 << BRK3_CTL); -parameter BRK3_STAT_D = (64'h1 << BRK3_STAT); -parameter BRK3_ADDR0_D = (64'h1 << BRK3_ADDR0); -parameter BRK3_ADDR1_D = (64'h1 << BRK3_ADDR1); -`endif - - -//============================================================================ -// 2) REGISTER DECODER -//============================================================================ - -// Select Data register during a burst -wire [5:0] dbg_addr_in = mem_burst ? MEM_DATA : dbg_addr; - -// Register address decode -reg [63:0] reg_dec; -always @(dbg_addr_in) - case (dbg_addr_in) - CPU_ID_LO : reg_dec = CPU_ID_LO_D; - CPU_ID_HI : reg_dec = CPU_ID_HI_D; - CPU_CTL : reg_dec = CPU_CTL_D; - CPU_STAT : reg_dec = CPU_STAT_D; - MEM_CTL : reg_dec = MEM_CTL_D; - MEM_ADDR : reg_dec = MEM_ADDR_D; - MEM_DATA : reg_dec = MEM_DATA_D; - MEM_CNT : reg_dec = MEM_CNT_D; -`ifdef DBG_HWBRK_0 - BRK0_CTL : reg_dec = BRK0_CTL_D; - BRK0_STAT : reg_dec = BRK0_STAT_D; - BRK0_ADDR0: reg_dec = BRK0_ADDR0_D; - BRK0_ADDR1: reg_dec = BRK0_ADDR1_D; -`endif -`ifdef DBG_HWBRK_1 - BRK1_CTL : reg_dec = BRK1_CTL_D; - BRK1_STAT : reg_dec = BRK1_STAT_D; - BRK1_ADDR0: reg_dec = BRK1_ADDR0_D; - BRK1_ADDR1: reg_dec = BRK1_ADDR1_D; -`endif -`ifdef DBG_HWBRK_2 - BRK2_CTL : reg_dec = BRK2_CTL_D; - BRK2_STAT : reg_dec = BRK2_STAT_D; - BRK2_ADDR0: reg_dec = BRK2_ADDR0_D; - BRK2_ADDR1: reg_dec = BRK2_ADDR1_D; -`endif -`ifdef DBG_HWBRK_3 - BRK3_CTL : reg_dec = BRK3_CTL_D; - BRK3_STAT : reg_dec = BRK3_STAT_D; - BRK3_ADDR0: reg_dec = BRK3_ADDR0_D; - BRK3_ADDR1: reg_dec = BRK3_ADDR1_D; -`endif - default: reg_dec = {64{1'b0}}; - endcase - -// Read/Write probes -wire reg_write = dbg_wr; -wire reg_read = 1'b1; - -// Read/Write vectors -wire [511:0] reg_wr = reg_dec & {64{reg_write}}; -wire [511:0] reg_rd = reg_dec & {64{reg_read}}; - - -//============================================================================= -// 3) REGISTER: CORE INTERFACE -//============================================================================= - -// CPU_ID Register -//----------------- - -wire [3:0] cpu_id_pmem = `PMEM_AWIDTH; -wire [3:0] cpu_id_dmem = `DMEM_AWIDTH; -wire [31:0] cpu_id = {`DBG_ID, cpu_id_pmem, cpu_id_dmem}; - - -// CPU_CTL Register -//----------------------------------------------------------------------------- -// 7 6 5 4 3 2 1 0 -// Reserved CPU_RST RST_BRK_EN FRZ_BRK_EN SW_BRK_EN ISTEP RUN HALT -//----------------------------------------------------------------------------- -reg [6:3] cpu_ctl; - -wire cpu_ctl_wr = reg_wr[CPU_CTL]; - -always @ (posedge mclk or posedge por) - if (por) cpu_ctl <= 4'h0; - else if (cpu_ctl_wr) cpu_ctl <= dbg_din[6:3]; - -wire [7:0] cpu_ctl_full = {1'b0, cpu_ctl, 3'b000}; - -wire halt_cpu = cpu_ctl_wr & dbg_din[`HALT] & ~dbg_halt_st; -wire run_cpu = cpu_ctl_wr & dbg_din[`RUN] & dbg_halt_st; -wire istep = cpu_ctl_wr & dbg_din[`ISTEP] & dbg_halt_st; - - -// CPU_STAT Register -//------------------------------------------------------------------------------------ -// 7 6 5 4 3 2 1 0 -// HWBRK3_PND HWBRK2_PND HWBRK1_PND HWBRK0_PND SWBRK_PND PUC_PND Res. HALT_RUN -//------------------------------------------------------------------------------------ -reg [3:2] cpu_stat; - -wire cpu_stat_wr = reg_wr[CPU_STAT]; -wire [3:2] cpu_stat_set = {dbg_swbrk, puc}; -wire [3:2] cpu_stat_clr = ~dbg_din[3:2]; - -always @ (posedge mclk or posedge por) - if (por) cpu_stat <= 2'b00; - else if (cpu_stat_wr) cpu_stat <= ((cpu_stat & cpu_stat_clr) | cpu_stat_set); - else cpu_stat <= (cpu_stat | cpu_stat_set); - -wire [7:0] cpu_stat_full = {brk3_pnd, brk2_pnd, brk1_pnd, brk0_pnd, - cpu_stat, 1'b0, dbg_halt_st}; - - -//============================================================================= -// 4) REGISTER: MEMORY INTERFACE -//============================================================================= - -// MEM_CTL Register -//----------------------------------------------------------------------------- -// 7 6 5 4 3 2 1 0 -// Reserved B/W MEM/REG RD/WR START -// -// START : - 0 : Do nothing. -// - 1 : Initiate memory transfer. -// -// RD/WR : - 0 : Read access. -// - 1 : Write access. -// -// MEM/REG: - 0 : Memory access. -// - 1 : CPU Register access. -// -// B/W : - 0 : 16 bit access. -// - 1 : 8 bit access (not valid for CPU Registers). -// -//----------------------------------------------------------------------------- -reg [3:1] mem_ctl; - -wire mem_ctl_wr = reg_wr[MEM_CTL]; - -always @ (posedge mclk or posedge por) - if (por) mem_ctl <= 3'h0; - else if (mem_ctl_wr) mem_ctl <= dbg_din[3:1]; - -wire [7:0] mem_ctl_full = {4'b0000, mem_ctl, 1'b0}; - -reg mem_start; -always @ (posedge mclk or posedge por) - if (por) mem_start <= 1'b0; - else mem_start <= mem_ctl_wr & dbg_din[0]; - -wire mem_bw = mem_ctl[3]; - -// MEM_DATA Register -//------------------ -reg [15:0] mem_data; -reg [15:0] mem_addr; -wire mem_access; - -wire mem_data_wr = reg_wr[MEM_DATA]; - -wire [15:0] dbg_mem_din_bw = ~mem_bw ? dbg_mem_din : - mem_addr[0] ? {8'h00, dbg_mem_din[15:8]} : - {8'h00, dbg_mem_din[7:0]}; - -always @ (posedge mclk or posedge por) - if (por) mem_data <= 16'h0000; - else if (mem_data_wr) mem_data <= dbg_din; - else if (dbg_reg_rd) mem_data <= dbg_reg_din; - else if (dbg_mem_rd_dly) mem_data <= dbg_mem_din_bw; - - -// MEM_ADDR Register -//------------------ -reg [15:0] mem_cnt; - -wire mem_addr_wr = reg_wr[MEM_ADDR]; -wire dbg_mem_acc = (|dbg_mem_wr | (dbg_rd_rdy & ~mem_ctl[2])); -wire dbg_reg_acc = ( dbg_reg_wr | (dbg_rd_rdy & mem_ctl[2])); - -wire [15:0] mem_addr_inc = (mem_cnt==16'h0000) ? 16'h0000 : - (dbg_mem_acc & ~mem_bw) ? 16'h0002 : - (dbg_mem_acc | dbg_reg_acc) ? 16'h0001 : 16'h0000; - -always @ (posedge mclk or posedge por) - if (por) mem_addr <= 16'h0000; - else if (mem_addr_wr) mem_addr <= dbg_din; - else mem_addr <= mem_addr + mem_addr_inc; - -// MEM_CNT Register -//------------------ - -wire mem_cnt_wr = reg_wr[MEM_CNT]; - -wire [15:0] mem_cnt_dec = (mem_cnt==16'h0000) ? 16'h0000 : - (dbg_mem_acc | dbg_reg_acc) ? 16'hffff : 16'h0000; - -always @ (posedge mclk or posedge por) - if (por) mem_cnt <= 16'h0000; - else if (mem_cnt_wr) mem_cnt <= dbg_din; - else mem_cnt <= mem_cnt + mem_cnt_dec; - - -//============================================================================= -// 5) BREAKPOINTS / WATCHPOINTS -//============================================================================= - -`ifdef DBG_HWBRK_0 -// Hardware Breakpoint/Watchpoint Register read select -wire [3:0] brk0_reg_rd = {reg_rd[BRK0_ADDR1], - reg_rd[BRK0_ADDR0], - reg_rd[BRK0_STAT], - reg_rd[BRK0_CTL]}; - -// Hardware Breakpoint/Watchpoint Register write select -wire [3:0] brk0_reg_wr = {reg_wr[BRK0_ADDR1], - reg_wr[BRK0_ADDR0], - reg_wr[BRK0_STAT], - reg_wr[BRK0_CTL]}; - -dbg_hwbrk dbg_hwbr_0 ( - -// OUTPUTs - .brk_halt (brk0_halt), // Hardware breakpoint command - .brk_pnd (brk0_pnd), // Hardware break/watch-point pending - .brk_dout (brk0_dout), // Hardware break/watch-point register data input - -// INPUTs - .brk_reg_rd (brk0_reg_rd), // Hardware break/watch-point register read select - .brk_reg_wr (brk0_reg_wr), // Hardware break/watch-point register write select - .dbg_din (dbg_din), // Debug register data input - .eu_mab (eu_mab), // Execution-Unit Memory address bus - .eu_mb_en (eu_mb_en), // Execution-Unit Memory bus enable - .eu_mb_wr (eu_mb_wr), // Execution-Unit Memory bus write transfer - .eu_mdb_in (eu_mdb_in), // Memory data bus input - .eu_mdb_out (eu_mdb_out), // Memory data bus output - .exec_done (exec_done), // Execution completed - .fe_mb_en (fe_mb_en), // Frontend Memory bus enable - .mclk (mclk), // Main system clock - .pc (pc), // Program counter - .por (por) // Power on reset -); - -`else -assign brk0_halt = 1'b0; -assign brk0_pnd = 1'b0; -assign brk0_dout = 16'h0000; -`endif - -`ifdef DBG_HWBRK_1 -// Hardware Breakpoint/Watchpoint Register read select -wire [3:0] brk1_reg_rd = {reg_rd[BRK1_ADDR1], - reg_rd[BRK1_ADDR0], - reg_rd[BRK1_STAT], - reg_rd[BRK1_CTL]}; - -// Hardware Breakpoint/Watchpoint Register write select -wire [3:0] brk1_reg_wr = {reg_wr[BRK1_ADDR1], - reg_wr[BRK1_ADDR0], - reg_wr[BRK1_STAT], - reg_wr[BRK1_CTL]}; - -dbg_hwbrk dbg_hwbr_1 ( - -// OUTPUTs - .brk_halt (brk1_halt), // Hardware breakpoint command - .brk_pnd (brk1_pnd), // Hardware break/watch-point pending - .brk_dout (brk1_dout), // Hardware break/watch-point register data input - -// INPUTs - .brk_reg_rd (brk1_reg_rd), // Hardware break/watch-point register read select - .brk_reg_wr (brk1_reg_wr), // Hardware break/watch-point register write select - .dbg_din (dbg_din), // Debug register data input - .eu_mab (eu_mab), // Execution-Unit Memory address bus - .eu_mb_en (eu_mb_en), // Execution-Unit Memory bus enable - .eu_mb_wr (eu_mb_wr), // Execution-Unit Memory bus write transfer - .eu_mdb_in (eu_mdb_in), // Memory data bus input - .eu_mdb_out (eu_mdb_out), // Memory data bus output - .exec_done (exec_done), // Execution completed - .fe_mb_en (fe_mb_en), // Frontend Memory bus enable - .mclk (mclk), // Main system clock - .pc (pc), // Program counter - .por (por) // Power on reset -); - -`else -assign brk1_halt = 1'b0; -assign brk1_pnd = 1'b0; -assign brk1_dout = 16'h0000; -`endif - - `ifdef DBG_HWBRK_2 -// Hardware Breakpoint/Watchpoint Register read select -wire [3:0] brk2_reg_rd = {reg_rd[BRK2_ADDR1], - reg_rd[BRK2_ADDR0], - reg_rd[BRK2_STAT], - reg_rd[BRK2_CTL]}; - -// Hardware Breakpoint/Watchpoint Register write select -wire [3:0] brk2_reg_wr = {reg_wr[BRK2_ADDR1], - reg_wr[BRK2_ADDR0], - reg_wr[BRK2_STAT], - reg_wr[BRK2_CTL]}; - -dbg_hwbrk dbg_hwbr_2 ( - -// OUTPUTs - .brk_halt (brk2_halt), // Hardware breakpoint command - .brk_pnd (brk2_pnd), // Hardware break/watch-point pending - .brk_dout (brk2_dout), // Hardware break/watch-point register data input - -// INPUTs - .brk_reg_rd (brk2_reg_rd), // Hardware break/watch-point register read select - .brk_reg_wr (brk2_reg_wr), // Hardware break/watch-point register write select - .dbg_din (dbg_din), // Debug register data input - .eu_mab (eu_mab), // Execution-Unit Memory address bus - .eu_mb_en (eu_mb_en), // Execution-Unit Memory bus enable - .eu_mb_wr (eu_mb_wr), // Execution-Unit Memory bus write transfer - .eu_mdb_in (eu_mdb_in), // Memory data bus input - .eu_mdb_out (eu_mdb_out), // Memory data bus output - .exec_done (exec_done), // Execution completed - .fe_mb_en (fe_mb_en), // Frontend Memory bus enable - .mclk (mclk), // Main system clock - .pc (pc), // Program counter - .por (por) // Power on reset -); - -`else -assign brk2_halt = 1'b0; -assign brk2_pnd = 1'b0; -assign brk2_dout = 16'h0000; -`endif - -`ifdef DBG_HWBRK_3 -// Hardware Breakpoint/Watchpoint Register read select -wire [3:0] brk3_reg_rd = {reg_rd[BRK3_ADDR1], - reg_rd[BRK3_ADDR0], - reg_rd[BRK3_STAT], - reg_rd[BRK3_CTL]}; - -// Hardware Breakpoint/Watchpoint Register write select -wire [3:0] brk3_reg_wr = {reg_wr[BRK3_ADDR1], - reg_wr[BRK3_ADDR0], - reg_wr[BRK3_STAT], - reg_wr[BRK3_CTL]}; - -dbg_hwbrk dbg_hwbr_3 ( - -// OUTPUTs - .brk_halt (brk3_halt), // Hardware breakpoint command - .brk_pnd (brk3_pnd), // Hardware break/watch-point pending - .brk_dout (brk3_dout), // Hardware break/watch-point register data input - -// INPUTs - .brk_reg_rd (brk3_reg_rd), // Hardware break/watch-point register read select - .brk_reg_wr (brk3_reg_wr), // Hardware break/watch-point register write select - .dbg_din (dbg_din), // Debug register data input - .eu_mab (eu_mab), // Execution-Unit Memory address bus - .eu_mb_en (eu_mb_en), // Execution-Unit Memory bus enable - .eu_mb_wr (eu_mb_wr), // Execution-Unit Memory bus write transfer - .eu_mdb_in (eu_mdb_in), // Memory data bus input - .eu_mdb_out (eu_mdb_out), // Memory data bus output - .exec_done (exec_done), // Execution completed - .fe_mb_en (fe_mb_en), // Frontend Memory bus enable - .mclk (mclk), // Main system clock - .pc (pc), // Program counter - .por (por) // Power on reset -); - -`else -assign brk3_halt = 1'b0; -assign brk3_pnd = 1'b0; -assign brk3_dout = 16'h0000; -`endif - - -//============================================================================ -// 6) DATA OUTPUT GENERATION -//============================================================================ - -wire [15:0] cpu_id_lo_rd = cpu_id[15:0] & {16{reg_rd[CPU_ID_LO]}}; -wire [15:0] cpu_id_hi_rd = cpu_id[31:16] & {16{reg_rd[CPU_ID_HI]}}; -wire [15:0] cpu_ctl_rd = {8'h00, cpu_ctl_full} & {16{reg_rd[CPU_CTL]}}; -wire [15:0] cpu_stat_rd = {8'h00, cpu_stat_full} & {16{reg_rd[CPU_STAT]}}; -wire [15:0] mem_ctl_rd = {8'h00, mem_ctl_full} & {16{reg_rd[MEM_CTL]}}; -wire [15:0] mem_data_rd = mem_data & {16{reg_rd[MEM_DATA]}}; -wire [15:0] mem_addr_rd = mem_addr & {16{reg_rd[MEM_ADDR]}}; -wire [15:0] mem_cnt_rd = mem_cnt & {16{reg_rd[MEM_CNT]}}; - -wire [15:0] dbg_dout = cpu_id_lo_rd | - cpu_id_hi_rd | - cpu_ctl_rd | - cpu_stat_rd | - mem_ctl_rd | - mem_data_rd | - mem_addr_rd | - mem_cnt_rd | - brk0_dout | - brk1_dout | - brk2_dout | - brk3_dout; - -// Tell UART/JTAG interface that the data is ready to be read -always @ (posedge mclk or posedge por) - if (por) dbg_rd_rdy <= 1'b0; - else if (mem_burst | mem_burst_rd) dbg_rd_rdy <= (dbg_reg_rd | dbg_mem_rd_dly); - else dbg_rd_rdy <= dbg_rd; - - -//============================================================================ -// 7) CPU CONTROL -//============================================================================ - -// Reset CPU -//-------------------------- -wire dbg_reset = cpu_ctl[`CPU_RST]; - - -// Break after reset -//-------------------------- -wire halt_rst = cpu_ctl[`RST_BRK_EN] & puc; - - -// Freeze peripherals -//-------------------------- -wire dbg_freeze = dbg_halt_st & cpu_ctl[`FRZ_BRK_EN]; - - -// Software break -//-------------------------- -assign dbg_swbrk = (fe_mdb_in==`DBG_SWBRK_OP) & decode & cpu_ctl[`SW_BRK_EN]; - - -// Single step -//-------------------------- -reg [1:0] inc_step; -always @(posedge mclk or posedge por) - if (por) inc_step <= 2'b00; - else if (istep) inc_step <= 2'b11; - else inc_step <= {inc_step[0], 1'b0}; - - -// Run / Halt -//-------------------------- -reg halt_flag; - -wire mem_halt_cpu; -wire mem_run_cpu; - -wire halt_flag_clr = run_cpu | mem_run_cpu; -wire halt_flag_set = halt_cpu | halt_rst | dbg_swbrk | mem_halt_cpu | - brk0_halt | brk1_halt | brk2_halt | brk3_halt; - -always @(posedge mclk or posedge por) - if (por) halt_flag <= 1'b0; - else if (halt_flag_clr) halt_flag <= 1'b0; - else if (halt_flag_set) halt_flag <= 1'b1; - -wire dbg_halt_cmd = (halt_flag | halt_flag_set) & ~inc_step[1]; - - -//============================================================================ -// 8) MEMORY CONTROL -//============================================================================ - -// Control Memory bursts -//------------------------------ - -wire mem_burst_start = (mem_start & |mem_cnt); -wire mem_burst_end = ((dbg_wr | dbg_rd_rdy) & ~|mem_cnt); - -// Detect when burst is on going -always @(posedge mclk or posedge por) - if (por) mem_burst <= 1'b0; - else if (mem_burst_start) mem_burst <= 1'b1; - else if (mem_burst_end) mem_burst <= 1'b0; - -// Control signals for UART/JTAG interface -assign mem_burst_rd = (mem_burst_start & ~mem_ctl[1]); -assign mem_burst_wr = (mem_burst_start & mem_ctl[1]); - -// Trigger CPU Register or memory access during a burst -reg mem_startb; -always @(posedge mclk or posedge por) - if (por) mem_startb <= 1'b0; - else mem_startb <= (mem_burst & (dbg_wr | dbg_rd)) | mem_burst_rd; - -// Combine single and burst memory start of sequence -wire mem_seq_start = ((mem_start & ~|mem_cnt) | mem_startb); - - -// Memory access state machine -//------------------------------ -reg [1:0] mem_state; -reg [1:0] mem_state_nxt; - -// State machine definition -parameter M_IDLE = 2'h0; -parameter M_SET_BRK = 2'h1; -parameter M_ACCESS_BRK = 2'h2; -parameter M_ACCESS = 2'h3; - -// State transition -always @(mem_state or mem_seq_start or dbg_halt_st) - case (mem_state) - M_IDLE : mem_state_nxt = ~mem_seq_start ? M_IDLE : - dbg_halt_st ? M_ACCESS : M_SET_BRK; - M_SET_BRK : mem_state_nxt = dbg_halt_st ? M_ACCESS_BRK : M_SET_BRK; - M_ACCESS_BRK : mem_state_nxt = M_IDLE; - M_ACCESS : mem_state_nxt = M_IDLE; - default : mem_state_nxt = M_IDLE; - endcase - -// State machine -always @(posedge mclk or posedge por) - if (por) mem_state <= M_IDLE; - else mem_state <= mem_state_nxt; - -// Utility signals -assign mem_halt_cpu = (mem_state==M_IDLE) & (mem_state_nxt==M_SET_BRK); -assign mem_run_cpu = (mem_state==M_ACCESS_BRK) & (mem_state_nxt==M_IDLE); -assign mem_access = (mem_state==M_ACCESS) | (mem_state==M_ACCESS_BRK); - - -// Interface to CPU Registers and Memory bacbkone -//------------------------------------------------ -assign dbg_mem_addr = mem_addr; -assign dbg_mem_dout = ~mem_bw ? mem_data : - mem_addr[0] ? {mem_data[7:0], 8'h00} : - {8'h00, mem_data[7:0]}; - -assign dbg_reg_wr = mem_access & mem_ctl[1] & mem_ctl[2]; -assign dbg_reg_rd = mem_access & ~mem_ctl[1] & mem_ctl[2]; - -assign dbg_mem_en = mem_access & ~mem_ctl[2]; -assign dbg_mem_rd = dbg_mem_en & ~mem_ctl[1]; - -wire [1:0] dbg_mem_wr_msk = ~mem_bw ? 2'b11 : - mem_addr[0] ? 2'b10 : 2'b01; -assign dbg_mem_wr = {2{dbg_mem_en & mem_ctl[1]}} & dbg_mem_wr_msk; - - -// It takes one additional cycle to read from Memory as from registers -always @(posedge mclk or posedge por) - if (por) dbg_mem_rd_dly <= 1'b0; - else dbg_mem_rd_dly <= dbg_mem_rd; - - -//============================================================================= -// 9) UART COMMUNICATION -//============================================================================= -`ifdef DBG_UART -dbg_uart dbg_uart_0 ( - -// OUTPUTs - .dbg_addr (dbg_addr), // Debug register address - .dbg_din (dbg_din), // Debug register data input - .dbg_rd (dbg_rd), // Debug register data read - .dbg_uart_txd (dbg_uart_txd), // Debug interface: UART TXD - .dbg_wr (dbg_wr), // Debug register data write - -// INPUTs - .dbg_dout (dbg_dout), // Debug register data output - .dbg_rd_rdy (dbg_rd_rdy), // Debug register data is ready for read - .dbg_uart_rxd (dbg_uart_rxd), // Debug interface: UART RXD - .mclk (mclk), // Main system clock - .mem_burst (mem_burst), // Burst on going - .mem_burst_end(mem_burst_end), // End TX/RX burst - .mem_burst_rd (mem_burst_rd), // Start TX burst - .mem_burst_wr (mem_burst_wr), // Start RX burst - .mem_bw (mem_bw), // Burst byte width - .por (por) // Power on reset -); - -`else -assign dbg_addr = 6'h00; -assign dbg_din = 16'h0000; -assign dbg_rd = 1'b0; -assign dbg_uart_txd = 1'b0; -assign dbg_wr = 1'b0; -`endif - - -//============================================================================= -// 10) JTAG COMMUNICATION -//============================================================================= -`ifdef DBG_JTAG -JTAG INTERFACE IS NOT SUPPORTED YET -`else -`endif - -endmodule // dbg - -`include "openMSP430_undefines.v"
dbg.v Property changes : Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Date Revision Author \ No newline at end of property Index: alu.v =================================================================== --- alu.v (revision 33) +++ alu.v (nonexistent) @@ -1,248 +0,0 @@ -//---------------------------------------------------------------------------- -// Copyright (C) 2001 Authors -// -// This source file may be used and distributed without restriction provided -// that this copyright statement is not removed from the file and that any -// derivative work contains the original copyright notice and the associated -// disclaimer. -// -// This source file is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This source is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -// License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this source; if not, write to the Free Software Foundation, -// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -//---------------------------------------------------------------------------- -// -// *File Name: alu.v -// -// *Module Description: -// openMSP430 ALU -// -// *Author(s): -// - Olivier Girard, olgirard@gmail.com -// -//---------------------------------------------------------------------------- -// $Rev$ -// $LastChangedBy$ -// $LastChangedDate$ -//---------------------------------------------------------------------------- -`include "timescale.v" -`include "openMSP430_defines.v" - -module alu ( - -// OUTPUTs - alu_out, // ALU output value - alu_out_add, // ALU adder output value - alu_stat, // ALU Status {V,N,Z,C} - alu_stat_wr, // ALU Status write {V,N,Z,C} - -// INPUTs - dbg_halt_st, // Halt/Run status from CPU - exec_cycle, // Instruction execution cycle - inst_alu, // ALU control signals - inst_bw, // Decoded Inst: byte width - inst_jmp, // Decoded Inst: Conditional jump - inst_so, // Single-operand arithmetic - op_dst, // Destination operand - op_src, // Source operand - status // R2 Status {V,N,Z,C} -); - -// OUTPUTs -//========= -output [15:0] alu_out; // ALU output value -output [15:0] alu_out_add; // ALU adder output value -output [3:0] alu_stat; // ALU Status {V,N,Z,C} -output [3:0] alu_stat_wr; // ALU Status write {V,N,Z,C} - -// INPUTs -//========= -input dbg_halt_st; // Halt/Run status from CPU -input exec_cycle; // Instruction execution cycle -input [11:0] inst_alu; // ALU control signals -input inst_bw; // Decoded Inst: byte width -input [7:0] inst_jmp; // Decoded Inst: Conditional jump -input [7:0] inst_so; // Single-operand arithmetic -input [15:0] op_dst; // Destination operand -input [15:0] op_src; // Source operand -input [3:0] status; // R2 Status {V,N,Z,C} - - -//============================================================================= -// 1) FUNCTIONS -//============================================================================= - -function [4:0] bcd_add; - - input [3:0] X; - input [3:0] Y; - input C; - - reg [4:0] Z; - begin - Z = {1'b0,X}+{1'b0,Y}+C; - if (Z<10) bcd_add = Z; - else bcd_add = Z+6; - end - -endfunction - - -//============================================================================= -// 2) INSTRUCTION FETCH/DECODE CONTROL STATE MACHINE -//============================================================================= -// SINGLE-OPERAND ARITHMETIC: -//----------------------------------------------------------------------------- -// Mnemonic S-Reg, Operation Status bits -// D-Reg, V N Z C -// -// RRC dst C->MSB->...LSB->C * * * * -// RRA dst MSB->MSB->...LSB->C 0 * * * -// SWPB dst Swap bytes - - - - -// SXT dst Bit7->Bit8...Bit15 0 * * * -// PUSH src SP-2->SP, src->@SP - - - - -// CALL dst SP-2->SP, PC+2->@SP, dst->PC - - - - -// RETI TOS->SR, SP+2->SP, TOS->PC, SP+2->SP * * * * -// -//----------------------------------------------------------------------------- -// TWO-OPERAND ARITHMETIC: -//----------------------------------------------------------------------------- -// Mnemonic S-Reg, Operation Status bits -// D-Reg, V N Z C -// -// MOV src,dst src -> dst - - - - -// ADD src,dst src + dst -> dst * * * * -// ADDC src,dst src + dst + C -> dst * * * * -// SUB src,dst dst + ~src + 1 -> dst * * * * -// SUBC src,dst dst + ~src + C -> dst * * * * -// CMP src,dst dst + ~src + 1 * * * * -// DADD src,dst src + dst + C -> dst (decimaly) * * * * -// BIT src,dst src & dst 0 * * * -// BIC src,dst ~src & dst -> dst - - - - -// BIS src,dst src | dst -> dst - - - - -// XOR src,dst src ^ dst -> dst * * * * -// AND src,dst src & dst -> dst 0 * * * -// -//----------------------------------------------------------------------------- -// * the status bit is affected -// - the status bit is not affected -// 0 the status bit is cleared -// 1 the status bit is set -//----------------------------------------------------------------------------- - -// Invert source for substract and compare instructions. -wire op_src_inv_cmd = exec_cycle & (inst_alu[`ALU_SRC_INV]); -wire [15:0] op_src_inv = {16{op_src_inv_cmd}} ^ op_src; - - -// Mask the bit 8 for the Byte instructions for correct flags generation -wire op_bit8_msk = ~exec_cycle | ~inst_bw; -wire [16:0] op_src_in = {1'b0, op_src_inv[15:9], op_src_inv[8] & op_bit8_msk, op_src_inv[7:0]}; -wire [16:0] op_dst_in = {1'b0, op_dst[15:9], op_dst[8] & op_bit8_msk, op_dst[7:0]}; - -// Clear the source operand (= jump offset) for conditional jumps -wire jmp_not_taken = (inst_jmp[`JL] & ~(status[3]^status[2])) | - (inst_jmp[`JGE] & (status[3]^status[2])) | - (inst_jmp[`JN] & ~status[2]) | - (inst_jmp[`JC] & ~status[0]) | - (inst_jmp[`JNC] & status[0]) | - (inst_jmp[`JEQ] & ~status[1]) | - (inst_jmp[`JNE] & status[1]); -wire [16:0] op_src_in_jmp = op_src_in & {17{~jmp_not_taken}}; - -// Adder / AND / OR / XOR -wire [16:0] alu_add = op_src_in_jmp + op_dst_in; -wire [16:0] alu_and = op_src_in & op_dst_in; -wire [16:0] alu_or = op_src_in | op_dst_in; -wire [16:0] alu_xor = op_src_in ^ op_dst_in; - - -// Incrementer -wire alu_inc = exec_cycle & ((inst_alu[`ALU_INC_C] & status[0]) | - inst_alu[`ALU_INC]); -wire [16:0] alu_add_inc = alu_add + {16'h0000, alu_inc}; - - - -// Decimal adder (DADD) -wire [4:0] alu_dadd0 = bcd_add(op_src_in[3:0], op_dst_in[3:0], status[0]); -wire [4:0] alu_dadd1 = bcd_add(op_src_in[7:4], op_dst_in[7:4], alu_dadd0[4]); -wire [4:0] alu_dadd2 = bcd_add(op_src_in[11:8], op_dst_in[11:8], alu_dadd1[4]); -wire [4:0] alu_dadd3 = bcd_add(op_src_in[15:12], op_dst_in[15:12],alu_dadd2[4]); -wire [16:0] alu_dadd = {alu_dadd3, alu_dadd2[3:0], alu_dadd1[3:0], alu_dadd0[3:0]}; - - -// Shifter for rotate instructions (RRC & RRA) -wire alu_shift_msb = inst_so[`RRC] ? status[0] : - inst_bw ? op_src[7] : op_src[15]; -wire alu_shift_7 = inst_bw ? alu_shift_msb : op_src[8]; -wire [16:0] alu_shift = {1'b0, alu_shift_msb, op_src[15:9], alu_shift_7, op_src[7:1]}; - - -// Swap bytes / Extend Sign -wire [16:0] alu_swpb = {1'b0, op_src[7:0],op_src[15:8]}; -wire [16:0] alu_sxt = {1'b0, {8{op_src[7]}},op_src[7:0]}; - - -// Combine short paths toghether to simplify final ALU mux -wire alu_short_thro = ~(inst_alu[`ALU_AND] | - inst_alu[`ALU_OR] | - inst_alu[`ALU_XOR] | - inst_alu[`ALU_SHIFT] | - inst_so[`SWPB] | - inst_so[`SXT]); - -wire [16:0] alu_short = ({16{inst_alu[`ALU_AND]}} & alu_and) | - ({16{inst_alu[`ALU_OR]}} & alu_or) | - ({16{inst_alu[`ALU_XOR]}} & alu_xor) | - ({16{inst_alu[`ALU_SHIFT]}} & alu_shift) | - ({16{inst_so[`SWPB]}} & alu_swpb) | - ({16{inst_so[`SXT]}} & alu_sxt) | - ({16{alu_short_thro}} & op_src_in); - - -// ALU output mux -wire [16:0] alu_out_nxt = (inst_so[`IRQ] | dbg_halt_st | - inst_alu[`ALU_ADD]) ? alu_add_inc : - inst_alu[`ALU_DADD] ? alu_dadd : alu_short; - -assign alu_out = alu_out_nxt[15:0]; -assign alu_out_add = alu_add[15:0]; - - -//----------------------------------------------------------------------------- -// STATUS FLAG GENERATION -//----------------------------------------------------------------------------- - -wire V_xor = inst_bw ? (op_src_in[7] & op_dst_in[7]) : - (op_src_in[15] & op_dst_in[15]); - -wire V = inst_bw ? ((~op_src_in[7] & ~op_dst_in[7] & alu_out[7]) | - ( op_src_in[7] & op_dst_in[7] & ~alu_out[7])) : - ((~op_src_in[15] & ~op_dst_in[15] & alu_out[15]) | - ( op_src_in[15] & op_dst_in[15] & ~alu_out[15])); - -wire N = inst_bw ? alu_out[7] : alu_out[15]; -wire Z = inst_bw ? (alu_out[7:0]==0) : (alu_out==0); -wire C = inst_bw ? alu_out[8] : alu_out_nxt[16]; - -assign alu_stat = inst_alu[`ALU_SHIFT] ? {1'b0, N,Z,op_src_in[0]} : - inst_alu[`ALU_STAT_7] ? {1'b0, N,Z,~Z} : - inst_alu[`ALU_XOR] ? {V_xor,N,Z,~Z} : {V,N,Z,C}; - -assign alu_stat_wr = (inst_alu[`ALU_STAT_F] & exec_cycle) ? 4'b1111 : 4'b0000; - - -endmodule // alu - -`include "openMSP430_undefines.v"
alu.v Property changes : Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Date Revision Author \ No newline at end of property Index: mem_backbone.v =================================================================== --- mem_backbone.v (revision 33) +++ mem_backbone.v (nonexistent) @@ -1,244 +0,0 @@ -//---------------------------------------------------------------------------- -// Copyright (C) 2001 Authors -// -// This source file may be used and distributed without restriction provided -// that this copyright statement is not removed from the file and that any -// derivative work contains the original copyright notice and the associated -// disclaimer. -// -// This source file is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This source is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -// License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this source; if not, write to the Free Software Foundation, -// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -//---------------------------------------------------------------------------- -// -// *File Name: mem_backbone.v -// -// *Module Description: -// Memory interface backbone (decoder + arbiter) -// -// *Author(s): -// - Olivier Girard, olgirard@gmail.com -// -//---------------------------------------------------------------------------- -// $Rev$ -// $LastChangedBy$ -// $LastChangedDate$ -//---------------------------------------------------------------------------- -`include "timescale.v" -`include "openMSP430_defines.v" - -module mem_backbone ( - -// OUTPUTs - dbg_mem_din, // Debug unit Memory data input - dmem_addr, // Data Memory address - dmem_cen, // Data Memory chip enable (low active) - dmem_din, // Data Memory data input - dmem_wen, // Data Memory write enable (low active) - eu_mdb_in, // Execution Unit Memory data bus input - fe_mdb_in, // Frontend Memory data bus input - fe_pmem_wait, // Frontend wait for Instruction fetch - per_addr, // Peripheral address - per_din, // Peripheral data input - per_wen, // Peripheral write enable (high active) - per_en, // Peripheral enable (high active) - pmem_addr, // Program Memory address - pmem_cen, // Program Memory chip enable (low active) - pmem_din, // Program Memory data input (optional) - pmem_wen, // Program Memory write enable (low active) (optional) - -// INPUTs - dbg_halt_st, // Halt/Run status from CPU - dbg_mem_addr, // Debug address for rd/wr access - dbg_mem_dout, // Debug unit data output - dbg_mem_en, // Debug unit memory enable - dbg_mem_wr, // Debug unit memory write - dmem_dout, // Data Memory data output - eu_mab, // Execution Unit Memory address bus - eu_mb_en, // Execution Unit Memory bus enable - eu_mb_wr, // Execution Unit Memory bus write transfer - eu_mdb_out, // Execution Unit Memory data bus output - fe_mab, // Frontend Memory address bus - fe_mb_en, // Frontend Memory bus enable - mclk, // Main system clock - per_dout, // Peripheral data output - pmem_dout, // Program Memory data output - puc // Main system reset -); - -// OUTPUTs -//========= -output [15:0] dbg_mem_din; // Debug unit Memory data input -output [`DMEM_MSB:0] dmem_addr; // Data Memory address -output dmem_cen; // Data Memory chip enable (low active) -output [15:0] dmem_din; // Data Memory data input -output [1:0] dmem_wen; // Data Memory write enable (low active) -output [15:0] eu_mdb_in; // Execution Unit Memory data bus input -output [15:0] fe_mdb_in; // Frontend Memory data bus input -output fe_pmem_wait; // Frontend wait for Instruction fetch -output [7:0] per_addr; // Peripheral address -output [15:0] per_din; // Peripheral data input -output [1:0] per_wen; // Peripheral write enable (high active) -output per_en; // Peripheral enable (high active) -output [`PMEM_MSB:0] pmem_addr; // Program Memory address -output pmem_cen; // Program Memory chip enable (low active) -output [15:0] pmem_din; // Program Memory data input (optional) -output [1:0] pmem_wen; // Program Memory write enable (low active) (optional) - -// INPUTs -//========= -input dbg_halt_st; // Halt/Run status from CPU -input [15:0] dbg_mem_addr; // Debug address for rd/wr access -input [15:0] dbg_mem_dout; // Debug unit data output -input dbg_mem_en; // Debug unit memory enable -input [1:0] dbg_mem_wr; // Debug unit memory write -input [15:0] dmem_dout; // Data Memory data output -input [14:0] eu_mab; // Execution Unit Memory address bus -input eu_mb_en; // Execution Unit Memory bus enable -input [1:0] eu_mb_wr; // Execution Unit Memory bus write transfer -input [15:0] eu_mdb_out; // Execution Unit Memory data bus output -input [14:0] fe_mab; // Frontend Memory address bus -input fe_mb_en; // Frontend Memory bus enable -input mclk; // Main system clock -input [15:0] per_dout; // Peripheral data output -input [15:0] pmem_dout; // Program Memory data output -input puc; // Main system reset - - -//============================================================================= -// 1) DECODER -//============================================================================= - -// RAM Interface -//------------------ - -// Execution unit access -wire eu_dmem_cen = ~(eu_mb_en & (eu_mab>=(`DMEM_BASE>>1)) & - (eu_mab<((`DMEM_BASE+`DMEM_SIZE)>>1))); -wire [15:0] eu_dmem_addr = eu_mab-(`DMEM_BASE>>1); - -// Debug interface access -wire dbg_dmem_cen = ~(dbg_mem_en & (dbg_mem_addr[15:1]>=(`DMEM_BASE>>1)) & - (dbg_mem_addr[15:1]<((`DMEM_BASE+`DMEM_SIZE)>>1))); -wire [15:0] dbg_dmem_addr = dbg_mem_addr[15:1]-(`DMEM_BASE>>1); - - -// RAM Interface -wire [`DMEM_MSB:0] dmem_addr = ~dbg_dmem_cen ? dbg_dmem_addr[`DMEM_MSB:0] : eu_dmem_addr[`DMEM_MSB:0]; -wire dmem_cen = dbg_dmem_cen & eu_dmem_cen; -wire [1:0] dmem_wen = ~(dbg_mem_wr | eu_mb_wr); -wire [15:0] dmem_din = ~dbg_dmem_cen ? dbg_mem_dout : eu_mdb_out; - - -// ROM Interface -//------------------ -parameter PMEM_OFFSET = (16'hFFFF-`PMEM_SIZE+1); - -// Execution unit access (only read access are accepted) -wire eu_pmem_cen = ~(eu_mb_en & ~|eu_mb_wr & (eu_mab>=(PMEM_OFFSET>>1))); -wire [15:0] eu_pmem_addr = eu_mab-(PMEM_OFFSET>>1); - -// Front-end access -wire fe_pmem_cen = ~(fe_mb_en & (fe_mab>=(PMEM_OFFSET>>1))); -wire [15:0] fe_pmem_addr = fe_mab-(PMEM_OFFSET>>1); - -// Debug interface access -wire dbg_pmem_cen = ~(dbg_mem_en & (dbg_mem_addr[15:1]>=(PMEM_OFFSET>>1))); -wire [15:0] dbg_pmem_addr = dbg_mem_addr[15:1]-(PMEM_OFFSET>>1); - - -// ROM Interface (Execution unit has priority) -wire [`PMEM_MSB:0] pmem_addr = ~dbg_pmem_cen ? dbg_pmem_addr[`PMEM_MSB:0] : - ~eu_pmem_cen ? eu_pmem_addr[`PMEM_MSB:0] : fe_pmem_addr[`PMEM_MSB:0]; -wire pmem_cen = fe_pmem_cen & eu_pmem_cen & dbg_pmem_cen; -wire [1:0] pmem_wen = ~dbg_mem_wr; -wire [15:0] pmem_din = dbg_mem_dout; - -wire fe_pmem_wait = (~fe_pmem_cen & ~eu_pmem_cen); - - -// Peripherals -//-------------------- -wire dbg_per_en = dbg_mem_en & (dbg_mem_addr[15:9]==7'h00); -wire eu_per_en = eu_mb_en & (eu_mab[14:8]==7'h00); - -wire [7:0] per_addr = dbg_mem_en ? dbg_mem_addr[8:1] : eu_mab[7:0]; -wire [15:0] per_din = dbg_mem_en ? dbg_mem_dout : eu_mdb_out; -wire [1:0] per_wen = dbg_mem_en ? dbg_mem_wr : eu_mb_wr; -wire per_en = dbg_mem_en ? dbg_per_en : eu_per_en; - -reg [15:0] per_dout_val; -always @ (posedge mclk or posedge puc) - if (puc) per_dout_val <= 16'h0000; - else per_dout_val <= per_dout; - - -// Frontend data Mux -//--------------------------------- -// Whenever the frontend doesn't access the ROM, backup the data - -// Detect whenever the data should be backuped and restored -reg fe_pmem_cen_dly; -always @(posedge mclk or posedge puc) - if (puc) fe_pmem_cen_dly <= 1'b0; - else fe_pmem_cen_dly <= fe_pmem_cen; - -wire fe_pmem_save = ( fe_pmem_cen & ~fe_pmem_cen_dly) & ~dbg_halt_st; -wire fe_pmem_restore = (~fe_pmem_cen & fe_pmem_cen_dly) | dbg_halt_st; - -reg [15:0] pmem_dout_bckup; -always @(posedge mclk or posedge puc) - if (puc) pmem_dout_bckup <= 16'h0000; - else if (fe_pmem_save) pmem_dout_bckup <= pmem_dout; - -// Mux between the ROM data and the backup -reg pmem_dout_bckup_sel; -always @(posedge mclk or posedge puc) - if (puc) pmem_dout_bckup_sel <= 1'b0; - else if (fe_pmem_save) pmem_dout_bckup_sel <= 1'b1; - else if (fe_pmem_restore) pmem_dout_bckup_sel <= 1'b0; - -assign fe_mdb_in = pmem_dout_bckup_sel ? pmem_dout_bckup : pmem_dout; - - -// Execution-Unit data Mux -//--------------------------------- - -// Select between peripherals, RAM and ROM -reg [1:0] eu_mdb_in_sel; -always @(posedge mclk or posedge puc) - if (puc) eu_mdb_in_sel <= 2'b00; - else eu_mdb_in_sel <= {~eu_pmem_cen, per_en}; - -// Mux -assign eu_mdb_in = eu_mdb_in_sel[1] ? pmem_dout : - eu_mdb_in_sel[0] ? per_dout_val : dmem_dout; - -// Debug interface data Mux -//--------------------------------- - -// Select between peripherals, RAM and ROM -reg [1:0] dbg_mem_din_sel; -always @(posedge mclk or posedge puc) - if (puc) dbg_mem_din_sel <= 2'b00; - else dbg_mem_din_sel <= {~dbg_pmem_cen, dbg_per_en}; - -// Mux -assign dbg_mem_din = dbg_mem_din_sel[1] ? pmem_dout : - dbg_mem_din_sel[0] ? per_dout_val : dmem_dout; - - -endmodule // mem_backbone - -`include "openMSP430_undefines.v"
mem_backbone.v Property changes : Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Date Revision Author \ No newline at end of property Index: watchdog.v =================================================================== --- watchdog.v (revision 33) +++ watchdog.v (nonexistent) @@ -1,217 +0,0 @@ -//---------------------------------------------------------------------------- -// Copyright (C) 2001 Authors -// -// This source file may be used and distributed without restriction provided -// that this copyright statement is not removed from the file and that any -// derivative work contains the original copyright notice and the associated -// disclaimer. -// -// This source file is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This source is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -// License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this source; if not, write to the Free Software Foundation, -// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -//---------------------------------------------------------------------------- -// -// *File Name: watchdog.v -// -// *Module Description: -// Watchdog Timer -// -// *Author(s): -// - Olivier Girard, olgirard@gmail.com -// -//---------------------------------------------------------------------------- -// $Rev$ -// $LastChangedBy$ -// $LastChangedDate$ -//---------------------------------------------------------------------------- -`include "timescale.v" -`include "openMSP430_defines.v" - -module watchdog ( - -// OUTPUTs - nmi_evt, // NMI Event - per_dout, // Peripheral data output - wdtifg_set, // Set Watchdog-timer interrupt flag - wdtpw_error, // Watchdog-timer password error - wdttmsel, // Watchdog-timer mode select - -// INPUTs - aclk_en, // ACLK enable - dbg_freeze, // Freeze Watchdog counter - mclk, // Main system clock - nmi, // Non-maskable interrupt (asynchronous) - nmie, // Non-maskable interrupt enable - per_addr, // Peripheral address - per_din, // Peripheral data input - per_en, // Peripheral enable (high active) - per_wen, // Peripheral write enable (high active) - puc, // Main system reset - smclk_en, // SMCLK enable - wdtie // Watchdog timer interrupt enable -); - -// OUTPUTs -//========= -output nmi_evt; // NMI Event -output [15:0] per_dout; // Peripheral data output -output wdtifg_set; // Set Watchdog-timer interrupt flag -output wdtpw_error; // Watchdog-timer password error -output wdttmsel; // Watchdog-timer mode select - -// INPUTs -//========= -input aclk_en; // ACLK enable -input dbg_freeze; // Freeze Watchdog counter -input mclk; // Main system clock -input nmi; // Non-maskable interrupt (asynchronous) -input nmie; // Non-maskable interrupt enable -input [7:0] per_addr; // Peripheral address -input [15:0] per_din; // Peripheral data input -input per_en; // Peripheral enable (high active) -input [1:0] per_wen; // Peripheral write enable (high active) -input puc; // Main system reset -input smclk_en; // SMCLK enable -input wdtie; // Watchdog timer interrupt enable - - -//============================================================================= -// 1) PARAMETER DECLARATION -//============================================================================= - -// Register addresses -parameter WDTCTL = 9'h120; - - -// Register one-hot decoder -parameter WDTCTL_D = (512'h1 << WDTCTL); - - -//============================================================================ -// 2) REGISTER DECODER -//============================================================================ - -// Register address decode -reg [511:0] reg_dec; -always @(per_addr) - case ({per_addr,1'b0}) - WDTCTL : reg_dec = WDTCTL_D; - default: reg_dec = {512{1'b0}}; - endcase - -// Read/Write probes -wire reg_write = |per_wen & per_en; -wire reg_read = ~|per_wen & per_en; - -// Read/Write vectors -wire [511:0] reg_wr = reg_dec & {512{reg_write}}; -wire [511:0] reg_rd = reg_dec & {512{reg_read}}; - - -//============================================================================ -// 3) REGISTERS -//============================================================================ - -// WDTCTL Register -//----------------- -// WDTNMI & WDTSSEL are not implemented and therefore masked - -reg [7:0] wdtctl; - -wire wdtctl_wr = reg_wr[WDTCTL]; - -always @ (posedge mclk or posedge puc) - if (puc) wdtctl <= 8'h00; - else if (wdtctl_wr) wdtctl <= per_din[7:0] & 8'hd7; - -wire wdtpw_error = wdtctl_wr & (per_din[15:8]!=8'h5a); -wire wdttmsel = wdtctl[4]; - - -//============================================================================ -// 3) REGISTERS -//============================================================================ - -// Data output mux -wire [15:0] wdtctl_rd = {8'h69, wdtctl} & {16{reg_rd[WDTCTL]}}; - -wire [15:0] per_dout = wdtctl_rd; - - -//============================================================================= -// 4) NMI GENERATION -//============================================================================= - -// Synchronization state -reg [2:0] nmi_sync; -always @ (posedge mclk or posedge puc) - if (puc) nmi_sync <= 3'h0; - else nmi_sync <= {nmi_sync[1:0], nmi}; - -// Edge detection -wire nmi_re = ~nmi_sync[2] & nmi_sync[0] & nmie; -wire nmi_fe = nmi_sync[2] & ~nmi_sync[0] & nmie; - -// NMI event -wire nmi_evt = wdtctl[6] ? nmi_fe : nmi_re; - - -//============================================================================= -// 5) WATCHDOG TIMER -//============================================================================= - -// Watchdog clock source selection -//--------------------------------- -wire clk_src_en = wdtctl[2] ? aclk_en : smclk_en; - - -// Watchdog 16 bit counter -//-------------------------- -reg [15:0] wdtcnt; - -wire wdtcnt_clr = (wdtctl_wr & per_din[3]) | wdtifg_set; - -always @ (posedge mclk or posedge puc) - if (puc) wdtcnt <= 16'h0000; - else if (wdtcnt_clr) wdtcnt <= 16'h0000; - else if (~wdtctl[7] & clk_src_en & ~dbg_freeze) wdtcnt <= wdtcnt+16'h0001; - - -// Interval selection mux -//-------------------------- -reg wdtqn; - -always @(wdtctl or wdtcnt) - case(wdtctl[1:0]) - 2'b00 : wdtqn = wdtcnt[15]; - 2'b01 : wdtqn = wdtcnt[13]; - 2'b10 : wdtqn = wdtcnt[9]; - default: wdtqn = wdtcnt[6]; - endcase - - -// Watchdog event detection -//----------------------------- -reg wdtqn_dly; - -always @ (posedge mclk or posedge puc) - if (puc) wdtqn_dly <= 1'b0; - else wdtqn_dly <= wdtqn; - -wire wdtifg_set = (~wdtqn_dly & wdtqn) | wdtpw_error; - - -endmodule // watchdog - -`include "openMSP430_undefines.v"
watchdog.v Property changes : Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Date Revision Author \ No newline at end of property Index: clock_module.v =================================================================== --- clock_module.v (revision 33) +++ clock_module.v (nonexistent) @@ -1,247 +0,0 @@ -//---------------------------------------------------------------------------- -// Copyright (C) 2001 Authors -// -// This source file may be used and distributed without restriction provided -// that this copyright statement is not removed from the file and that any -// derivative work contains the original copyright notice and the associated -// disclaimer. -// -// This source file is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This source is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -// License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this source; if not, write to the Free Software Foundation, -// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -//---------------------------------------------------------------------------- -// -// *File Name: clock_module.v -// -// *Module Description: -// Basic clock module implementation. -// Since the openMSP430 mainly targets FPGA and hobby -// designers. The clock structure has been greatly -// symplified in order to ease integration. -// See online wiki for more info. -// -// *Author(s): -// - Olivier Girard, olgirard@gmail.com -// -//---------------------------------------------------------------------------- -// $Rev$ -// $LastChangedBy$ -// $LastChangedDate$ -//---------------------------------------------------------------------------- -`include "timescale.v" -`include "openMSP430_defines.v" - -module clock_module ( - -// OUTPUTs - aclk_en, // ACLK enable - mclk, // Main system clock - per_dout, // Peripheral data output - por, // Power-on reset - puc, // Main system reset - smclk_en, // SMCLK enable - -// INPUTs - dbg_reset, // Reset CPU from debug interface - dco_clk, // Fast oscillator (fast clock) - lfxt_clk, // Low frequency oscillator (typ 32kHz) - oscoff, // Turns off LFXT1 clock input - per_addr, // Peripheral address - per_din, // Peripheral data input - per_en, // Peripheral enable (high active) - per_wen, // Peripheral write enable (high active) - reset_n, // Reset Pin (low active) - scg1, // System clock generator 1. Turns off the SMCLK - wdt_reset // Watchdog-timer reset -); - -// OUTPUTs -//========= -output aclk_en; // ACLK enable -output mclk; // Main system clock -output [15:0] per_dout; // Peripheral data output -output por; // Power-on reset -output puc; // Main system reset -output smclk_en; // SMCLK enable - -// INPUTs -//========= -input dbg_reset; // Reset CPU from debug interface -input dco_clk; // Fast oscillator (fast clock) -input lfxt_clk; // Low frequency oscillator (typ 32kHz) -input oscoff; // Turns off LFXT1 clock input -input [7:0] per_addr; // Peripheral address -input [15:0] per_din; // Peripheral data input -input per_en; // Peripheral enable (high active) -input [1:0] per_wen; // Peripheral write enable (high active) -input reset_n; // Reset Pin (low active) -input scg1; // System clock generator 1. Turns off the SMCLK -input wdt_reset; // Watchdog-timer reset - - -//============================================================================= -// 1) PARAMETER DECLARATION -//============================================================================= - -// Register addresses -parameter BCSCTL1 = 9'h057; -parameter BCSCTL2 = 9'h058; - -// Register one-hot decoder -parameter BCSCTL1_D = (256'h1 << (BCSCTL1 /2)); -parameter BCSCTL2_D = (256'h1 << (BCSCTL2 /2)); - - -//============================================================================ -// 2) REGISTER DECODER -//============================================================================ - -// Register address decode -reg [255:0] reg_dec; -always @(per_addr) - case (per_addr) - (BCSCTL1 /2): reg_dec = BCSCTL1_D; - (BCSCTL2 /2): reg_dec = BCSCTL2_D; - default : reg_dec = {256{1'b0}}; - endcase - -// Read/Write probes -wire reg_lo_write = per_wen[0] & per_en; -wire reg_hi_write = per_wen[1] & per_en; -wire reg_read = ~|per_wen & per_en; - -// Read/Write vectors -wire [255:0] reg_hi_wr = reg_dec & {256{reg_hi_write}}; -wire [255:0] reg_lo_wr = reg_dec & {256{reg_lo_write}}; -wire [255:0] reg_rd = reg_dec & {256{reg_read}}; - - -//============================================================================ -// 3) REGISTERS -//============================================================================ - -// BCSCTL1 Register -//-------------- -reg [7:0] bcsctl1; -wire bcsctl1_wr = BCSCTL1[0] ? reg_hi_wr[BCSCTL1/2] : reg_lo_wr[BCSCTL1/2]; -wire [7:0] bcsctl1_nxt = BCSCTL1[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) bcsctl1 <= 8'h00; - else if (bcsctl1_wr) bcsctl1 <= bcsctl1_nxt & 8'h30; // Mask unused bits - - -// BCSCTL2 Register -//-------------- -reg [7:0] bcsctl2; -wire bcsctl2_wr = BCSCTL2[0] ? reg_hi_wr[BCSCTL2/2] : reg_lo_wr[BCSCTL2/2]; -wire [7:0] bcsctl2_nxt = BCSCTL2[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) bcsctl2 <= 8'h00; - else if (bcsctl2_wr) bcsctl2 <= bcsctl2_nxt & 8'h0e; // Mask unused bits - - -//============================================================================ -// 4) DATA OUTPUT GENERATION -//============================================================================ - -// Data output mux -wire [15:0] bcsctl1_rd = (bcsctl1 & {8{reg_rd[BCSCTL1/2]}}) << (8 & {4{BCSCTL1[0]}}); -wire [15:0] bcsctl2_rd = (bcsctl2 & {8{reg_rd[BCSCTL2/2]}}) << (8 & {4{BCSCTL2[0]}}); - -wire [15:0] per_dout = bcsctl1_rd | - bcsctl2_rd; - - -//============================================================================= -// 5) CLOCK GENERATION -//============================================================================= - -// Synchronize LFXT_CLK & edge detection -//--------------------------------------- -reg [2:0] lfxt_clk_s; - -always @ (posedge mclk or posedge puc) - if (puc) lfxt_clk_s <= 3'b000; - else lfxt_clk_s <= {lfxt_clk_s[1:0], lfxt_clk}; - -wire lfxt_clk_en = (lfxt_clk_s[1] & ~lfxt_clk_s[2]) & ~(oscoff & ~bcsctl2[`SELS]); - - -// Generate main system clock -//---------------------------- - -wire mclk = dco_clk; -wire mclk_n = !dco_clk; - - -// Generate ACLK -//---------------------------- - -reg [2:0] aclk_div; - -wire aclk_en = lfxt_clk_en & ((bcsctl1[`DIVAx]==2'b00) ? 1'b1 : - (bcsctl1[`DIVAx]==2'b01) ? aclk_div[0] : - (bcsctl1[`DIVAx]==2'b10) ? &aclk_div[1:0] : - &aclk_div[2:0]); - -always @ (posedge mclk or posedge puc) - if (puc) aclk_div <= 3'h0; - else if ((bcsctl1[`DIVAx]!=2'b00) & lfxt_clk_en) aclk_div <= aclk_div+3'h1; - - -// Generate SMCLK -//---------------------------- - -reg [2:0] smclk_div; - -wire smclk_in = ~scg1 & (bcsctl2[`SELS] ? lfxt_clk_en : 1'b1); - -wire smclk_en = smclk_in & ((bcsctl2[`DIVSx]==2'b00) ? 1'b1 : - (bcsctl2[`DIVSx]==2'b01) ? smclk_div[0] : - (bcsctl2[`DIVSx]==2'b10) ? &smclk_div[1:0] : - &smclk_div[2:0]); - -always @ (posedge mclk or posedge puc) - if (puc) smclk_div <= 3'h0; - else if ((bcsctl2[`DIVSx]!=2'b00) & smclk_in) smclk_div <= smclk_div+3'h1; - - -//============================================================================= -// 6) RESET GENERATION -//============================================================================= - -// Generate synchronized POR -wire por_reset = !reset_n; - -reg [1:0] por_s; -always @(posedge mclk_n or posedge por_reset) - if (por_reset) por_s <= 2'b11; - else por_s <= {por_s[0], 1'b0}; -wire por = por_s[1]; - -// Generate main system reset -wire puc_reset = por_reset | wdt_reset | dbg_reset; - -reg [1:0] puc_s; -always @(posedge mclk_n or posedge puc_reset) - if (puc_reset) puc_s <= 2'b11; - else puc_s <= {puc_s[0], 1'b0}; -wire puc = puc_s[1]; - - -endmodule // clock_module - -`include "openMSP430_undefines.v"
clock_module.v Property changes : Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Date Revision Author \ No newline at end of property Index: dbg_hwbrk.v =================================================================== --- dbg_hwbrk.v (revision 33) +++ dbg_hwbrk.v (nonexistent) @@ -1,269 +0,0 @@ -//---------------------------------------------------------------------------- -// Copyright (C) 2001 Authors -// -// This source file may be used and distributed without restriction provided -// that this copyright statement is not removed from the file and that any -// derivative work contains the original copyright notice and the associated -// disclaimer. -// -// This source file is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This source is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -// License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this source; if not, write to the Free Software Foundation, -// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -//---------------------------------------------------------------------------- -// -// *File Name: dbg_hwbrk.v -// -// *Module Description: -// Hardware Breakpoint / Watchpoint module -// -// *Author(s): -// - Olivier Girard, olgirard@gmail.com -// -//---------------------------------------------------------------------------- -// $Rev$ -// $LastChangedBy$ -// $LastChangedDate$ -//---------------------------------------------------------------------------- -`include "timescale.v" -`include "openMSP430_defines.v" - -module dbg_hwbrk ( - -// OUTPUTs - brk_halt, // Hardware breakpoint command - brk_pnd, // Hardware break/watch-point pending - brk_dout, // Hardware break/watch-point register data input - -// INPUTs - brk_reg_rd, // Hardware break/watch-point register read select - brk_reg_wr, // Hardware break/watch-point register write select - dbg_din, // Debug register data input - eu_mab, // Execution-Unit Memory address bus - eu_mb_en, // Execution-Unit Memory bus enable - eu_mb_wr, // Execution-Unit Memory bus write transfer - eu_mdb_in, // Memory data bus input - eu_mdb_out, // Memory data bus output - exec_done, // Execution completed - fe_mb_en, // Frontend Memory bus enable - mclk, // Main system clock - pc, // Program counter - por // Power on reset -); - -// OUTPUTs -//========= -output brk_halt; // Hardware breakpoint command -output brk_pnd; // Hardware break/watch-point pending -output [15:0] brk_dout; // Hardware break/watch-point register data input - -// INPUTs -//========= -input [3:0] brk_reg_rd; // Hardware break/watch-point register read select -input [3:0] brk_reg_wr; // Hardware break/watch-point register write select -input [15:0] dbg_din; // Debug register data input -input [15:0] eu_mab; // Execution-Unit Memory address bus -input eu_mb_en; // Execution-Unit Memory bus enable -input [1:0] eu_mb_wr; // Execution-Unit Memory bus write transfer -input [15:0] eu_mdb_in; // Memory data bus input -input [15:0] eu_mdb_out; // Memory data bus output -input exec_done; // Execution completed -input fe_mb_en; // Frontend Memory bus enable -input mclk; // Main system clock -input [15:0] pc; // Program counter -input por; // Power on reset - - -//============================================================================= -// 1) WIRE & PARAMETER DECLARATION -//============================================================================= - -wire range_wr_set; -wire range_rd_set; -wire addr1_wr_set; -wire addr1_rd_set; -wire addr0_wr_set; -wire addr0_rd_set; - - -parameter BRK_CTL = 0, - BRK_STAT = 1, - BRK_ADDR0 = 2, - BRK_ADDR1 = 3; - - -//============================================================================= -// 2) CONFIGURATION REGISTERS -//============================================================================= - -// BRK_CTL Register -//----------------------------------------------------------------------------- -// 7 6 5 4 3 2 1 0 -// Reserved RANGE_MODE INST_EN BREAK_EN ACCESS_MODE -// -// ACCESS_MODE: - 00 : Disabled -// - 01 : Detect read access -// - 10 : Detect write access -// - 11 : Detect read/write access -// NOTE: '10' & '11' modes are not supported on the instruction flow -// -// BREAK_EN: - 0 : Watchmode enable -// - 1 : Break enable -// -// INST_EN: - 0 : Checks are done on the execution unit (data flow) -// - 1 : Checks are done on the frontend (instruction flow) -// -// RANGE_MODE: - 0 : Address match on BRK_ADDR0 or BRK_ADDR1 -// - 1 : Address match on BRK_ADDR0->BRK_ADDR1 range -// -//----------------------------------------------------------------------------- -reg [4:0] brk_ctl; - -wire brk_ctl_wr = brk_reg_wr[BRK_CTL]; - -always @ (posedge mclk or posedge por) - if (por) brk_ctl <= 5'h00; - else if (brk_ctl_wr) brk_ctl <= dbg_din[4:0]; - -wire [7:0] brk_ctl_full = {3'b000, brk_ctl}; - - -// BRK_STAT Register -//----------------------------------------------------------------------------- -// 7 6 5 4 3 2 1 0 -// Reserved RANGE_WR RANGE_RD ADDR1_WR ADDR1_RD ADDR0_WR ADDR0_RD -//----------------------------------------------------------------------------- -reg [5:0] brk_stat; - -wire brk_stat_wr = brk_reg_wr[BRK_STAT]; -wire [5:0] brk_stat_set = {range_wr_set, range_rd_set, - addr1_wr_set, addr1_rd_set, - addr0_wr_set, addr0_rd_set}; -wire [5:0] brk_stat_clr = ~dbg_din[5:0]; - -always @ (posedge mclk or posedge por) - if (por) brk_stat <= 6'h00; - else if (brk_stat_wr) brk_stat <= ((brk_stat & brk_stat_clr) | brk_stat_set); - else brk_stat <= (brk_stat | brk_stat_set); - -wire [7:0] brk_stat_full = {2'b00, brk_stat}; -wire brk_pnd = |brk_stat; - - -// BRK_ADDR0 Register -//----------------------------------------------------------------------------- -reg [15:0] brk_addr0; - -wire brk_addr0_wr = brk_reg_wr[BRK_ADDR0]; - -always @ (posedge mclk or posedge por) - if (por) brk_addr0 <= 16'h0000; - else if (brk_addr0_wr) brk_addr0 <= dbg_din; - - -// BRK_ADDR1/DATA0 Register -//----------------------------------------------------------------------------- -reg [15:0] brk_addr1; - -wire brk_addr1_wr = brk_reg_wr[BRK_ADDR1]; - -always @ (posedge mclk or posedge por) - if (por) brk_addr1 <= 16'h0000; - else if (brk_addr1_wr) brk_addr1 <= dbg_din; - - -//============================================================================ -// 3) DATA OUTPUT GENERATION -//============================================================================ - -wire [15:0] brk_ctl_rd = {8'h00, brk_ctl_full} & {16{brk_reg_rd[BRK_CTL]}}; -wire [15:0] brk_stat_rd = {8'h00, brk_stat_full} & {16{brk_reg_rd[BRK_STAT]}}; -wire [15:0] brk_addr0_rd = brk_addr0 & {16{brk_reg_rd[BRK_ADDR0]}}; -wire [15:0] brk_addr1_rd = brk_addr1 & {16{brk_reg_rd[BRK_ADDR1]}}; - -wire [15:0] brk_dout = brk_ctl_rd | - brk_stat_rd | - brk_addr0_rd | - brk_addr1_rd; - - -//============================================================================ -// 4) BREAKPOINT / WATCHPOINT GENERATION -//============================================================================ - -// Comparators -//--------------------------- -// Note: here the comparison logic is instanciated several times in order -// to improve the timings, at the cost of a bit more area. - -wire equ_d_addr0 = eu_mb_en & (eu_mab==brk_addr0) & ~brk_ctl[`BRK_RANGE]; -wire equ_d_addr1 = eu_mb_en & (eu_mab==brk_addr1) & ~brk_ctl[`BRK_RANGE]; -wire equ_d_range = eu_mb_en & ((eu_mab>=brk_addr0) & (eu_mab<=brk_addr1)) & brk_ctl[`BRK_RANGE]; - -reg fe_mb_en_buf; -always @ (posedge mclk or posedge por) - if (por) fe_mb_en_buf <= 1'b0; - else fe_mb_en_buf <= fe_mb_en; - -wire equ_i_addr0 = fe_mb_en_buf & (pc==brk_addr0) & ~brk_ctl[`BRK_RANGE]; -wire equ_i_addr1 = fe_mb_en_buf & (pc==brk_addr1) & ~brk_ctl[`BRK_RANGE]; -wire equ_i_range = fe_mb_en_buf & ((pc>=brk_addr0) & (pc<=brk_addr1)) & brk_ctl[`BRK_RANGE]; - - -// Detect accesses -//--------------------------- - -// Detect Instruction read access -wire i_addr0_rd = equ_i_addr0 & brk_ctl[`BRK_I_EN]; -wire i_addr1_rd = equ_i_addr1 & brk_ctl[`BRK_I_EN]; -wire i_range_rd = equ_i_range & brk_ctl[`BRK_I_EN]; - -// Detect Execution-Unit write access -wire d_addr0_wr = equ_d_addr0 & ~brk_ctl[`BRK_I_EN] & |eu_mb_wr; -wire d_addr1_wr = equ_d_addr1 & ~brk_ctl[`BRK_I_EN] & |eu_mb_wr; -wire d_range_wr = equ_d_range & ~brk_ctl[`BRK_I_EN] & |eu_mb_wr; - -// Detect DATA read access -// Whenever an "ADD r9. &0x200" instruction is executed, &0x200 will be read -// before being written back. In that case, the read flag should not be set. -// In general, We should here make sure no write access occures during the -// same instruction cycle before setting the read flag. -reg [2:0] d_rd_trig; -always @ (posedge mclk or posedge por) - if (por) d_rd_trig <= 3'h0; - else if (exec_done) d_rd_trig <= 3'h0; - else d_rd_trig <= {equ_d_range & ~brk_ctl[`BRK_I_EN] & ~|eu_mb_wr, - equ_d_addr1 & ~brk_ctl[`BRK_I_EN] & ~|eu_mb_wr, - equ_d_addr0 & ~brk_ctl[`BRK_I_EN] & ~|eu_mb_wr}; - -wire d_addr0_rd = d_rd_trig[0] & exec_done & ~d_addr0_wr; -wire d_addr1_rd = d_rd_trig[1] & exec_done & ~d_addr1_wr; -wire d_range_rd = d_rd_trig[2] & exec_done & ~d_range_wr; - - -// Set flags -assign addr0_rd_set = brk_ctl[`BRK_MODE_RD] & (d_addr0_rd | i_addr0_rd); -assign addr0_wr_set = brk_ctl[`BRK_MODE_WR] & d_addr0_wr; -assign addr1_rd_set = brk_ctl[`BRK_MODE_RD] & (d_addr1_rd | i_addr1_rd); -assign addr1_wr_set = brk_ctl[`BRK_MODE_WR] & d_addr1_wr; -assign range_rd_set = brk_ctl[`BRK_MODE_RD] & (d_range_rd | i_range_rd); -assign range_wr_set = brk_ctl[`BRK_MODE_WR] & d_range_wr; - - -// Break CPU -assign brk_halt = brk_ctl[`BRK_EN] & |brk_stat_set; - - -endmodule // dbg_hwbrk - -`include "openMSP430_undefines.v"
dbg_hwbrk.v Property changes : Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Date Revision Author \ No newline at end of property Index: omsp_frontend.v =================================================================== --- omsp_frontend.v (nonexistent) +++ omsp_frontend.v (revision 34) @@ -0,0 +1,758 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2001 Authors +// +// This source file may be used and distributed without restriction provided +// that this copyright statement is not removed from the file and that any +// derivative work contains the original copyright notice and the associated +// disclaimer. +// +// This source file is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This source is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +// License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this source; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_frontend.v +// +// *Module Description: +// openMSP430 Instruction fetch and decode unit +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev$ +// $LastChangedBy$ +// $LastChangedDate$ +//---------------------------------------------------------------------------- +`include "timescale.v" +`include "openMSP430_defines.v" + +module omsp_frontend ( + +// OUTPUTs + dbg_halt_st, // Halt/Run status from CPU + decode, // Frontend decode instruction + e_state, // Execution state + exec_done, // Execution completed + inst_ad, // Decoded Inst: destination addressing mode + inst_as, // Decoded Inst: source addressing mode + inst_alu, // ALU control signals + inst_bw, // Decoded Inst: byte width + inst_dest, // Decoded Inst: destination (one hot) + inst_dext, // Decoded Inst: destination extended instruction word + inst_irq_rst, // Decoded Inst: Reset interrupt + inst_jmp, // Decoded Inst: Conditional jump + inst_sext, // Decoded Inst: source extended instruction word + inst_so, // Decoded Inst: Single-operand arithmetic + inst_src, // Decoded Inst: source (one hot) + inst_type, // Decoded Instruction type + irq_acc, // Interrupt request accepted (one-hot signal) + mab, // Frontend Memory address bus + mb_en, // Frontend Memory bus enable + nmi_acc, // Non-Maskable interrupt request accepted + pc, // Program counter + pc_nxt, // Next PC value (for CALL & IRQ) + +// INPUTs + cpuoff, // Turns off the CPU + dbg_halt_cmd, // Halt CPU command + dbg_reg_sel, // Debug selected register for rd/wr access + fe_pmem_wait, // Frontend wait for Instruction fetch + gie, // General interrupt enable + irq, // Maskable interrupts + mclk, // Main system clock + mdb_in, // Frontend Memory data bus input + nmi_evt, // Non-maskable interrupt event + pc_sw, // Program counter software value + pc_sw_wr, // Program counter software write + puc, // Main system reset + wdt_irq // Watchdog-timer interrupt +); + +// OUTPUTs +//========= +output dbg_halt_st; // Halt/Run status from CPU +output decode; // Frontend decode instruction +output [3:0] e_state; // Execution state +output exec_done; // Execution completed +output [7:0] inst_ad; // Decoded Inst: destination addressing mode +output [7:0] inst_as; // Decoded Inst: source addressing mode +output [11:0] inst_alu; // ALU control signals +output inst_bw; // Decoded Inst: byte width +output [15:0] inst_dest; // Decoded Inst: destination (one hot) +output [15:0] inst_dext; // Decoded Inst: destination extended instruction word +output inst_irq_rst; // Decoded Inst: Reset interrupt +output [7:0] inst_jmp; // Decoded Inst: Conditional jump +output [15:0] inst_sext; // Decoded Inst: source extended instruction word +output [7:0] inst_so; // Decoded Inst: Single-operand arithmetic +output [15:0] inst_src; // Decoded Inst: source (one hot) +output [2:0] inst_type; // Decoded Instruction type +output [13:0] irq_acc; // Interrupt request accepted (one-hot signal) +output [15:0] mab; // Frontend Memory address bus +output mb_en; // Frontend Memory bus enable +output nmi_acc; // Non-Maskable interrupt request accepted +output [15:0] pc; // Program counter +output [15:0] pc_nxt; // Next PC value (for CALL & IRQ) + +// INPUTs +//========= +input cpuoff; // Turns off the CPU +input dbg_halt_cmd; // Halt CPU command +input [3:0] dbg_reg_sel; // Debug selected register for rd/wr access +input fe_pmem_wait; // Frontend wait for Instruction fetch +input gie; // General interrupt enable +input [13:0] irq; // Maskable interrupts +input mclk; // Main system clock +input [15:0] mdb_in; // Frontend Memory data bus input +input nmi_evt; // Non-maskable interrupt event +input [15:0] pc_sw; // Program counter software value +input pc_sw_wr; // Program counter software write +input puc; // Main system reset +input wdt_irq; // Watchdog-timer interrupt + + +//============================================================================= +// 1) FRONTEND STATE MACHINE +//============================================================================= + +// The wire "conv" is used as state bits to calculate the next response +reg [2:0] i_state; +reg [2:0] i_state_nxt; + +reg [1:0] inst_sz; +wire [1:0] inst_sz_nxt; +wire irq_detect; +wire [2:0] inst_type_nxt; +wire is_const; +reg [15:0] sconst_nxt; +reg [3:0] e_state_nxt; + +// State machine definitons +parameter I_IRQ_FETCH = 3'h0; +parameter I_IRQ_DONE = 3'h1; +parameter I_DEC = 3'h2; // New instruction ready for decode +parameter I_EXT1 = 3'h3; // 1st Extension word +parameter I_EXT2 = 3'h4; // 2nd Extension word +parameter I_IDLE = 3'h5; // CPU is in IDLE mode + +// States Transitions +always @(i_state or inst_sz or inst_sz_nxt or pc_sw_wr or exec_done or + exec_done or irq_detect or cpuoff or dbg_halt_cmd or e_state) + case(i_state) + I_IDLE : i_state_nxt = (irq_detect & ~dbg_halt_cmd) ? I_IRQ_FETCH : + (~cpuoff & ~dbg_halt_cmd) ? I_DEC : I_IDLE; + I_IRQ_FETCH: i_state_nxt = I_IRQ_DONE; + I_IRQ_DONE : i_state_nxt = I_DEC; + I_DEC : i_state_nxt = irq_detect ? I_IRQ_FETCH : + (cpuoff | dbg_halt_cmd) & exec_done ? I_IDLE : + dbg_halt_cmd & (e_state==`E_IDLE) ? I_IDLE : + pc_sw_wr ? I_DEC : + ~exec_done & ~(e_state==`E_IDLE) ? I_DEC : // Wait in decode state + (inst_sz_nxt!=2'b00) ? I_EXT1 : I_DEC; // until execution is completed + I_EXT1 : i_state_nxt = irq_detect ? I_IRQ_FETCH : + pc_sw_wr ? I_DEC : + (inst_sz!=2'b01) ? I_EXT2 : I_DEC; + I_EXT2 : i_state_nxt = irq_detect ? I_IRQ_FETCH : I_DEC; + default : i_state_nxt = I_IRQ_FETCH; + endcase + +// State machine +always @(posedge mclk or posedge puc) + if (puc) i_state <= I_IRQ_FETCH; + else i_state <= i_state_nxt; + +// Utility signals +wire decode = ((i_state==I_DEC) & (exec_done | (e_state==`E_IDLE))) | irq_detect; +wire fetch = ~((i_state==I_DEC) & ~(exec_done | (e_state==`E_IDLE))) & ~(e_state_nxt==`E_IDLE); + +// Debug interface cpu status +reg dbg_halt_st; +always @(posedge mclk or posedge puc) + if (puc) dbg_halt_st <= 1'b0; + else dbg_halt_st <= dbg_halt_cmd & (i_state_nxt==I_IDLE); + + +//============================================================================= +// 2) INTERRUPT HANDLING +//============================================================================= + +// Detect nmi interrupt +reg inst_nmi; +always @(posedge mclk or posedge puc) + if (puc) inst_nmi <= 1'b0; + else if (nmi_evt) inst_nmi <= 1'b1; + else if (i_state==I_IRQ_DONE) inst_nmi <= 1'b0; + + +// Detect reset interrupt +reg inst_irq_rst; +always @(posedge mclk or posedge puc) + if (puc) inst_irq_rst <= 1'b1; + else if (exec_done) inst_irq_rst <= 1'b0; + +// Detect other interrupts +assign irq_detect = (inst_nmi | ((|irq | wdt_irq) & gie)) & ~dbg_halt_cmd & (exec_done | (i_state==I_IDLE)); + +// Select interrupt vector +reg [3:0] irq_num; +always @(posedge mclk or posedge puc) + if (puc) irq_num <= 4'hf; + else if (irq_detect) irq_num <= inst_nmi ? 4'he : + irq[13] ? 4'hd : + irq[12] ? 4'hc : + irq[11] ? 4'hb : + (irq[10] | wdt_irq) ? 4'ha : + irq[9] ? 4'h9 : + irq[8] ? 4'h8 : + irq[7] ? 4'h7 : + irq[6] ? 4'h6 : + irq[5] ? 4'h5 : + irq[4] ? 4'h4 : + irq[3] ? 4'h3 : + irq[2] ? 4'h2 : + irq[1] ? 4'h1 : + irq[0] ? 4'h0 : 4'hf; + +wire [15:0] irq_addr = {11'h7ff, irq_num, 1'b0}; + +// Interrupt request accepted +wire [15:0] irq_acc_all = (16'h0001 << irq_num) & {16{(i_state==I_IRQ_FETCH)}}; +wire [13:0] irq_acc = irq_acc_all[13:0]; +wire nmi_acc = irq_acc_all[14]; + + +//============================================================================= +// 3) FETCH INSTRUCTION +//============================================================================= + +// +// 3.1) PROGRAM COUNTER & MEMORY INTERFACE +//----------------------------------------- + +// Program counter +reg [15:0] pc; + +// Detect if PC needs to be incremented +wire pc_inc = (~pc_sw_wr & fetch) & ~(i_state==I_IRQ_FETCH) & ~(i_state==I_IRQ_DONE); + +// Mux between software update and old PC +wire [15:0] pc_sel = pc_sw_wr ? pc_sw : + (i_state==I_IRQ_FETCH) ? irq_addr : + (i_state==I_IRQ_DONE) ? mdb_in : pc; + +// Compute next PC value +wire [15:0] pc_nxt = pc_sel + {14'h0000, pc_inc, 1'b0}; + +always @(posedge mclk or posedge puc) + if (puc) pc <= 16'h0000; + else pc <= pc_nxt; + +// Check if ROM has been busy in order to retry ROM access +reg pmem_busy; +always @(posedge mclk or posedge puc) + if (puc) pmem_busy <= 16'h0000; + else pmem_busy <= fe_pmem_wait; + +// Memory interface +wire [15:0] mab = pc_nxt; +wire mb_en = fetch | pc_sw_wr | (i_state==I_IRQ_FETCH) | pmem_busy | (dbg_halt_st & ~dbg_halt_cmd); + + +// +// 3.2) INSTRUCTION REGISTER +//-------------------------------- + +// Instruction register +wire [15:0] ir = mdb_in; + +// Detect if source extension word is required +wire is_sext = (inst_as[`IDX] | inst_as[`SYMB] | inst_as[`ABS] | inst_as[`IMM]); + +// Detect if destination extension word is required +wire is_dext = (inst_ad[`IDX] | inst_ad[`SYMB] | inst_ad[`ABS]); + +// For the Symbolic addressing mode, add -2 to the extension word in order +// to make up for the PC address +wire [15:0] ext_incr = ((i_state==I_EXT1) & inst_as[`SYMB]) | + ((i_state==I_EXT2) & inst_ad[`SYMB]) | + ((i_state==I_EXT1) & ~inst_as[`SYMB] & + ~(i_state_nxt==I_EXT2) & inst_ad[`SYMB]) ? 16'hfffe : 16'h0000; + +wire [15:0] ext_nxt = ir + ext_incr; + +// Store source extension word +reg [15:0] inst_sext; +always @(posedge mclk or posedge puc) + if (puc) inst_sext <= 16'h0000; + else if (decode & is_const) inst_sext <= sconst_nxt; + else if (decode & inst_type_nxt[`INST_JMP]) inst_sext <= {{5{ir[9]}},ir[9:0],1'b0}; + else if ((i_state==I_EXT1) & is_sext) inst_sext <= ext_nxt; + +// Source extension word is ready +wire inst_sext_rdy = (i_state==I_EXT1) & is_sext; + + +// Store destination extension word +reg [15:0] inst_dext; +always @(posedge mclk or posedge puc) + if (puc) inst_dext <= 16'h0000; + else if ((i_state==I_EXT1) & ~is_sext) inst_dext <= ext_nxt; + else if (i_state==I_EXT2) inst_dext <= ext_nxt; + +// Destination extension word is ready +wire inst_dext_rdy = (((i_state==I_EXT1) & ~is_sext) | (i_state==I_EXT2)); + + +//============================================================================= +// 4) DECODE INSTRUCTION +//============================================================================= + +// +// 4.1) OPCODE: INSTRUCTION TYPE +//---------------------------------------- +// Instructions type is encoded in a one hot fashion as following: +// +// 3'b001: Single-operand arithmetic +// 3'b010: Conditional jump +// 3'b100: Two-operand arithmetic + +reg [2:0] inst_type; +assign inst_type_nxt = {(ir[15:14]!=2'b00), + (ir[15:13]==3'b001), + (ir[15:13]==3'b000)} & {3{~irq_detect}}; + +always @(posedge mclk or posedge puc) + if (puc) inst_type <= 3'b000; + else if (decode) inst_type <= inst_type_nxt; + +// +// 4.2) OPCODE: SINGLE-OPERAND ARITHMETIC +//---------------------------------------- +// Instructions are encoded in a one hot fashion as following: +// +// 8'b00000001: RRC +// 8'b00000010: SWPB +// 8'b00000100: RRA +// 8'b00001000: SXT +// 8'b00010000: PUSH +// 8'b00100000: CALL +// 8'b01000000: RETI +// 8'b10000000: IRQ + +reg [7:0] inst_so; +wire [7:0] inst_so_nxt = irq_detect ? 8'h80 : ((8'h01<
omsp_frontend.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Date Revision Author \ No newline at end of property Index: omsp_alu.v =================================================================== --- omsp_alu.v (nonexistent) +++ omsp_alu.v (revision 34) @@ -0,0 +1,248 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2001 Authors +// +// This source file may be used and distributed without restriction provided +// that this copyright statement is not removed from the file and that any +// derivative work contains the original copyright notice and the associated +// disclaimer. +// +// This source file is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This source is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +// License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this source; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_alu.v +// +// *Module Description: +// openMSP430 ALU +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev$ +// $LastChangedBy$ +// $LastChangedDate$ +//---------------------------------------------------------------------------- +`include "timescale.v" +`include "openMSP430_defines.v" + +module omsp_alu ( + +// OUTPUTs + alu_out, // ALU output value + alu_out_add, // ALU adder output value + alu_stat, // ALU Status {V,N,Z,C} + alu_stat_wr, // ALU Status write {V,N,Z,C} + +// INPUTs + dbg_halt_st, // Halt/Run status from CPU + exec_cycle, // Instruction execution cycle + inst_alu, // ALU control signals + inst_bw, // Decoded Inst: byte width + inst_jmp, // Decoded Inst: Conditional jump + inst_so, // Single-operand arithmetic + op_dst, // Destination operand + op_src, // Source operand + status // R2 Status {V,N,Z,C} +); + +// OUTPUTs +//========= +output [15:0] alu_out; // ALU output value +output [15:0] alu_out_add; // ALU adder output value +output [3:0] alu_stat; // ALU Status {V,N,Z,C} +output [3:0] alu_stat_wr; // ALU Status write {V,N,Z,C} + +// INPUTs +//========= +input dbg_halt_st; // Halt/Run status from CPU +input exec_cycle; // Instruction execution cycle +input [11:0] inst_alu; // ALU control signals +input inst_bw; // Decoded Inst: byte width +input [7:0] inst_jmp; // Decoded Inst: Conditional jump +input [7:0] inst_so; // Single-operand arithmetic +input [15:0] op_dst; // Destination operand +input [15:0] op_src; // Source operand +input [3:0] status; // R2 Status {V,N,Z,C} + + +//============================================================================= +// 1) FUNCTIONS +//============================================================================= + +function [4:0] bcd_add; + + input [3:0] X; + input [3:0] Y; + input C; + + reg [4:0] Z; + begin + Z = {1'b0,X}+{1'b0,Y}+C; + if (Z<10) bcd_add = Z; + else bcd_add = Z+6; + end + +endfunction + + +//============================================================================= +// 2) INSTRUCTION FETCH/DECODE CONTROL STATE MACHINE +//============================================================================= +// SINGLE-OPERAND ARITHMETIC: +//----------------------------------------------------------------------------- +// Mnemonic S-Reg, Operation Status bits +// D-Reg, V N Z C +// +// RRC dst C->MSB->...LSB->C * * * * +// RRA dst MSB->MSB->...LSB->C 0 * * * +// SWPB dst Swap bytes - - - - +// SXT dst Bit7->Bit8...Bit15 0 * * * +// PUSH src SP-2->SP, src->@SP - - - - +// CALL dst SP-2->SP, PC+2->@SP, dst->PC - - - - +// RETI TOS->SR, SP+2->SP, TOS->PC, SP+2->SP * * * * +// +//----------------------------------------------------------------------------- +// TWO-OPERAND ARITHMETIC: +//----------------------------------------------------------------------------- +// Mnemonic S-Reg, Operation Status bits +// D-Reg, V N Z C +// +// MOV src,dst src -> dst - - - - +// ADD src,dst src + dst -> dst * * * * +// ADDC src,dst src + dst + C -> dst * * * * +// SUB src,dst dst + ~src + 1 -> dst * * * * +// SUBC src,dst dst + ~src + C -> dst * * * * +// CMP src,dst dst + ~src + 1 * * * * +// DADD src,dst src + dst + C -> dst (decimaly) * * * * +// BIT src,dst src & dst 0 * * * +// BIC src,dst ~src & dst -> dst - - - - +// BIS src,dst src | dst -> dst - - - - +// XOR src,dst src ^ dst -> dst * * * * +// AND src,dst src & dst -> dst 0 * * * +// +//----------------------------------------------------------------------------- +// * the status bit is affected +// - the status bit is not affected +// 0 the status bit is cleared +// 1 the status bit is set +//----------------------------------------------------------------------------- + +// Invert source for substract and compare instructions. +wire op_src_inv_cmd = exec_cycle & (inst_alu[`ALU_SRC_INV]); +wire [15:0] op_src_inv = {16{op_src_inv_cmd}} ^ op_src; + + +// Mask the bit 8 for the Byte instructions for correct flags generation +wire op_bit8_msk = ~exec_cycle | ~inst_bw; +wire [16:0] op_src_in = {1'b0, op_src_inv[15:9], op_src_inv[8] & op_bit8_msk, op_src_inv[7:0]}; +wire [16:0] op_dst_in = {1'b0, op_dst[15:9], op_dst[8] & op_bit8_msk, op_dst[7:0]}; + +// Clear the source operand (= jump offset) for conditional jumps +wire jmp_not_taken = (inst_jmp[`JL] & ~(status[3]^status[2])) | + (inst_jmp[`JGE] & (status[3]^status[2])) | + (inst_jmp[`JN] & ~status[2]) | + (inst_jmp[`JC] & ~status[0]) | + (inst_jmp[`JNC] & status[0]) | + (inst_jmp[`JEQ] & ~status[1]) | + (inst_jmp[`JNE] & status[1]); +wire [16:0] op_src_in_jmp = op_src_in & {17{~jmp_not_taken}}; + +// Adder / AND / OR / XOR +wire [16:0] alu_add = op_src_in_jmp + op_dst_in; +wire [16:0] alu_and = op_src_in & op_dst_in; +wire [16:0] alu_or = op_src_in | op_dst_in; +wire [16:0] alu_xor = op_src_in ^ op_dst_in; + + +// Incrementer +wire alu_inc = exec_cycle & ((inst_alu[`ALU_INC_C] & status[0]) | + inst_alu[`ALU_INC]); +wire [16:0] alu_add_inc = alu_add + {16'h0000, alu_inc}; + + + +// Decimal adder (DADD) +wire [4:0] alu_dadd0 = bcd_add(op_src_in[3:0], op_dst_in[3:0], status[0]); +wire [4:0] alu_dadd1 = bcd_add(op_src_in[7:4], op_dst_in[7:4], alu_dadd0[4]); +wire [4:0] alu_dadd2 = bcd_add(op_src_in[11:8], op_dst_in[11:8], alu_dadd1[4]); +wire [4:0] alu_dadd3 = bcd_add(op_src_in[15:12], op_dst_in[15:12],alu_dadd2[4]); +wire [16:0] alu_dadd = {alu_dadd3, alu_dadd2[3:0], alu_dadd1[3:0], alu_dadd0[3:0]}; + + +// Shifter for rotate instructions (RRC & RRA) +wire alu_shift_msb = inst_so[`RRC] ? status[0] : + inst_bw ? op_src[7] : op_src[15]; +wire alu_shift_7 = inst_bw ? alu_shift_msb : op_src[8]; +wire [16:0] alu_shift = {1'b0, alu_shift_msb, op_src[15:9], alu_shift_7, op_src[7:1]}; + + +// Swap bytes / Extend Sign +wire [16:0] alu_swpb = {1'b0, op_src[7:0],op_src[15:8]}; +wire [16:0] alu_sxt = {1'b0, {8{op_src[7]}},op_src[7:0]}; + + +// Combine short paths toghether to simplify final ALU mux +wire alu_short_thro = ~(inst_alu[`ALU_AND] | + inst_alu[`ALU_OR] | + inst_alu[`ALU_XOR] | + inst_alu[`ALU_SHIFT] | + inst_so[`SWPB] | + inst_so[`SXT]); + +wire [16:0] alu_short = ({16{inst_alu[`ALU_AND]}} & alu_and) | + ({16{inst_alu[`ALU_OR]}} & alu_or) | + ({16{inst_alu[`ALU_XOR]}} & alu_xor) | + ({16{inst_alu[`ALU_SHIFT]}} & alu_shift) | + ({16{inst_so[`SWPB]}} & alu_swpb) | + ({16{inst_so[`SXT]}} & alu_sxt) | + ({16{alu_short_thro}} & op_src_in); + + +// ALU output mux +wire [16:0] alu_out_nxt = (inst_so[`IRQ] | dbg_halt_st | + inst_alu[`ALU_ADD]) ? alu_add_inc : + inst_alu[`ALU_DADD] ? alu_dadd : alu_short; + +assign alu_out = alu_out_nxt[15:0]; +assign alu_out_add = alu_add[15:0]; + + +//----------------------------------------------------------------------------- +// STATUS FLAG GENERATION +//----------------------------------------------------------------------------- + +wire V_xor = inst_bw ? (op_src_in[7] & op_dst_in[7]) : + (op_src_in[15] & op_dst_in[15]); + +wire V = inst_bw ? ((~op_src_in[7] & ~op_dst_in[7] & alu_out[7]) | + ( op_src_in[7] & op_dst_in[7] & ~alu_out[7])) : + ((~op_src_in[15] & ~op_dst_in[15] & alu_out[15]) | + ( op_src_in[15] & op_dst_in[15] & ~alu_out[15])); + +wire N = inst_bw ? alu_out[7] : alu_out[15]; +wire Z = inst_bw ? (alu_out[7:0]==0) : (alu_out==0); +wire C = inst_bw ? alu_out[8] : alu_out_nxt[16]; + +assign alu_stat = inst_alu[`ALU_SHIFT] ? {1'b0, N,Z,op_src_in[0]} : + inst_alu[`ALU_STAT_7] ? {1'b0, N,Z,~Z} : + inst_alu[`ALU_XOR] ? {V_xor,N,Z,~Z} : {V,N,Z,C}; + +assign alu_stat_wr = (inst_alu[`ALU_STAT_F] & exec_cycle) ? 4'b1111 : 4'b0000; + + +endmodule // omsp_alu + +`include "openMSP430_undefines.v"
omsp_alu.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Date Revision Author \ No newline at end of property Index: omsp_register_file.v =================================================================== --- omsp_register_file.v (nonexistent) +++ omsp_register_file.v (revision 34) @@ -0,0 +1,345 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2001 Authors +// +// This source file may be used and distributed without restriction provided +// that this copyright statement is not removed from the file and that any +// derivative work contains the original copyright notice and the associated +// disclaimer. +// +// This source file is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This source is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +// License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this source; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_register_file.v +// +// *Module Description: +// openMSP430 Register files +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev$ +// $LastChangedBy$ +// $LastChangedDate$ +//---------------------------------------------------------------------------- +`include "timescale.v" +`include "openMSP430_defines.v" + +module omsp_register_file ( + +// OUTPUTs + cpuoff, // Turns off the CPU + gie, // General interrupt enable + oscoff, // Turns off LFXT1 clock input + pc_sw, // Program counter software value + pc_sw_wr, // Program counter software write + reg_dest, // Selected register destination content + reg_src, // Selected register source content + scg1, // System clock generator 1. Turns off the SMCLK + status, // R2 Status {V,N,Z,C} + +// INPUTs + alu_stat, // ALU Status {V,N,Z,C} + alu_stat_wr, // ALU Status write {V,N,Z,C} + inst_bw, // Decoded Inst: byte width + inst_dest, // Register destination selection + inst_src, // Register source selection + mclk, // Main system clock + pc, // Program counter + puc, // Main system reset + reg_dest_val, // Selected register destination value + reg_dest_wr, // Write selected register destination + reg_pc_call, // Trigger PC update for a CALL instruction + reg_sp_val, // Stack Pointer next value + reg_sp_wr, // Stack Pointer write + reg_sr_wr, // Status register update for RETI instruction + reg_sr_clr, // Status register clear for interrupts + reg_incr // Increment source register +); + +// OUTPUTs +//========= +output cpuoff; // Turns off the CPU +output gie; // General interrupt enable +output oscoff; // Turns off LFXT1 clock input +output [15:0] pc_sw; // Program counter software value +output pc_sw_wr; // Program counter software write +output [15:0] reg_dest; // Selected register destination content +output [15:0] reg_src; // Selected register source content +output scg1; // System clock generator 1. Turns off the SMCLK +output [3:0] status; // R2 Status {V,N,Z,C} + +// INPUTs +//========= +input [3:0] alu_stat; // ALU Status {V,N,Z,C} +input [3:0] alu_stat_wr; // ALU Status write {V,N,Z,C} +input inst_bw; // Decoded Inst: byte width +input [15:0] inst_dest; // Register destination selection +input [15:0] inst_src; // Register source selection +input mclk; // Main system clock +input [15:0] pc; // Program counter +input puc; // Main system reset +input [15:0] reg_dest_val; // Selected register destination value +input reg_dest_wr; // Write selected register destination +input reg_pc_call; // Trigger PC update for a CALL instruction +input [15:0] reg_sp_val; // Stack Pointer next value +input reg_sp_wr; // Stack Pointer write +input reg_sr_wr; // Status register update for RETI instruction +input reg_sr_clr; // Status register clear for interrupts +input reg_incr; // Increment source register + + +//============================================================================= +// 1) AUTOINCREMENT UNIT +//============================================================================= + +wire [15:0] incr_op = inst_bw ? 16'h0001 : 16'h0002; +wire [15:0] reg_incr_val = reg_src+incr_op; + +wire [15:0] reg_dest_val_in = inst_bw ? {8'h00,reg_dest_val[7:0]} : reg_dest_val; + + +//============================================================================= +// 2) SPECIAL REGISTERS (R1/R2/R3) +//============================================================================= + +// Source input selection mask (for interrupt support) +//----------------------------------------------------- + +wire [15:0] inst_src_in = reg_sr_clr ? 16'h0004 : inst_src; + + +// R0: Program counter +//--------------------- + +wire [15:0] r0 = pc; + +wire [15:0] pc_sw = reg_dest_val_in; +wire pc_sw_wr = (inst_dest[0] & reg_dest_wr) | reg_pc_call; + + +// R1: Stack pointer +//------------------- +reg [15:0] r1; +wire r1_wr = inst_dest[1] & reg_dest_wr; +wire r1_inc = inst_src_in[1] & reg_incr; + +always @(posedge mclk or posedge puc) + if (puc) r1 <= 16'h0000; + else if (r1_wr) r1 <= reg_dest_val_in & 16'hfffe; + else if (reg_sp_wr) r1 <= reg_sp_val & 16'hfffe; + else if (r1_inc) r1 <= reg_incr_val & 16'hfffe; + + +// R2: Status register +//--------------------- +reg [15:0] r2; +wire r2_wr = (inst_dest[2] & reg_dest_wr) | reg_sr_wr; + +wire r2_c = alu_stat_wr[0] ? alu_stat[0] : + r2_wr ? reg_dest_val_in[0] : r2[0]; // C + +wire r2_z = alu_stat_wr[1] ? alu_stat[1] : + r2_wr ? reg_dest_val_in[1] : r2[1]; // Z + +wire r2_n = alu_stat_wr[2] ? alu_stat[2] : + r2_wr ? reg_dest_val_in[2] : r2[2]; // N + +wire [7:3] r2_nxt = r2_wr ? reg_dest_val_in[7:3] : r2[7:3]; + +wire r2_v = alu_stat_wr[3] ? alu_stat[3] : + r2_wr ? reg_dest_val_in[8] : r2[8]; // V + + +always @(posedge mclk or posedge puc) + if (puc) r2 <= 16'h0000; + else if (reg_sr_clr) r2 <= 16'h0000; + else r2 <= {7'h00, r2_v, r2_nxt, r2_n, r2_z, r2_c}; + +assign status = {r2[8], r2[2:0]}; +assign gie = r2[3]; +assign cpuoff = r2[4] | (r2_nxt[4] & r2_wr); +assign oscoff = r2[5]; +assign scg1 = r2[7]; + + +// R3: Constant generator +//------------------------ +reg [15:0] r3; +wire r3_wr = inst_dest[3] & reg_dest_wr; +wire r3_inc = inst_src_in[3] & reg_incr; + +always @(posedge mclk or posedge puc) + if (puc) r3 <= 16'h0000; + else if (r3_wr) r3 <= reg_dest_val_in; + else if (r3_inc) r3 <= reg_incr_val; + + +//============================================================================= +// 4) GENERAL PURPOSE REGISTERS (R4...R15) +//============================================================================= + +// R4 +reg [15:0] r4; +wire r4_wr = inst_dest[4] & reg_dest_wr; +wire r4_inc = inst_src_in[4] & reg_incr; +always @(posedge mclk or posedge puc) + if (puc) r4 <= 16'h0000; + else if (r4_wr) r4 <= reg_dest_val_in; + else if (r4_inc) r4 <= reg_incr_val; + +// R5 +reg [15:0] r5; +wire r5_wr = inst_dest[5] & reg_dest_wr; +wire r5_inc = inst_src_in[5] & reg_incr; +always @(posedge mclk or posedge puc) + if (puc) r5 <= 16'h0000; + else if (r5_wr) r5 <= reg_dest_val_in; + else if (r5_inc) r5 <= reg_incr_val; + +// R6 +reg [15:0] r6; +wire r6_wr = inst_dest[6] & reg_dest_wr; +wire r6_inc = inst_src_in[6] & reg_incr; +always @(posedge mclk or posedge puc) + if (puc) r6 <= 16'h0000; + else if (r6_wr) r6 <= reg_dest_val_in; + else if (r6_inc) r6 <= reg_incr_val; + +// R7 +reg [15:0] r7; +wire r7_wr = inst_dest[7] & reg_dest_wr; +wire r7_inc = inst_src_in[7] & reg_incr; +always @(posedge mclk or posedge puc) + if (puc) r7 <= 16'h0000; + else if (r7_wr) r7 <= reg_dest_val_in; + else if (r7_inc) r7 <= reg_incr_val; + +// R8 +reg [15:0] r8; +wire r8_wr = inst_dest[8] & reg_dest_wr; +wire r8_inc = inst_src_in[8] & reg_incr; +always @(posedge mclk or posedge puc) + if (puc) r8 <= 16'h0000; + else if (r8_wr) r8 <= reg_dest_val_in; + else if (r8_inc) r8 <= reg_incr_val; + +// R9 +reg [15:0] r9; +wire r9_wr = inst_dest[9] & reg_dest_wr; +wire r9_inc = inst_src_in[9] & reg_incr; +always @(posedge mclk or posedge puc) + if (puc) r9 <= 16'h0000; + else if (r9_wr) r9 <= reg_dest_val_in; + else if (r9_inc) r9 <= reg_incr_val; + +// R10 +reg [15:0] r10; +wire r10_wr = inst_dest[10] & reg_dest_wr; +wire r10_inc = inst_src_in[10] & reg_incr; +always @(posedge mclk or posedge puc) + if (puc) r10 <= 16'h0000; + else if (r10_wr) r10 <= reg_dest_val_in; + else if (r10_inc) r10 <= reg_incr_val; + +// R11 +reg [15:0] r11; +wire r11_wr = inst_dest[11] & reg_dest_wr; +wire r11_inc = inst_src_in[11] & reg_incr; +always @(posedge mclk or posedge puc) + if (puc) r11 <= 16'h0000; + else if (r11_wr) r11 <= reg_dest_val_in; + else if (r11_inc) r11 <= reg_incr_val; + +// R12 +reg [15:0] r12; +wire r12_wr = inst_dest[12] & reg_dest_wr; +wire r12_inc = inst_src_in[12] & reg_incr; +always @(posedge mclk or posedge puc) + if (puc) r12 <= 16'h0000; + else if (r12_wr) r12 <= reg_dest_val_in; + else if (r12_inc) r12 <= reg_incr_val; + +// R13 +reg [15:0] r13; +wire r13_wr = inst_dest[13] & reg_dest_wr; +wire r13_inc = inst_src_in[13] & reg_incr; +always @(posedge mclk or posedge puc) + if (puc) r13 <= 16'h0000; + else if (r13_wr) r13 <= reg_dest_val_in; + else if (r13_inc) r13 <= reg_incr_val; + +// R14 +reg [15:0] r14; +wire r14_wr = inst_dest[14] & reg_dest_wr; +wire r14_inc = inst_src_in[14] & reg_incr; +always @(posedge mclk or posedge puc) + if (puc) r14 <= 16'h0000; + else if (r14_wr) r14 <= reg_dest_val_in; + else if (r14_inc) r14 <= reg_incr_val; + +// R15 +reg [15:0] r15; +wire r15_wr = inst_dest[15] & reg_dest_wr; +wire r15_inc = inst_src_in[15] & reg_incr; +always @(posedge mclk or posedge puc) + if (puc) r15 <= 16'h0000; + else if (r15_wr) r15 <= reg_dest_val_in; + else if (r15_inc) r15 <= reg_incr_val; + + +//============================================================================= +// 5) READ MUX +//============================================================================= + +assign reg_src = (r0 & {16{inst_src_in[0]}}) | + (r1 & {16{inst_src_in[1]}}) | + (r2 & {16{inst_src_in[2]}}) | + (r3 & {16{inst_src_in[3]}}) | + (r4 & {16{inst_src_in[4]}}) | + (r5 & {16{inst_src_in[5]}}) | + (r6 & {16{inst_src_in[6]}}) | + (r7 & {16{inst_src_in[7]}}) | + (r8 & {16{inst_src_in[8]}}) | + (r9 & {16{inst_src_in[9]}}) | + (r10 & {16{inst_src_in[10]}}) | + (r11 & {16{inst_src_in[11]}}) | + (r12 & {16{inst_src_in[12]}}) | + (r13 & {16{inst_src_in[13]}}) | + (r14 & {16{inst_src_in[14]}}) | + (r15 & {16{inst_src_in[15]}}); + +assign reg_dest = (r0 & {16{inst_dest[0]}}) | + (r1 & {16{inst_dest[1]}}) | + (r2 & {16{inst_dest[2]}}) | + (r3 & {16{inst_dest[3]}}) | + (r4 & {16{inst_dest[4]}}) | + (r5 & {16{inst_dest[5]}}) | + (r6 & {16{inst_dest[6]}}) | + (r7 & {16{inst_dest[7]}}) | + (r8 & {16{inst_dest[8]}}) | + (r9 & {16{inst_dest[9]}}) | + (r10 & {16{inst_dest[10]}}) | + (r11 & {16{inst_dest[11]}}) | + (r12 & {16{inst_dest[12]}}) | + (r13 & {16{inst_dest[13]}}) | + (r14 & {16{inst_dest[14]}}) | + (r15 & {16{inst_dest[15]}}); + + +endmodule // omsp_register_file + +`include "openMSP430_undefines.v"
omsp_register_file.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Date Revision Author \ No newline at end of property Index: periph/timerA.v =================================================================== --- periph/timerA.v (revision 33) +++ periph/timerA.v (nonexistent) @@ -1,689 +0,0 @@ -//---------------------------------------------------------------------------- -// Copyright (C) 2001 Authors -// -// This source file may be used and distributed without restriction provided -// that this copyright statement is not removed from the file and that any -// derivative work contains the original copyright notice and the associated -// disclaimer. -// -// This source file is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This source is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -// License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this source; if not, write to the Free Software Foundation, -// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -//---------------------------------------------------------------------------- -// -// *File Name: timerA.v -// -// *Module Description: -// Timer A top-level -// -// *Author(s): -// - Olivier Girard, olgirard@gmail.com -// -//---------------------------------------------------------------------------- -// $Rev$ -// $LastChangedBy$ -// $LastChangedDate$ -//---------------------------------------------------------------------------- -`include "timescale.v" -`include "openMSP430_defines.v" - -module timerA ( - -// OUTPUTs - irq_ta0, // Timer A interrupt: TACCR0 - irq_ta1, // Timer A interrupt: TAIV, TACCR1, TACCR2 - per_dout, // Peripheral data output - ta_out0, // Timer A output 0 - ta_out0_en, // Timer A output 0 enable - ta_out1, // Timer A output 1 - ta_out1_en, // Timer A output 1 enable - ta_out2, // Timer A output 2 - ta_out2_en, // Timer A output 2 enable - -// INPUTs - aclk_en, // ACLK enable (from CPU) - dbg_freeze, // Freeze Timer A counter - inclk, // INCLK external timer clock (SLOW) - irq_ta0_acc, // Interrupt request TACCR0 accepted - mclk, // Main system clock - per_addr, // Peripheral address - per_din, // Peripheral data input - per_en, // Peripheral enable (high active) - per_wen, // Peripheral write enable (high active) - puc, // Main system reset - smclk_en, // SMCLK enable (from CPU) - ta_cci0a, // Timer A capture 0 input A - ta_cci0b, // Timer A capture 0 input B - ta_cci1a, // Timer A capture 1 input A - ta_cci1b, // Timer A capture 1 input B - ta_cci2a, // Timer A capture 2 input A - ta_cci2b, // Timer A capture 2 input B - taclk // TACLK external timer clock (SLOW) -); - -// OUTPUTs -//========= -output irq_ta0; // Timer A interrupt: TACCR0 -output irq_ta1; // Timer A interrupt: TAIV, TACCR1, TACCR2 -output [15:0] per_dout; // Peripheral data output -output ta_out0; // Timer A output 0 -output ta_out0_en; // Timer A output 0 enable -output ta_out1; // Timer A output 1 -output ta_out1_en; // Timer A output 1 enable -output ta_out2; // Timer A output 2 -output ta_out2_en; // Timer A output 2 enable - -// INPUTs -//========= -input aclk_en; // ACLK enable (from CPU) -input dbg_freeze; // Freeze Timer A counter -input inclk; // INCLK external timer clock (SLOW) -input irq_ta0_acc; // Interrupt request TACCR0 accepted -input mclk; // Main system clock -input [7:0] per_addr; // Peripheral address -input [15:0] per_din; // Peripheral data input -input per_en; // Peripheral enable (high active) -input [1:0] per_wen; // Peripheral write enable (high active) -input puc; // Main system reset -input smclk_en; // SMCLK enable (from CPU) -input ta_cci0a; // Timer A capture 0 input A -input ta_cci0b; // Timer A capture 0 input B -input ta_cci1a; // Timer A capture 1 input A -input ta_cci1b; // Timer A capture 1 input B -input ta_cci2a; // Timer A capture 2 input A -input ta_cci2b; // Timer A capture 2 input B -input taclk; // TACLK external timer clock (SLOW) - - -//============================================================================= -// 1) PARAMETER DECLARATION -//============================================================================= - -// Register addresses -parameter TACTL = 9'h160; -parameter TAR = 9'h170; -parameter TACCTL0 = 9'h162; -parameter TACCR0 = 9'h172; -parameter TACCTL1 = 9'h164; -parameter TACCR1 = 9'h174; -parameter TACCTL2 = 9'h166; -parameter TACCR2 = 9'h176; -parameter TAIV = 9'h12E; - - -// Register one-hot decoder -parameter TACTL_D = (512'h1 << TACTL); -parameter TAR_D = (512'h1 << TAR); -parameter TACCTL0_D = (512'h1 << TACCTL0); -parameter TACCR0_D = (512'h1 << TACCR0); -parameter TACCTL1_D = (512'h1 << TACCTL1); -parameter TACCR1_D = (512'h1 << TACCR1); -parameter TACCTL2_D = (512'h1 << TACCTL2); -parameter TACCR2_D = (512'h1 << TACCR2); -parameter TAIV_D = (512'h1 << TAIV); - - -//============================================================================ -// 2) REGISTER DECODER -//============================================================================ - -// Register address decode -reg [511:0] reg_dec; -always @(per_addr) - case ({per_addr,1'b0}) - TACTL : reg_dec = TACTL_D; - TAR : reg_dec = TAR_D; - TACCTL0: reg_dec = TACCTL0_D; - TACCR0 : reg_dec = TACCR0_D; - TACCTL1: reg_dec = TACCTL1_D; - TACCR1 : reg_dec = TACCR1_D; - TACCTL2: reg_dec = TACCTL2_D; - TACCR2 : reg_dec = TACCR2_D; - TAIV : reg_dec = TAIV_D; - default: reg_dec = {512{1'b0}}; - endcase - -// Read/Write probes -wire reg_write = |per_wen & per_en; -wire reg_read = ~|per_wen & per_en; - -// Read/Write vectors -wire [511:0] reg_wr = reg_dec & {512{reg_write}}; -wire [511:0] reg_rd = reg_dec & {512{reg_read}}; - - -//============================================================================ -// 3) REGISTERS -//============================================================================ - -// TACTL Register -//----------------- -reg [9:0] tactl; - -wire tactl_wr = reg_wr[TACTL]; -wire taclr = tactl_wr & per_din[`TACLR]; -wire taifg_set; -wire taifg_clr; - -always @ (posedge mclk or posedge puc) - if (puc) tactl <= 10'h000; - else if (tactl_wr) tactl <= ((per_din[9:0] & 10'h3f3) | {9'h000, taifg_set}) & {9'h1ff, ~taifg_clr}; - else tactl <= (tactl | {9'h000, taifg_set}) & {9'h1ff, ~taifg_clr}; - - -// TAR Register -//----------------- -reg [15:0] tar; - -wire tar_wr = reg_wr[TAR]; - -wire tar_clk; -wire tar_clr; -wire tar_inc; -wire tar_dec; -wire [15:0] tar_add = tar_inc ? 16'h0001 : - tar_dec ? 16'hffff : 16'h0000; -wire [15:0] tar_nxt = tar_clr ? 16'h0000 : (tar+tar_add); - -always @ (posedge mclk or posedge puc) - if (puc) tar <= 16'h0000; - else if (tar_wr) tar <= per_din; - else if (taclr) tar <= 16'h0000; - else if (tar_clk & ~dbg_freeze) tar <= tar_nxt; - - -// TACCTL0 Register -//------------------ -reg [15:0] tacctl0; - -wire tacctl0_wr = reg_wr[TACCTL0]; -wire ccifg0_set; -wire cov0_set; - -always @ (posedge mclk or posedge puc) - if (puc) tacctl0 <= 16'h0000; - else if (tacctl0_wr) tacctl0 <= ((per_din & 16'hf9f7) | {14'h0000, cov0_set, ccifg0_set}) & {15'h7fff, ~irq_ta0_acc}; - else tacctl0 <= (tacctl0 | {14'h0000, cov0_set, ccifg0_set}) & {15'h7fff, ~irq_ta0_acc}; - -wire cci0; -reg scci0; -wire [15:0] tacctl0_full = tacctl0 | {5'h00, scci0, 6'h00, cci0, 3'h0}; - - -// TACCR0 Register -//------------------ -reg [15:0] taccr0; - -wire taccr0_wr = reg_wr[TACCR0]; -wire cci0_cap; - -always @ (posedge mclk or posedge puc) - if (puc) taccr0 <= 16'h0000; - else if (taccr0_wr) taccr0 <= per_din; - else if (cci0_cap) taccr0 <= tar; - - -// TACCTL1 Register -//------------------ -reg [15:0] tacctl1; - -wire tacctl1_wr = reg_wr[TACCTL1]; -wire ccifg1_set; -wire ccifg1_clr; -wire cov1_set; - -always @ (posedge mclk or posedge puc) - if (puc) tacctl1 <= 16'h0000; - else if (tacctl1_wr) tacctl1 <= ((per_din & 16'hf9f7) | {14'h0000, cov1_set, ccifg1_set}) & {15'h7fff, ~ccifg1_clr}; - else tacctl1 <= (tacctl1 | {14'h0000, cov1_set, ccifg1_set}) & {15'h7fff, ~ccifg1_clr}; - -wire cci1; -reg scci1; -wire [15:0] tacctl1_full = tacctl1 | {5'h00, scci1, 6'h00, cci1, 3'h0}; - - -// TACCR1 Register -//------------------ -reg [15:0] taccr1; - -wire taccr1_wr = reg_wr[TACCR1]; -wire cci1_cap; - -always @ (posedge mclk or posedge puc) - if (puc) taccr1 <= 16'h0000; - else if (taccr1_wr) taccr1 <= per_din; - else if (cci1_cap) taccr1 <= tar; - - -// TACCTL2 Register -//------------------ -reg [15:0] tacctl2; - -wire tacctl2_wr = reg_wr[TACCTL2]; -wire ccifg2_set; -wire ccifg2_clr; -wire cov2_set; - -always @ (posedge mclk or posedge puc) - if (puc) tacctl2 <= 16'h0000; - else if (tacctl2_wr) tacctl2 <= ((per_din & 16'hf9f7) | {14'h0000, cov2_set, ccifg2_set}) & {15'h7fff, ~ccifg2_clr}; - else tacctl2 <= (tacctl2 | {14'h0000, cov2_set, ccifg2_set}) & {15'h7fff, ~ccifg2_clr}; - -wire cci2; -reg scci2; -wire [15:0] tacctl2_full = tacctl2 | {5'h00, scci2, 6'h00, cci2, 3'h0}; - - -// TACCR2 Register -//------------------ -reg [15:0] taccr2; - -wire taccr2_wr = reg_wr[TACCR2]; -wire cci2_cap; - -always @ (posedge mclk or posedge puc) - if (puc) taccr2 <= 16'h0000; - else if (taccr2_wr) taccr2 <= per_din; - else if (cci2_cap) taccr2 <= tar; - - -// TAIV Register -//------------------ - -wire [3:0] taiv = (tacctl1[`TACCIFG] & tacctl1[`TACCIE]) ? 4'h2 : - (tacctl2[`TACCIFG] & tacctl2[`TACCIE]) ? 4'h4 : - (tactl[`TAIFG] & tactl[`TAIE]) ? 4'hA : - 4'h0; - -assign ccifg1_clr = (reg_rd[TAIV] | reg_wr[TAIV]) & (taiv==4'h2); -assign ccifg2_clr = (reg_rd[TAIV] | reg_wr[TAIV]) & (taiv==4'h4); -assign taifg_clr = (reg_rd[TAIV] | reg_wr[TAIV]) & (taiv==4'hA); - - -//============================================================================ -// 4) DATA OUTPUT GENERATION -//============================================================================ - -// Data output mux -wire [15:0] tactl_rd = {6'h00, tactl} & {16{reg_rd[TACTL]}}; -wire [15:0] tar_rd = tar & {16{reg_rd[TAR]}}; -wire [15:0] tacctl0_rd = tacctl0_full & {16{reg_rd[TACCTL0]}}; -wire [15:0] taccr0_rd = taccr0 & {16{reg_rd[TACCR0]}}; -wire [15:0] tacctl1_rd = tacctl1_full & {16{reg_rd[TACCTL1]}}; -wire [15:0] taccr1_rd = taccr1 & {16{reg_rd[TACCR1]}}; -wire [15:0] tacctl2_rd = tacctl2_full & {16{reg_rd[TACCTL2]}}; -wire [15:0] taccr2_rd = taccr2 & {16{reg_rd[TACCR2]}}; -wire [15:0] taiv_rd = {12'h000, taiv} & {16{reg_rd[TAIV]}}; - -wire [15:0] per_dout = tactl_rd | - tar_rd | - tacctl0_rd | - taccr0_rd | - tacctl1_rd | - taccr1_rd | - tacctl2_rd | - taccr2_rd | - taiv_rd; - - -//============================================================================ -// 5) Timer A counter control -//============================================================================ - -// Clock input synchronization (TACLK & INCLK) -//----------------------------------------------------------- -reg [2:0] taclk_s; - -always @ (posedge mclk or posedge puc) - if (puc) taclk_s <= 3'b000; - else taclk_s <= {taclk_s[1:0], taclk}; - -wire taclk_en = taclk_s[1] & ~taclk_s[2]; - - -reg [2:0] inclk_s; - -always @ (posedge mclk or posedge puc) - if (puc) inclk_s <= 3'b000; - else inclk_s <= {inclk_s[1:0], inclk}; - -wire inclk_en = inclk_s[1] & ~inclk_s[2]; - - -// Timer clock input mux -//----------------------------------------------------------- - -wire sel_clk = (tactl[`TASSELx]==2'b00) ? taclk_en : - (tactl[`TASSELx]==2'b01) ? aclk_en : - (tactl[`TASSELx]==2'b10) ? smclk_en : inclk_en; - - -// Generate update pluse for the counter (<=> divided clock) -//----------------------------------------------------------- -reg [2:0] clk_div; - -assign tar_clk = sel_clk & ((tactl[`TAIDx]==2'b00) ? 1'b1 : - (tactl[`TAIDx]==2'b01) ? clk_div[0] : - (tactl[`TAIDx]==2'b10) ? &clk_div[1:0] : - &clk_div[2:0]); - -always @ (posedge mclk or posedge puc) - if (puc) clk_div <= 3'h0; - else if (tar_clk | taclr) clk_div <= 3'h0; - else if ((tactl[`TAMCx]!=2'b00) & sel_clk) clk_div <= clk_div+3'h1; - - -// Time counter control signals -//----------------------------------------------------------- - -assign tar_clr = ((tactl[`TAMCx]==2'b01) & (tar>=taccr0)) | - ((tactl[`TAMCx]==2'b11) & (taccr0==16'h0000)); - -assign tar_inc = (tactl[`TAMCx]==2'b01) | (tactl[`TAMCx]==2'b10) | - ((tactl[`TAMCx]==2'b11) & ~tar_dec); - -reg tar_dir; -always @ (posedge mclk or posedge puc) - if (puc) tar_dir <= 1'b0; - else if (taclr) tar_dir <= 1'b0; - else if (tactl[`TAMCx]==2'b11) - begin - if (tar_clk & (tar==16'h0001)) tar_dir <= 1'b0; - else if (tar>=taccr0) tar_dir <= 1'b1; - end - else tar_dir <= 1'b0; - -assign tar_dec = tar_dir | ((tactl[`TAMCx]==2'b11) & (tar>=taccr0)); - - -//============================================================================ -// 6) Timer A comparator -//============================================================================ - -wire equ0 = (tar_nxt==taccr0) & (tar!=taccr0); -wire equ1 = (tar_nxt==taccr1) & (tar!=taccr1); -wire equ2 = (tar_nxt==taccr2) & (tar!=taccr2); - - -//============================================================================ -// 7) Timer A capture logic -//============================================================================ - -// Input selection -//------------------ -assign cci0 = (tacctl0[`TACCISx]==2'b00) ? ta_cci0a : - (tacctl0[`TACCISx]==2'b01) ? ta_cci0b : - (tacctl0[`TACCISx]==2'b10) ? 1'b0 : 1'b1; - -assign cci1 = (tacctl1[`TACCISx]==2'b00) ? ta_cci1a : - (tacctl1[`TACCISx]==2'b01) ? ta_cci1b : - (tacctl1[`TACCISx]==2'b10) ? 1'b0 : 1'b1; - -assign cci2 = (tacctl2[`TACCISx]==2'b00) ? ta_cci2a : - (tacctl2[`TACCISx]==2'b01) ? ta_cci2b : - (tacctl2[`TACCISx]==2'b10) ? 1'b0 : 1'b1; - -// Register CCIx for synchronization and edge detection -reg [2:0] cci_s; -always @ (posedge mclk or posedge puc) - if (puc) cci_s <= 3'h0; - else cci_s <= {cci2, cci1, cci0}; -reg [2:0] cci_ss; -always @ (posedge mclk or posedge puc) - if (puc) cci_ss <= 3'h0; - else cci_ss <= cci_s; -reg [2:0] cci_sss; -always @ (posedge mclk or posedge puc) - if (puc) cci_sss <= 3'h0; - else cci_sss <= cci_ss; - - -// Generate SCCIx -//------------------ - -always @ (posedge mclk or posedge puc) - if (puc) scci0 <= 1'b0; - else if (tar_clk & equ0) scci0 <= cci_ss[0]; - -always @ (posedge mclk or posedge puc) - if (puc) scci1 <= 1'b0; - else if (tar_clk & equ1) scci1 <= cci_ss[1]; - -always @ (posedge mclk or posedge puc) - if (puc) scci2 <= 1'b0; - else if (tar_clk & equ2) scci2 <= cci_ss[2]; - - -// Capture mode -//------------------ -wire cci0_evt = (tacctl0[`TACMx]==2'b00) ? 1'b0 : - (tacctl0[`TACMx]==2'b01) ? ( cci_ss[0] & ~cci_sss[0]) : // Rising edge - (tacctl0[`TACMx]==2'b10) ? (~cci_ss[0] & cci_sss[0]) : // Falling edge - ( cci_ss[0] ^ cci_sss[0]); // Both edges - -wire cci1_evt = (tacctl1[`TACMx]==2'b00) ? 1'b0 : - (tacctl1[`TACMx]==2'b01) ? ( cci_ss[1] & ~cci_sss[1]) : // Rising edge - (tacctl1[`TACMx]==2'b10) ? (~cci_ss[1] & cci_sss[1]) : // Falling edge - ( cci_ss[1] ^ cci_sss[1]); // Both edges - -wire cci2_evt = (tacctl2[`TACMx]==2'b00) ? 1'b0 : - (tacctl2[`TACMx]==2'b01) ? ( cci_ss[2] & ~cci_sss[2]) : // Rising edge - (tacctl2[`TACMx]==2'b10) ? (~cci_ss[2] & cci_sss[2]) : // Falling edge - ( cci_ss[2] ^ cci_sss[2]); // Both edges - -// Event Synchronization -//----------------------- - -reg cci0_evt_s; -always @ (posedge mclk or posedge puc) - if (puc) cci0_evt_s <= 1'b0; - else if (tar_clk) cci0_evt_s <= 1'b0; - else if (cci0_evt) cci0_evt_s <= 1'b1; - -reg cci1_evt_s; -always @ (posedge mclk or posedge puc) - if (puc) cci1_evt_s <= 1'b0; - else if (tar_clk) cci1_evt_s <= 1'b0; - else if (cci1_evt) cci1_evt_s <= 1'b1; - -reg cci2_evt_s; -always @ (posedge mclk or posedge puc) - if (puc) cci2_evt_s <= 1'b0; - else if (tar_clk) cci2_evt_s <= 1'b0; - else if (cci2_evt) cci2_evt_s <= 1'b1; - -reg cci0_sync; -always @ (posedge mclk or posedge puc) - if (puc) cci0_sync <= 1'b0; - else cci0_sync <= (tar_clk & cci0_evt_s) | (tar_clk & cci0_evt & ~cci0_evt_s); - -reg cci1_sync; -always @ (posedge mclk or posedge puc) - if (puc) cci1_sync <= 1'b0; - else cci1_sync <= (tar_clk & cci1_evt_s) | (tar_clk & cci1_evt & ~cci1_evt_s); - -reg cci2_sync; -always @ (posedge mclk or posedge puc) - if (puc) cci2_sync <= 1'b0; - else cci2_sync <= (tar_clk & cci2_evt_s) | (tar_clk & cci2_evt & ~cci2_evt_s); - - -// Generate final capture command -//----------------------------------- - -assign cci0_cap = tacctl0[`TASCS] ? cci0_sync : cci0_evt; -assign cci1_cap = tacctl1[`TASCS] ? cci1_sync : cci1_evt; -assign cci2_cap = tacctl2[`TASCS] ? cci2_sync : cci2_evt; - - -// Generate capture overflow flag -//----------------------------------- - -reg cap0_taken; -wire cap0_taken_clr = reg_rd[TACCR0] | (tacctl0_wr & tacctl0[`TACOV] & ~per_din[`TACOV]); -always @ (posedge mclk or posedge puc) - if (puc) cap0_taken <= 1'b0; - else if (cci0_cap) cap0_taken <= 1'b1; - else if (cap0_taken_clr) cap0_taken <= 1'b0; - -reg cap1_taken; -wire cap1_taken_clr = reg_rd[TACCR1] | (tacctl1_wr & tacctl1[`TACOV] & ~per_din[`TACOV]); -always @ (posedge mclk or posedge puc) - if (puc) cap1_taken <= 1'b0; - else if (cci1_cap) cap1_taken <= 1'b1; - else if (cap1_taken_clr) cap1_taken <= 1'b0; - -reg cap2_taken; -wire cap2_taken_clr = reg_rd[TACCR2] | (tacctl2_wr & tacctl2[`TACOV] & ~per_din[`TACOV]); -always @ (posedge mclk or posedge puc) - if (puc) cap2_taken <= 1'b0; - else if (cci2_cap) cap2_taken <= 1'b1; - else if (cap2_taken_clr) cap2_taken <= 1'b0; - - -assign cov0_set = cap0_taken & cci0_cap & ~reg_rd[TACCR0]; -assign cov1_set = cap1_taken & cci1_cap & ~reg_rd[TACCR1]; -assign cov2_set = cap2_taken & cci2_cap & ~reg_rd[TACCR2]; - - -//============================================================================ -// 8) Timer A output unit -//============================================================================ - -// Output unit 0 -//------------------- -reg ta_out0; - -wire ta_out0_mode0 = tacctl0[`TAOUT]; // Output -wire ta_out0_mode1 = equ0 ? 1'b1 : ta_out0; // Set -wire ta_out0_mode2 = equ0 ? ~ta_out0 : // Toggle/Reset - equ0 ? 1'b0 : ta_out0; -wire ta_out0_mode3 = equ0 ? 1'b1 : // Set/Reset - equ0 ? 1'b0 : ta_out0; -wire ta_out0_mode4 = equ0 ? ~ta_out0 : ta_out0; // Toggle -wire ta_out0_mode5 = equ0 ? 1'b0 : ta_out0; // Reset -wire ta_out0_mode6 = equ0 ? ~ta_out0 : // Toggle/Set - equ0 ? 1'b1 : ta_out0; -wire ta_out0_mode7 = equ0 ? 1'b0 : // Reset/Set - equ0 ? 1'b1 : ta_out0; - -wire ta_out0_nxt = (tacctl0[`TAOUTMODx]==3'b000) ? ta_out0_mode0 : - (tacctl0[`TAOUTMODx]==3'b001) ? ta_out0_mode1 : - (tacctl0[`TAOUTMODx]==3'b010) ? ta_out0_mode2 : - (tacctl0[`TAOUTMODx]==3'b011) ? ta_out0_mode3 : - (tacctl0[`TAOUTMODx]==3'b100) ? ta_out0_mode4 : - (tacctl0[`TAOUTMODx]==3'b101) ? ta_out0_mode5 : - (tacctl0[`TAOUTMODx]==3'b110) ? ta_out0_mode6 : - ta_out0_mode7; - -always @ (posedge mclk or posedge puc) - if (puc) ta_out0 <= 1'b0; - else if ((tacctl0[`TAOUTMODx]==3'b001) & taclr) ta_out0 <= 1'b0; - else if (tar_clk) ta_out0 <= ta_out0_nxt; - -assign ta_out0_en = ~tacctl0[`TACAP]; - - -// Output unit 1 -//------------------- -reg ta_out1; - -wire ta_out1_mode0 = tacctl1[`TAOUT]; // Output -wire ta_out1_mode1 = equ1 ? 1'b1 : ta_out1; // Set -wire ta_out1_mode2 = equ1 ? ~ta_out1 : // Toggle/Reset - equ0 ? 1'b0 : ta_out1; -wire ta_out1_mode3 = equ1 ? 1'b1 : // Set/Reset - equ0 ? 1'b0 : ta_out1; -wire ta_out1_mode4 = equ1 ? ~ta_out1 : ta_out1; // Toggle -wire ta_out1_mode5 = equ1 ? 1'b0 : ta_out1; // Reset -wire ta_out1_mode6 = equ1 ? ~ta_out1 : // Toggle/Set - equ0 ? 1'b1 : ta_out1; -wire ta_out1_mode7 = equ1 ? 1'b0 : // Reset/Set - equ0 ? 1'b1 : ta_out1; - -wire ta_out1_nxt = (tacctl1[`TAOUTMODx]==3'b000) ? ta_out1_mode0 : - (tacctl1[`TAOUTMODx]==3'b001) ? ta_out1_mode1 : - (tacctl1[`TAOUTMODx]==3'b010) ? ta_out1_mode2 : - (tacctl1[`TAOUTMODx]==3'b011) ? ta_out1_mode3 : - (tacctl1[`TAOUTMODx]==3'b100) ? ta_out1_mode4 : - (tacctl1[`TAOUTMODx]==3'b101) ? ta_out1_mode5 : - (tacctl1[`TAOUTMODx]==3'b110) ? ta_out1_mode6 : - ta_out1_mode7; - -always @ (posedge mclk or posedge puc) - if (puc) ta_out1 <= 1'b0; - else if ((tacctl1[`TAOUTMODx]==3'b001) & taclr) ta_out1 <= 1'b0; - else if (tar_clk) ta_out1 <= ta_out1_nxt; - -assign ta_out1_en = ~tacctl1[`TACAP]; - - -// Output unit 2 -//------------------- -reg ta_out2; - -wire ta_out2_mode0 = tacctl2[`TAOUT]; // Output -wire ta_out2_mode1 = equ2 ? 1'b1 : ta_out2; // Set -wire ta_out2_mode2 = equ2 ? ~ta_out2 : // Toggle/Reset - equ0 ? 1'b0 : ta_out2; -wire ta_out2_mode3 = equ2 ? 1'b1 : // Set/Reset - equ0 ? 1'b0 : ta_out2; -wire ta_out2_mode4 = equ2 ? ~ta_out2 : ta_out2; // Toggle -wire ta_out2_mode5 = equ2 ? 1'b0 : ta_out2; // Reset -wire ta_out2_mode6 = equ2 ? ~ta_out2 : // Toggle/Set - equ0 ? 1'b1 : ta_out2; -wire ta_out2_mode7 = equ2 ? 1'b0 : // Reset/Set - equ0 ? 1'b1 : ta_out2; - -wire ta_out2_nxt = (tacctl2[`TAOUTMODx]==3'b000) ? ta_out2_mode0 : - (tacctl2[`TAOUTMODx]==3'b001) ? ta_out2_mode1 : - (tacctl2[`TAOUTMODx]==3'b010) ? ta_out2_mode2 : - (tacctl2[`TAOUTMODx]==3'b011) ? ta_out2_mode3 : - (tacctl2[`TAOUTMODx]==3'b100) ? ta_out2_mode4 : - (tacctl2[`TAOUTMODx]==3'b101) ? ta_out2_mode5 : - (tacctl2[`TAOUTMODx]==3'b110) ? ta_out2_mode6 : - ta_out2_mode7; - -always @ (posedge mclk or posedge puc) - if (puc) ta_out2 <= 1'b0; - else if ((tacctl2[`TAOUTMODx]==3'b001) & taclr) ta_out2 <= 1'b0; - else if (tar_clk) ta_out2 <= ta_out2_nxt; - -assign ta_out2_en = ~tacctl2[`TACAP]; - - -//============================================================================ -// 9) Timer A interrupt generation -//============================================================================ - - -assign taifg_set = tar_clk & (((tactl[`TAMCx]==2'b01) & (tar==taccr0)) | - ((tactl[`TAMCx]==2'b10) & (tar==16'hffff)) | - ((tactl[`TAMCx]==2'b11) & (tar_nxt==16'h0000) & tar_dec)); - -assign ccifg0_set = tacctl0[`TACAP] ? cci0_cap : (tar_clk & ((tactl[`TAMCx]!=2'b00) & equ0)); -assign ccifg1_set = tacctl1[`TACAP] ? cci1_cap : (tar_clk & ((tactl[`TAMCx]!=2'b00) & equ1)); -assign ccifg2_set = tacctl2[`TACAP] ? cci2_cap : (tar_clk & ((tactl[`TAMCx]!=2'b00) & equ2)); - - -wire irq_ta0 = (tacctl0[`TACCIFG] & tacctl0[`TACCIE]); - -wire irq_ta1 = (tactl[`TAIFG] & tactl[`TAIE]) | - (tacctl1[`TACCIFG] & tacctl1[`TACCIE]) | - (tacctl2[`TACCIFG] & tacctl2[`TACCIE]); - - -endmodule // timerA - -`include "openMSP430_undefines.v"
periph/timerA.v Property changes : Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Date Revision Author \ No newline at end of property Index: periph/gpio.v =================================================================== --- periph/gpio.v (revision 33) +++ periph/gpio.v (nonexistent) @@ -1,774 +0,0 @@ -//---------------------------------------------------------------------------- -// Copyright (C) 2001 Authors -// -// This source file may be used and distributed without restriction provided -// that this copyright statement is not removed from the file and that any -// derivative work contains the original copyright notice and the associated -// disclaimer. -// -// This source file is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This source is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -// License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this source; if not, write to the Free Software Foundation, -// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -//---------------------------------------------------------------------------- -// -// *File Name: gpio.v -// -// *Module Description: -// Digital I/O interface -// -// *Author(s): -// - Olivier Girard, olgirard@gmail.com -// -//---------------------------------------------------------------------------- -// $Rev$ -// $LastChangedBy$ -// $LastChangedDate$ -//---------------------------------------------------------------------------- -`include "timescale.v" -`include "openMSP430_defines.v" - -module gpio ( - -// OUTPUTs - irq_port1, // Port 1 interrupt - irq_port2, // Port 2 interrupt - p1_dout, // Port 1 data output - p1_dout_en, // Port 1 data output enable - p1_sel, // Port 1 function select - p2_dout, // Port 2 data output - p2_dout_en, // Port 2 data output enable - p2_sel, // Port 2 function select - p3_dout, // Port 3 data output - p3_dout_en, // Port 3 data output enable - p3_sel, // Port 3 function select - p4_dout, // Port 4 data output - p4_dout_en, // Port 4 data output enable - p4_sel, // Port 4 function select - p5_dout, // Port 5 data output - p5_dout_en, // Port 5 data output enable - p5_sel, // Port 5 function select - p6_dout, // Port 6 data output - p6_dout_en, // Port 6 data output enable - p6_sel, // Port 6 function select - per_dout, // Peripheral data output - -// INPUTs - mclk, // Main system clock - p1_din, // Port 1 data input - p2_din, // Port 2 data input - p3_din, // Port 3 data input - p4_din, // Port 4 data input - p5_din, // Port 5 data input - p6_din, // Port 6 data input - per_addr, // Peripheral address - per_din, // Peripheral data input - per_en, // Peripheral enable (high active) - per_wen, // Peripheral write enable (high active) - puc // Main system reset -); - -// PARAMETERs -//============ -parameter P1_EN = 1'b1; // Enable Port 1 -parameter P2_EN = 1'b1; // Enable Port 2 -parameter P3_EN = 1'b0; // Enable Port 3 -parameter P4_EN = 1'b0; // Enable Port 4 -parameter P5_EN = 1'b0; // Enable Port 5 -parameter P6_EN = 1'b0; // Enable Port 6 - - -// OUTPUTs -//========= -output irq_port1; // Port 1 interrupt -output irq_port2; // Port 2 interrupt -output [7:0] p1_dout; // Port 1 data output -output [7:0] p1_dout_en; // Port 1 data output enable -output [7:0] p1_sel; // Port 1 function select -output [7:0] p2_dout; // Port 2 data output -output [7:0] p2_dout_en; // Port 2 data output enable -output [7:0] p2_sel; // Port 2 function select -output [7:0] p3_dout; // Port 3 data output -output [7:0] p3_dout_en; // Port 3 data output enable -output [7:0] p3_sel; // Port 3 function select -output [7:0] p4_dout; // Port 4 data output -output [7:0] p4_dout_en; // Port 4 data output enable -output [7:0] p4_sel; // Port 4 function select -output [7:0] p5_dout; // Port 5 data output -output [7:0] p5_dout_en; // Port 5 data output enable -output [7:0] p5_sel; // Port 5 function select -output [7:0] p6_dout; // Port 6 data output -output [7:0] p6_dout_en; // Port 6 data output enable -output [7:0] p6_sel; // Port 6 function select -output [15:0] per_dout; // Peripheral data output - -// INPUTs -//========= -input mclk; // Main system clock -input [7:0] p1_din; // Port 1 data input -input [7:0] p2_din; // Port 2 data input -input [7:0] p3_din; // Port 3 data input -input [7:0] p4_din; // Port 4 data input -input [7:0] p5_din; // Port 5 data input -input [7:0] p6_din; // Port 6 data input -input [7:0] per_addr; // Peripheral address -input [15:0] per_din; // Peripheral data input -input per_en; // Peripheral enable (high active) -input [1:0] per_wen; // Peripheral write enable (high active) -input puc; // Main system reset - - -//============================================================================= -// 1) PARAMETER DECLARATION -//============================================================================= - -// Masks -parameter P1_EN_MSK = {8{P1_EN[0]}}; -parameter P2_EN_MSK = {8{P2_EN[0]}}; -parameter P3_EN_MSK = {8{P3_EN[0]}}; -parameter P4_EN_MSK = {8{P4_EN[0]}}; -parameter P5_EN_MSK = {8{P5_EN[0]}}; -parameter P6_EN_MSK = {8{P6_EN[0]}}; - -// Register addresses -parameter P1IN = 9'h020; // Port 1 -parameter P1OUT = 9'h021; -parameter P1DIR = 9'h022; -parameter P1IFG = 9'h023; -parameter P1IES = 9'h024; -parameter P1IE = 9'h025; -parameter P1SEL = 9'h026; -parameter P2IN = 9'h028; // Port 2 -parameter P2OUT = 9'h029; -parameter P2DIR = 9'h02A; -parameter P2IFG = 9'h02B; -parameter P2IES = 9'h02C; -parameter P2IE = 9'h02D; -parameter P2SEL = 9'h02E; -parameter P3IN = 9'h018; // Port 3 -parameter P3OUT = 9'h019; -parameter P3DIR = 9'h01A; -parameter P3SEL = 9'h01B; -parameter P4IN = 9'h01C; // Port 4 -parameter P4OUT = 9'h01D; -parameter P4DIR = 9'h01E; -parameter P4SEL = 9'h01F; -parameter P5IN = 9'h030; // Port 5 -parameter P5OUT = 9'h031; -parameter P5DIR = 9'h032; -parameter P5SEL = 9'h033; -parameter P6IN = 9'h034; // Port 6 -parameter P6OUT = 9'h035; -parameter P6DIR = 9'h036; -parameter P6SEL = 9'h037; - - -// Register one-hot decoder -parameter P1IN_D = (256'h1 << (P1IN /2)); // Port 1 -parameter P1OUT_D = (256'h1 << (P1OUT /2)); -parameter P1DIR_D = (256'h1 << (P1DIR /2)); -parameter P1IFG_D = (256'h1 << (P1IFG /2)); -parameter P1IES_D = (256'h1 << (P1IES /2)); -parameter P1IE_D = (256'h1 << (P1IE /2)); -parameter P1SEL_D = (256'h1 << (P1SEL /2)); -parameter P2IN_D = (256'h1 << (P2IN /2)); // Port 2 -parameter P2OUT_D = (256'h1 << (P2OUT /2)); -parameter P2DIR_D = (256'h1 << (P2DIR /2)); -parameter P2IFG_D = (256'h1 << (P2IFG /2)); -parameter P2IES_D = (256'h1 << (P2IES /2)); -parameter P2IE_D = (256'h1 << (P2IE /2)); -parameter P2SEL_D = (256'h1 << (P2SEL /2)); -parameter P3IN_D = (256'h1 << (P3IN /2)); // Port 3 -parameter P3OUT_D = (256'h1 << (P3OUT /2)); -parameter P3DIR_D = (256'h1 << (P3DIR /2)); -parameter P3SEL_D = (256'h1 << (P3SEL /2)); -parameter P4IN_D = (256'h1 << (P4IN /2)); // Port 4 -parameter P4OUT_D = (256'h1 << (P4OUT /2)); -parameter P4DIR_D = (256'h1 << (P4DIR /2)); -parameter P4SEL_D = (256'h1 << (P4SEL /2)); -parameter P5IN_D = (256'h1 << (P5IN /2)); // Port 5 -parameter P5OUT_D = (256'h1 << (P5OUT /2)); -parameter P5DIR_D = (256'h1 << (P5DIR /2)); -parameter P5SEL_D = (256'h1 << (P5SEL /2)); -parameter P6IN_D = (256'h1 << (P6IN /2)); // Port 6 -parameter P6OUT_D = (256'h1 << (P6OUT /2)); -parameter P6DIR_D = (256'h1 << (P6DIR /2)); -parameter P6SEL_D = (256'h1 << (P6SEL /2)); - - -//============================================================================ -// 2) REGISTER DECODER -//============================================================================ - -// Register address decode -reg [255:0] reg_dec; -always @(per_addr) - case (per_addr) - (P1IN /2): reg_dec = P1IN_D & {256{P1_EN[0]}}; - (P1OUT /2): reg_dec = P1OUT_D & {256{P1_EN[0]}}; - (P1DIR /2): reg_dec = P1DIR_D & {256{P1_EN[0]}}; - (P1IFG /2): reg_dec = P1IFG_D & {256{P1_EN[0]}}; - (P1IES /2): reg_dec = P1IES_D & {256{P1_EN[0]}}; - (P1IE /2): reg_dec = P1IE_D & {256{P1_EN[0]}}; - (P1SEL /2): reg_dec = P1SEL_D & {256{P1_EN[0]}}; - (P2IN /2): reg_dec = P2IN_D & {256{P2_EN[0]}}; - (P2OUT /2): reg_dec = P2OUT_D & {256{P2_EN[0]}}; - (P2DIR /2): reg_dec = P2DIR_D & {256{P2_EN[0]}}; - (P2IFG /2): reg_dec = P2IFG_D & {256{P2_EN[0]}}; - (P2IES /2): reg_dec = P2IES_D & {256{P2_EN[0]}}; - (P2IE /2): reg_dec = P2IE_D & {256{P2_EN[0]}}; - (P2SEL /2): reg_dec = P2SEL_D & {256{P2_EN[0]}}; - (P3IN /2): reg_dec = P3IN_D & {256{P3_EN[0]}}; - (P3OUT /2): reg_dec = P3OUT_D & {256{P3_EN[0]}}; - (P3DIR /2): reg_dec = P3DIR_D & {256{P3_EN[0]}}; - (P3SEL /2): reg_dec = P3SEL_D & {256{P3_EN[0]}}; - (P4IN /2): reg_dec = P4IN_D & {256{P4_EN[0]}}; - (P4OUT /2): reg_dec = P4OUT_D & {256{P4_EN[0]}}; - (P4DIR /2): reg_dec = P4DIR_D & {256{P4_EN[0]}}; - (P4SEL /2): reg_dec = P4SEL_D & {256{P4_EN[0]}}; - (P5IN /2): reg_dec = P5IN_D & {256{P5_EN[0]}}; - (P5OUT /2): reg_dec = P5OUT_D & {256{P5_EN[0]}}; - (P5DIR /2): reg_dec = P5DIR_D & {256{P5_EN[0]}}; - (P5SEL /2): reg_dec = P5SEL_D & {256{P5_EN[0]}}; - (P6IN /2): reg_dec = P6IN_D & {256{P6_EN[0]}}; - (P6OUT /2): reg_dec = P6OUT_D & {256{P6_EN[0]}}; - (P6DIR /2): reg_dec = P6DIR_D & {256{P6_EN[0]}}; - (P6SEL /2): reg_dec = P6SEL_D & {256{P6_EN[0]}}; - default : reg_dec = {256{1'b0}}; - endcase - -// Read/Write probes -wire reg_lo_write = per_wen[0] & per_en; -wire reg_hi_write = per_wen[1] & per_en; -wire reg_read = ~|per_wen & per_en; - -// Read/Write vectors -wire [255:0] reg_hi_wr = reg_dec & {256{reg_hi_write}}; -wire [255:0] reg_lo_wr = reg_dec & {256{reg_lo_write}}; -wire [255:0] reg_rd = reg_dec & {256{reg_read}}; - - -//============================================================================ -// 3) REGISTERS -//============================================================================ - -// P1IN Register -//--------------- -reg [7:0] p1in; - -always @ (posedge mclk or posedge puc) - if (puc) p1in <= 8'h00; - else p1in <= p1_din & P1_EN_MSK; - - -// P1OUT Register -//---------------- -reg [7:0] p1out; - -wire p1out_wr = P1OUT[0] ? reg_hi_wr[P1OUT/2] : reg_lo_wr[P1OUT/2]; -wire [7:0] p1out_nxt = P1OUT[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p1out <= 8'h00; - else if (p1out_wr) p1out <= p1out_nxt & P1_EN_MSK; - -assign p1_dout = p1out; - - -// P1DIR Register -//---------------- -reg [7:0] p1dir; - -wire p1dir_wr = P1DIR[0] ? reg_hi_wr[P1DIR/2] : reg_lo_wr[P1DIR/2]; -wire [7:0] p1dir_nxt = P1DIR[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p1dir <= 8'h00; - else if (p1dir_wr) p1dir <= p1dir_nxt & P1_EN_MSK; - -assign p1_dout_en = p1dir; - - -// P1IFG Register -//---------------- -reg [7:0] p1ifg; - -wire p1ifg_wr = P1IFG[0] ? reg_hi_wr[P1IFG/2] : reg_lo_wr[P1IFG/2]; -wire [7:0] p1ifg_nxt = P1IFG[0] ? per_din[15:8] : per_din[7:0]; -wire [7:0] p1ifg_set; - -always @ (posedge mclk or posedge puc) - if (puc) p1ifg <= 8'h00; - else if (p1ifg_wr) p1ifg <= (p1ifg_nxt | p1ifg_set) & P1_EN_MSK; - else p1ifg <= (p1ifg | p1ifg_set) & P1_EN_MSK; - -// P1IES Register -//---------------- -reg [7:0] p1ies; - -wire p1ies_wr = P1IES[0] ? reg_hi_wr[P1IES/2] : reg_lo_wr[P1IES/2]; -wire [7:0] p1ies_nxt = P1IES[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p1ies <= 8'h00; - else if (p1ies_wr) p1ies <= p1ies_nxt & P1_EN_MSK; - - -// P1IE Register -//---------------- -reg [7:0] p1ie; - -wire p1ie_wr = P1IE[0] ? reg_hi_wr[P1IE/2] : reg_lo_wr[P1IE/2]; -wire [7:0] p1ie_nxt = P1IE[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p1ie <= 8'h00; - else if (p1ie_wr) p1ie <= p1ie_nxt & P1_EN_MSK; - - -// P1SEL Register -//---------------- -reg [7:0] p1sel; - -wire p1sel_wr = P1SEL[0] ? reg_hi_wr[P1SEL/2] : reg_lo_wr[P1SEL/2]; -wire [7:0] p1sel_nxt = P1SEL[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p1sel <= 8'h00; - else if (p1sel_wr) p1sel <= p1sel_nxt & P1_EN_MSK; - -assign p1_sel = p1sel; - - -// P2IN Register -//--------------- -reg [7:0] p2in; - -always @ (posedge mclk or posedge puc) - if (puc) p2in <= 8'h00; - else p2in <= p2_din & P2_EN_MSK; - - -// P2OUT Register -//---------------- -reg [7:0] p2out; - -wire p2out_wr = P2OUT[0] ? reg_hi_wr[P2OUT/2] : reg_lo_wr[P2OUT/2]; -wire [7:0] p2out_nxt = P2OUT[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p2out <= 8'h00; - else if (p2out_wr) p2out <= p2out_nxt & P2_EN_MSK; - -assign p2_dout = p2out; - - -// P2DIR Register -//---------------- -reg [7:0] p2dir; - -wire p2dir_wr = P2DIR[0] ? reg_hi_wr[P2DIR/2] : reg_lo_wr[P2DIR/2]; -wire [7:0] p2dir_nxt = P2DIR[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p2dir <= 8'h00; - else if (p2dir_wr) p2dir <= p2dir_nxt & P2_EN_MSK; - -assign p2_dout_en = p2dir; - - -// P2IFG Register -//---------------- -reg [7:0] p2ifg; - -wire p2ifg_wr = P2IFG[0] ? reg_hi_wr[P2IFG/2] : reg_lo_wr[P2IFG/2]; -wire [7:0] p2ifg_nxt = P2IFG[0] ? per_din[15:8] : per_din[7:0]; -wire [7:0] p2ifg_set; - -always @ (posedge mclk or posedge puc) - if (puc) p2ifg <= 8'h00; - else if (p2ifg_wr) p2ifg <= (p2ifg_nxt | p2ifg_set) & P2_EN_MSK; - else p2ifg <= (p2ifg | p2ifg_set) & P2_EN_MSK; - - -// P2IES Register -//---------------- -reg [7:0] p2ies; - -wire p2ies_wr = P2IES[0] ? reg_hi_wr[P2IES/2] : reg_lo_wr[P2IES/2]; -wire [7:0] p2ies_nxt = P2IES[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p2ies <= 8'h00; - else if (p2ies_wr) p2ies <= p2ies_nxt & P2_EN_MSK; - - -// P2IE Register -//---------------- -reg [7:0] p2ie; - -wire p2ie_wr = P2IE[0] ? reg_hi_wr[P2IE/2] : reg_lo_wr[P2IE/2]; -wire [7:0] p2ie_nxt = P2IE[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p2ie <= 8'h00; - else if (p2ie_wr) p2ie <= p2ie_nxt & P2_EN_MSK; - - -// P2SEL Register -//---------------- -reg [7:0] p2sel; - -wire p2sel_wr = P2SEL[0] ? reg_hi_wr[P2SEL/2] : reg_lo_wr[P2SEL/2]; -wire [7:0] p2sel_nxt = P2SEL[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p2sel <= 8'h00; - else if (p2sel_wr) p2sel <= p2sel_nxt & P2_EN_MSK; - -assign p2_sel = p2sel; - - -// P3IN Register -//--------------- -reg [7:0] p3in; - -always @ (posedge mclk or posedge puc) - if (puc) p3in <= 8'h00; - else p3in <= p3_din & P3_EN_MSK; - - -// P3OUT Register -//---------------- -reg [7:0] p3out; - -wire p3out_wr = P3OUT[0] ? reg_hi_wr[P3OUT/2] : reg_lo_wr[P3OUT/2]; -wire [7:0] p3out_nxt = P3OUT[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p3out <= 8'h00; - else if (p3out_wr) p3out <= p3out_nxt & P3_EN_MSK; - -assign p3_dout = p3out; - - -// P3DIR Register -//---------------- -reg [7:0] p3dir; - -wire p3dir_wr = P3DIR[0] ? reg_hi_wr[P3DIR/2] : reg_lo_wr[P3DIR/2]; -wire [7:0] p3dir_nxt = P3DIR[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p3dir <= 8'h00; - else if (p3dir_wr) p3dir <= p3dir_nxt & P3_EN_MSK; - -assign p3_dout_en = p3dir; - - -// P3SEL Register -//---------------- -reg [7:0] p3sel; - -wire p3sel_wr = P3SEL[0] ? reg_hi_wr[P3SEL/2] : reg_lo_wr[P3SEL/2]; -wire [7:0] p3sel_nxt = P3SEL[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p3sel <= 8'h00; - else if (p3sel_wr) p3sel <= p3sel_nxt & P3_EN_MSK; - -assign p3_sel = p3sel; - - -// P4IN Register -//--------------- -reg [7:0] p4in; - -always @ (posedge mclk or posedge puc) - if (puc) p4in <= 8'h00; - else p4in <= p4_din & P4_EN_MSK; - - -// P4OUT Register -//---------------- -reg [7:0] p4out; - -wire p4out_wr = P4OUT[0] ? reg_hi_wr[P4OUT/2] : reg_lo_wr[P4OUT/2]; -wire [7:0] p4out_nxt = P4OUT[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p4out <= 8'h00; - else if (p4out_wr) p4out <= p4out_nxt & P4_EN_MSK; - -assign p4_dout = p4out; - - -// P4DIR Register -//---------------- -reg [7:0] p4dir; - -wire p4dir_wr = P4DIR[0] ? reg_hi_wr[P4DIR/2] : reg_lo_wr[P4DIR/2]; -wire [7:0] p4dir_nxt = P4DIR[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p4dir <= 8'h00; - else if (p4dir_wr) p4dir <= p4dir_nxt & P4_EN_MSK; - -assign p4_dout_en = p4dir; - - -// P4SEL Register -//---------------- -reg [7:0] p4sel; - -wire p4sel_wr = P4SEL[0] ? reg_hi_wr[P4SEL/2] : reg_lo_wr[P4SEL/2]; -wire [7:0] p4sel_nxt = P4SEL[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p4sel <= 8'h00; - else if (p4sel_wr) p4sel <= p4sel_nxt & P4_EN_MSK; - -assign p4_sel = p4sel; - - -// P5IN Register -//--------------- -reg [7:0] p5in; - -always @ (posedge mclk or posedge puc) - if (puc) p5in <= 8'h00; - else p5in <= p5_din & P5_EN_MSK; - - -// P5OUT Register -//---------------- -reg [7:0] p5out; - -wire p5out_wr = P5OUT[0] ? reg_hi_wr[P5OUT/2] : reg_lo_wr[P5OUT/2]; -wire [7:0] p5out_nxt = P5OUT[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p5out <= 8'h00; - else if (p5out_wr) p5out <= p5out_nxt & P5_EN_MSK; - -assign p5_dout = p5out; - - -// P5DIR Register -//---------------- -reg [7:0] p5dir; - -wire p5dir_wr = P5DIR[0] ? reg_hi_wr[P5DIR/2] : reg_lo_wr[P5DIR/2]; -wire [7:0] p5dir_nxt = P5DIR[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p5dir <= 8'h00; - else if (p5dir_wr) p5dir <= p5dir_nxt & P5_EN_MSK; - -assign p5_dout_en = p5dir; - - -// P5SEL Register -//---------------- -reg [7:0] p5sel; - -wire p5sel_wr = P5SEL[0] ? reg_hi_wr[P5SEL/2] : reg_lo_wr[P5SEL/2]; -wire [7:0] p5sel_nxt = P5SEL[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p5sel <= 8'h00; - else if (p5sel_wr) p5sel <= p5sel_nxt & P5_EN_MSK; - -assign p5_sel = p5sel; - - -// P6IN Register -//--------------- -reg [7:0] p6in; - -always @ (posedge mclk or posedge puc) - if (puc) p6in <= 8'h00; - else p6in <= p6_din & P6_EN_MSK; - - -// P6OUT Register -//---------------- -reg [7:0] p6out; - -wire p6out_wr = P6OUT[0] ? reg_hi_wr[P6OUT/2] : reg_lo_wr[P6OUT/2]; -wire [7:0] p6out_nxt = P6OUT[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p6out <= 8'h00; - else if (p6out_wr) p6out <= p6out_nxt & P6_EN_MSK; - -assign p6_dout = p6out; - - -// P6DIR Register -//---------------- -reg [7:0] p6dir; - -wire p6dir_wr = P6DIR[0] ? reg_hi_wr[P6DIR/2] : reg_lo_wr[P6DIR/2]; -wire [7:0] p6dir_nxt = P6DIR[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p6dir <= 8'h00; - else if (p6dir_wr) p6dir <= p6dir_nxt & P6_EN_MSK; - -assign p6_dout_en = p6dir; - - -// P6SEL Register -//---------------- -reg [7:0] p6sel; - -wire p6sel_wr = P6SEL[0] ? reg_hi_wr[P6SEL/2] : reg_lo_wr[P6SEL/2]; -wire [7:0] p6sel_nxt = P6SEL[0] ? per_din[15:8] : per_din[7:0]; - -always @ (posedge mclk or posedge puc) - if (puc) p6sel <= 8'h00; - else if (p6sel_wr) p6sel <= p6sel_nxt & P6_EN_MSK; - -assign p6_sel = p6sel; - - - -//============================================================================ -// 4) INTERRUPT GENERATION -//============================================================================ - -// Port 1 interrupt -//------------------ - -// Delay input -reg [7:0] p1in_dly; -always @ (posedge mclk or posedge puc) - if (puc) p1in_dly <= 8'h00; - else p1in_dly <= p1in & P1_EN_MSK; - -// Edge detection -wire [7:0] p1in_re = p1in & ~p1in_dly; -wire [7:0] p1in_fe = ~p1in & p1in_dly; - -// Set interrupt flag -assign p1ifg_set = {p1ies[7] ? p1in_fe[7] : p1in_re[7], - p1ies[6] ? p1in_fe[6] : p1in_re[6], - p1ies[5] ? p1in_fe[5] : p1in_re[5], - p1ies[4] ? p1in_fe[4] : p1in_re[4], - p1ies[3] ? p1in_fe[3] : p1in_re[3], - p1ies[2] ? p1in_fe[2] : p1in_re[2], - p1ies[1] ? p1in_fe[1] : p1in_re[1], - p1ies[0] ? p1in_fe[0] : p1in_re[0]} & P1_EN_MSK; - -// Generate CPU interrupt -assign irq_port1 = |(p1ie & p1ifg) & P1_EN[0]; - - -// Port 1 interrupt -//------------------ - -// Delay input -reg [7:0] p2in_dly; -always @ (posedge mclk or posedge puc) - if (puc) p2in_dly <= 8'h00; - else p2in_dly <= p2in & P2_EN_MSK; - -// Edge detection -wire [7:0] p2in_re = p2in & ~p2in_dly; -wire [7:0] p2in_fe = ~p2in & p2in_dly; - -// Set interrupt flag -assign p2ifg_set = {p2ies[7] ? p2in_fe[7] : p2in_re[7], - p2ies[6] ? p2in_fe[6] : p2in_re[6], - p2ies[5] ? p2in_fe[5] : p2in_re[5], - p2ies[4] ? p2in_fe[4] : p2in_re[4], - p2ies[3] ? p2in_fe[3] : p2in_re[3], - p2ies[2] ? p2in_fe[2] : p2in_re[2], - p2ies[1] ? p2in_fe[1] : p2in_re[1], - p2ies[0] ? p2in_fe[0] : p2in_re[0]} & P2_EN_MSK; - -// Generate CPU interrupt -assign irq_port2 = |(p2ie & p2ifg) & P2_EN[0]; - - -//============================================================================ -// 5) DATA OUTPUT GENERATION -//============================================================================ - -// Data output mux -wire [15:0] p1in_rd = (p1in & {8{reg_rd[P1IN/2]}}) << (8 & {4{P1IN[0]}}); -wire [15:0] p1out_rd = (p1out & {8{reg_rd[P1OUT/2]}}) << (8 & {4{P1OUT[0]}}); -wire [15:0] p1dir_rd = (p1dir & {8{reg_rd[P1DIR/2]}}) << (8 & {4{P1DIR[0]}}); -wire [15:0] p1ifg_rd = (p1ifg & {8{reg_rd[P1IFG/2]}}) << (8 & {4{P1IFG[0]}}); -wire [15:0] p1ies_rd = (p1ies & {8{reg_rd[P1IES/2]}}) << (8 & {4{P1IES[0]}}); -wire [15:0] p1ie_rd = (p1ie & {8{reg_rd[P1IE/2]}}) << (8 & {4{P1IE[0]}}); -wire [15:0] p1sel_rd = (p1sel & {8{reg_rd[P1SEL/2]}}) << (8 & {4{P1SEL[0]}}); -wire [15:0] p2in_rd = (p2in & {8{reg_rd[P2IN/2]}}) << (8 & {4{P2IN[0]}}); -wire [15:0] p2out_rd = (p2out & {8{reg_rd[P2OUT/2]}}) << (8 & {4{P2OUT[0]}}); -wire [15:0] p2dir_rd = (p2dir & {8{reg_rd[P2DIR/2]}}) << (8 & {4{P2DIR[0]}}); -wire [15:0] p2ifg_rd = (p2ifg & {8{reg_rd[P2IFG/2]}}) << (8 & {4{P2IFG[0]}}); -wire [15:0] p2ies_rd = (p2ies & {8{reg_rd[P2IES/2]}}) << (8 & {4{P2IES[0]}}); -wire [15:0] p2ie_rd = (p2ie & {8{reg_rd[P2IE/2]}}) << (8 & {4{P2IE[0]}}); -wire [15:0] p2sel_rd = (p2sel & {8{reg_rd[P2SEL/2]}}) << (8 & {4{P2SEL[0]}}); -wire [15:0] p3in_rd = (p3in & {8{reg_rd[P3IN/2]}}) << (8 & {4{P3IN[0]}}); -wire [15:0] p3out_rd = (p3out & {8{reg_rd[P3OUT/2]}}) << (8 & {4{P3OUT[0]}}); -wire [15:0] p3dir_rd = (p3dir & {8{reg_rd[P3DIR/2]}}) << (8 & {4{P3DIR[0]}}); -wire [15:0] p3sel_rd = (p3sel & {8{reg_rd[P3SEL/2]}}) << (8 & {4{P3SEL[0]}}); -wire [15:0] p4in_rd = (p4in & {8{reg_rd[P4IN/2]}}) << (8 & {4{P4IN[0]}}); -wire [15:0] p4out_rd = (p4out & {8{reg_rd[P4OUT/2]}}) << (8 & {4{P4OUT[0]}}); -wire [15:0] p4dir_rd = (p4dir & {8{reg_rd[P4DIR/2]}}) << (8 & {4{P4DIR[0]}}); -wire [15:0] p4sel_rd = (p4sel & {8{reg_rd[P4SEL/2]}}) << (8 & {4{P4SEL[0]}}); -wire [15:0] p5in_rd = (p5in & {8{reg_rd[P5IN/2]}}) << (8 & {4{P5IN[0]}}); -wire [15:0] p5out_rd = (p5out & {8{reg_rd[P5OUT/2]}}) << (8 & {4{P5OUT[0]}}); -wire [15:0] p5dir_rd = (p5dir & {8{reg_rd[P5DIR/2]}}) << (8 & {4{P5DIR[0]}}); -wire [15:0] p5sel_rd = (p5sel & {8{reg_rd[P5SEL/2]}}) << (8 & {4{P5SEL[0]}}); -wire [15:0] p6in_rd = (p6in & {8{reg_rd[P6IN/2]}}) << (8 & {4{P6IN[0]}}); -wire [15:0] p6out_rd = (p6out & {8{reg_rd[P6OUT/2]}}) << (8 & {4{P6OUT[0]}}); -wire [15:0] p6dir_rd = (p6dir & {8{reg_rd[P6DIR/2]}}) << (8 & {4{P6DIR[0]}}); -wire [15:0] p6sel_rd = (p6sel & {8{reg_rd[P6SEL/2]}}) << (8 & {4{P6SEL[0]}}); - -wire [15:0] per_dout = p1in_rd | - p1out_rd | - p1dir_rd | - p1ifg_rd | - p1ies_rd | - p1ie_rd | - p1sel_rd | - p2in_rd | - p2out_rd | - p2dir_rd | - p2ifg_rd | - p2ies_rd | - p2ie_rd | - p2sel_rd | - p3in_rd | - p3out_rd | - p3dir_rd | - p3sel_rd | - p4in_rd | - p4out_rd | - p4dir_rd | - p4sel_rd | - p5in_rd | - p5out_rd | - p5dir_rd | - p5sel_rd | - p6in_rd | - p6out_rd | - p6dir_rd | - p6sel_rd; - -endmodule // gpio - -`include "openMSP430_undefines.v"
periph/gpio.v Property changes : Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Date Revision Author \ No newline at end of property Index: periph/omsp_gpio.v =================================================================== --- periph/omsp_gpio.v (nonexistent) +++ periph/omsp_gpio.v (revision 34) @@ -0,0 +1,774 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2001 Authors +// +// This source file may be used and distributed without restriction provided +// that this copyright statement is not removed from the file and that any +// derivative work contains the original copyright notice and the associated +// disclaimer. +// +// This source file is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This source is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +// License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this source; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_gpio.v +// +// *Module Description: +// Digital I/O interface +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev$ +// $LastChangedBy$ +// $LastChangedDate$ +//---------------------------------------------------------------------------- +`include "timescale.v" +`include "openMSP430_defines.v" + +module omsp_gpio ( + +// OUTPUTs + irq_port1, // Port 1 interrupt + irq_port2, // Port 2 interrupt + p1_dout, // Port 1 data output + p1_dout_en, // Port 1 data output enable + p1_sel, // Port 1 function select + p2_dout, // Port 2 data output + p2_dout_en, // Port 2 data output enable + p2_sel, // Port 2 function select + p3_dout, // Port 3 data output + p3_dout_en, // Port 3 data output enable + p3_sel, // Port 3 function select + p4_dout, // Port 4 data output + p4_dout_en, // Port 4 data output enable + p4_sel, // Port 4 function select + p5_dout, // Port 5 data output + p5_dout_en, // Port 5 data output enable + p5_sel, // Port 5 function select + p6_dout, // Port 6 data output + p6_dout_en, // Port 6 data output enable + p6_sel, // Port 6 function select + per_dout, // Peripheral data output + +// INPUTs + mclk, // Main system clock + p1_din, // Port 1 data input + p2_din, // Port 2 data input + p3_din, // Port 3 data input + p4_din, // Port 4 data input + p5_din, // Port 5 data input + p6_din, // Port 6 data input + per_addr, // Peripheral address + per_din, // Peripheral data input + per_en, // Peripheral enable (high active) + per_wen, // Peripheral write enable (high active) + puc // Main system reset +); + +// PARAMETERs +//============ +parameter P1_EN = 1'b1; // Enable Port 1 +parameter P2_EN = 1'b1; // Enable Port 2 +parameter P3_EN = 1'b0; // Enable Port 3 +parameter P4_EN = 1'b0; // Enable Port 4 +parameter P5_EN = 1'b0; // Enable Port 5 +parameter P6_EN = 1'b0; // Enable Port 6 + + +// OUTPUTs +//========= +output irq_port1; // Port 1 interrupt +output irq_port2; // Port 2 interrupt +output [7:0] p1_dout; // Port 1 data output +output [7:0] p1_dout_en; // Port 1 data output enable +output [7:0] p1_sel; // Port 1 function select +output [7:0] p2_dout; // Port 2 data output +output [7:0] p2_dout_en; // Port 2 data output enable +output [7:0] p2_sel; // Port 2 function select +output [7:0] p3_dout; // Port 3 data output +output [7:0] p3_dout_en; // Port 3 data output enable +output [7:0] p3_sel; // Port 3 function select +output [7:0] p4_dout; // Port 4 data output +output [7:0] p4_dout_en; // Port 4 data output enable +output [7:0] p4_sel; // Port 4 function select +output [7:0] p5_dout; // Port 5 data output +output [7:0] p5_dout_en; // Port 5 data output enable +output [7:0] p5_sel; // Port 5 function select +output [7:0] p6_dout; // Port 6 data output +output [7:0] p6_dout_en; // Port 6 data output enable +output [7:0] p6_sel; // Port 6 function select +output [15:0] per_dout; // Peripheral data output + +// INPUTs +//========= +input mclk; // Main system clock +input [7:0] p1_din; // Port 1 data input +input [7:0] p2_din; // Port 2 data input +input [7:0] p3_din; // Port 3 data input +input [7:0] p4_din; // Port 4 data input +input [7:0] p5_din; // Port 5 data input +input [7:0] p6_din; // Port 6 data input +input [7:0] per_addr; // Peripheral address +input [15:0] per_din; // Peripheral data input +input per_en; // Peripheral enable (high active) +input [1:0] per_wen; // Peripheral write enable (high active) +input puc; // Main system reset + + +//============================================================================= +// 1) PARAMETER DECLARATION +//============================================================================= + +// Masks +parameter P1_EN_MSK = {8{P1_EN[0]}}; +parameter P2_EN_MSK = {8{P2_EN[0]}}; +parameter P3_EN_MSK = {8{P3_EN[0]}}; +parameter P4_EN_MSK = {8{P4_EN[0]}}; +parameter P5_EN_MSK = {8{P5_EN[0]}}; +parameter P6_EN_MSK = {8{P6_EN[0]}}; + +// Register addresses +parameter P1IN = 9'h020; // Port 1 +parameter P1OUT = 9'h021; +parameter P1DIR = 9'h022; +parameter P1IFG = 9'h023; +parameter P1IES = 9'h024; +parameter P1IE = 9'h025; +parameter P1SEL = 9'h026; +parameter P2IN = 9'h028; // Port 2 +parameter P2OUT = 9'h029; +parameter P2DIR = 9'h02A; +parameter P2IFG = 9'h02B; +parameter P2IES = 9'h02C; +parameter P2IE = 9'h02D; +parameter P2SEL = 9'h02E; +parameter P3IN = 9'h018; // Port 3 +parameter P3OUT = 9'h019; +parameter P3DIR = 9'h01A; +parameter P3SEL = 9'h01B; +parameter P4IN = 9'h01C; // Port 4 +parameter P4OUT = 9'h01D; +parameter P4DIR = 9'h01E; +parameter P4SEL = 9'h01F; +parameter P5IN = 9'h030; // Port 5 +parameter P5OUT = 9'h031; +parameter P5DIR = 9'h032; +parameter P5SEL = 9'h033; +parameter P6IN = 9'h034; // Port 6 +parameter P6OUT = 9'h035; +parameter P6DIR = 9'h036; +parameter P6SEL = 9'h037; + + +// Register one-hot decoder +parameter P1IN_D = (256'h1 << (P1IN /2)); // Port 1 +parameter P1OUT_D = (256'h1 << (P1OUT /2)); +parameter P1DIR_D = (256'h1 << (P1DIR /2)); +parameter P1IFG_D = (256'h1 << (P1IFG /2)); +parameter P1IES_D = (256'h1 << (P1IES /2)); +parameter P1IE_D = (256'h1 << (P1IE /2)); +parameter P1SEL_D = (256'h1 << (P1SEL /2)); +parameter P2IN_D = (256'h1 << (P2IN /2)); // Port 2 +parameter P2OUT_D = (256'h1 << (P2OUT /2)); +parameter P2DIR_D = (256'h1 << (P2DIR /2)); +parameter P2IFG_D = (256'h1 << (P2IFG /2)); +parameter P2IES_D = (256'h1 << (P2IES /2)); +parameter P2IE_D = (256'h1 << (P2IE /2)); +parameter P2SEL_D = (256'h1 << (P2SEL /2)); +parameter P3IN_D = (256'h1 << (P3IN /2)); // Port 3 +parameter P3OUT_D = (256'h1 << (P3OUT /2)); +parameter P3DIR_D = (256'h1 << (P3DIR /2)); +parameter P3SEL_D = (256'h1 << (P3SEL /2)); +parameter P4IN_D = (256'h1 << (P4IN /2)); // Port 4 +parameter P4OUT_D = (256'h1 << (P4OUT /2)); +parameter P4DIR_D = (256'h1 << (P4DIR /2)); +parameter P4SEL_D = (256'h1 << (P4SEL /2)); +parameter P5IN_D = (256'h1 << (P5IN /2)); // Port 5 +parameter P5OUT_D = (256'h1 << (P5OUT /2)); +parameter P5DIR_D = (256'h1 << (P5DIR /2)); +parameter P5SEL_D = (256'h1 << (P5SEL /2)); +parameter P6IN_D = (256'h1 << (P6IN /2)); // Port 6 +parameter P6OUT_D = (256'h1 << (P6OUT /2)); +parameter P6DIR_D = (256'h1 << (P6DIR /2)); +parameter P6SEL_D = (256'h1 << (P6SEL /2)); + + +//============================================================================ +// 2) REGISTER DECODER +//============================================================================ + +// Register address decode +reg [255:0] reg_dec; +always @(per_addr) + case (per_addr) + (P1IN /2): reg_dec = P1IN_D & {256{P1_EN[0]}}; + (P1OUT /2): reg_dec = P1OUT_D & {256{P1_EN[0]}}; + (P1DIR /2): reg_dec = P1DIR_D & {256{P1_EN[0]}}; + (P1IFG /2): reg_dec = P1IFG_D & {256{P1_EN[0]}}; + (P1IES /2): reg_dec = P1IES_D & {256{P1_EN[0]}}; + (P1IE /2): reg_dec = P1IE_D & {256{P1_EN[0]}}; + (P1SEL /2): reg_dec = P1SEL_D & {256{P1_EN[0]}}; + (P2IN /2): reg_dec = P2IN_D & {256{P2_EN[0]}}; + (P2OUT /2): reg_dec = P2OUT_D & {256{P2_EN[0]}}; + (P2DIR /2): reg_dec = P2DIR_D & {256{P2_EN[0]}}; + (P2IFG /2): reg_dec = P2IFG_D & {256{P2_EN[0]}}; + (P2IES /2): reg_dec = P2IES_D & {256{P2_EN[0]}}; + (P2IE /2): reg_dec = P2IE_D & {256{P2_EN[0]}}; + (P2SEL /2): reg_dec = P2SEL_D & {256{P2_EN[0]}}; + (P3IN /2): reg_dec = P3IN_D & {256{P3_EN[0]}}; + (P3OUT /2): reg_dec = P3OUT_D & {256{P3_EN[0]}}; + (P3DIR /2): reg_dec = P3DIR_D & {256{P3_EN[0]}}; + (P3SEL /2): reg_dec = P3SEL_D & {256{P3_EN[0]}}; + (P4IN /2): reg_dec = P4IN_D & {256{P4_EN[0]}}; + (P4OUT /2): reg_dec = P4OUT_D & {256{P4_EN[0]}}; + (P4DIR /2): reg_dec = P4DIR_D & {256{P4_EN[0]}}; + (P4SEL /2): reg_dec = P4SEL_D & {256{P4_EN[0]}}; + (P5IN /2): reg_dec = P5IN_D & {256{P5_EN[0]}}; + (P5OUT /2): reg_dec = P5OUT_D & {256{P5_EN[0]}}; + (P5DIR /2): reg_dec = P5DIR_D & {256{P5_EN[0]}}; + (P5SEL /2): reg_dec = P5SEL_D & {256{P5_EN[0]}}; + (P6IN /2): reg_dec = P6IN_D & {256{P6_EN[0]}}; + (P6OUT /2): reg_dec = P6OUT_D & {256{P6_EN[0]}}; + (P6DIR /2): reg_dec = P6DIR_D & {256{P6_EN[0]}}; + (P6SEL /2): reg_dec = P6SEL_D & {256{P6_EN[0]}}; + default : reg_dec = {256{1'b0}}; + endcase + +// Read/Write probes +wire reg_lo_write = per_wen[0] & per_en; +wire reg_hi_write = per_wen[1] & per_en; +wire reg_read = ~|per_wen & per_en; + +// Read/Write vectors +wire [255:0] reg_hi_wr = reg_dec & {256{reg_hi_write}}; +wire [255:0] reg_lo_wr = reg_dec & {256{reg_lo_write}}; +wire [255:0] reg_rd = reg_dec & {256{reg_read}}; + + +//============================================================================ +// 3) REGISTERS +//============================================================================ + +// P1IN Register +//--------------- +reg [7:0] p1in; + +always @ (posedge mclk or posedge puc) + if (puc) p1in <= 8'h00; + else p1in <= p1_din & P1_EN_MSK; + + +// P1OUT Register +//---------------- +reg [7:0] p1out; + +wire p1out_wr = P1OUT[0] ? reg_hi_wr[P1OUT/2] : reg_lo_wr[P1OUT/2]; +wire [7:0] p1out_nxt = P1OUT[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p1out <= 8'h00; + else if (p1out_wr) p1out <= p1out_nxt & P1_EN_MSK; + +assign p1_dout = p1out; + + +// P1DIR Register +//---------------- +reg [7:0] p1dir; + +wire p1dir_wr = P1DIR[0] ? reg_hi_wr[P1DIR/2] : reg_lo_wr[P1DIR/2]; +wire [7:0] p1dir_nxt = P1DIR[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p1dir <= 8'h00; + else if (p1dir_wr) p1dir <= p1dir_nxt & P1_EN_MSK; + +assign p1_dout_en = p1dir; + + +// P1IFG Register +//---------------- +reg [7:0] p1ifg; + +wire p1ifg_wr = P1IFG[0] ? reg_hi_wr[P1IFG/2] : reg_lo_wr[P1IFG/2]; +wire [7:0] p1ifg_nxt = P1IFG[0] ? per_din[15:8] : per_din[7:0]; +wire [7:0] p1ifg_set; + +always @ (posedge mclk or posedge puc) + if (puc) p1ifg <= 8'h00; + else if (p1ifg_wr) p1ifg <= (p1ifg_nxt | p1ifg_set) & P1_EN_MSK; + else p1ifg <= (p1ifg | p1ifg_set) & P1_EN_MSK; + +// P1IES Register +//---------------- +reg [7:0] p1ies; + +wire p1ies_wr = P1IES[0] ? reg_hi_wr[P1IES/2] : reg_lo_wr[P1IES/2]; +wire [7:0] p1ies_nxt = P1IES[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p1ies <= 8'h00; + else if (p1ies_wr) p1ies <= p1ies_nxt & P1_EN_MSK; + + +// P1IE Register +//---------------- +reg [7:0] p1ie; + +wire p1ie_wr = P1IE[0] ? reg_hi_wr[P1IE/2] : reg_lo_wr[P1IE/2]; +wire [7:0] p1ie_nxt = P1IE[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p1ie <= 8'h00; + else if (p1ie_wr) p1ie <= p1ie_nxt & P1_EN_MSK; + + +// P1SEL Register +//---------------- +reg [7:0] p1sel; + +wire p1sel_wr = P1SEL[0] ? reg_hi_wr[P1SEL/2] : reg_lo_wr[P1SEL/2]; +wire [7:0] p1sel_nxt = P1SEL[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p1sel <= 8'h00; + else if (p1sel_wr) p1sel <= p1sel_nxt & P1_EN_MSK; + +assign p1_sel = p1sel; + + +// P2IN Register +//--------------- +reg [7:0] p2in; + +always @ (posedge mclk or posedge puc) + if (puc) p2in <= 8'h00; + else p2in <= p2_din & P2_EN_MSK; + + +// P2OUT Register +//---------------- +reg [7:0] p2out; + +wire p2out_wr = P2OUT[0] ? reg_hi_wr[P2OUT/2] : reg_lo_wr[P2OUT/2]; +wire [7:0] p2out_nxt = P2OUT[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p2out <= 8'h00; + else if (p2out_wr) p2out <= p2out_nxt & P2_EN_MSK; + +assign p2_dout = p2out; + + +// P2DIR Register +//---------------- +reg [7:0] p2dir; + +wire p2dir_wr = P2DIR[0] ? reg_hi_wr[P2DIR/2] : reg_lo_wr[P2DIR/2]; +wire [7:0] p2dir_nxt = P2DIR[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p2dir <= 8'h00; + else if (p2dir_wr) p2dir <= p2dir_nxt & P2_EN_MSK; + +assign p2_dout_en = p2dir; + + +// P2IFG Register +//---------------- +reg [7:0] p2ifg; + +wire p2ifg_wr = P2IFG[0] ? reg_hi_wr[P2IFG/2] : reg_lo_wr[P2IFG/2]; +wire [7:0] p2ifg_nxt = P2IFG[0] ? per_din[15:8] : per_din[7:0]; +wire [7:0] p2ifg_set; + +always @ (posedge mclk or posedge puc) + if (puc) p2ifg <= 8'h00; + else if (p2ifg_wr) p2ifg <= (p2ifg_nxt | p2ifg_set) & P2_EN_MSK; + else p2ifg <= (p2ifg | p2ifg_set) & P2_EN_MSK; + + +// P2IES Register +//---------------- +reg [7:0] p2ies; + +wire p2ies_wr = P2IES[0] ? reg_hi_wr[P2IES/2] : reg_lo_wr[P2IES/2]; +wire [7:0] p2ies_nxt = P2IES[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p2ies <= 8'h00; + else if (p2ies_wr) p2ies <= p2ies_nxt & P2_EN_MSK; + + +// P2IE Register +//---------------- +reg [7:0] p2ie; + +wire p2ie_wr = P2IE[0] ? reg_hi_wr[P2IE/2] : reg_lo_wr[P2IE/2]; +wire [7:0] p2ie_nxt = P2IE[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p2ie <= 8'h00; + else if (p2ie_wr) p2ie <= p2ie_nxt & P2_EN_MSK; + + +// P2SEL Register +//---------------- +reg [7:0] p2sel; + +wire p2sel_wr = P2SEL[0] ? reg_hi_wr[P2SEL/2] : reg_lo_wr[P2SEL/2]; +wire [7:0] p2sel_nxt = P2SEL[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p2sel <= 8'h00; + else if (p2sel_wr) p2sel <= p2sel_nxt & P2_EN_MSK; + +assign p2_sel = p2sel; + + +// P3IN Register +//--------------- +reg [7:0] p3in; + +always @ (posedge mclk or posedge puc) + if (puc) p3in <= 8'h00; + else p3in <= p3_din & P3_EN_MSK; + + +// P3OUT Register +//---------------- +reg [7:0] p3out; + +wire p3out_wr = P3OUT[0] ? reg_hi_wr[P3OUT/2] : reg_lo_wr[P3OUT/2]; +wire [7:0] p3out_nxt = P3OUT[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p3out <= 8'h00; + else if (p3out_wr) p3out <= p3out_nxt & P3_EN_MSK; + +assign p3_dout = p3out; + + +// P3DIR Register +//---------------- +reg [7:0] p3dir; + +wire p3dir_wr = P3DIR[0] ? reg_hi_wr[P3DIR/2] : reg_lo_wr[P3DIR/2]; +wire [7:0] p3dir_nxt = P3DIR[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p3dir <= 8'h00; + else if (p3dir_wr) p3dir <= p3dir_nxt & P3_EN_MSK; + +assign p3_dout_en = p3dir; + + +// P3SEL Register +//---------------- +reg [7:0] p3sel; + +wire p3sel_wr = P3SEL[0] ? reg_hi_wr[P3SEL/2] : reg_lo_wr[P3SEL/2]; +wire [7:0] p3sel_nxt = P3SEL[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p3sel <= 8'h00; + else if (p3sel_wr) p3sel <= p3sel_nxt & P3_EN_MSK; + +assign p3_sel = p3sel; + + +// P4IN Register +//--------------- +reg [7:0] p4in; + +always @ (posedge mclk or posedge puc) + if (puc) p4in <= 8'h00; + else p4in <= p4_din & P4_EN_MSK; + + +// P4OUT Register +//---------------- +reg [7:0] p4out; + +wire p4out_wr = P4OUT[0] ? reg_hi_wr[P4OUT/2] : reg_lo_wr[P4OUT/2]; +wire [7:0] p4out_nxt = P4OUT[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p4out <= 8'h00; + else if (p4out_wr) p4out <= p4out_nxt & P4_EN_MSK; + +assign p4_dout = p4out; + + +// P4DIR Register +//---------------- +reg [7:0] p4dir; + +wire p4dir_wr = P4DIR[0] ? reg_hi_wr[P4DIR/2] : reg_lo_wr[P4DIR/2]; +wire [7:0] p4dir_nxt = P4DIR[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p4dir <= 8'h00; + else if (p4dir_wr) p4dir <= p4dir_nxt & P4_EN_MSK; + +assign p4_dout_en = p4dir; + + +// P4SEL Register +//---------------- +reg [7:0] p4sel; + +wire p4sel_wr = P4SEL[0] ? reg_hi_wr[P4SEL/2] : reg_lo_wr[P4SEL/2]; +wire [7:0] p4sel_nxt = P4SEL[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p4sel <= 8'h00; + else if (p4sel_wr) p4sel <= p4sel_nxt & P4_EN_MSK; + +assign p4_sel = p4sel; + + +// P5IN Register +//--------------- +reg [7:0] p5in; + +always @ (posedge mclk or posedge puc) + if (puc) p5in <= 8'h00; + else p5in <= p5_din & P5_EN_MSK; + + +// P5OUT Register +//---------------- +reg [7:0] p5out; + +wire p5out_wr = P5OUT[0] ? reg_hi_wr[P5OUT/2] : reg_lo_wr[P5OUT/2]; +wire [7:0] p5out_nxt = P5OUT[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p5out <= 8'h00; + else if (p5out_wr) p5out <= p5out_nxt & P5_EN_MSK; + +assign p5_dout = p5out; + + +// P5DIR Register +//---------------- +reg [7:0] p5dir; + +wire p5dir_wr = P5DIR[0] ? reg_hi_wr[P5DIR/2] : reg_lo_wr[P5DIR/2]; +wire [7:0] p5dir_nxt = P5DIR[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p5dir <= 8'h00; + else if (p5dir_wr) p5dir <= p5dir_nxt & P5_EN_MSK; + +assign p5_dout_en = p5dir; + + +// P5SEL Register +//---------------- +reg [7:0] p5sel; + +wire p5sel_wr = P5SEL[0] ? reg_hi_wr[P5SEL/2] : reg_lo_wr[P5SEL/2]; +wire [7:0] p5sel_nxt = P5SEL[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p5sel <= 8'h00; + else if (p5sel_wr) p5sel <= p5sel_nxt & P5_EN_MSK; + +assign p5_sel = p5sel; + + +// P6IN Register +//--------------- +reg [7:0] p6in; + +always @ (posedge mclk or posedge puc) + if (puc) p6in <= 8'h00; + else p6in <= p6_din & P6_EN_MSK; + + +// P6OUT Register +//---------------- +reg [7:0] p6out; + +wire p6out_wr = P6OUT[0] ? reg_hi_wr[P6OUT/2] : reg_lo_wr[P6OUT/2]; +wire [7:0] p6out_nxt = P6OUT[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p6out <= 8'h00; + else if (p6out_wr) p6out <= p6out_nxt & P6_EN_MSK; + +assign p6_dout = p6out; + + +// P6DIR Register +//---------------- +reg [7:0] p6dir; + +wire p6dir_wr = P6DIR[0] ? reg_hi_wr[P6DIR/2] : reg_lo_wr[P6DIR/2]; +wire [7:0] p6dir_nxt = P6DIR[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p6dir <= 8'h00; + else if (p6dir_wr) p6dir <= p6dir_nxt & P6_EN_MSK; + +assign p6_dout_en = p6dir; + + +// P6SEL Register +//---------------- +reg [7:0] p6sel; + +wire p6sel_wr = P6SEL[0] ? reg_hi_wr[P6SEL/2] : reg_lo_wr[P6SEL/2]; +wire [7:0] p6sel_nxt = P6SEL[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) p6sel <= 8'h00; + else if (p6sel_wr) p6sel <= p6sel_nxt & P6_EN_MSK; + +assign p6_sel = p6sel; + + + +//============================================================================ +// 4) INTERRUPT GENERATION +//============================================================================ + +// Port 1 interrupt +//------------------ + +// Delay input +reg [7:0] p1in_dly; +always @ (posedge mclk or posedge puc) + if (puc) p1in_dly <= 8'h00; + else p1in_dly <= p1in & P1_EN_MSK; + +// Edge detection +wire [7:0] p1in_re = p1in & ~p1in_dly; +wire [7:0] p1in_fe = ~p1in & p1in_dly; + +// Set interrupt flag +assign p1ifg_set = {p1ies[7] ? p1in_fe[7] : p1in_re[7], + p1ies[6] ? p1in_fe[6] : p1in_re[6], + p1ies[5] ? p1in_fe[5] : p1in_re[5], + p1ies[4] ? p1in_fe[4] : p1in_re[4], + p1ies[3] ? p1in_fe[3] : p1in_re[3], + p1ies[2] ? p1in_fe[2] : p1in_re[2], + p1ies[1] ? p1in_fe[1] : p1in_re[1], + p1ies[0] ? p1in_fe[0] : p1in_re[0]} & P1_EN_MSK; + +// Generate CPU interrupt +assign irq_port1 = |(p1ie & p1ifg) & P1_EN[0]; + + +// Port 1 interrupt +//------------------ + +// Delay input +reg [7:0] p2in_dly; +always @ (posedge mclk or posedge puc) + if (puc) p2in_dly <= 8'h00; + else p2in_dly <= p2in & P2_EN_MSK; + +// Edge detection +wire [7:0] p2in_re = p2in & ~p2in_dly; +wire [7:0] p2in_fe = ~p2in & p2in_dly; + +// Set interrupt flag +assign p2ifg_set = {p2ies[7] ? p2in_fe[7] : p2in_re[7], + p2ies[6] ? p2in_fe[6] : p2in_re[6], + p2ies[5] ? p2in_fe[5] : p2in_re[5], + p2ies[4] ? p2in_fe[4] : p2in_re[4], + p2ies[3] ? p2in_fe[3] : p2in_re[3], + p2ies[2] ? p2in_fe[2] : p2in_re[2], + p2ies[1] ? p2in_fe[1] : p2in_re[1], + p2ies[0] ? p2in_fe[0] : p2in_re[0]} & P2_EN_MSK; + +// Generate CPU interrupt +assign irq_port2 = |(p2ie & p2ifg) & P2_EN[0]; + + +//============================================================================ +// 5) DATA OUTPUT GENERATION +//============================================================================ + +// Data output mux +wire [15:0] p1in_rd = (p1in & {8{reg_rd[P1IN/2]}}) << (8 & {4{P1IN[0]}}); +wire [15:0] p1out_rd = (p1out & {8{reg_rd[P1OUT/2]}}) << (8 & {4{P1OUT[0]}}); +wire [15:0] p1dir_rd = (p1dir & {8{reg_rd[P1DIR/2]}}) << (8 & {4{P1DIR[0]}}); +wire [15:0] p1ifg_rd = (p1ifg & {8{reg_rd[P1IFG/2]}}) << (8 & {4{P1IFG[0]}}); +wire [15:0] p1ies_rd = (p1ies & {8{reg_rd[P1IES/2]}}) << (8 & {4{P1IES[0]}}); +wire [15:0] p1ie_rd = (p1ie & {8{reg_rd[P1IE/2]}}) << (8 & {4{P1IE[0]}}); +wire [15:0] p1sel_rd = (p1sel & {8{reg_rd[P1SEL/2]}}) << (8 & {4{P1SEL[0]}}); +wire [15:0] p2in_rd = (p2in & {8{reg_rd[P2IN/2]}}) << (8 & {4{P2IN[0]}}); +wire [15:0] p2out_rd = (p2out & {8{reg_rd[P2OUT/2]}}) << (8 & {4{P2OUT[0]}}); +wire [15:0] p2dir_rd = (p2dir & {8{reg_rd[P2DIR/2]}}) << (8 & {4{P2DIR[0]}}); +wire [15:0] p2ifg_rd = (p2ifg & {8{reg_rd[P2IFG/2]}}) << (8 & {4{P2IFG[0]}}); +wire [15:0] p2ies_rd = (p2ies & {8{reg_rd[P2IES/2]}}) << (8 & {4{P2IES[0]}}); +wire [15:0] p2ie_rd = (p2ie & {8{reg_rd[P2IE/2]}}) << (8 & {4{P2IE[0]}}); +wire [15:0] p2sel_rd = (p2sel & {8{reg_rd[P2SEL/2]}}) << (8 & {4{P2SEL[0]}}); +wire [15:0] p3in_rd = (p3in & {8{reg_rd[P3IN/2]}}) << (8 & {4{P3IN[0]}}); +wire [15:0] p3out_rd = (p3out & {8{reg_rd[P3OUT/2]}}) << (8 & {4{P3OUT[0]}}); +wire [15:0] p3dir_rd = (p3dir & {8{reg_rd[P3DIR/2]}}) << (8 & {4{P3DIR[0]}}); +wire [15:0] p3sel_rd = (p3sel & {8{reg_rd[P3SEL/2]}}) << (8 & {4{P3SEL[0]}}); +wire [15:0] p4in_rd = (p4in & {8{reg_rd[P4IN/2]}}) << (8 & {4{P4IN[0]}}); +wire [15:0] p4out_rd = (p4out & {8{reg_rd[P4OUT/2]}}) << (8 & {4{P4OUT[0]}}); +wire [15:0] p4dir_rd = (p4dir & {8{reg_rd[P4DIR/2]}}) << (8 & {4{P4DIR[0]}}); +wire [15:0] p4sel_rd = (p4sel & {8{reg_rd[P4SEL/2]}}) << (8 & {4{P4SEL[0]}}); +wire [15:0] p5in_rd = (p5in & {8{reg_rd[P5IN/2]}}) << (8 & {4{P5IN[0]}}); +wire [15:0] p5out_rd = (p5out & {8{reg_rd[P5OUT/2]}}) << (8 & {4{P5OUT[0]}}); +wire [15:0] p5dir_rd = (p5dir & {8{reg_rd[P5DIR/2]}}) << (8 & {4{P5DIR[0]}}); +wire [15:0] p5sel_rd = (p5sel & {8{reg_rd[P5SEL/2]}}) << (8 & {4{P5SEL[0]}}); +wire [15:0] p6in_rd = (p6in & {8{reg_rd[P6IN/2]}}) << (8 & {4{P6IN[0]}}); +wire [15:0] p6out_rd = (p6out & {8{reg_rd[P6OUT/2]}}) << (8 & {4{P6OUT[0]}}); +wire [15:0] p6dir_rd = (p6dir & {8{reg_rd[P6DIR/2]}}) << (8 & {4{P6DIR[0]}}); +wire [15:0] p6sel_rd = (p6sel & {8{reg_rd[P6SEL/2]}}) << (8 & {4{P6SEL[0]}}); + +wire [15:0] per_dout = p1in_rd | + p1out_rd | + p1dir_rd | + p1ifg_rd | + p1ies_rd | + p1ie_rd | + p1sel_rd | + p2in_rd | + p2out_rd | + p2dir_rd | + p2ifg_rd | + p2ies_rd | + p2ie_rd | + p2sel_rd | + p3in_rd | + p3out_rd | + p3dir_rd | + p3sel_rd | + p4in_rd | + p4out_rd | + p4dir_rd | + p4sel_rd | + p5in_rd | + p5out_rd | + p5dir_rd | + p5sel_rd | + p6in_rd | + p6out_rd | + p6dir_rd | + p6sel_rd; + +endmodule // omsp_gpio + +`include "openMSP430_undefines.v"
periph/omsp_gpio.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Date Revision Author \ No newline at end of property Index: periph/omsp_timerA.v =================================================================== --- periph/omsp_timerA.v (nonexistent) +++ periph/omsp_timerA.v (revision 34) @@ -0,0 +1,689 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2001 Authors +// +// This source file may be used and distributed without restriction provided +// that this copyright statement is not removed from the file and that any +// derivative work contains the original copyright notice and the associated +// disclaimer. +// +// This source file is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This source is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +// License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this source; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_timerA.v +// +// *Module Description: +// Timer A top-level +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev$ +// $LastChangedBy$ +// $LastChangedDate$ +//---------------------------------------------------------------------------- +`include "timescale.v" +`include "openMSP430_defines.v" + +module omsp_timerA ( + +// OUTPUTs + irq_ta0, // Timer A interrupt: TACCR0 + irq_ta1, // Timer A interrupt: TAIV, TACCR1, TACCR2 + per_dout, // Peripheral data output + ta_out0, // Timer A output 0 + ta_out0_en, // Timer A output 0 enable + ta_out1, // Timer A output 1 + ta_out1_en, // Timer A output 1 enable + ta_out2, // Timer A output 2 + ta_out2_en, // Timer A output 2 enable + +// INPUTs + aclk_en, // ACLK enable (from CPU) + dbg_freeze, // Freeze Timer A counter + inclk, // INCLK external timer clock (SLOW) + irq_ta0_acc, // Interrupt request TACCR0 accepted + mclk, // Main system clock + per_addr, // Peripheral address + per_din, // Peripheral data input + per_en, // Peripheral enable (high active) + per_wen, // Peripheral write enable (high active) + puc, // Main system reset + smclk_en, // SMCLK enable (from CPU) + ta_cci0a, // Timer A capture 0 input A + ta_cci0b, // Timer A capture 0 input B + ta_cci1a, // Timer A capture 1 input A + ta_cci1b, // Timer A capture 1 input B + ta_cci2a, // Timer A capture 2 input A + ta_cci2b, // Timer A capture 2 input B + taclk // TACLK external timer clock (SLOW) +); + +// OUTPUTs +//========= +output irq_ta0; // Timer A interrupt: TACCR0 +output irq_ta1; // Timer A interrupt: TAIV, TACCR1, TACCR2 +output [15:0] per_dout; // Peripheral data output +output ta_out0; // Timer A output 0 +output ta_out0_en; // Timer A output 0 enable +output ta_out1; // Timer A output 1 +output ta_out1_en; // Timer A output 1 enable +output ta_out2; // Timer A output 2 +output ta_out2_en; // Timer A output 2 enable + +// INPUTs +//========= +input aclk_en; // ACLK enable (from CPU) +input dbg_freeze; // Freeze Timer A counter +input inclk; // INCLK external timer clock (SLOW) +input irq_ta0_acc; // Interrupt request TACCR0 accepted +input mclk; // Main system clock +input [7:0] per_addr; // Peripheral address +input [15:0] per_din; // Peripheral data input +input per_en; // Peripheral enable (high active) +input [1:0] per_wen; // Peripheral write enable (high active) +input puc; // Main system reset +input smclk_en; // SMCLK enable (from CPU) +input ta_cci0a; // Timer A capture 0 input A +input ta_cci0b; // Timer A capture 0 input B +input ta_cci1a; // Timer A capture 1 input A +input ta_cci1b; // Timer A capture 1 input B +input ta_cci2a; // Timer A capture 2 input A +input ta_cci2b; // Timer A capture 2 input B +input taclk; // TACLK external timer clock (SLOW) + + +//============================================================================= +// 1) PARAMETER DECLARATION +//============================================================================= + +// Register addresses +parameter TACTL = 9'h160; +parameter TAR = 9'h170; +parameter TACCTL0 = 9'h162; +parameter TACCR0 = 9'h172; +parameter TACCTL1 = 9'h164; +parameter TACCR1 = 9'h174; +parameter TACCTL2 = 9'h166; +parameter TACCR2 = 9'h176; +parameter TAIV = 9'h12E; + + +// Register one-hot decoder +parameter TACTL_D = (512'h1 << TACTL); +parameter TAR_D = (512'h1 << TAR); +parameter TACCTL0_D = (512'h1 << TACCTL0); +parameter TACCR0_D = (512'h1 << TACCR0); +parameter TACCTL1_D = (512'h1 << TACCTL1); +parameter TACCR1_D = (512'h1 << TACCR1); +parameter TACCTL2_D = (512'h1 << TACCTL2); +parameter TACCR2_D = (512'h1 << TACCR2); +parameter TAIV_D = (512'h1 << TAIV); + + +//============================================================================ +// 2) REGISTER DECODER +//============================================================================ + +// Register address decode +reg [511:0] reg_dec; +always @(per_addr) + case ({per_addr,1'b0}) + TACTL : reg_dec = TACTL_D; + TAR : reg_dec = TAR_D; + TACCTL0: reg_dec = TACCTL0_D; + TACCR0 : reg_dec = TACCR0_D; + TACCTL1: reg_dec = TACCTL1_D; + TACCR1 : reg_dec = TACCR1_D; + TACCTL2: reg_dec = TACCTL2_D; + TACCR2 : reg_dec = TACCR2_D; + TAIV : reg_dec = TAIV_D; + default: reg_dec = {512{1'b0}}; + endcase + +// Read/Write probes +wire reg_write = |per_wen & per_en; +wire reg_read = ~|per_wen & per_en; + +// Read/Write vectors +wire [511:0] reg_wr = reg_dec & {512{reg_write}}; +wire [511:0] reg_rd = reg_dec & {512{reg_read}}; + + +//============================================================================ +// 3) REGISTERS +//============================================================================ + +// TACTL Register +//----------------- +reg [9:0] tactl; + +wire tactl_wr = reg_wr[TACTL]; +wire taclr = tactl_wr & per_din[`TACLR]; +wire taifg_set; +wire taifg_clr; + +always @ (posedge mclk or posedge puc) + if (puc) tactl <= 10'h000; + else if (tactl_wr) tactl <= ((per_din[9:0] & 10'h3f3) | {9'h000, taifg_set}) & {9'h1ff, ~taifg_clr}; + else tactl <= (tactl | {9'h000, taifg_set}) & {9'h1ff, ~taifg_clr}; + + +// TAR Register +//----------------- +reg [15:0] tar; + +wire tar_wr = reg_wr[TAR]; + +wire tar_clk; +wire tar_clr; +wire tar_inc; +wire tar_dec; +wire [15:0] tar_add = tar_inc ? 16'h0001 : + tar_dec ? 16'hffff : 16'h0000; +wire [15:0] tar_nxt = tar_clr ? 16'h0000 : (tar+tar_add); + +always @ (posedge mclk or posedge puc) + if (puc) tar <= 16'h0000; + else if (tar_wr) tar <= per_din; + else if (taclr) tar <= 16'h0000; + else if (tar_clk & ~dbg_freeze) tar <= tar_nxt; + + +// TACCTL0 Register +//------------------ +reg [15:0] tacctl0; + +wire tacctl0_wr = reg_wr[TACCTL0]; +wire ccifg0_set; +wire cov0_set; + +always @ (posedge mclk or posedge puc) + if (puc) tacctl0 <= 16'h0000; + else if (tacctl0_wr) tacctl0 <= ((per_din & 16'hf9f7) | {14'h0000, cov0_set, ccifg0_set}) & {15'h7fff, ~irq_ta0_acc}; + else tacctl0 <= (tacctl0 | {14'h0000, cov0_set, ccifg0_set}) & {15'h7fff, ~irq_ta0_acc}; + +wire cci0; +reg scci0; +wire [15:0] tacctl0_full = tacctl0 | {5'h00, scci0, 6'h00, cci0, 3'h0}; + + +// TACCR0 Register +//------------------ +reg [15:0] taccr0; + +wire taccr0_wr = reg_wr[TACCR0]; +wire cci0_cap; + +always @ (posedge mclk or posedge puc) + if (puc) taccr0 <= 16'h0000; + else if (taccr0_wr) taccr0 <= per_din; + else if (cci0_cap) taccr0 <= tar; + + +// TACCTL1 Register +//------------------ +reg [15:0] tacctl1; + +wire tacctl1_wr = reg_wr[TACCTL1]; +wire ccifg1_set; +wire ccifg1_clr; +wire cov1_set; + +always @ (posedge mclk or posedge puc) + if (puc) tacctl1 <= 16'h0000; + else if (tacctl1_wr) tacctl1 <= ((per_din & 16'hf9f7) | {14'h0000, cov1_set, ccifg1_set}) & {15'h7fff, ~ccifg1_clr}; + else tacctl1 <= (tacctl1 | {14'h0000, cov1_set, ccifg1_set}) & {15'h7fff, ~ccifg1_clr}; + +wire cci1; +reg scci1; +wire [15:0] tacctl1_full = tacctl1 | {5'h00, scci1, 6'h00, cci1, 3'h0}; + + +// TACCR1 Register +//------------------ +reg [15:0] taccr1; + +wire taccr1_wr = reg_wr[TACCR1]; +wire cci1_cap; + +always @ (posedge mclk or posedge puc) + if (puc) taccr1 <= 16'h0000; + else if (taccr1_wr) taccr1 <= per_din; + else if (cci1_cap) taccr1 <= tar; + + +// TACCTL2 Register +//------------------ +reg [15:0] tacctl2; + +wire tacctl2_wr = reg_wr[TACCTL2]; +wire ccifg2_set; +wire ccifg2_clr; +wire cov2_set; + +always @ (posedge mclk or posedge puc) + if (puc) tacctl2 <= 16'h0000; + else if (tacctl2_wr) tacctl2 <= ((per_din & 16'hf9f7) | {14'h0000, cov2_set, ccifg2_set}) & {15'h7fff, ~ccifg2_clr}; + else tacctl2 <= (tacctl2 | {14'h0000, cov2_set, ccifg2_set}) & {15'h7fff, ~ccifg2_clr}; + +wire cci2; +reg scci2; +wire [15:0] tacctl2_full = tacctl2 | {5'h00, scci2, 6'h00, cci2, 3'h0}; + + +// TACCR2 Register +//------------------ +reg [15:0] taccr2; + +wire taccr2_wr = reg_wr[TACCR2]; +wire cci2_cap; + +always @ (posedge mclk or posedge puc) + if (puc) taccr2 <= 16'h0000; + else if (taccr2_wr) taccr2 <= per_din; + else if (cci2_cap) taccr2 <= tar; + + +// TAIV Register +//------------------ + +wire [3:0] taiv = (tacctl1[`TACCIFG] & tacctl1[`TACCIE]) ? 4'h2 : + (tacctl2[`TACCIFG] & tacctl2[`TACCIE]) ? 4'h4 : + (tactl[`TAIFG] & tactl[`TAIE]) ? 4'hA : + 4'h0; + +assign ccifg1_clr = (reg_rd[TAIV] | reg_wr[TAIV]) & (taiv==4'h2); +assign ccifg2_clr = (reg_rd[TAIV] | reg_wr[TAIV]) & (taiv==4'h4); +assign taifg_clr = (reg_rd[TAIV] | reg_wr[TAIV]) & (taiv==4'hA); + + +//============================================================================ +// 4) DATA OUTPUT GENERATION +//============================================================================ + +// Data output mux +wire [15:0] tactl_rd = {6'h00, tactl} & {16{reg_rd[TACTL]}}; +wire [15:0] tar_rd = tar & {16{reg_rd[TAR]}}; +wire [15:0] tacctl0_rd = tacctl0_full & {16{reg_rd[TACCTL0]}}; +wire [15:0] taccr0_rd = taccr0 & {16{reg_rd[TACCR0]}}; +wire [15:0] tacctl1_rd = tacctl1_full & {16{reg_rd[TACCTL1]}}; +wire [15:0] taccr1_rd = taccr1 & {16{reg_rd[TACCR1]}}; +wire [15:0] tacctl2_rd = tacctl2_full & {16{reg_rd[TACCTL2]}}; +wire [15:0] taccr2_rd = taccr2 & {16{reg_rd[TACCR2]}}; +wire [15:0] taiv_rd = {12'h000, taiv} & {16{reg_rd[TAIV]}}; + +wire [15:0] per_dout = tactl_rd | + tar_rd | + tacctl0_rd | + taccr0_rd | + tacctl1_rd | + taccr1_rd | + tacctl2_rd | + taccr2_rd | + taiv_rd; + + +//============================================================================ +// 5) Timer A counter control +//============================================================================ + +// Clock input synchronization (TACLK & INCLK) +//----------------------------------------------------------- +reg [2:0] taclk_s; + +always @ (posedge mclk or posedge puc) + if (puc) taclk_s <= 3'b000; + else taclk_s <= {taclk_s[1:0], taclk}; + +wire taclk_en = taclk_s[1] & ~taclk_s[2]; + + +reg [2:0] inclk_s; + +always @ (posedge mclk or posedge puc) + if (puc) inclk_s <= 3'b000; + else inclk_s <= {inclk_s[1:0], inclk}; + +wire inclk_en = inclk_s[1] & ~inclk_s[2]; + + +// Timer clock input mux +//----------------------------------------------------------- + +wire sel_clk = (tactl[`TASSELx]==2'b00) ? taclk_en : + (tactl[`TASSELx]==2'b01) ? aclk_en : + (tactl[`TASSELx]==2'b10) ? smclk_en : inclk_en; + + +// Generate update pluse for the counter (<=> divided clock) +//----------------------------------------------------------- +reg [2:0] clk_div; + +assign tar_clk = sel_clk & ((tactl[`TAIDx]==2'b00) ? 1'b1 : + (tactl[`TAIDx]==2'b01) ? clk_div[0] : + (tactl[`TAIDx]==2'b10) ? &clk_div[1:0] : + &clk_div[2:0]); + +always @ (posedge mclk or posedge puc) + if (puc) clk_div <= 3'h0; + else if (tar_clk | taclr) clk_div <= 3'h0; + else if ((tactl[`TAMCx]!=2'b00) & sel_clk) clk_div <= clk_div+3'h1; + + +// Time counter control signals +//----------------------------------------------------------- + +assign tar_clr = ((tactl[`TAMCx]==2'b01) & (tar>=taccr0)) | + ((tactl[`TAMCx]==2'b11) & (taccr0==16'h0000)); + +assign tar_inc = (tactl[`TAMCx]==2'b01) | (tactl[`TAMCx]==2'b10) | + ((tactl[`TAMCx]==2'b11) & ~tar_dec); + +reg tar_dir; +always @ (posedge mclk or posedge puc) + if (puc) tar_dir <= 1'b0; + else if (taclr) tar_dir <= 1'b0; + else if (tactl[`TAMCx]==2'b11) + begin + if (tar_clk & (tar==16'h0001)) tar_dir <= 1'b0; + else if (tar>=taccr0) tar_dir <= 1'b1; + end + else tar_dir <= 1'b0; + +assign tar_dec = tar_dir | ((tactl[`TAMCx]==2'b11) & (tar>=taccr0)); + + +//============================================================================ +// 6) Timer A comparator +//============================================================================ + +wire equ0 = (tar_nxt==taccr0) & (tar!=taccr0); +wire equ1 = (tar_nxt==taccr1) & (tar!=taccr1); +wire equ2 = (tar_nxt==taccr2) & (tar!=taccr2); + + +//============================================================================ +// 7) Timer A capture logic +//============================================================================ + +// Input selection +//------------------ +assign cci0 = (tacctl0[`TACCISx]==2'b00) ? ta_cci0a : + (tacctl0[`TACCISx]==2'b01) ? ta_cci0b : + (tacctl0[`TACCISx]==2'b10) ? 1'b0 : 1'b1; + +assign cci1 = (tacctl1[`TACCISx]==2'b00) ? ta_cci1a : + (tacctl1[`TACCISx]==2'b01) ? ta_cci1b : + (tacctl1[`TACCISx]==2'b10) ? 1'b0 : 1'b1; + +assign cci2 = (tacctl2[`TACCISx]==2'b00) ? ta_cci2a : + (tacctl2[`TACCISx]==2'b01) ? ta_cci2b : + (tacctl2[`TACCISx]==2'b10) ? 1'b0 : 1'b1; + +// Register CCIx for synchronization and edge detection +reg [2:0] cci_s; +always @ (posedge mclk or posedge puc) + if (puc) cci_s <= 3'h0; + else cci_s <= {cci2, cci1, cci0}; +reg [2:0] cci_ss; +always @ (posedge mclk or posedge puc) + if (puc) cci_ss <= 3'h0; + else cci_ss <= cci_s; +reg [2:0] cci_sss; +always @ (posedge mclk or posedge puc) + if (puc) cci_sss <= 3'h0; + else cci_sss <= cci_ss; + + +// Generate SCCIx +//------------------ + +always @ (posedge mclk or posedge puc) + if (puc) scci0 <= 1'b0; + else if (tar_clk & equ0) scci0 <= cci_ss[0]; + +always @ (posedge mclk or posedge puc) + if (puc) scci1 <= 1'b0; + else if (tar_clk & equ1) scci1 <= cci_ss[1]; + +always @ (posedge mclk or posedge puc) + if (puc) scci2 <= 1'b0; + else if (tar_clk & equ2) scci2 <= cci_ss[2]; + + +// Capture mode +//------------------ +wire cci0_evt = (tacctl0[`TACMx]==2'b00) ? 1'b0 : + (tacctl0[`TACMx]==2'b01) ? ( cci_ss[0] & ~cci_sss[0]) : // Rising edge + (tacctl0[`TACMx]==2'b10) ? (~cci_ss[0] & cci_sss[0]) : // Falling edge + ( cci_ss[0] ^ cci_sss[0]); // Both edges + +wire cci1_evt = (tacctl1[`TACMx]==2'b00) ? 1'b0 : + (tacctl1[`TACMx]==2'b01) ? ( cci_ss[1] & ~cci_sss[1]) : // Rising edge + (tacctl1[`TACMx]==2'b10) ? (~cci_ss[1] & cci_sss[1]) : // Falling edge + ( cci_ss[1] ^ cci_sss[1]); // Both edges + +wire cci2_evt = (tacctl2[`TACMx]==2'b00) ? 1'b0 : + (tacctl2[`TACMx]==2'b01) ? ( cci_ss[2] & ~cci_sss[2]) : // Rising edge + (tacctl2[`TACMx]==2'b10) ? (~cci_ss[2] & cci_sss[2]) : // Falling edge + ( cci_ss[2] ^ cci_sss[2]); // Both edges + +// Event Synchronization +//----------------------- + +reg cci0_evt_s; +always @ (posedge mclk or posedge puc) + if (puc) cci0_evt_s <= 1'b0; + else if (tar_clk) cci0_evt_s <= 1'b0; + else if (cci0_evt) cci0_evt_s <= 1'b1; + +reg cci1_evt_s; +always @ (posedge mclk or posedge puc) + if (puc) cci1_evt_s <= 1'b0; + else if (tar_clk) cci1_evt_s <= 1'b0; + else if (cci1_evt) cci1_evt_s <= 1'b1; + +reg cci2_evt_s; +always @ (posedge mclk or posedge puc) + if (puc) cci2_evt_s <= 1'b0; + else if (tar_clk) cci2_evt_s <= 1'b0; + else if (cci2_evt) cci2_evt_s <= 1'b1; + +reg cci0_sync; +always @ (posedge mclk or posedge puc) + if (puc) cci0_sync <= 1'b0; + else cci0_sync <= (tar_clk & cci0_evt_s) | (tar_clk & cci0_evt & ~cci0_evt_s); + +reg cci1_sync; +always @ (posedge mclk or posedge puc) + if (puc) cci1_sync <= 1'b0; + else cci1_sync <= (tar_clk & cci1_evt_s) | (tar_clk & cci1_evt & ~cci1_evt_s); + +reg cci2_sync; +always @ (posedge mclk or posedge puc) + if (puc) cci2_sync <= 1'b0; + else cci2_sync <= (tar_clk & cci2_evt_s) | (tar_clk & cci2_evt & ~cci2_evt_s); + + +// Generate final capture command +//----------------------------------- + +assign cci0_cap = tacctl0[`TASCS] ? cci0_sync : cci0_evt; +assign cci1_cap = tacctl1[`TASCS] ? cci1_sync : cci1_evt; +assign cci2_cap = tacctl2[`TASCS] ? cci2_sync : cci2_evt; + + +// Generate capture overflow flag +//----------------------------------- + +reg cap0_taken; +wire cap0_taken_clr = reg_rd[TACCR0] | (tacctl0_wr & tacctl0[`TACOV] & ~per_din[`TACOV]); +always @ (posedge mclk or posedge puc) + if (puc) cap0_taken <= 1'b0; + else if (cci0_cap) cap0_taken <= 1'b1; + else if (cap0_taken_clr) cap0_taken <= 1'b0; + +reg cap1_taken; +wire cap1_taken_clr = reg_rd[TACCR1] | (tacctl1_wr & tacctl1[`TACOV] & ~per_din[`TACOV]); +always @ (posedge mclk or posedge puc) + if (puc) cap1_taken <= 1'b0; + else if (cci1_cap) cap1_taken <= 1'b1; + else if (cap1_taken_clr) cap1_taken <= 1'b0; + +reg cap2_taken; +wire cap2_taken_clr = reg_rd[TACCR2] | (tacctl2_wr & tacctl2[`TACOV] & ~per_din[`TACOV]); +always @ (posedge mclk or posedge puc) + if (puc) cap2_taken <= 1'b0; + else if (cci2_cap) cap2_taken <= 1'b1; + else if (cap2_taken_clr) cap2_taken <= 1'b0; + + +assign cov0_set = cap0_taken & cci0_cap & ~reg_rd[TACCR0]; +assign cov1_set = cap1_taken & cci1_cap & ~reg_rd[TACCR1]; +assign cov2_set = cap2_taken & cci2_cap & ~reg_rd[TACCR2]; + + +//============================================================================ +// 8) Timer A output unit +//============================================================================ + +// Output unit 0 +//------------------- +reg ta_out0; + +wire ta_out0_mode0 = tacctl0[`TAOUT]; // Output +wire ta_out0_mode1 = equ0 ? 1'b1 : ta_out0; // Set +wire ta_out0_mode2 = equ0 ? ~ta_out0 : // Toggle/Reset + equ0 ? 1'b0 : ta_out0; +wire ta_out0_mode3 = equ0 ? 1'b1 : // Set/Reset + equ0 ? 1'b0 : ta_out0; +wire ta_out0_mode4 = equ0 ? ~ta_out0 : ta_out0; // Toggle +wire ta_out0_mode5 = equ0 ? 1'b0 : ta_out0; // Reset +wire ta_out0_mode6 = equ0 ? ~ta_out0 : // Toggle/Set + equ0 ? 1'b1 : ta_out0; +wire ta_out0_mode7 = equ0 ? 1'b0 : // Reset/Set + equ0 ? 1'b1 : ta_out0; + +wire ta_out0_nxt = (tacctl0[`TAOUTMODx]==3'b000) ? ta_out0_mode0 : + (tacctl0[`TAOUTMODx]==3'b001) ? ta_out0_mode1 : + (tacctl0[`TAOUTMODx]==3'b010) ? ta_out0_mode2 : + (tacctl0[`TAOUTMODx]==3'b011) ? ta_out0_mode3 : + (tacctl0[`TAOUTMODx]==3'b100) ? ta_out0_mode4 : + (tacctl0[`TAOUTMODx]==3'b101) ? ta_out0_mode5 : + (tacctl0[`TAOUTMODx]==3'b110) ? ta_out0_mode6 : + ta_out0_mode7; + +always @ (posedge mclk or posedge puc) + if (puc) ta_out0 <= 1'b0; + else if ((tacctl0[`TAOUTMODx]==3'b001) & taclr) ta_out0 <= 1'b0; + else if (tar_clk) ta_out0 <= ta_out0_nxt; + +assign ta_out0_en = ~tacctl0[`TACAP]; + + +// Output unit 1 +//------------------- +reg ta_out1; + +wire ta_out1_mode0 = tacctl1[`TAOUT]; // Output +wire ta_out1_mode1 = equ1 ? 1'b1 : ta_out1; // Set +wire ta_out1_mode2 = equ1 ? ~ta_out1 : // Toggle/Reset + equ0 ? 1'b0 : ta_out1; +wire ta_out1_mode3 = equ1 ? 1'b1 : // Set/Reset + equ0 ? 1'b0 : ta_out1; +wire ta_out1_mode4 = equ1 ? ~ta_out1 : ta_out1; // Toggle +wire ta_out1_mode5 = equ1 ? 1'b0 : ta_out1; // Reset +wire ta_out1_mode6 = equ1 ? ~ta_out1 : // Toggle/Set + equ0 ? 1'b1 : ta_out1; +wire ta_out1_mode7 = equ1 ? 1'b0 : // Reset/Set + equ0 ? 1'b1 : ta_out1; + +wire ta_out1_nxt = (tacctl1[`TAOUTMODx]==3'b000) ? ta_out1_mode0 : + (tacctl1[`TAOUTMODx]==3'b001) ? ta_out1_mode1 : + (tacctl1[`TAOUTMODx]==3'b010) ? ta_out1_mode2 : + (tacctl1[`TAOUTMODx]==3'b011) ? ta_out1_mode3 : + (tacctl1[`TAOUTMODx]==3'b100) ? ta_out1_mode4 : + (tacctl1[`TAOUTMODx]==3'b101) ? ta_out1_mode5 : + (tacctl1[`TAOUTMODx]==3'b110) ? ta_out1_mode6 : + ta_out1_mode7; + +always @ (posedge mclk or posedge puc) + if (puc) ta_out1 <= 1'b0; + else if ((tacctl1[`TAOUTMODx]==3'b001) & taclr) ta_out1 <= 1'b0; + else if (tar_clk) ta_out1 <= ta_out1_nxt; + +assign ta_out1_en = ~tacctl1[`TACAP]; + + +// Output unit 2 +//------------------- +reg ta_out2; + +wire ta_out2_mode0 = tacctl2[`TAOUT]; // Output +wire ta_out2_mode1 = equ2 ? 1'b1 : ta_out2; // Set +wire ta_out2_mode2 = equ2 ? ~ta_out2 : // Toggle/Reset + equ0 ? 1'b0 : ta_out2; +wire ta_out2_mode3 = equ2 ? 1'b1 : // Set/Reset + equ0 ? 1'b0 : ta_out2; +wire ta_out2_mode4 = equ2 ? ~ta_out2 : ta_out2; // Toggle +wire ta_out2_mode5 = equ2 ? 1'b0 : ta_out2; // Reset +wire ta_out2_mode6 = equ2 ? ~ta_out2 : // Toggle/Set + equ0 ? 1'b1 : ta_out2; +wire ta_out2_mode7 = equ2 ? 1'b0 : // Reset/Set + equ0 ? 1'b1 : ta_out2; + +wire ta_out2_nxt = (tacctl2[`TAOUTMODx]==3'b000) ? ta_out2_mode0 : + (tacctl2[`TAOUTMODx]==3'b001) ? ta_out2_mode1 : + (tacctl2[`TAOUTMODx]==3'b010) ? ta_out2_mode2 : + (tacctl2[`TAOUTMODx]==3'b011) ? ta_out2_mode3 : + (tacctl2[`TAOUTMODx]==3'b100) ? ta_out2_mode4 : + (tacctl2[`TAOUTMODx]==3'b101) ? ta_out2_mode5 : + (tacctl2[`TAOUTMODx]==3'b110) ? ta_out2_mode6 : + ta_out2_mode7; + +always @ (posedge mclk or posedge puc) + if (puc) ta_out2 <= 1'b0; + else if ((tacctl2[`TAOUTMODx]==3'b001) & taclr) ta_out2 <= 1'b0; + else if (tar_clk) ta_out2 <= ta_out2_nxt; + +assign ta_out2_en = ~tacctl2[`TACAP]; + + +//============================================================================ +// 9) Timer A interrupt generation +//============================================================================ + + +assign taifg_set = tar_clk & (((tactl[`TAMCx]==2'b01) & (tar==taccr0)) | + ((tactl[`TAMCx]==2'b10) & (tar==16'hffff)) | + ((tactl[`TAMCx]==2'b11) & (tar_nxt==16'h0000) & tar_dec)); + +assign ccifg0_set = tacctl0[`TACAP] ? cci0_cap : (tar_clk & ((tactl[`TAMCx]!=2'b00) & equ0)); +assign ccifg1_set = tacctl1[`TACAP] ? cci1_cap : (tar_clk & ((tactl[`TAMCx]!=2'b00) & equ1)); +assign ccifg2_set = tacctl2[`TACAP] ? cci2_cap : (tar_clk & ((tactl[`TAMCx]!=2'b00) & equ2)); + + +wire irq_ta0 = (tacctl0[`TACCIFG] & tacctl0[`TACCIE]); + +wire irq_ta1 = (tactl[`TAIFG] & tactl[`TAIE]) | + (tacctl1[`TACCIFG] & tacctl1[`TACCIE]) | + (tacctl2[`TACCIFG] & tacctl2[`TACCIE]); + + +endmodule // omsp_timerA + +`include "openMSP430_undefines.v"
periph/omsp_timerA.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Date Revision Author \ No newline at end of property Index: omsp_dbg_uart.v =================================================================== --- omsp_dbg_uart.v (nonexistent) +++ omsp_dbg_uart.v (revision 34) @@ -0,0 +1,268 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2001 Authors +// +// This source file may be used and distributed without restriction provided +// that this copyright statement is not removed from the file and that any +// derivative work contains the original copyright notice and the associated +// disclaimer. +// +// This source file is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This source is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +// License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this source; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_dbg_uart.v +// +// *Module Description: +// Debug UART communication interface (8N1, Half-duplex) +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev$ +// $LastChangedBy$ +// $LastChangedDate$ +//---------------------------------------------------------------------------- +`include "timescale.v" +`include "openMSP430_defines.v" + +module omsp_dbg_uart ( + +// OUTPUTs + dbg_addr, // Debug register address + dbg_din, // Debug register data input + dbg_rd, // Debug register data read + dbg_uart_txd, // Debug interface: UART TXD + dbg_wr, // Debug register data write + +// INPUTs + dbg_dout, // Debug register data output + dbg_rd_rdy, // Debug register data is ready for read + dbg_uart_rxd, // Debug interface: UART RXD + mclk, // Main system clock + mem_burst, // Burst on going + mem_burst_end, // End TX/RX burst + mem_burst_rd, // Start TX burst + mem_burst_wr, // Start RX burst + mem_bw, // Burst byte width + por // Power on reset +); + +// OUTPUTs +//========= +output [5:0] dbg_addr; // Debug register address +output [15:0] dbg_din; // Debug register data input +output dbg_rd; // Debug register data read +output dbg_uart_txd; // Debug interface: UART TXD +output dbg_wr; // Debug register data write + +// INPUTs +//========= +input [15:0] dbg_dout; // Debug register data output +input dbg_rd_rdy; // Debug register data is ready for read +input dbg_uart_rxd; // Debug interface: UART RXD +input mclk; // Main system clock +input mem_burst; // Burst on going +input mem_burst_end; // End TX/RX burst +input mem_burst_rd; // Start TX burst +input mem_burst_wr; // Start RX burst +input mem_bw; // Burst byte width +input por; // Power on reset + + +//============================================================================= +// 1) UART RECEIVE LINE SYNCHRONIZTION & FILTERING +//============================================================================= + +// Synchronize RXD input & buffer +//-------------------------------- +reg [3:0] rxd_sync; +always @ (posedge mclk or posedge por) + if (por) rxd_sync <= 4'h0; + else rxd_sync <= {rxd_sync[2:0], dbg_uart_rxd}; + +// Majority decision +//------------------------ +reg rxd_maj; + +wire [1:0] rxd_maj_cnt = {1'b0, rxd_sync[1]} + + {1'b0, rxd_sync[2]} + + {1'b0, rxd_sync[3]}; +wire rxd_maj_nxt = (rxd_maj_cnt>=2'b10); + +always @ (posedge mclk or posedge por) + if (por) rxd_maj <= 1'b0; + else rxd_maj <= rxd_maj_nxt; + +wire rxd_s = rxd_maj; +wire rxd_fe = rxd_maj & ~rxd_maj_nxt; +wire rxd_re = ~rxd_maj & rxd_maj_nxt; + + +//============================================================================= +// 2) UART STATE MACHINE +//============================================================================= + +// Receive state +//------------------------ +reg [2:0] uart_state; +reg [2:0] uart_state_nxt; + +wire sync_done; +wire xfer_done; +reg [19:0] xfer_buf; + +// State machine definition +parameter RX_SYNC = 3'h0; +parameter RX_CMD = 3'h1; +parameter RX_DATA1 = 3'h2; +parameter RX_DATA2 = 3'h3; +parameter TX_DATA1 = 3'h4; +parameter TX_DATA2 = 3'h5; + +// State transition +always @(uart_state or xfer_buf or mem_burst or mem_burst_wr or mem_burst_rd or mem_burst_end or mem_bw) + case (uart_state) + RX_SYNC : uart_state_nxt = RX_CMD; + RX_CMD : uart_state_nxt = mem_burst_wr ? + (mem_bw ? RX_DATA2 : RX_DATA1) : + mem_burst_rd ? + (mem_bw ? TX_DATA2 : TX_DATA1) : + (xfer_buf[`DBG_UART_WR] ? + (xfer_buf[`DBG_UART_BW] ? RX_DATA2 : RX_DATA1) : + (xfer_buf[`DBG_UART_BW] ? TX_DATA2 : TX_DATA1)); + RX_DATA1 : uart_state_nxt = RX_DATA2; + RX_DATA2 : uart_state_nxt = (mem_burst & ~mem_burst_end) ? + (mem_bw ? RX_DATA2 : RX_DATA1) : + RX_CMD; + TX_DATA1 : uart_state_nxt = TX_DATA2; + TX_DATA2 : uart_state_nxt = (mem_burst & ~mem_burst_end) ? + (mem_bw ? TX_DATA2 : TX_DATA1) : + RX_CMD; + default : uart_state_nxt = RX_CMD; + endcase + +// State machine +always @(posedge mclk or posedge por) + if (por) uart_state <= RX_SYNC; + else if (xfer_done | sync_done | + mem_burst_wr | mem_burst_rd) uart_state <= uart_state_nxt; + +// Utility signals +wire cmd_valid = (uart_state==RX_CMD) & xfer_done; +wire tx_active = (uart_state==TX_DATA1) | (uart_state==TX_DATA2); + + +//============================================================================= +// 3) UART SYNCHRONIZATION +//============================================================================= +// After POR, the host needs to fist send a synchronization character (0x80) +// If this feature doesn't work properly, it is possible to disable it by +// commenting the DBG_UART_AUTO_SYNC define in the openMSP430.inc file. + +reg sync_busy; +always @ (posedge mclk or posedge por) + if (por) sync_busy <= 1'b0; + else if ((uart_state==RX_SYNC) & rxd_fe) sync_busy <= 1'b1; + else if ((uart_state==RX_SYNC) & rxd_re) sync_busy <= 1'b0; + +assign sync_done = (uart_state==RX_SYNC) & rxd_re & sync_busy; + +`ifdef DBG_UART_AUTO_SYNC + +reg [14:0] sync_cnt; +always @ (posedge mclk or posedge por) + if (por) sync_cnt <= 15'h7ff8; + else if (sync_busy) sync_cnt <= sync_cnt+15'h0001; + +wire [11:0] bit_cnt_max = sync_cnt[14:3]; +`else +wire [11:0] bit_cnt_max = `DBG_UART_CNT; +`endif + + +//============================================================================= +// 4) UART RECEIVE / TRANSMIT +//============================================================================= + +// Transfer counter +//------------------------ +reg [3:0] xfer_bit; +reg [11:0] xfer_cnt; + +wire txd_start = dbg_rd_rdy | (xfer_done & (uart_state==TX_DATA1)); +wire rxd_start = (xfer_bit==4'h0) & rxd_fe & ((uart_state!=RX_SYNC)); +wire xfer_bit_inc = (xfer_bit!=4'h0) & (xfer_cnt==12'h000); +assign xfer_done = (xfer_bit==4'hb); + +always @ (posedge mclk or posedge por) + if (por) xfer_bit <= 4'h0; + else if (txd_start | rxd_start) xfer_bit <= 4'h1; + else if (xfer_done) xfer_bit <= 4'h0; + else if (xfer_bit_inc) xfer_bit <= xfer_bit+4'h1; + +always @ (posedge mclk or posedge por) + if (por) xfer_cnt <= 12'h000; + else if (rxd_start) xfer_cnt <= {1'b0, bit_cnt_max[11:1]}; + else if (txd_start | xfer_bit_inc) xfer_cnt <= bit_cnt_max; + else xfer_cnt <= xfer_cnt+12'hfff; + + +// Receive/Transmit buffer +//------------------------- +wire [19:0] xfer_buf_nxt = {rxd_s, xfer_buf[19:1]}; + +always @ (posedge mclk or posedge por) + if (por) xfer_buf <= 18'h00000; + else if (dbg_rd_rdy) xfer_buf <= {1'b1, dbg_dout[15:8], 2'b01, dbg_dout[7:0], 1'b0}; + else if (xfer_bit_inc) xfer_buf <= xfer_buf_nxt; + + +// Generate TXD output +//------------------------ +reg dbg_uart_txd; + +always @ (posedge mclk or posedge por) + if (por) dbg_uart_txd <= 1'b1; + else if (xfer_bit_inc & tx_active) dbg_uart_txd <= xfer_buf[0]; + + +//============================================================================= +// 5) INTERFACE TO DEBUG REGISTERS +//============================================================================= + +reg [5:0] dbg_addr; + always @ (posedge mclk or posedge por) + if (por) dbg_addr <= 6'h00; + else if (cmd_valid) dbg_addr <= xfer_buf[`DBG_UART_ADDR]; + +reg dbg_bw; +always @ (posedge mclk or posedge por) + if (por) dbg_bw <= 1'b0; + else if (cmd_valid) dbg_bw <= xfer_buf[`DBG_UART_BW]; + +wire dbg_din_bw = mem_burst ? mem_bw : dbg_bw; + +wire [15:0] dbg_din = dbg_din_bw ? {8'h00, xfer_buf[18:11]} : + {xfer_buf[18:11], xfer_buf[8:1]}; +wire dbg_wr = (xfer_done & (uart_state==RX_DATA2)); +wire dbg_rd = mem_burst ? (xfer_done & (uart_state==TX_DATA2)) : + (cmd_valid & ~xfer_buf[`DBG_UART_WR]) | mem_burst_rd; + + + +endmodule // omsp_dbg_uart + +`include "openMSP430_undefines.v"
omsp_dbg_uart.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Date Revision Author \ No newline at end of property Index: omsp_dbg_hwbrk.v =================================================================== --- omsp_dbg_hwbrk.v (nonexistent) +++ omsp_dbg_hwbrk.v (revision 34) @@ -0,0 +1,269 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2001 Authors +// +// This source file may be used and distributed without restriction provided +// that this copyright statement is not removed from the file and that any +// derivative work contains the original copyright notice and the associated +// disclaimer. +// +// This source file is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This source is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +// License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this source; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_dbg_hwbrk.v +// +// *Module Description: +// Hardware Breakpoint / Watchpoint module +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev$ +// $LastChangedBy$ +// $LastChangedDate$ +//---------------------------------------------------------------------------- +`include "timescale.v" +`include "openMSP430_defines.v" + +module omsp_dbg_hwbrk ( + +// OUTPUTs + brk_halt, // Hardware breakpoint command + brk_pnd, // Hardware break/watch-point pending + brk_dout, // Hardware break/watch-point register data input + +// INPUTs + brk_reg_rd, // Hardware break/watch-point register read select + brk_reg_wr, // Hardware break/watch-point register write select + dbg_din, // Debug register data input + eu_mab, // Execution-Unit Memory address bus + eu_mb_en, // Execution-Unit Memory bus enable + eu_mb_wr, // Execution-Unit Memory bus write transfer + eu_mdb_in, // Memory data bus input + eu_mdb_out, // Memory data bus output + exec_done, // Execution completed + fe_mb_en, // Frontend Memory bus enable + mclk, // Main system clock + pc, // Program counter + por // Power on reset +); + +// OUTPUTs +//========= +output brk_halt; // Hardware breakpoint command +output brk_pnd; // Hardware break/watch-point pending +output [15:0] brk_dout; // Hardware break/watch-point register data input + +// INPUTs +//========= +input [3:0] brk_reg_rd; // Hardware break/watch-point register read select +input [3:0] brk_reg_wr; // Hardware break/watch-point register write select +input [15:0] dbg_din; // Debug register data input +input [15:0] eu_mab; // Execution-Unit Memory address bus +input eu_mb_en; // Execution-Unit Memory bus enable +input [1:0] eu_mb_wr; // Execution-Unit Memory bus write transfer +input [15:0] eu_mdb_in; // Memory data bus input +input [15:0] eu_mdb_out; // Memory data bus output +input exec_done; // Execution completed +input fe_mb_en; // Frontend Memory bus enable +input mclk; // Main system clock +input [15:0] pc; // Program counter +input por; // Power on reset + + +//============================================================================= +// 1) WIRE & PARAMETER DECLARATION +//============================================================================= + +wire range_wr_set; +wire range_rd_set; +wire addr1_wr_set; +wire addr1_rd_set; +wire addr0_wr_set; +wire addr0_rd_set; + + +parameter BRK_CTL = 0, + BRK_STAT = 1, + BRK_ADDR0 = 2, + BRK_ADDR1 = 3; + + +//============================================================================= +// 2) CONFIGURATION REGISTERS +//============================================================================= + +// BRK_CTL Register +//----------------------------------------------------------------------------- +// 7 6 5 4 3 2 1 0 +// Reserved RANGE_MODE INST_EN BREAK_EN ACCESS_MODE +// +// ACCESS_MODE: - 00 : Disabled +// - 01 : Detect read access +// - 10 : Detect write access +// - 11 : Detect read/write access +// NOTE: '10' & '11' modes are not supported on the instruction flow +// +// BREAK_EN: - 0 : Watchmode enable +// - 1 : Break enable +// +// INST_EN: - 0 : Checks are done on the execution unit (data flow) +// - 1 : Checks are done on the frontend (instruction flow) +// +// RANGE_MODE: - 0 : Address match on BRK_ADDR0 or BRK_ADDR1 +// - 1 : Address match on BRK_ADDR0->BRK_ADDR1 range +// +//----------------------------------------------------------------------------- +reg [4:0] brk_ctl; + +wire brk_ctl_wr = brk_reg_wr[BRK_CTL]; + +always @ (posedge mclk or posedge por) + if (por) brk_ctl <= 5'h00; + else if (brk_ctl_wr) brk_ctl <= dbg_din[4:0]; + +wire [7:0] brk_ctl_full = {3'b000, brk_ctl}; + + +// BRK_STAT Register +//----------------------------------------------------------------------------- +// 7 6 5 4 3 2 1 0 +// Reserved RANGE_WR RANGE_RD ADDR1_WR ADDR1_RD ADDR0_WR ADDR0_RD +//----------------------------------------------------------------------------- +reg [5:0] brk_stat; + +wire brk_stat_wr = brk_reg_wr[BRK_STAT]; +wire [5:0] brk_stat_set = {range_wr_set, range_rd_set, + addr1_wr_set, addr1_rd_set, + addr0_wr_set, addr0_rd_set}; +wire [5:0] brk_stat_clr = ~dbg_din[5:0]; + +always @ (posedge mclk or posedge por) + if (por) brk_stat <= 6'h00; + else if (brk_stat_wr) brk_stat <= ((brk_stat & brk_stat_clr) | brk_stat_set); + else brk_stat <= (brk_stat | brk_stat_set); + +wire [7:0] brk_stat_full = {2'b00, brk_stat}; +wire brk_pnd = |brk_stat; + + +// BRK_ADDR0 Register +//----------------------------------------------------------------------------- +reg [15:0] brk_addr0; + +wire brk_addr0_wr = brk_reg_wr[BRK_ADDR0]; + +always @ (posedge mclk or posedge por) + if (por) brk_addr0 <= 16'h0000; + else if (brk_addr0_wr) brk_addr0 <= dbg_din; + + +// BRK_ADDR1/DATA0 Register +//----------------------------------------------------------------------------- +reg [15:0] brk_addr1; + +wire brk_addr1_wr = brk_reg_wr[BRK_ADDR1]; + +always @ (posedge mclk or posedge por) + if (por) brk_addr1 <= 16'h0000; + else if (brk_addr1_wr) brk_addr1 <= dbg_din; + + +//============================================================================ +// 3) DATA OUTPUT GENERATION +//============================================================================ + +wire [15:0] brk_ctl_rd = {8'h00, brk_ctl_full} & {16{brk_reg_rd[BRK_CTL]}}; +wire [15:0] brk_stat_rd = {8'h00, brk_stat_full} & {16{brk_reg_rd[BRK_STAT]}}; +wire [15:0] brk_addr0_rd = brk_addr0 & {16{brk_reg_rd[BRK_ADDR0]}}; +wire [15:0] brk_addr1_rd = brk_addr1 & {16{brk_reg_rd[BRK_ADDR1]}}; + +wire [15:0] brk_dout = brk_ctl_rd | + brk_stat_rd | + brk_addr0_rd | + brk_addr1_rd; + + +//============================================================================ +// 4) BREAKPOINT / WATCHPOINT GENERATION +//============================================================================ + +// Comparators +//--------------------------- +// Note: here the comparison logic is instanciated several times in order +// to improve the timings, at the cost of a bit more area. + +wire equ_d_addr0 = eu_mb_en & (eu_mab==brk_addr0) & ~brk_ctl[`BRK_RANGE]; +wire equ_d_addr1 = eu_mb_en & (eu_mab==brk_addr1) & ~brk_ctl[`BRK_RANGE]; +wire equ_d_range = eu_mb_en & ((eu_mab>=brk_addr0) & (eu_mab<=brk_addr1)) & brk_ctl[`BRK_RANGE]; + +reg fe_mb_en_buf; +always @ (posedge mclk or posedge por) + if (por) fe_mb_en_buf <= 1'b0; + else fe_mb_en_buf <= fe_mb_en; + +wire equ_i_addr0 = fe_mb_en_buf & (pc==brk_addr0) & ~brk_ctl[`BRK_RANGE]; +wire equ_i_addr1 = fe_mb_en_buf & (pc==brk_addr1) & ~brk_ctl[`BRK_RANGE]; +wire equ_i_range = fe_mb_en_buf & ((pc>=brk_addr0) & (pc<=brk_addr1)) & brk_ctl[`BRK_RANGE]; + + +// Detect accesses +//--------------------------- + +// Detect Instruction read access +wire i_addr0_rd = equ_i_addr0 & brk_ctl[`BRK_I_EN]; +wire i_addr1_rd = equ_i_addr1 & brk_ctl[`BRK_I_EN]; +wire i_range_rd = equ_i_range & brk_ctl[`BRK_I_EN]; + +// Detect Execution-Unit write access +wire d_addr0_wr = equ_d_addr0 & ~brk_ctl[`BRK_I_EN] & |eu_mb_wr; +wire d_addr1_wr = equ_d_addr1 & ~brk_ctl[`BRK_I_EN] & |eu_mb_wr; +wire d_range_wr = equ_d_range & ~brk_ctl[`BRK_I_EN] & |eu_mb_wr; + +// Detect DATA read access +// Whenever an "ADD r9. &0x200" instruction is executed, &0x200 will be read +// before being written back. In that case, the read flag should not be set. +// In general, We should here make sure no write access occures during the +// same instruction cycle before setting the read flag. +reg [2:0] d_rd_trig; +always @ (posedge mclk or posedge por) + if (por) d_rd_trig <= 3'h0; + else if (exec_done) d_rd_trig <= 3'h0; + else d_rd_trig <= {equ_d_range & ~brk_ctl[`BRK_I_EN] & ~|eu_mb_wr, + equ_d_addr1 & ~brk_ctl[`BRK_I_EN] & ~|eu_mb_wr, + equ_d_addr0 & ~brk_ctl[`BRK_I_EN] & ~|eu_mb_wr}; + +wire d_addr0_rd = d_rd_trig[0] & exec_done & ~d_addr0_wr; +wire d_addr1_rd = d_rd_trig[1] & exec_done & ~d_addr1_wr; +wire d_range_rd = d_rd_trig[2] & exec_done & ~d_range_wr; + + +// Set flags +assign addr0_rd_set = brk_ctl[`BRK_MODE_RD] & (d_addr0_rd | i_addr0_rd); +assign addr0_wr_set = brk_ctl[`BRK_MODE_WR] & d_addr0_wr; +assign addr1_rd_set = brk_ctl[`BRK_MODE_RD] & (d_addr1_rd | i_addr1_rd); +assign addr1_wr_set = brk_ctl[`BRK_MODE_WR] & d_addr1_wr; +assign range_rd_set = brk_ctl[`BRK_MODE_RD] & (d_range_rd | i_range_rd); +assign range_wr_set = brk_ctl[`BRK_MODE_WR] & d_range_wr; + + +// Break CPU +assign brk_halt = brk_ctl[`BRK_EN] & |brk_stat_set; + + +endmodule // omsp_dbg_hwbrk + +`include "openMSP430_undefines.v"
omsp_dbg_hwbrk.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Date Revision Author \ No newline at end of property Index: omsp_sfr.v =================================================================== --- omsp_sfr.v (nonexistent) +++ omsp_sfr.v (revision 34) @@ -0,0 +1,204 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2001 Authors +// +// This source file may be used and distributed without restriction provided +// that this copyright statement is not removed from the file and that any +// derivative work contains the original copyright notice and the associated +// disclaimer. +// +// This source file is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This source is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +// License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this source; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_sfr.v +// +// *Module Description: +// Processor Special function register +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev$ +// $LastChangedBy$ +// $LastChangedDate$ +//---------------------------------------------------------------------------- +`include "timescale.v" +`include "openMSP430_defines.v" + +module omsp_sfr ( + +// OUTPUTs + nmie, // Non-maskable interrupt enable + per_dout, // Peripheral data output + wdt_irq, // Watchdog-timer interrupt + wdt_reset, // Watchdog-timer reset + wdtie, // Watchdog-timer interrupt enable + +// INPUTs + mclk, // Main system clock + nmi_acc, // Non-Maskable interrupt request accepted + per_addr, // Peripheral address + per_din, // Peripheral data input + per_en, // Peripheral enable (high active) + per_wen, // Peripheral write enable (high active) + por, // Power-on reset + puc, // Main system reset + wdtifg_clr, // Clear Watchdog-timer interrupt flag + wdtifg_set, // Set Watchdog-timer interrupt flag + wdtpw_error, // Watchdog-timer password error + wdttmsel // Watchdog-timer mode select +); + +// OUTPUTs +//========= +output nmie; // Non-maskable interrupt enable +output [15:0] per_dout; // Peripheral data output +output wdt_irq; // Watchdog-timer interrupt +output wdt_reset; // Watchdog-timer reset +output wdtie; // Watchdog-timer interrupt enable + +// INPUTs +//========= +input mclk; // Main system clock +input nmi_acc; // Non-Maskable interrupt request accepted +input [7:0] per_addr; // Peripheral address +input [15:0] per_din; // Peripheral data input +input per_en; // Peripheral enable (high active) +input [1:0] per_wen; // Peripheral write enable (high active) +input por; // Power-on reset +input puc; // Main system reset +input wdtifg_clr; // Clear Watchdog-timer interrupt flag +input wdtifg_set; // Set Watchdog-timer interrupt flag +input wdtpw_error; // Watchdog-timer password error +input wdttmsel; // Watchdog-timer mode select + + +//============================================================================= +// 1) PARAMETER DECLARATION +//============================================================================= + +// Register addresses +parameter IE1 = 9'h000; +parameter IFG1 = 9'h002; + +// Register one-hot decoder +parameter IE1_D = (256'h1 << (IE1 /2)); +parameter IFG1_D = (256'h1 << (IFG1 /2)); + + +//============================================================================ +// 2) REGISTER DECODER +//============================================================================ + +// Register address decode +reg [255:0] reg_dec; +always @(per_addr) + case (per_addr) + (IE1 /2): reg_dec = IE1_D; + (IFG1 /2): reg_dec = IFG1_D; + default : reg_dec = {256{1'b0}}; + endcase + +// Read/Write probes +wire reg_lo_write = per_wen[0] & per_en; +wire reg_hi_write = per_wen[1] & per_en; +wire reg_read = ~|per_wen & per_en; + +// Read/Write vectors +wire [255:0] reg_hi_wr = reg_dec & {256{reg_hi_write}}; +wire [255:0] reg_lo_wr = reg_dec & {256{reg_lo_write}}; +wire [255:0] reg_rd = reg_dec & {256{reg_read}}; + + +//============================================================================ +// 3) REGISTERS +//============================================================================ + +// IE1 Register +//-------------- +wire [7:0] ie1; +wire ie1_wr = IE1[0] ? reg_hi_wr[IE1/2] : reg_lo_wr[IE1/2]; +wire [7:0] ie1_nxt = IE1[0] ? per_din[15:8] : per_din[7:0]; + +reg nmie; +always @ (posedge mclk or posedge puc) + if (puc) nmie <= 1'b0; + else if (nmi_acc) nmie <= 1'b0; + else if (ie1_wr) nmie <= ie1_nxt[4]; + +reg wdtie; +always @ (posedge mclk or posedge puc) + if (puc) wdtie <= 1'b0; + else if (ie1_wr) wdtie <= ie1_nxt[0]; + +assign ie1 = {3'b000, nmie, 3'b000, wdtie}; + + +// IFG1 Register +//--------------- +wire [7:0] ifg1; +wire ifg1_wr = IFG1[0] ? reg_hi_wr[IFG1/2] : reg_lo_wr[IFG1/2]; +wire [7:0] ifg1_nxt = IFG1[0] ? per_din[15:8] : per_din[7:0]; + +reg nmiifg; +always @ (posedge mclk or posedge puc) + if (puc) nmiifg <= 1'b0; + else if (nmi_acc) nmiifg <= 1'b1; + else if (ifg1_wr) nmiifg <= ifg1_nxt[4]; + +reg wdtifg; +always @ (posedge mclk or posedge por) + if (por) wdtifg <= 1'b0; + else if (wdtifg_set) wdtifg <= 1'b1; + else if (wdttmsel & wdtifg_clr) wdtifg <= 1'b0; + else if (ifg1_wr) wdtifg <= ifg1_nxt[0]; + +assign ifg1 = {3'b000, nmiifg, 3'b000, wdtifg}; + + +//============================================================================ +// 4) DATA OUTPUT GENERATION +//============================================================================ + +// Data output mux +wire [15:0] ie1_rd = (ie1 & {8{reg_rd[IE1/2]}}) << (8 & {4{IE1[0]}}); +wire [15:0] ifg1_rd = (ifg1 & {8{reg_rd[IFG1/2]}}) << (8 & {4{IFG1[0]}}); + +wire [15:0] per_dout = ie1_rd | + ifg1_rd; + + +//============================================================================= +// 5) WATCHDOG INTERRUPT & RESET +//============================================================================= + +// Watchdog interrupt generation +//--------------------------------- +wire wdt_irq = wdttmsel & wdtifg & wdtie; + + +// Watchdog reset generation +//----------------------------- +reg wdt_reset; + +always @ (posedge mclk or posedge por) + if (por) wdt_reset <= 1'b0; + else wdt_reset <= wdtpw_error | (wdtifg_set & ~wdttmsel); + + +endmodule // omsp_sfr + +`include "openMSP430_undefines.v"
omsp_sfr.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Date Revision Author \ No newline at end of property Index: omsp_dbg.v =================================================================== --- omsp_dbg.v (nonexistent) +++ omsp_dbg.v (revision 34) @@ -0,0 +1,792 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2001 Authors +// +// This source file may be used and distributed without restriction provided +// that this copyright statement is not removed from the file and that any +// derivative work contains the original copyright notice and the associated +// disclaimer. +// +// This source file is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This source is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +// License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this source; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_dbg.v +// +// *Module Description: +// Debug interface +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev$ +// $LastChangedBy$ +// $LastChangedDate$ +//---------------------------------------------------------------------------- +`include "timescale.v" +`include "openMSP430_defines.v" + +module omsp_dbg ( + +// OUTPUTs + dbg_freeze, // Freeze peripherals + dbg_halt_cmd, // Halt CPU command + dbg_mem_addr, // Debug address for rd/wr access + dbg_mem_dout, // Debug unit data output + dbg_mem_en, // Debug unit memory enable + dbg_mem_wr, // Debug unit memory write + dbg_reg_wr, // Debug unit CPU register write + dbg_reset, // Reset CPU from debug interface + dbg_uart_txd, // Debug interface: UART TXD + +// INPUTs + dbg_halt_st, // Halt/Run status from CPU + dbg_mem_din, // Debug unit Memory data input + dbg_reg_din, // Debug unit CPU register data input + dbg_uart_rxd, // Debug interface: UART RXD + decode, // Frontend decode instruction + eu_mab, // Execution-Unit Memory address bus + eu_mb_en, // Execution-Unit Memory bus enable + eu_mb_wr, // Execution-Unit Memory bus write transfer + eu_mdb_in, // Memory data bus input + eu_mdb_out, // Memory data bus output + exec_done, // Execution completed + fe_mb_en, // Frontend Memory bus enable + fe_mdb_in, // Frontend Memory data bus input + mclk, // Main system clock + pc, // Program counter + por, // Power on reset + puc // Main system reset +); + +// OUTPUTs +//========= +output dbg_freeze; // Freeze peripherals +output dbg_halt_cmd; // Halt CPU command +output [15:0] dbg_mem_addr; // Debug address for rd/wr access +output [15:0] dbg_mem_dout; // Debug unit data output +output dbg_mem_en; // Debug unit memory enable +output [1:0] dbg_mem_wr; // Debug unit memory write +output dbg_reg_wr; // Debug unit CPU register write +output dbg_reset; // Reset CPU from debug interface +output dbg_uart_txd; // Debug interface: UART TXD + +// INPUTs +//========= +input dbg_halt_st; // Halt/Run status from CPU +input [15:0] dbg_mem_din; // Debug unit Memory data input +input [15:0] dbg_reg_din; // Debug unit CPU register data input +input dbg_uart_rxd; // Debug interface: UART RXD +input decode; // Frontend decode instruction +input [15:0] eu_mab; // Execution-Unit Memory address bus +input eu_mb_en; // Execution-Unit Memory bus enable +input [1:0] eu_mb_wr; // Execution-Unit Memory bus write transfer +input [15:0] eu_mdb_in; // Memory data bus input +input [15:0] eu_mdb_out; // Memory data bus output +input exec_done; // Execution completed +input fe_mb_en; // Frontend Memory bus enable +input [15:0] fe_mdb_in; // Frontend Memory data bus input +input mclk; // Main system clock +input [15:0] pc; // Program counter +input por; // Power on reset +input puc; // Main system reset + + +//============================================================================= +// 1) WIRE & PARAMETER DECLARATION +//============================================================================= + +// Diverse wires and registers +wire [5:0] dbg_addr; +wire [15:0] dbg_din; +wire dbg_wr; +reg mem_burst; +wire dbg_reg_rd; +wire dbg_mem_rd; +reg dbg_mem_rd_dly; +wire dbg_swbrk; +wire dbg_rd; +reg dbg_rd_rdy; +wire mem_burst_rd; +wire mem_burst_wr; +wire brk0_halt; +wire brk0_pnd; +wire [15:0] brk0_dout; +wire brk1_halt; +wire brk1_pnd; +wire [15:0] brk1_dout; +wire brk2_halt; +wire brk2_pnd; +wire [15:0] brk2_dout; +wire brk3_halt; +wire brk3_pnd; +wire [15:0] brk3_dout; + +// Register addresses +parameter CPU_ID_LO = 6'h00; +parameter CPU_ID_HI = 6'h01; +parameter CPU_CTL = 6'h02; +parameter CPU_STAT = 6'h03; +parameter MEM_CTL = 6'h04; +parameter MEM_ADDR = 6'h05; +parameter MEM_DATA = 6'h06; +parameter MEM_CNT = 6'h07; +`ifdef DBG_HWBRK_0 +parameter BRK0_CTL = 6'h08; +parameter BRK0_STAT = 6'h09; +parameter BRK0_ADDR0 = 6'h0A; +parameter BRK0_ADDR1 = 6'h0B; +`endif +`ifdef DBG_HWBRK_1 +parameter BRK1_CTL = 6'h0C; +parameter BRK1_STAT = 6'h0D; +parameter BRK1_ADDR0 = 6'h0E; +parameter BRK1_ADDR1 = 6'h0F; +`endif +`ifdef DBG_HWBRK_2 +parameter BRK2_CTL = 6'h10; +parameter BRK2_STAT = 6'h11; +parameter BRK2_ADDR0 = 6'h12; +parameter BRK2_ADDR1 = 6'h13; +`endif +`ifdef DBG_HWBRK_3 +parameter BRK3_CTL = 6'h14; +parameter BRK3_STAT = 6'h15; +parameter BRK3_ADDR0 = 6'h16; +parameter BRK3_ADDR1 = 6'h17; +`endif + +// Register one-hot decoder +parameter CPU_ID_LO_D = (64'h1 << CPU_ID_LO); +parameter CPU_ID_HI_D = (64'h1 << CPU_ID_HI); +parameter CPU_CTL_D = (64'h1 << CPU_CTL); +parameter CPU_STAT_D = (64'h1 << CPU_STAT); +parameter MEM_CTL_D = (64'h1 << MEM_CTL); +parameter MEM_ADDR_D = (64'h1 << MEM_ADDR); +parameter MEM_DATA_D = (64'h1 << MEM_DATA); +parameter MEM_CNT_D = (64'h1 << MEM_CNT); +`ifdef DBG_HWBRK_0 +parameter BRK0_CTL_D = (64'h1 << BRK0_CTL); +parameter BRK0_STAT_D = (64'h1 << BRK0_STAT); +parameter BRK0_ADDR0_D = (64'h1 << BRK0_ADDR0); +parameter BRK0_ADDR1_D = (64'h1 << BRK0_ADDR1); +`endif +`ifdef DBG_HWBRK_1 +parameter BRK1_CTL_D = (64'h1 << BRK1_CTL); +parameter BRK1_STAT_D = (64'h1 << BRK1_STAT); +parameter BRK1_ADDR0_D = (64'h1 << BRK1_ADDR0); +parameter BRK1_ADDR1_D = (64'h1 << BRK1_ADDR1); +`endif +`ifdef DBG_HWBRK_2 +parameter BRK2_CTL_D = (64'h1 << BRK2_CTL); +parameter BRK2_STAT_D = (64'h1 << BRK2_STAT); +parameter BRK2_ADDR0_D = (64'h1 << BRK2_ADDR0); +parameter BRK2_ADDR1_D = (64'h1 << BRK2_ADDR1); +`endif +`ifdef DBG_HWBRK_3 +parameter BRK3_CTL_D = (64'h1 << BRK3_CTL); +parameter BRK3_STAT_D = (64'h1 << BRK3_STAT); +parameter BRK3_ADDR0_D = (64'h1 << BRK3_ADDR0); +parameter BRK3_ADDR1_D = (64'h1 << BRK3_ADDR1); +`endif + + +//============================================================================ +// 2) REGISTER DECODER +//============================================================================ + +// Select Data register during a burst +wire [5:0] dbg_addr_in = mem_burst ? MEM_DATA : dbg_addr; + +// Register address decode +reg [63:0] reg_dec; +always @(dbg_addr_in) + case (dbg_addr_in) + CPU_ID_LO : reg_dec = CPU_ID_LO_D; + CPU_ID_HI : reg_dec = CPU_ID_HI_D; + CPU_CTL : reg_dec = CPU_CTL_D; + CPU_STAT : reg_dec = CPU_STAT_D; + MEM_CTL : reg_dec = MEM_CTL_D; + MEM_ADDR : reg_dec = MEM_ADDR_D; + MEM_DATA : reg_dec = MEM_DATA_D; + MEM_CNT : reg_dec = MEM_CNT_D; +`ifdef DBG_HWBRK_0 + BRK0_CTL : reg_dec = BRK0_CTL_D; + BRK0_STAT : reg_dec = BRK0_STAT_D; + BRK0_ADDR0: reg_dec = BRK0_ADDR0_D; + BRK0_ADDR1: reg_dec = BRK0_ADDR1_D; +`endif +`ifdef DBG_HWBRK_1 + BRK1_CTL : reg_dec = BRK1_CTL_D; + BRK1_STAT : reg_dec = BRK1_STAT_D; + BRK1_ADDR0: reg_dec = BRK1_ADDR0_D; + BRK1_ADDR1: reg_dec = BRK1_ADDR1_D; +`endif +`ifdef DBG_HWBRK_2 + BRK2_CTL : reg_dec = BRK2_CTL_D; + BRK2_STAT : reg_dec = BRK2_STAT_D; + BRK2_ADDR0: reg_dec = BRK2_ADDR0_D; + BRK2_ADDR1: reg_dec = BRK2_ADDR1_D; +`endif +`ifdef DBG_HWBRK_3 + BRK3_CTL : reg_dec = BRK3_CTL_D; + BRK3_STAT : reg_dec = BRK3_STAT_D; + BRK3_ADDR0: reg_dec = BRK3_ADDR0_D; + BRK3_ADDR1: reg_dec = BRK3_ADDR1_D; +`endif + default: reg_dec = {64{1'b0}}; + endcase + +// Read/Write probes +wire reg_write = dbg_wr; +wire reg_read = 1'b1; + +// Read/Write vectors +wire [511:0] reg_wr = reg_dec & {64{reg_write}}; +wire [511:0] reg_rd = reg_dec & {64{reg_read}}; + + +//============================================================================= +// 3) REGISTER: CORE INTERFACE +//============================================================================= + +// CPU_ID Register +//----------------- + +wire [3:0] cpu_id_pmem = `PMEM_AWIDTH; +wire [3:0] cpu_id_dmem = `DMEM_AWIDTH; +wire [31:0] cpu_id = {`DBG_ID, cpu_id_pmem, cpu_id_dmem}; + + +// CPU_CTL Register +//----------------------------------------------------------------------------- +// 7 6 5 4 3 2 1 0 +// Reserved CPU_RST RST_BRK_EN FRZ_BRK_EN SW_BRK_EN ISTEP RUN HALT +//----------------------------------------------------------------------------- +reg [6:3] cpu_ctl; + +wire cpu_ctl_wr = reg_wr[CPU_CTL]; + +always @ (posedge mclk or posedge por) + if (por) cpu_ctl <= 4'h0; + else if (cpu_ctl_wr) cpu_ctl <= dbg_din[6:3]; + +wire [7:0] cpu_ctl_full = {1'b0, cpu_ctl, 3'b000}; + +wire halt_cpu = cpu_ctl_wr & dbg_din[`HALT] & ~dbg_halt_st; +wire run_cpu = cpu_ctl_wr & dbg_din[`RUN] & dbg_halt_st; +wire istep = cpu_ctl_wr & dbg_din[`ISTEP] & dbg_halt_st; + + +// CPU_STAT Register +//------------------------------------------------------------------------------------ +// 7 6 5 4 3 2 1 0 +// HWBRK3_PND HWBRK2_PND HWBRK1_PND HWBRK0_PND SWBRK_PND PUC_PND Res. HALT_RUN +//------------------------------------------------------------------------------------ +reg [3:2] cpu_stat; + +wire cpu_stat_wr = reg_wr[CPU_STAT]; +wire [3:2] cpu_stat_set = {dbg_swbrk, puc}; +wire [3:2] cpu_stat_clr = ~dbg_din[3:2]; + +always @ (posedge mclk or posedge por) + if (por) cpu_stat <= 2'b00; + else if (cpu_stat_wr) cpu_stat <= ((cpu_stat & cpu_stat_clr) | cpu_stat_set); + else cpu_stat <= (cpu_stat | cpu_stat_set); + +wire [7:0] cpu_stat_full = {brk3_pnd, brk2_pnd, brk1_pnd, brk0_pnd, + cpu_stat, 1'b0, dbg_halt_st}; + + +//============================================================================= +// 4) REGISTER: MEMORY INTERFACE +//============================================================================= + +// MEM_CTL Register +//----------------------------------------------------------------------------- +// 7 6 5 4 3 2 1 0 +// Reserved B/W MEM/REG RD/WR START +// +// START : - 0 : Do nothing. +// - 1 : Initiate memory transfer. +// +// RD/WR : - 0 : Read access. +// - 1 : Write access. +// +// MEM/REG: - 0 : Memory access. +// - 1 : CPU Register access. +// +// B/W : - 0 : 16 bit access. +// - 1 : 8 bit access (not valid for CPU Registers). +// +//----------------------------------------------------------------------------- +reg [3:1] mem_ctl; + +wire mem_ctl_wr = reg_wr[MEM_CTL]; + +always @ (posedge mclk or posedge por) + if (por) mem_ctl <= 3'h0; + else if (mem_ctl_wr) mem_ctl <= dbg_din[3:1]; + +wire [7:0] mem_ctl_full = {4'b0000, mem_ctl, 1'b0}; + +reg mem_start; +always @ (posedge mclk or posedge por) + if (por) mem_start <= 1'b0; + else mem_start <= mem_ctl_wr & dbg_din[0]; + +wire mem_bw = mem_ctl[3]; + +// MEM_DATA Register +//------------------ +reg [15:0] mem_data; +reg [15:0] mem_addr; +wire mem_access; + +wire mem_data_wr = reg_wr[MEM_DATA]; + +wire [15:0] dbg_mem_din_bw = ~mem_bw ? dbg_mem_din : + mem_addr[0] ? {8'h00, dbg_mem_din[15:8]} : + {8'h00, dbg_mem_din[7:0]}; + +always @ (posedge mclk or posedge por) + if (por) mem_data <= 16'h0000; + else if (mem_data_wr) mem_data <= dbg_din; + else if (dbg_reg_rd) mem_data <= dbg_reg_din; + else if (dbg_mem_rd_dly) mem_data <= dbg_mem_din_bw; + + +// MEM_ADDR Register +//------------------ +reg [15:0] mem_cnt; + +wire mem_addr_wr = reg_wr[MEM_ADDR]; +wire dbg_mem_acc = (|dbg_mem_wr | (dbg_rd_rdy & ~mem_ctl[2])); +wire dbg_reg_acc = ( dbg_reg_wr | (dbg_rd_rdy & mem_ctl[2])); + +wire [15:0] mem_addr_inc = (mem_cnt==16'h0000) ? 16'h0000 : + (dbg_mem_acc & ~mem_bw) ? 16'h0002 : + (dbg_mem_acc | dbg_reg_acc) ? 16'h0001 : 16'h0000; + +always @ (posedge mclk or posedge por) + if (por) mem_addr <= 16'h0000; + else if (mem_addr_wr) mem_addr <= dbg_din; + else mem_addr <= mem_addr + mem_addr_inc; + +// MEM_CNT Register +//------------------ + +wire mem_cnt_wr = reg_wr[MEM_CNT]; + +wire [15:0] mem_cnt_dec = (mem_cnt==16'h0000) ? 16'h0000 : + (dbg_mem_acc | dbg_reg_acc) ? 16'hffff : 16'h0000; + +always @ (posedge mclk or posedge por) + if (por) mem_cnt <= 16'h0000; + else if (mem_cnt_wr) mem_cnt <= dbg_din; + else mem_cnt <= mem_cnt + mem_cnt_dec; + + +//============================================================================= +// 5) BREAKPOINTS / WATCHPOINTS +//============================================================================= + +`ifdef DBG_HWBRK_0 +// Hardware Breakpoint/Watchpoint Register read select +wire [3:0] brk0_reg_rd = {reg_rd[BRK0_ADDR1], + reg_rd[BRK0_ADDR0], + reg_rd[BRK0_STAT], + reg_rd[BRK0_CTL]}; + +// Hardware Breakpoint/Watchpoint Register write select +wire [3:0] brk0_reg_wr = {reg_wr[BRK0_ADDR1], + reg_wr[BRK0_ADDR0], + reg_wr[BRK0_STAT], + reg_wr[BRK0_CTL]}; + +omsp_dbg_hwbrk dbg_hwbr_0 ( + +// OUTPUTs + .brk_halt (brk0_halt), // Hardware breakpoint command + .brk_pnd (brk0_pnd), // Hardware break/watch-point pending + .brk_dout (brk0_dout), // Hardware break/watch-point register data input + +// INPUTs + .brk_reg_rd (brk0_reg_rd), // Hardware break/watch-point register read select + .brk_reg_wr (brk0_reg_wr), // Hardware break/watch-point register write select + .dbg_din (dbg_din), // Debug register data input + .eu_mab (eu_mab), // Execution-Unit Memory address bus + .eu_mb_en (eu_mb_en), // Execution-Unit Memory bus enable + .eu_mb_wr (eu_mb_wr), // Execution-Unit Memory bus write transfer + .eu_mdb_in (eu_mdb_in), // Memory data bus input + .eu_mdb_out (eu_mdb_out), // Memory data bus output + .exec_done (exec_done), // Execution completed + .fe_mb_en (fe_mb_en), // Frontend Memory bus enable + .mclk (mclk), // Main system clock + .pc (pc), // Program counter + .por (por) // Power on reset +); + +`else +assign brk0_halt = 1'b0; +assign brk0_pnd = 1'b0; +assign brk0_dout = 16'h0000; +`endif + +`ifdef DBG_HWBRK_1 +// Hardware Breakpoint/Watchpoint Register read select +wire [3:0] brk1_reg_rd = {reg_rd[BRK1_ADDR1], + reg_rd[BRK1_ADDR0], + reg_rd[BRK1_STAT], + reg_rd[BRK1_CTL]}; + +// Hardware Breakpoint/Watchpoint Register write select +wire [3:0] brk1_reg_wr = {reg_wr[BRK1_ADDR1], + reg_wr[BRK1_ADDR0], + reg_wr[BRK1_STAT], + reg_wr[BRK1_CTL]}; + +omsp_dbg_hwbrk dbg_hwbr_1 ( + +// OUTPUTs + .brk_halt (brk1_halt), // Hardware breakpoint command + .brk_pnd (brk1_pnd), // Hardware break/watch-point pending + .brk_dout (brk1_dout), // Hardware break/watch-point register data input + +// INPUTs + .brk_reg_rd (brk1_reg_rd), // Hardware break/watch-point register read select + .brk_reg_wr (brk1_reg_wr), // Hardware break/watch-point register write select + .dbg_din (dbg_din), // Debug register data input + .eu_mab (eu_mab), // Execution-Unit Memory address bus + .eu_mb_en (eu_mb_en), // Execution-Unit Memory bus enable + .eu_mb_wr (eu_mb_wr), // Execution-Unit Memory bus write transfer + .eu_mdb_in (eu_mdb_in), // Memory data bus input + .eu_mdb_out (eu_mdb_out), // Memory data bus output + .exec_done (exec_done), // Execution completed + .fe_mb_en (fe_mb_en), // Frontend Memory bus enable + .mclk (mclk), // Main system clock + .pc (pc), // Program counter + .por (por) // Power on reset +); + +`else +assign brk1_halt = 1'b0; +assign brk1_pnd = 1'b0; +assign brk1_dout = 16'h0000; +`endif + + `ifdef DBG_HWBRK_2 +// Hardware Breakpoint/Watchpoint Register read select +wire [3:0] brk2_reg_rd = {reg_rd[BRK2_ADDR1], + reg_rd[BRK2_ADDR0], + reg_rd[BRK2_STAT], + reg_rd[BRK2_CTL]}; + +// Hardware Breakpoint/Watchpoint Register write select +wire [3:0] brk2_reg_wr = {reg_wr[BRK2_ADDR1], + reg_wr[BRK2_ADDR0], + reg_wr[BRK2_STAT], + reg_wr[BRK2_CTL]}; + +omsp_dbg_hwbrk dbg_hwbr_2 ( + +// OUTPUTs + .brk_halt (brk2_halt), // Hardware breakpoint command + .brk_pnd (brk2_pnd), // Hardware break/watch-point pending + .brk_dout (brk2_dout), // Hardware break/watch-point register data input + +// INPUTs + .brk_reg_rd (brk2_reg_rd), // Hardware break/watch-point register read select + .brk_reg_wr (brk2_reg_wr), // Hardware break/watch-point register write select + .dbg_din (dbg_din), // Debug register data input + .eu_mab (eu_mab), // Execution-Unit Memory address bus + .eu_mb_en (eu_mb_en), // Execution-Unit Memory bus enable + .eu_mb_wr (eu_mb_wr), // Execution-Unit Memory bus write transfer + .eu_mdb_in (eu_mdb_in), // Memory data bus input + .eu_mdb_out (eu_mdb_out), // Memory data bus output + .exec_done (exec_done), // Execution completed + .fe_mb_en (fe_mb_en), // Frontend Memory bus enable + .mclk (mclk), // Main system clock + .pc (pc), // Program counter + .por (por) // Power on reset +); + +`else +assign brk2_halt = 1'b0; +assign brk2_pnd = 1'b0; +assign brk2_dout = 16'h0000; +`endif + +`ifdef DBG_HWBRK_3 +// Hardware Breakpoint/Watchpoint Register read select +wire [3:0] brk3_reg_rd = {reg_rd[BRK3_ADDR1], + reg_rd[BRK3_ADDR0], + reg_rd[BRK3_STAT], + reg_rd[BRK3_CTL]}; + +// Hardware Breakpoint/Watchpoint Register write select +wire [3:0] brk3_reg_wr = {reg_wr[BRK3_ADDR1], + reg_wr[BRK3_ADDR0], + reg_wr[BRK3_STAT], + reg_wr[BRK3_CTL]}; + +omsp_dbg_hwbrk dbg_hwbr_3 ( + +// OUTPUTs + .brk_halt (brk3_halt), // Hardware breakpoint command + .brk_pnd (brk3_pnd), // Hardware break/watch-point pending + .brk_dout (brk3_dout), // Hardware break/watch-point register data input + +// INPUTs + .brk_reg_rd (brk3_reg_rd), // Hardware break/watch-point register read select + .brk_reg_wr (brk3_reg_wr), // Hardware break/watch-point register write select + .dbg_din (dbg_din), // Debug register data input + .eu_mab (eu_mab), // Execution-Unit Memory address bus + .eu_mb_en (eu_mb_en), // Execution-Unit Memory bus enable + .eu_mb_wr (eu_mb_wr), // Execution-Unit Memory bus write transfer + .eu_mdb_in (eu_mdb_in), // Memory data bus input + .eu_mdb_out (eu_mdb_out), // Memory data bus output + .exec_done (exec_done), // Execution completed + .fe_mb_en (fe_mb_en), // Frontend Memory bus enable + .mclk (mclk), // Main system clock + .pc (pc), // Program counter + .por (por) // Power on reset +); + +`else +assign brk3_halt = 1'b0; +assign brk3_pnd = 1'b0; +assign brk3_dout = 16'h0000; +`endif + + +//============================================================================ +// 6) DATA OUTPUT GENERATION +//============================================================================ + +wire [15:0] cpu_id_lo_rd = cpu_id[15:0] & {16{reg_rd[CPU_ID_LO]}}; +wire [15:0] cpu_id_hi_rd = cpu_id[31:16] & {16{reg_rd[CPU_ID_HI]}}; +wire [15:0] cpu_ctl_rd = {8'h00, cpu_ctl_full} & {16{reg_rd[CPU_CTL]}}; +wire [15:0] cpu_stat_rd = {8'h00, cpu_stat_full} & {16{reg_rd[CPU_STAT]}}; +wire [15:0] mem_ctl_rd = {8'h00, mem_ctl_full} & {16{reg_rd[MEM_CTL]}}; +wire [15:0] mem_data_rd = mem_data & {16{reg_rd[MEM_DATA]}}; +wire [15:0] mem_addr_rd = mem_addr & {16{reg_rd[MEM_ADDR]}}; +wire [15:0] mem_cnt_rd = mem_cnt & {16{reg_rd[MEM_CNT]}}; + +wire [15:0] dbg_dout = cpu_id_lo_rd | + cpu_id_hi_rd | + cpu_ctl_rd | + cpu_stat_rd | + mem_ctl_rd | + mem_data_rd | + mem_addr_rd | + mem_cnt_rd | + brk0_dout | + brk1_dout | + brk2_dout | + brk3_dout; + +// Tell UART/JTAG interface that the data is ready to be read +always @ (posedge mclk or posedge por) + if (por) dbg_rd_rdy <= 1'b0; + else if (mem_burst | mem_burst_rd) dbg_rd_rdy <= (dbg_reg_rd | dbg_mem_rd_dly); + else dbg_rd_rdy <= dbg_rd; + + +//============================================================================ +// 7) CPU CONTROL +//============================================================================ + +// Reset CPU +//-------------------------- +wire dbg_reset = cpu_ctl[`CPU_RST]; + + +// Break after reset +//-------------------------- +wire halt_rst = cpu_ctl[`RST_BRK_EN] & puc; + + +// Freeze peripherals +//-------------------------- +wire dbg_freeze = dbg_halt_st & cpu_ctl[`FRZ_BRK_EN]; + + +// Software break +//-------------------------- +assign dbg_swbrk = (fe_mdb_in==`DBG_SWBRK_OP) & decode & cpu_ctl[`SW_BRK_EN]; + + +// Single step +//-------------------------- +reg [1:0] inc_step; +always @(posedge mclk or posedge por) + if (por) inc_step <= 2'b00; + else if (istep) inc_step <= 2'b11; + else inc_step <= {inc_step[0], 1'b0}; + + +// Run / Halt +//-------------------------- +reg halt_flag; + +wire mem_halt_cpu; +wire mem_run_cpu; + +wire halt_flag_clr = run_cpu | mem_run_cpu; +wire halt_flag_set = halt_cpu | halt_rst | dbg_swbrk | mem_halt_cpu | + brk0_halt | brk1_halt | brk2_halt | brk3_halt; + +always @(posedge mclk or posedge por) + if (por) halt_flag <= 1'b0; + else if (halt_flag_clr) halt_flag <= 1'b0; + else if (halt_flag_set) halt_flag <= 1'b1; + +wire dbg_halt_cmd = (halt_flag | halt_flag_set) & ~inc_step[1]; + + +//============================================================================ +// 8) MEMORY CONTROL +//============================================================================ + +// Control Memory bursts +//------------------------------ + +wire mem_burst_start = (mem_start & |mem_cnt); +wire mem_burst_end = ((dbg_wr | dbg_rd_rdy) & ~|mem_cnt); + +// Detect when burst is on going +always @(posedge mclk or posedge por) + if (por) mem_burst <= 1'b0; + else if (mem_burst_start) mem_burst <= 1'b1; + else if (mem_burst_end) mem_burst <= 1'b0; + +// Control signals for UART/JTAG interface +assign mem_burst_rd = (mem_burst_start & ~mem_ctl[1]); +assign mem_burst_wr = (mem_burst_start & mem_ctl[1]); + +// Trigger CPU Register or memory access during a burst +reg mem_startb; +always @(posedge mclk or posedge por) + if (por) mem_startb <= 1'b0; + else mem_startb <= (mem_burst & (dbg_wr | dbg_rd)) | mem_burst_rd; + +// Combine single and burst memory start of sequence +wire mem_seq_start = ((mem_start & ~|mem_cnt) | mem_startb); + + +// Memory access state machine +//------------------------------ +reg [1:0] mem_state; +reg [1:0] mem_state_nxt; + +// State machine definition +parameter M_IDLE = 2'h0; +parameter M_SET_BRK = 2'h1; +parameter M_ACCESS_BRK = 2'h2; +parameter M_ACCESS = 2'h3; + +// State transition +always @(mem_state or mem_seq_start or dbg_halt_st) + case (mem_state) + M_IDLE : mem_state_nxt = ~mem_seq_start ? M_IDLE : + dbg_halt_st ? M_ACCESS : M_SET_BRK; + M_SET_BRK : mem_state_nxt = dbg_halt_st ? M_ACCESS_BRK : M_SET_BRK; + M_ACCESS_BRK : mem_state_nxt = M_IDLE; + M_ACCESS : mem_state_nxt = M_IDLE; + default : mem_state_nxt = M_IDLE; + endcase + +// State machine +always @(posedge mclk or posedge por) + if (por) mem_state <= M_IDLE; + else mem_state <= mem_state_nxt; + +// Utility signals +assign mem_halt_cpu = (mem_state==M_IDLE) & (mem_state_nxt==M_SET_BRK); +assign mem_run_cpu = (mem_state==M_ACCESS_BRK) & (mem_state_nxt==M_IDLE); +assign mem_access = (mem_state==M_ACCESS) | (mem_state==M_ACCESS_BRK); + + +// Interface to CPU Registers and Memory bacbkone +//------------------------------------------------ +assign dbg_mem_addr = mem_addr; +assign dbg_mem_dout = ~mem_bw ? mem_data : + mem_addr[0] ? {mem_data[7:0], 8'h00} : + {8'h00, mem_data[7:0]}; + +assign dbg_reg_wr = mem_access & mem_ctl[1] & mem_ctl[2]; +assign dbg_reg_rd = mem_access & ~mem_ctl[1] & mem_ctl[2]; + +assign dbg_mem_en = mem_access & ~mem_ctl[2]; +assign dbg_mem_rd = dbg_mem_en & ~mem_ctl[1]; + +wire [1:0] dbg_mem_wr_msk = ~mem_bw ? 2'b11 : + mem_addr[0] ? 2'b10 : 2'b01; +assign dbg_mem_wr = {2{dbg_mem_en & mem_ctl[1]}} & dbg_mem_wr_msk; + + +// It takes one additional cycle to read from Memory as from registers +always @(posedge mclk or posedge por) + if (por) dbg_mem_rd_dly <= 1'b0; + else dbg_mem_rd_dly <= dbg_mem_rd; + + +//============================================================================= +// 9) UART COMMUNICATION +//============================================================================= +`ifdef DBG_UART +omsp_dbg_uart dbg_uart_0 ( + +// OUTPUTs + .dbg_addr (dbg_addr), // Debug register address + .dbg_din (dbg_din), // Debug register data input + .dbg_rd (dbg_rd), // Debug register data read + .dbg_uart_txd (dbg_uart_txd), // Debug interface: UART TXD + .dbg_wr (dbg_wr), // Debug register data write + +// INPUTs + .dbg_dout (dbg_dout), // Debug register data output + .dbg_rd_rdy (dbg_rd_rdy), // Debug register data is ready for read + .dbg_uart_rxd (dbg_uart_rxd), // Debug interface: UART RXD + .mclk (mclk), // Main system clock + .mem_burst (mem_burst), // Burst on going + .mem_burst_end(mem_burst_end), // End TX/RX burst + .mem_burst_rd (mem_burst_rd), // Start TX burst + .mem_burst_wr (mem_burst_wr), // Start RX burst + .mem_bw (mem_bw), // Burst byte width + .por (por) // Power on reset +); + +`else +assign dbg_addr = 6'h00; +assign dbg_din = 16'h0000; +assign dbg_rd = 1'b0; +assign dbg_uart_txd = 1'b0; +assign dbg_wr = 1'b0; +`endif + + +//============================================================================= +// 10) JTAG COMMUNICATION +//============================================================================= +`ifdef DBG_JTAG +JTAG INTERFACE IS NOT SUPPORTED YET +`else +`endif + +endmodule // dbg + +`include "openMSP430_undefines.v"
omsp_dbg.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Date Revision Author \ No newline at end of property Index: omsp_watchdog.v =================================================================== --- omsp_watchdog.v (nonexistent) +++ omsp_watchdog.v (revision 34) @@ -0,0 +1,217 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2001 Authors +// +// This source file may be used and distributed without restriction provided +// that this copyright statement is not removed from the file and that any +// derivative work contains the original copyright notice and the associated +// disclaimer. +// +// This source file is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This source is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +// License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this source; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_watchdog.v +// +// *Module Description: +// Watchdog Timer +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev$ +// $LastChangedBy$ +// $LastChangedDate$ +//---------------------------------------------------------------------------- +`include "timescale.v" +`include "openMSP430_defines.v" + +module omsp_watchdog ( + +// OUTPUTs + nmi_evt, // NMI Event + per_dout, // Peripheral data output + wdtifg_set, // Set Watchdog-timer interrupt flag + wdtpw_error, // Watchdog-timer password error + wdttmsel, // Watchdog-timer mode select + +// INPUTs + aclk_en, // ACLK enable + dbg_freeze, // Freeze Watchdog counter + mclk, // Main system clock + nmi, // Non-maskable interrupt (asynchronous) + nmie, // Non-maskable interrupt enable + per_addr, // Peripheral address + per_din, // Peripheral data input + per_en, // Peripheral enable (high active) + per_wen, // Peripheral write enable (high active) + puc, // Main system reset + smclk_en, // SMCLK enable + wdtie // Watchdog timer interrupt enable +); + +// OUTPUTs +//========= +output nmi_evt; // NMI Event +output [15:0] per_dout; // Peripheral data output +output wdtifg_set; // Set Watchdog-timer interrupt flag +output wdtpw_error; // Watchdog-timer password error +output wdttmsel; // Watchdog-timer mode select + +// INPUTs +//========= +input aclk_en; // ACLK enable +input dbg_freeze; // Freeze Watchdog counter +input mclk; // Main system clock +input nmi; // Non-maskable interrupt (asynchronous) +input nmie; // Non-maskable interrupt enable +input [7:0] per_addr; // Peripheral address +input [15:0] per_din; // Peripheral data input +input per_en; // Peripheral enable (high active) +input [1:0] per_wen; // Peripheral write enable (high active) +input puc; // Main system reset +input smclk_en; // SMCLK enable +input wdtie; // Watchdog timer interrupt enable + + +//============================================================================= +// 1) PARAMETER DECLARATION +//============================================================================= + +// Register addresses +parameter WDTCTL = 9'h120; + + +// Register one-hot decoder +parameter WDTCTL_D = (512'h1 << WDTCTL); + + +//============================================================================ +// 2) REGISTER DECODER +//============================================================================ + +// Register address decode +reg [511:0] reg_dec; +always @(per_addr) + case ({per_addr,1'b0}) + WDTCTL : reg_dec = WDTCTL_D; + default: reg_dec = {512{1'b0}}; + endcase + +// Read/Write probes +wire reg_write = |per_wen & per_en; +wire reg_read = ~|per_wen & per_en; + +// Read/Write vectors +wire [511:0] reg_wr = reg_dec & {512{reg_write}}; +wire [511:0] reg_rd = reg_dec & {512{reg_read}}; + + +//============================================================================ +// 3) REGISTERS +//============================================================================ + +// WDTCTL Register +//----------------- +// WDTNMI & WDTSSEL are not implemented and therefore masked + +reg [7:0] wdtctl; + +wire wdtctl_wr = reg_wr[WDTCTL]; + +always @ (posedge mclk or posedge puc) + if (puc) wdtctl <= 8'h00; + else if (wdtctl_wr) wdtctl <= per_din[7:0] & 8'hd7; + +wire wdtpw_error = wdtctl_wr & (per_din[15:8]!=8'h5a); +wire wdttmsel = wdtctl[4]; + + +//============================================================================ +// 3) REGISTERS +//============================================================================ + +// Data output mux +wire [15:0] wdtctl_rd = {8'h69, wdtctl} & {16{reg_rd[WDTCTL]}}; + +wire [15:0] per_dout = wdtctl_rd; + + +//============================================================================= +// 4) NMI GENERATION +//============================================================================= + +// Synchronization state +reg [2:0] nmi_sync; +always @ (posedge mclk or posedge puc) + if (puc) nmi_sync <= 3'h0; + else nmi_sync <= {nmi_sync[1:0], nmi}; + +// Edge detection +wire nmi_re = ~nmi_sync[2] & nmi_sync[0] & nmie; +wire nmi_fe = nmi_sync[2] & ~nmi_sync[0] & nmie; + +// NMI event +wire nmi_evt = wdtctl[6] ? nmi_fe : nmi_re; + + +//============================================================================= +// 5) WATCHDOG TIMER +//============================================================================= + +// Watchdog clock source selection +//--------------------------------- +wire clk_src_en = wdtctl[2] ? aclk_en : smclk_en; + + +// Watchdog 16 bit counter +//-------------------------- +reg [15:0] wdtcnt; + +wire wdtcnt_clr = (wdtctl_wr & per_din[3]) | wdtifg_set; + +always @ (posedge mclk or posedge puc) + if (puc) wdtcnt <= 16'h0000; + else if (wdtcnt_clr) wdtcnt <= 16'h0000; + else if (~wdtctl[7] & clk_src_en & ~dbg_freeze) wdtcnt <= wdtcnt+16'h0001; + + +// Interval selection mux +//-------------------------- +reg wdtqn; + +always @(wdtctl or wdtcnt) + case(wdtctl[1:0]) + 2'b00 : wdtqn = wdtcnt[15]; + 2'b01 : wdtqn = wdtcnt[13]; + 2'b10 : wdtqn = wdtcnt[9]; + default: wdtqn = wdtcnt[6]; + endcase + + +// Watchdog event detection +//----------------------------- +reg wdtqn_dly; + +always @ (posedge mclk or posedge puc) + if (puc) wdtqn_dly <= 1'b0; + else wdtqn_dly <= wdtqn; + +wire wdtifg_set = (~wdtqn_dly & wdtqn) | wdtpw_error; + + +endmodule // omsp_watchdog + +`include "openMSP430_undefines.v"
omsp_watchdog.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Date Revision Author \ No newline at end of property Index: omsp_clock_module.v =================================================================== --- omsp_clock_module.v (nonexistent) +++ omsp_clock_module.v (revision 34) @@ -0,0 +1,247 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2001 Authors +// +// This source file may be used and distributed without restriction provided +// that this copyright statement is not removed from the file and that any +// derivative work contains the original copyright notice and the associated +// disclaimer. +// +// This source file is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This source is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +// License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this source; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_clock_module.v +// +// *Module Description: +// Basic clock module implementation. +// Since the openMSP430 mainly targets FPGA and hobby +// designers. The clock structure has been greatly +// symplified in order to ease integration. +// See online wiki for more info. +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev$ +// $LastChangedBy$ +// $LastChangedDate$ +//---------------------------------------------------------------------------- +`include "timescale.v" +`include "openMSP430_defines.v" + +module omsp_clock_module ( + +// OUTPUTs + aclk_en, // ACLK enable + mclk, // Main system clock + per_dout, // Peripheral data output + por, // Power-on reset + puc, // Main system reset + smclk_en, // SMCLK enable + +// INPUTs + dbg_reset, // Reset CPU from debug interface + dco_clk, // Fast oscillator (fast clock) + lfxt_clk, // Low frequency oscillator (typ 32kHz) + oscoff, // Turns off LFXT1 clock input + per_addr, // Peripheral address + per_din, // Peripheral data input + per_en, // Peripheral enable (high active) + per_wen, // Peripheral write enable (high active) + reset_n, // Reset Pin (low active) + scg1, // System clock generator 1. Turns off the SMCLK + wdt_reset // Watchdog-timer reset +); + +// OUTPUTs +//========= +output aclk_en; // ACLK enable +output mclk; // Main system clock +output [15:0] per_dout; // Peripheral data output +output por; // Power-on reset +output puc; // Main system reset +output smclk_en; // SMCLK enable + +// INPUTs +//========= +input dbg_reset; // Reset CPU from debug interface +input dco_clk; // Fast oscillator (fast clock) +input lfxt_clk; // Low frequency oscillator (typ 32kHz) +input oscoff; // Turns off LFXT1 clock input +input [7:0] per_addr; // Peripheral address +input [15:0] per_din; // Peripheral data input +input per_en; // Peripheral enable (high active) +input [1:0] per_wen; // Peripheral write enable (high active) +input reset_n; // Reset Pin (low active) +input scg1; // System clock generator 1. Turns off the SMCLK +input wdt_reset; // Watchdog-timer reset + + +//============================================================================= +// 1) PARAMETER DECLARATION +//============================================================================= + +// Register addresses +parameter BCSCTL1 = 9'h057; +parameter BCSCTL2 = 9'h058; + +// Register one-hot decoder +parameter BCSCTL1_D = (256'h1 << (BCSCTL1 /2)); +parameter BCSCTL2_D = (256'h1 << (BCSCTL2 /2)); + + +//============================================================================ +// 2) REGISTER DECODER +//============================================================================ + +// Register address decode +reg [255:0] reg_dec; +always @(per_addr) + case (per_addr) + (BCSCTL1 /2): reg_dec = BCSCTL1_D; + (BCSCTL2 /2): reg_dec = BCSCTL2_D; + default : reg_dec = {256{1'b0}}; + endcase + +// Read/Write probes +wire reg_lo_write = per_wen[0] & per_en; +wire reg_hi_write = per_wen[1] & per_en; +wire reg_read = ~|per_wen & per_en; + +// Read/Write vectors +wire [255:0] reg_hi_wr = reg_dec & {256{reg_hi_write}}; +wire [255:0] reg_lo_wr = reg_dec & {256{reg_lo_write}}; +wire [255:0] reg_rd = reg_dec & {256{reg_read}}; + + +//============================================================================ +// 3) REGISTERS +//============================================================================ + +// BCSCTL1 Register +//-------------- +reg [7:0] bcsctl1; +wire bcsctl1_wr = BCSCTL1[0] ? reg_hi_wr[BCSCTL1/2] : reg_lo_wr[BCSCTL1/2]; +wire [7:0] bcsctl1_nxt = BCSCTL1[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) bcsctl1 <= 8'h00; + else if (bcsctl1_wr) bcsctl1 <= bcsctl1_nxt & 8'h30; // Mask unused bits + + +// BCSCTL2 Register +//-------------- +reg [7:0] bcsctl2; +wire bcsctl2_wr = BCSCTL2[0] ? reg_hi_wr[BCSCTL2/2] : reg_lo_wr[BCSCTL2/2]; +wire [7:0] bcsctl2_nxt = BCSCTL2[0] ? per_din[15:8] : per_din[7:0]; + +always @ (posedge mclk or posedge puc) + if (puc) bcsctl2 <= 8'h00; + else if (bcsctl2_wr) bcsctl2 <= bcsctl2_nxt & 8'h0e; // Mask unused bits + + +//============================================================================ +// 4) DATA OUTPUT GENERATION +//============================================================================ + +// Data output mux +wire [15:0] bcsctl1_rd = (bcsctl1 & {8{reg_rd[BCSCTL1/2]}}) << (8 & {4{BCSCTL1[0]}}); +wire [15:0] bcsctl2_rd = (bcsctl2 & {8{reg_rd[BCSCTL2/2]}}) << (8 & {4{BCSCTL2[0]}}); + +wire [15:0] per_dout = bcsctl1_rd | + bcsctl2_rd; + + +//============================================================================= +// 5) CLOCK GENERATION +//============================================================================= + +// Synchronize LFXT_CLK & edge detection +//--------------------------------------- +reg [2:0] lfxt_clk_s; + +always @ (posedge mclk or posedge puc) + if (puc) lfxt_clk_s <= 3'b000; + else lfxt_clk_s <= {lfxt_clk_s[1:0], lfxt_clk}; + +wire lfxt_clk_en = (lfxt_clk_s[1] & ~lfxt_clk_s[2]) & ~(oscoff & ~bcsctl2[`SELS]); + + +// Generate main system clock +//---------------------------- + +wire mclk = dco_clk; +wire mclk_n = !dco_clk; + + +// Generate ACLK +//---------------------------- + +reg [2:0] aclk_div; + +wire aclk_en = lfxt_clk_en & ((bcsctl1[`DIVAx]==2'b00) ? 1'b1 : + (bcsctl1[`DIVAx]==2'b01) ? aclk_div[0] : + (bcsctl1[`DIVAx]==2'b10) ? &aclk_div[1:0] : + &aclk_div[2:0]); + +always @ (posedge mclk or posedge puc) + if (puc) aclk_div <= 3'h0; + else if ((bcsctl1[`DIVAx]!=2'b00) & lfxt_clk_en) aclk_div <= aclk_div+3'h1; + + +// Generate SMCLK +//---------------------------- + +reg [2:0] smclk_div; + +wire smclk_in = ~scg1 & (bcsctl2[`SELS] ? lfxt_clk_en : 1'b1); + +wire smclk_en = smclk_in & ((bcsctl2[`DIVSx]==2'b00) ? 1'b1 : + (bcsctl2[`DIVSx]==2'b01) ? smclk_div[0] : + (bcsctl2[`DIVSx]==2'b10) ? &smclk_div[1:0] : + &smclk_div[2:0]); + +always @ (posedge mclk or posedge puc) + if (puc) smclk_div <= 3'h0; + else if ((bcsctl2[`DIVSx]!=2'b00) & smclk_in) smclk_div <= smclk_div+3'h1; + + +//============================================================================= +// 6) RESET GENERATION +//============================================================================= + +// Generate synchronized POR +wire por_reset = !reset_n; + +reg [1:0] por_s; +always @(posedge mclk_n or posedge por_reset) + if (por_reset) por_s <= 2'b11; + else por_s <= {por_s[0], 1'b0}; +wire por = por_s[1]; + +// Generate main system reset +wire puc_reset = por_reset | wdt_reset | dbg_reset; + +reg [1:0] puc_s; +always @(posedge mclk_n or posedge puc_reset) + if (puc_reset) puc_s <= 2'b11; + else puc_s <= {puc_s[0], 1'b0}; +wire puc = puc_s[1]; + + +endmodule // omsp_clock_module + +`include "openMSP430_undefines.v"
omsp_clock_module.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Date Revision Author \ No newline at end of property Index: omsp_mem_backbone.v =================================================================== --- omsp_mem_backbone.v (nonexistent) +++ omsp_mem_backbone.v (revision 34) @@ -0,0 +1,244 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2001 Authors +// +// This source file may be used and distributed without restriction provided +// that this copyright statement is not removed from the file and that any +// derivative work contains the original copyright notice and the associated +// disclaimer. +// +// This source file is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This source is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +// License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this source; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_mem_backbone.v +// +// *Module Description: +// Memory interface backbone (decoder + arbiter) +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev$ +// $LastChangedBy$ +// $LastChangedDate$ +//---------------------------------------------------------------------------- +`include "timescale.v" +`include "openMSP430_defines.v" + +module omsp_mem_backbone ( + +// OUTPUTs + dbg_mem_din, // Debug unit Memory data input + dmem_addr, // Data Memory address + dmem_cen, // Data Memory chip enable (low active) + dmem_din, // Data Memory data input + dmem_wen, // Data Memory write enable (low active) + eu_mdb_in, // Execution Unit Memory data bus input + fe_mdb_in, // Frontend Memory data bus input + fe_pmem_wait, // Frontend wait for Instruction fetch + per_addr, // Peripheral address + per_din, // Peripheral data input + per_wen, // Peripheral write enable (high active) + per_en, // Peripheral enable (high active) + pmem_addr, // Program Memory address + pmem_cen, // Program Memory chip enable (low active) + pmem_din, // Program Memory data input (optional) + pmem_wen, // Program Memory write enable (low active) (optional) + +// INPUTs + dbg_halt_st, // Halt/Run status from CPU + dbg_mem_addr, // Debug address for rd/wr access + dbg_mem_dout, // Debug unit data output + dbg_mem_en, // Debug unit memory enable + dbg_mem_wr, // Debug unit memory write + dmem_dout, // Data Memory data output + eu_mab, // Execution Unit Memory address bus + eu_mb_en, // Execution Unit Memory bus enable + eu_mb_wr, // Execution Unit Memory bus write transfer + eu_mdb_out, // Execution Unit Memory data bus output + fe_mab, // Frontend Memory address bus + fe_mb_en, // Frontend Memory bus enable + mclk, // Main system clock + per_dout, // Peripheral data output + pmem_dout, // Program Memory data output + puc // Main system reset +); + +// OUTPUTs +//========= +output [15:0] dbg_mem_din; // Debug unit Memory data input +output [`DMEM_MSB:0] dmem_addr; // Data Memory address +output dmem_cen; // Data Memory chip enable (low active) +output [15:0] dmem_din; // Data Memory data input +output [1:0] dmem_wen; // Data Memory write enable (low active) +output [15:0] eu_mdb_in; // Execution Unit Memory data bus input +output [15:0] fe_mdb_in; // Frontend Memory data bus input +output fe_pmem_wait; // Frontend wait for Instruction fetch +output [7:0] per_addr; // Peripheral address +output [15:0] per_din; // Peripheral data input +output [1:0] per_wen; // Peripheral write enable (high active) +output per_en; // Peripheral enable (high active) +output [`PMEM_MSB:0] pmem_addr; // Program Memory address +output pmem_cen; // Program Memory chip enable (low active) +output [15:0] pmem_din; // Program Memory data input (optional) +output [1:0] pmem_wen; // Program Memory write enable (low active) (optional) + +// INPUTs +//========= +input dbg_halt_st; // Halt/Run status from CPU +input [15:0] dbg_mem_addr; // Debug address for rd/wr access +input [15:0] dbg_mem_dout; // Debug unit data output +input dbg_mem_en; // Debug unit memory enable +input [1:0] dbg_mem_wr; // Debug unit memory write +input [15:0] dmem_dout; // Data Memory data output +input [14:0] eu_mab; // Execution Unit Memory address bus +input eu_mb_en; // Execution Unit Memory bus enable +input [1:0] eu_mb_wr; // Execution Unit Memory bus write transfer +input [15:0] eu_mdb_out; // Execution Unit Memory data bus output +input [14:0] fe_mab; // Frontend Memory address bus +input fe_mb_en; // Frontend Memory bus enable +input mclk; // Main system clock +input [15:0] per_dout; // Peripheral data output +input [15:0] pmem_dout; // Program Memory data output +input puc; // Main system reset + + +//============================================================================= +// 1) DECODER +//============================================================================= + +// RAM Interface +//------------------ + +// Execution unit access +wire eu_dmem_cen = ~(eu_mb_en & (eu_mab>=(`DMEM_BASE>>1)) & + (eu_mab<((`DMEM_BASE+`DMEM_SIZE)>>1))); +wire [15:0] eu_dmem_addr = eu_mab-(`DMEM_BASE>>1); + +// Debug interface access +wire dbg_dmem_cen = ~(dbg_mem_en & (dbg_mem_addr[15:1]>=(`DMEM_BASE>>1)) & + (dbg_mem_addr[15:1]<((`DMEM_BASE+`DMEM_SIZE)>>1))); +wire [15:0] dbg_dmem_addr = dbg_mem_addr[15:1]-(`DMEM_BASE>>1); + + +// RAM Interface +wire [`DMEM_MSB:0] dmem_addr = ~dbg_dmem_cen ? dbg_dmem_addr[`DMEM_MSB:0] : eu_dmem_addr[`DMEM_MSB:0]; +wire dmem_cen = dbg_dmem_cen & eu_dmem_cen; +wire [1:0] dmem_wen = ~(dbg_mem_wr | eu_mb_wr); +wire [15:0] dmem_din = ~dbg_dmem_cen ? dbg_mem_dout : eu_mdb_out; + + +// ROM Interface +//------------------ +parameter PMEM_OFFSET = (16'hFFFF-`PMEM_SIZE+1); + +// Execution unit access (only read access are accepted) +wire eu_pmem_cen = ~(eu_mb_en & ~|eu_mb_wr & (eu_mab>=(PMEM_OFFSET>>1))); +wire [15:0] eu_pmem_addr = eu_mab-(PMEM_OFFSET>>1); + +// Front-end access +wire fe_pmem_cen = ~(fe_mb_en & (fe_mab>=(PMEM_OFFSET>>1))); +wire [15:0] fe_pmem_addr = fe_mab-(PMEM_OFFSET>>1); + +// Debug interface access +wire dbg_pmem_cen = ~(dbg_mem_en & (dbg_mem_addr[15:1]>=(PMEM_OFFSET>>1))); +wire [15:0] dbg_pmem_addr = dbg_mem_addr[15:1]-(PMEM_OFFSET>>1); + + +// ROM Interface (Execution unit has priority) +wire [`PMEM_MSB:0] pmem_addr = ~dbg_pmem_cen ? dbg_pmem_addr[`PMEM_MSB:0] : + ~eu_pmem_cen ? eu_pmem_addr[`PMEM_MSB:0] : fe_pmem_addr[`PMEM_MSB:0]; +wire pmem_cen = fe_pmem_cen & eu_pmem_cen & dbg_pmem_cen; +wire [1:0] pmem_wen = ~dbg_mem_wr; +wire [15:0] pmem_din = dbg_mem_dout; + +wire fe_pmem_wait = (~fe_pmem_cen & ~eu_pmem_cen); + + +// Peripherals +//-------------------- +wire dbg_per_en = dbg_mem_en & (dbg_mem_addr[15:9]==7'h00); +wire eu_per_en = eu_mb_en & (eu_mab[14:8]==7'h00); + +wire [7:0] per_addr = dbg_mem_en ? dbg_mem_addr[8:1] : eu_mab[7:0]; +wire [15:0] per_din = dbg_mem_en ? dbg_mem_dout : eu_mdb_out; +wire [1:0] per_wen = dbg_mem_en ? dbg_mem_wr : eu_mb_wr; +wire per_en = dbg_mem_en ? dbg_per_en : eu_per_en; + +reg [15:0] per_dout_val; +always @ (posedge mclk or posedge puc) + if (puc) per_dout_val <= 16'h0000; + else per_dout_val <= per_dout; + + +// Frontend data Mux +//--------------------------------- +// Whenever the frontend doesn't access the ROM, backup the data + +// Detect whenever the data should be backuped and restored +reg fe_pmem_cen_dly; +always @(posedge mclk or posedge puc) + if (puc) fe_pmem_cen_dly <= 1'b0; + else fe_pmem_cen_dly <= fe_pmem_cen; + +wire fe_pmem_save = ( fe_pmem_cen & ~fe_pmem_cen_dly) & ~dbg_halt_st; +wire fe_pmem_restore = (~fe_pmem_cen & fe_pmem_cen_dly) | dbg_halt_st; + +reg [15:0] pmem_dout_bckup; +always @(posedge mclk or posedge puc) + if (puc) pmem_dout_bckup <= 16'h0000; + else if (fe_pmem_save) pmem_dout_bckup <= pmem_dout; + +// Mux between the ROM data and the backup +reg pmem_dout_bckup_sel; +always @(posedge mclk or posedge puc) + if (puc) pmem_dout_bckup_sel <= 1'b0; + else if (fe_pmem_save) pmem_dout_bckup_sel <= 1'b1; + else if (fe_pmem_restore) pmem_dout_bckup_sel <= 1'b0; + +assign fe_mdb_in = pmem_dout_bckup_sel ? pmem_dout_bckup : pmem_dout; + + +// Execution-Unit data Mux +//--------------------------------- + +// Select between peripherals, RAM and ROM +reg [1:0] eu_mdb_in_sel; +always @(posedge mclk or posedge puc) + if (puc) eu_mdb_in_sel <= 2'b00; + else eu_mdb_in_sel <= {~eu_pmem_cen, per_en}; + +// Mux +assign eu_mdb_in = eu_mdb_in_sel[1] ? pmem_dout : + eu_mdb_in_sel[0] ? per_dout_val : dmem_dout; + +// Debug interface data Mux +//--------------------------------- + +// Select between peripherals, RAM and ROM +reg [1:0] dbg_mem_din_sel; +always @(posedge mclk or posedge puc) + if (puc) dbg_mem_din_sel <= 2'b00; + else dbg_mem_din_sel <= {~dbg_pmem_cen, dbg_per_en}; + +// Mux +assign dbg_mem_din = dbg_mem_din_sel[1] ? pmem_dout : + dbg_mem_din_sel[0] ? per_dout_val : dmem_dout; + + +endmodule // omsp_mem_backbone + +`include "openMSP430_undefines.v"
omsp_mem_backbone.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Date Revision Author \ No newline at end of property Index: omsp_execution_unit.v =================================================================== --- omsp_execution_unit.v (nonexistent) +++ omsp_execution_unit.v (revision 34) @@ -0,0 +1,367 @@ +//---------------------------------------------------------------------------- +// Copyright (C) 2001 Authors +// +// This source file may be used and distributed without restriction provided +// that this copyright statement is not removed from the file and that any +// derivative work contains the original copyright notice and the associated +// disclaimer. +// +// This source file is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This source is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +// License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this source; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +//---------------------------------------------------------------------------- +// +// *File Name: omsp_execution_unit.v +// +// *Module Description: +// openMSP430 Execution unit +// +// *Author(s): +// - Olivier Girard, olgirard@gmail.com +// +//---------------------------------------------------------------------------- +// $Rev$ +// $LastChangedBy$ +// $LastChangedDate$ +//---------------------------------------------------------------------------- +`include "timescale.v" +`include "openMSP430_defines.v" + +module omsp_execution_unit ( + +// OUTPUTs + cpuoff, // Turns off the CPU + dbg_reg_din, // Debug unit CPU register data input + gie, // General interrupt enable + mab, // Memory address bus + mb_en, // Memory bus enable + mb_wr, // Memory bus write transfer + mdb_out, // Memory data bus output + oscoff, // Turns off LFXT1 clock input + pc_sw, // Program counter software value + pc_sw_wr, // Program counter software write + scg1, // System clock generator 1. Turns off the SMCLK + +// INPUTs + dbg_halt_st, // Halt/Run status from CPU + dbg_mem_dout, // Debug unit data output + dbg_reg_wr, // Debug unit CPU register write + e_state, // Execution state + exec_done, // Execution completed + inst_ad, // Decoded Inst: destination addressing mode + inst_as, // Decoded Inst: source addressing mode + inst_alu, // ALU control signals + inst_bw, // Decoded Inst: byte width + inst_dest, // Decoded Inst: destination (one hot) + inst_dext, // Decoded Inst: destination extended instruction word + inst_irq_rst, // Decoded Inst: reset interrupt + inst_jmp, // Decoded Inst: Conditional jump + inst_sext, // Decoded Inst: source extended instruction word + inst_so, // Decoded Inst: Single-operand arithmetic + inst_src, // Decoded Inst: source (one hot) + inst_type, // Decoded Instruction type + mclk, // Main system clock + mdb_in, // Memory data bus input + pc, // Program counter + pc_nxt, // Next PC value (for CALL & IRQ) + puc // Main system reset +); + +// OUTPUTs +//========= +output cpuoff; // Turns off the CPU +output [15:0] dbg_reg_din; // Debug unit CPU register data input +output gie; // General interrupt enable +output [15:0] mab; // Memory address bus +output mb_en; // Memory bus enable +output [1:0] mb_wr; // Memory bus write transfer +output [15:0] mdb_out; // Memory data bus output +output oscoff; // Turns off LFXT1 clock input +output [15:0] pc_sw; // Program counter software value +output pc_sw_wr; // Program counter software write +output scg1; // System clock generator 1. Turns off the SMCLK + +// INPUTs +//========= +input dbg_halt_st; // Halt/Run status from CPU +input [15:0] dbg_mem_dout; // Debug unit data output +input dbg_reg_wr; // Debug unit CPU register write +input [3:0] e_state; // Execution state +input exec_done; // Execution completed +input [7:0] inst_ad; // Decoded Inst: destination addressing mode +input [7:0] inst_as; // Decoded Inst: source addressing mode +input [11:0] inst_alu; // ALU control signals +input inst_bw; // Decoded Inst: byte width +input [15:0] inst_dest; // Decoded Inst: destination (one hot) +input [15:0] inst_dext; // Decoded Inst: destination extended instruction word +input inst_irq_rst; // Decoded Inst: reset interrupt +input [7:0] inst_jmp; // Decoded Inst: Conditional jump +input [15:0] inst_sext; // Decoded Inst: source extended instruction word +input [7:0] inst_so; // Decoded Inst: Single-operand arithmetic +input [15:0] inst_src; // Decoded Inst: source (one hot) +input [2:0] inst_type; // Decoded Instruction type +input mclk; // Main system clock +input [15:0] mdb_in; // Memory data bus input +input [15:0] pc; // Program counter +input [15:0] pc_nxt; // Next PC value (for CALL & IRQ) +input puc; // Main system reset + + +//============================================================================= +// 1) INTERNAL WIRES/REGISTERS/PARAMETERS DECLARATION +//============================================================================= + +wire [15:0] alu_out; +wire [15:0] alu_out_add; +wire [3:0] alu_stat; +wire [3:0] alu_stat_wr; +wire [15:0] op_dst; +wire [15:0] op_src; +wire [15:0] reg_dest; +wire [15:0] reg_src; +wire [15:0] mdb_in_bw; +wire [15:0] mdb_in_val; +wire [3:0] status; + + +//============================================================================= +// 2) REGISTER FILE +//============================================================================= + +wire reg_dest_wr = ((e_state==`E_EXEC) & ( + (inst_type[`INST_TO] & inst_ad[`DIR] & ~inst_alu[`EXEC_NO_WR]) | + (inst_type[`INST_SO] & inst_as[`DIR] & ~(inst_so[`PUSH] | inst_so[`CALL] | inst_so[`RETI])) | + inst_type[`INST_JMP])) | dbg_reg_wr; + +wire reg_sp_wr = (((e_state==`E_IRQ_1) | (e_state==`E_IRQ_3)) & ~inst_irq_rst) | + ((e_state==`E_DST_RD) & (inst_so[`PUSH] | inst_so[`CALL])); + +wire reg_sr_wr = (e_state==`E_DST_RD) & inst_so[`RETI]; + +wire reg_sr_clr = (e_state==`E_IRQ_2); + +wire reg_pc_call = ((e_state==`E_EXEC) & inst_so[`CALL]) | + ((e_state==`E_DST_WR) & inst_so[`RETI]); + +wire reg_incr = (exec_done & inst_as[`INDIR_I]) | + ((e_state==`E_SRC_RD) & inst_so[`RETI]) | + ((e_state==`E_EXEC) & inst_so[`RETI]); + +assign dbg_reg_din = reg_dest; + + +omsp_register_file register_file_0 ( + +// OUTPUTs + .cpuoff (cpuoff), // Turns off the CPU + .gie (gie), // General interrupt enable + .oscoff (oscoff), // Turns off LFXT1 clock input + .pc_sw (pc_sw), // Program counter software value + .pc_sw_wr (pc_sw_wr), // Program counter software write + .reg_dest (reg_dest), // Selected register destination content + .reg_src (reg_src), // Selected register source content + .scg1 (scg1), // System clock generator 1. Turns off the SMCLK + .status (status), // R2 Status {V,N,Z,C} + +// INPUTs + .alu_stat (alu_stat), // ALU Status {V,N,Z,C} + .alu_stat_wr (alu_stat_wr), // ALU Status write {V,N,Z,C} + .inst_bw (inst_bw), // Decoded Inst: byte width + .inst_dest (inst_dest), // Register destination selection + .inst_src (inst_src), // Register source selection + .mclk (mclk), // Main system clock + .pc (pc), // Program counter + .puc (puc), // Main system reset + .reg_dest_val (alu_out), // Selected register destination value + .reg_dest_wr (reg_dest_wr), // Write selected register destination + .reg_pc_call (reg_pc_call), // Trigger PC update for a CALL instruction + .reg_sp_val (alu_out_add), // Stack Pointer next value + .reg_sp_wr (reg_sp_wr), // Stack Pointer write + .reg_sr_clr (reg_sr_clr), // Status register clear for interrupts + .reg_sr_wr (reg_sr_wr), // Status Register update for RETI instruction + .reg_incr (reg_incr) // Increment source register +); + + +//============================================================================= +// 3) SOURCE OPERAND MUXING +//============================================================================= +// inst_as[`DIR] : Register direct. -> Source is in register +// inst_as[`IDX] : Register indexed. -> Source is in memory, address is register+offset +// inst_as[`INDIR] : Register indirect. +// inst_as[`INDIR_I]: Register indirect autoincrement. +// inst_as[`SYMB] : Symbolic (operand is in memory at address PC+x). +// inst_as[`IMM] : Immediate (operand is next word in the instruction stream). +// inst_as[`ABS] : Absolute (operand is in memory at address x). +// inst_as[`CONST] : Constant. + +wire src_reg_src_sel = (e_state==`E_IRQ_0) | + (e_state==`E_IRQ_2) | + ((e_state==`E_SRC_RD) & ~inst_as[`ABS]) | + ((e_state==`E_SRC_WR) & ~inst_as[`ABS]) | + ((e_state==`E_EXEC) & inst_as[`DIR] & ~inst_type[`INST_JMP]); + +wire src_reg_dest_sel = (e_state==`E_IRQ_1) | + (e_state==`E_IRQ_3) | + ((e_state==`E_DST_RD) & (inst_so[`PUSH] | inst_so[`CALL])); + +wire src_mdb_in_val_sel = ((e_state==`E_DST_RD) & inst_so[`RETI]) | + ((e_state==`E_EXEC) & (inst_as[`INDIR] | inst_as[`INDIR_I] | + inst_as[`IDX] | inst_as[`SYMB] | + inst_as[`ABS])); + +wire src_inst_dext_sel = ((e_state==`E_DST_RD) & ~(inst_so[`PUSH] | inst_so[`CALL])) | + ((e_state==`E_DST_WR) & ~(inst_so[`PUSH] | inst_so[`CALL] | + inst_so[`RETI])); + +wire src_inst_sext_sel = ((e_state==`E_EXEC) & (inst_type[`INST_JMP] | inst_as[`IMM] | + inst_as[`CONST] | inst_so[`RETI])); + + +assign op_src = src_reg_src_sel ? reg_src : + src_reg_dest_sel ? reg_dest : + src_mdb_in_val_sel ? mdb_in_val : + src_inst_dext_sel ? inst_dext : + src_inst_sext_sel ? inst_sext : 16'h0000; + + +//============================================================================= +// 4) DESTINATION OPERAND MUXING +//============================================================================= +// inst_ad[`DIR] : Register direct. +// inst_ad[`IDX] : Register indexed. +// inst_ad[`SYMB] : Symbolic (operand is in memory at address PC+x). +// inst_ad[`ABS] : Absolute (operand is in memory at address x). + + +wire dst_inst_sext_sel = ((e_state==`E_SRC_RD) & (inst_as[`IDX] | inst_as[`SYMB] | + inst_as[`ABS])) | + ((e_state==`E_SRC_WR) & (inst_as[`IDX] | inst_as[`SYMB] | + inst_as[`ABS])); + +wire dst_mdb_in_bw_sel = ((e_state==`E_DST_WR) & inst_so[`RETI]) | + ((e_state==`E_EXEC) & ~(inst_ad[`DIR] | inst_type[`INST_JMP] | + inst_type[`INST_SO]) & ~inst_so[`RETI]); + +wire dst_fffe_sel = (e_state==`E_IRQ_0) | + (e_state==`E_IRQ_1) | + (e_state==`E_IRQ_3) | + ((e_state==`E_DST_RD) & (inst_so[`PUSH] | inst_so[`CALL]) & ~inst_so[`RETI]); + +wire dst_reg_dest_sel = ((e_state==`E_DST_RD) & ~(inst_so[`PUSH] | inst_so[`CALL] | inst_ad[`ABS] | inst_so[`RETI])) | + ((e_state==`E_DST_WR) & ~inst_ad[`ABS]) | + ((e_state==`E_EXEC) & (inst_ad[`DIR] | inst_type[`INST_JMP] | + inst_type[`INST_SO]) & ~inst_so[`RETI]); + + +assign op_dst = dbg_halt_st ? dbg_mem_dout : + dst_inst_sext_sel ? inst_sext : + dst_mdb_in_bw_sel ? mdb_in_bw : + dst_reg_dest_sel ? reg_dest : + dst_fffe_sel ? 16'hfffe : 16'h0000; + + +//============================================================================= +// 5) ALU +//============================================================================= + +wire exec_cycle = (e_state==`E_EXEC); + +omsp_alu alu_0 ( + +// OUTPUTs + .alu_out (alu_out), // ALU output value + .alu_out_add (alu_out_add), // ALU adder output value + .alu_stat (alu_stat), // ALU Status {V,N,Z,C} + .alu_stat_wr (alu_stat_wr), // ALU Status write {V,N,Z,C} + +// INPUTs + .dbg_halt_st (dbg_halt_st), // Halt/Run status from CPU + .exec_cycle (exec_cycle), // Instruction execution cycle + .inst_alu (inst_alu), // ALU control signals + .inst_bw (inst_bw), // Decoded Inst: byte width + .inst_jmp (inst_jmp), // Decoded Inst: Conditional jump + .inst_so (inst_so), // Single-operand arithmetic + .op_dst (op_dst), // Destination operand + .op_src (op_src), // Source operand + .status (status) // R2 Status {V,N,Z,C} +); + + +//============================================================================= +// 6) MEMORY INTERFACE +//============================================================================= + +// Detect memory read/write access +assign mb_en = ((e_state==`E_IRQ_1) & ~inst_irq_rst) | + ((e_state==`E_IRQ_3) & ~inst_irq_rst) | + ((e_state==`E_SRC_RD) & ~inst_as[`IMM]) | + (e_state==`E_SRC_WR) | + ((e_state==`E_EXEC) & inst_so[`RETI]) | + (e_state==`E_DST_RD) | + (e_state==`E_DST_WR); + +wire [1:0] mb_wr_msk = inst_alu[`EXEC_NO_WR] ? 2'b00 : + ~inst_bw ? 2'b11 : + alu_out_add[0] ? 2'b10 : 2'b01; +assign mb_wr = ({2{(e_state==`E_IRQ_1)}} | + {2{(e_state==`E_IRQ_3)}} | + {2{(e_state==`E_DST_WR)}} | + {2{(e_state==`E_SRC_WR)}}) & mb_wr_msk; + +// Memory address bus +assign mab = alu_out_add[15:0]; + +// Memory data bus output +reg [15:0] mdb_out_nxt; +always @(posedge mclk or posedge puc) + if (puc) mdb_out_nxt <= 16'h0000; + else if (e_state==`E_DST_RD) mdb_out_nxt <= pc_nxt; + else if ((e_state==`E_EXEC & ~inst_so[`CALL]) | + (e_state==`E_IRQ_0) | (e_state==`E_IRQ_2)) mdb_out_nxt <= alu_out; + +assign mdb_out = inst_bw ? {2{mdb_out_nxt[7:0]}} : mdb_out_nxt; + +// Format memory data bus input depending on BW +reg mab_lsb; +always @(posedge mclk or posedge puc) + if (puc) mab_lsb <= 1'b0; + else if (mb_en) mab_lsb <= alu_out_add[0]; + +assign mdb_in_bw = ~inst_bw ? mdb_in : + mab_lsb ? {2{mdb_in[15:8]}} : mdb_in; + +// Memory data bus input buffer (buffer after a source read) +reg mdb_in_buf_en; +always @(posedge mclk or posedge puc) + if (puc) mdb_in_buf_en <= 1'b0; + else mdb_in_buf_en <= (e_state==`E_SRC_RD); + +reg mdb_in_buf_valid; +always @(posedge mclk or posedge puc) + if (puc) mdb_in_buf_valid <= 1'b0; + else if (e_state==`E_EXEC) mdb_in_buf_valid <= 1'b0; + else if (mdb_in_buf_en) mdb_in_buf_valid <= 1'b1; + +reg [15:0] mdb_in_buf; +always @(posedge mclk or posedge puc) + if (puc) mdb_in_buf <= 16'h0000; + else if (mdb_in_buf_en) mdb_in_buf <= mdb_in_bw; + +assign mdb_in_val = mdb_in_buf_valid ? mdb_in_buf : mdb_in_bw; + + +endmodule // omsp_execution_unit + +`include "openMSP430_undefines.v"
omsp_execution_unit.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Date Revision Author \ No newline at end of property Index: openMSP430.v =================================================================== --- openMSP430.v (revision 33) +++ openMSP430.v (revision 34) @@ -155,7 +155,7 @@ // 2) GLOBAL CLOCK & RESET MANAGEMENT //============================================================================= -clock_module clock_module_0 ( +omsp_clock_module clock_module_0 ( // OUTPUTs .aclk_en (aclk_en), // ACLK enablex @@ -184,7 +184,7 @@ // 3) FRONTEND (<=> FETCH & DECODE) //============================================================================= -frontend frontend_0 ( +omsp_frontend frontend_0 ( // OUTPUTs .dbg_halt_st (dbg_halt_st), // Halt/Run status from CPU @@ -231,7 +231,7 @@ // 4) EXECUTION UNIT //============================================================================= -execution_unit execution_unit_0 ( +omsp_execution_unit execution_unit_0 ( // OUTPUTs .cpuoff (cpuoff), // Turns off the CPU @@ -276,7 +276,7 @@ // 5) MEMORY BACKBONE //============================================================================= -mem_backbone mem_backbone_0 ( +omsp_mem_backbone mem_backbone_0 ( // OUTPUTs .dbg_mem_din (dbg_mem_din), // Debug unit Memory data input @@ -320,7 +320,7 @@ // 6) SPECIAL FUNCTION REGISTERS //============================================================================= -sfr sfr_0 ( +omsp_sfr sfr_0 ( // OUTPUTs .nmie (nmie), // Non-maskable interrupt enable @@ -349,7 +349,7 @@ // 7) WATCHDOG TIMER //============================================================================= -watchdog watchdog_0 ( +omsp_watchdog watchdog_0 ( // OUTPUTs .nmi_evt (nmi_evt), // NMI Event @@ -389,7 +389,7 @@ //============================================================================= `ifdef DBG_EN -dbg dbg_0 ( +omsp_dbg dbg_0 ( // OUTPUTs .dbg_freeze (dbg_freeze), // Freeze peripherals

powered by: WebSVN 2.1.0

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