Line 1... |
Line 1... |
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
// Copyright (C) 2001 Authors
|
// Copyright (C) 2009 , Olivier Girard
|
//
|
//
|
// This source file may be used and distributed without restriction provided
|
// Redistribution and use in source and binary forms, with or without
|
// that this copyright statement is not removed from the file and that any
|
// modification, are permitted provided that the following conditions
|
// derivative work contains the original copyright notice and the associated
|
// are met:
|
// disclaimer.
|
// * Redistributions of source code must retain the above copyright
|
//
|
// notice, this list of conditions and the following disclaimer.
|
// This source file is free software; you can redistribute it and/or modify
|
// * Redistributions in binary form must reproduce the above copyright
|
// it under the terms of the GNU Lesser General Public License as published
|
// notice, this list of conditions and the following disclaimer in the
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
// documentation and/or other materials provided with the distribution.
|
// (at your option) any later version.
|
// * Neither the name of the authors nor the names of its contributors
|
//
|
// may be used to endorse or promote products derived from this software
|
// This source is distributed in the hope that it will be useful, but WITHOUT
|
// without specific prior written permission.
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
//
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
// License for more details.
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
//
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
// You should have received a copy of the GNU Lesser General Public License
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
// along with this source; if not, write to the Free Software Foundation,
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
// THE POSSIBILITY OF SUCH DAMAGE
|
//
|
//
|
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
//
|
//
|
// *File Name: omsp_frontend.v
|
// *File Name: omsp_frontend.v
|
//
|
//
|
Line 61... |
Line 66... |
inst_src, // Decoded Inst: source (one hot)
|
inst_src, // Decoded Inst: source (one hot)
|
inst_type, // Decoded Instruction type
|
inst_type, // Decoded Instruction type
|
irq_acc, // Interrupt request accepted (one-hot signal)
|
irq_acc, // Interrupt request accepted (one-hot signal)
|
mab, // Frontend Memory address bus
|
mab, // Frontend Memory address bus
|
mb_en, // Frontend Memory bus enable
|
mb_en, // Frontend Memory bus enable
|
|
mclk_enable, // Main System Clock enable
|
|
mclk_wkup, // Main System Clock wake-up (asynchronous)
|
nmi_acc, // Non-Maskable interrupt request accepted
|
nmi_acc, // Non-Maskable interrupt request accepted
|
pc, // Program counter
|
pc, // Program counter
|
pc_nxt, // Next PC value (for CALL & IRQ)
|
pc_nxt, // Next PC value (for CALL & IRQ)
|
|
|
// INPUTs
|
// INPUTs
|
Line 75... |
Line 82... |
fe_pmem_wait, // Frontend wait for Instruction fetch
|
fe_pmem_wait, // Frontend wait for Instruction fetch
|
gie, // General interrupt enable
|
gie, // General interrupt enable
|
irq, // Maskable interrupts
|
irq, // Maskable interrupts
|
mclk, // Main system clock
|
mclk, // Main system clock
|
mdb_in, // Frontend Memory data bus input
|
mdb_in, // Frontend Memory data bus input
|
nmi_evt, // Non-maskable interrupt event
|
nmi_pnd, // Non-maskable interrupt pending
|
|
nmi_wkup, // NMI Wakeup
|
pc_sw, // Program counter software value
|
pc_sw, // Program counter software value
|
pc_sw_wr, // Program counter software write
|
pc_sw_wr, // Program counter software write
|
puc_rst, // Main system reset
|
puc_rst, // Main system reset
|
wdt_irq // Watchdog-timer interrupt
|
scan_enable, // Scan enable (active during scan shifting)
|
|
wdt_irq, // Watchdog-timer interrupt
|
|
wdt_wkup, // Watchdog Wakeup
|
|
wkup // System Wake-up (asynchronous)
|
);
|
);
|
|
|
// OUTPUTs
|
// OUTPUTs
|
//=========
|
//=========
|
output dbg_halt_st; // Halt/Run status from CPU
|
output dbg_halt_st; // Halt/Run status from CPU
|
Line 104... |
Line 115... |
output [15:0] inst_src; // Decoded Inst: source (one hot)
|
output [15:0] inst_src; // Decoded Inst: source (one hot)
|
output [2:0] inst_type; // Decoded Instruction type
|
output [2:0] inst_type; // Decoded Instruction type
|
output [13:0] irq_acc; // Interrupt request accepted (one-hot signal)
|
output [13:0] irq_acc; // Interrupt request accepted (one-hot signal)
|
output [15:0] mab; // Frontend Memory address bus
|
output [15:0] mab; // Frontend Memory address bus
|
output mb_en; // Frontend Memory bus enable
|
output mb_en; // Frontend Memory bus enable
|
|
output mclk_enable; // Main System Clock enable
|
|
output mclk_wkup; // Main System Clock wake-up (asynchronous)
|
output nmi_acc; // Non-Maskable interrupt request accepted
|
output nmi_acc; // Non-Maskable interrupt request accepted
|
output [15:0] pc; // Program counter
|
output [15:0] pc; // Program counter
|
output [15:0] pc_nxt; // Next PC value (for CALL & IRQ)
|
output [15:0] pc_nxt; // Next PC value (for CALL & IRQ)
|
|
|
// INPUTs
|
// INPUTs
|
Line 119... |
Line 132... |
input fe_pmem_wait; // Frontend wait for Instruction fetch
|
input fe_pmem_wait; // Frontend wait for Instruction fetch
|
input gie; // General interrupt enable
|
input gie; // General interrupt enable
|
input [13:0] irq; // Maskable interrupts
|
input [13:0] irq; // Maskable interrupts
|
input mclk; // Main system clock
|
input mclk; // Main system clock
|
input [15:0] mdb_in; // Frontend Memory data bus input
|
input [15:0] mdb_in; // Frontend Memory data bus input
|
input nmi_evt; // Non-maskable interrupt event
|
input nmi_pnd; // Non-maskable interrupt pending
|
|
input nmi_wkup; // NMI Wakeup
|
input [15:0] pc_sw; // Program counter software value
|
input [15:0] pc_sw; // Program counter software value
|
input pc_sw_wr; // Program counter software write
|
input pc_sw_wr; // Program counter software write
|
input puc_rst; // Main system reset
|
input puc_rst; // Main system reset
|
|
input scan_enable; // Scan enable (active during scan shifting)
|
input wdt_irq; // Watchdog-timer interrupt
|
input wdt_irq; // Watchdog-timer interrupt
|
|
input wdt_wkup; // Watchdog Wakeup
|
|
input wkup; // System Wake-up (asynchronous)
|
|
|
|
|
//=============================================================================
|
//=============================================================================
|
// 1) UTILITY FUNCTIONS
|
// 1) UTILITY FUNCTIONS
|
//=============================================================================
|
//=============================================================================
|
Line 150... |
Line 167... |
end
|
end
|
endfunction
|
endfunction
|
|
|
|
|
//=============================================================================
|
//=============================================================================
|
// 2) Parameter definitions
|
// 2) PARAMETER DEFINITIONS
|
//=============================================================================
|
//=============================================================================
|
|
|
//
|
//
|
// 2.1) Instruction State machine definitons
|
// 2.1) Instruction State machine definitons
|
//-------------------------------------------
|
//-------------------------------------------
|
Line 217... |
Line 234... |
(cpuoff | cpu_halt_cmd) & exec_done ? I_IDLE :
|
(cpuoff | cpu_halt_cmd) & exec_done ? I_IDLE :
|
cpu_halt_cmd & (e_state==E_IDLE) ? I_IDLE :
|
cpu_halt_cmd & (e_state==E_IDLE) ? I_IDLE :
|
pc_sw_wr ? I_DEC :
|
pc_sw_wr ? I_DEC :
|
~exec_done & ~(e_state==E_IDLE) ? I_DEC : // Wait in decode state
|
~exec_done & ~(e_state==E_IDLE) ? I_DEC : // Wait in decode state
|
(inst_sz_nxt!=2'b00) ? I_EXT1 : I_DEC; // until execution is completed
|
(inst_sz_nxt!=2'b00) ? I_EXT1 : I_DEC; // until execution is completed
|
I_EXT1 : i_state_nxt = irq_detect ? I_IRQ_FETCH :
|
I_EXT1 : i_state_nxt = pc_sw_wr ? I_DEC :
|
pc_sw_wr ? I_DEC :
|
|
(inst_sz!=2'b01) ? I_EXT2 : I_DEC;
|
(inst_sz!=2'b01) ? I_EXT2 : I_DEC;
|
I_EXT2 : i_state_nxt = irq_detect ? I_IRQ_FETCH : I_DEC;
|
I_EXT2 : i_state_nxt = I_DEC;
|
|
// pragma coverage off
|
default : i_state_nxt = I_IRQ_FETCH;
|
default : i_state_nxt = I_IRQ_FETCH;
|
|
// pragma coverage on
|
endcase
|
endcase
|
|
|
// State machine
|
// State machine
|
always @(posedge mclk or posedge puc_rst)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc_rst) i_state <= I_IRQ_FETCH;
|
if (puc_rst) i_state <= I_IRQ_FETCH;
|
Line 242... |
Line 260... |
if (puc_rst) dbg_halt_st <= 1'b0;
|
if (puc_rst) dbg_halt_st <= 1'b0;
|
else dbg_halt_st <= cpu_halt_cmd & (i_state_nxt==I_IDLE);
|
else dbg_halt_st <= cpu_halt_cmd & (i_state_nxt==I_IDLE);
|
|
|
|
|
//=============================================================================
|
//=============================================================================
|
// 4) INTERRUPT HANDLING
|
// 4) INTERRUPT HANDLING & SYSTEM WAKEUP
|
//=============================================================================
|
//=============================================================================
|
|
|
// Detect nmi interrupt
|
//
|
reg inst_nmi;
|
// 4.1) INTERRUPT HANDLING
|
always @(posedge mclk or posedge puc_rst)
|
//-----------------------------------------
|
if (puc_rst) inst_nmi <= 1'b0;
|
|
else if (nmi_evt) inst_nmi <= 1'b1;
|
|
else if (i_state==I_IRQ_DONE) inst_nmi <= 1'b0;
|
|
|
|
|
|
// Detect reset interrupt
|
// Detect reset interrupt
|
reg inst_irq_rst;
|
reg inst_irq_rst;
|
always @(posedge mclk or posedge puc_rst)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc_rst) inst_irq_rst <= 1'b1;
|
if (puc_rst) inst_irq_rst <= 1'b1;
|
else if (exec_done) inst_irq_rst <= 1'b0;
|
else if (exec_done) inst_irq_rst <= 1'b0;
|
|
|
// Detect other interrupts
|
// Detect other interrupts
|
assign irq_detect = (inst_nmi | ((|irq | wdt_irq) & gie)) & ~cpu_halt_cmd & ~dbg_halt_st & (exec_done | (i_state==I_IDLE));
|
assign irq_detect = (nmi_pnd | ((|irq | wdt_irq) & gie)) & ~cpu_halt_cmd & ~dbg_halt_st & (exec_done | (i_state==I_IDLE));
|
|
|
|
`ifdef CLOCK_GATING
|
|
wire mclk_irq_num;
|
|
omsp_clock_gate clock_gate_irq_num (.gclk(mclk_irq_num),
|
|
.clk (mclk), .enable(irq_detect), .scan_enable(scan_enable));
|
|
`else
|
|
wire mclk_irq_num = mclk;
|
|
`endif
|
|
|
// Select interrupt vector
|
// Select interrupt vector
|
reg [3:0] irq_num;
|
reg [3:0] irq_num;
|
always @(posedge mclk or posedge puc_rst)
|
always @(posedge mclk_irq_num or posedge puc_rst)
|
if (puc_rst) irq_num <= 4'hf;
|
if (puc_rst) irq_num <= 4'hf;
|
else if (irq_detect) irq_num <= inst_nmi ? 4'he :
|
`ifdef CLOCK_GATING
|
|
else irq_num <= nmi_pnd ? 4'he :
|
|
`else
|
|
else if (irq_detect) irq_num <= nmi_pnd ? 4'he :
|
|
`endif
|
irq[13] ? 4'hd :
|
irq[13] ? 4'hd :
|
irq[12] ? 4'hc :
|
irq[12] ? 4'hc :
|
irq[11] ? 4'hb :
|
irq[11] ? 4'hb :
|
(irq[10] | wdt_irq) ? 4'ha :
|
(irq[10] | wdt_irq) ? 4'ha :
|
irq[9] ? 4'h9 :
|
irq[9] ? 4'h9 :
|
Line 289... |
Line 315... |
// Interrupt request accepted
|
// Interrupt request accepted
|
wire [15:0] irq_acc_all = one_hot16(irq_num) & {16{(i_state==I_IRQ_FETCH)}};
|
wire [15:0] irq_acc_all = one_hot16(irq_num) & {16{(i_state==I_IRQ_FETCH)}};
|
wire [13:0] irq_acc = irq_acc_all[13:0];
|
wire [13:0] irq_acc = irq_acc_all[13:0];
|
wire nmi_acc = irq_acc_all[14];
|
wire nmi_acc = irq_acc_all[14];
|
|
|
|
//
|
|
// 4.2) SYSTEM WAKEUP
|
|
//-----------------------------------------
|
|
`ifdef CPUOFF_EN
|
|
|
|
// Generate the main system clock enable signal
|
|
// Keep the clock running if:
|
|
wire mclk_enable = inst_irq_rst ? cpu_en_s : // - the RESET interrupt is currently executing
|
|
// and if the CPU is enabled
|
|
// otherwise if:
|
|
~((cpuoff | ~cpu_en_s) & // - the CPUOFF flag, cpu_en command, instruction
|
|
(i_state==I_IDLE) & // and execution state machines are all two
|
|
(e_state==E_IDLE)); // not idle.
|
|
|
|
|
|
// Wakeup condition from maskable interrupts
|
|
wire mirq_wkup;
|
|
omsp_and_gate and_mirq_wkup (.y(mirq_wkup), .a(wkup | wdt_wkup), .b(gie));
|
|
|
|
// Combined asynchronous wakeup detection from nmi & irq (masked if the cpu is disabled)
|
|
omsp_and_gate and_mclk_wkup (.y(mclk_wkup), .a(nmi_wkup | mirq_wkup), .b(cpu_en_s));
|
|
|
|
`else
|
|
|
|
// In the CPUOFF feature is disabled, the wake-up and enable signals are always 1
|
|
assign mclk_wkup = 1'b1;
|
|
assign mclk_enable = 1'b1;
|
|
`endif
|
|
|
//=============================================================================
|
//=============================================================================
|
// 5) FETCH INSTRUCTION
|
// 5) FETCH INSTRUCTION
|
//=============================================================================
|
//=============================================================================
|
|
|
Line 307... |
Line 361... |
wire [15:0] pc_incr = pc + {14'h0000, fetch, 1'b0};
|
wire [15:0] pc_incr = pc + {14'h0000, fetch, 1'b0};
|
wire [15:0] pc_nxt = pc_sw_wr ? pc_sw :
|
wire [15:0] pc_nxt = pc_sw_wr ? pc_sw :
|
(i_state==I_IRQ_FETCH) ? irq_addr :
|
(i_state==I_IRQ_FETCH) ? irq_addr :
|
(i_state==I_IRQ_DONE) ? mdb_in : pc_incr;
|
(i_state==I_IRQ_DONE) ? mdb_in : pc_incr;
|
|
|
always @(posedge mclk or posedge puc_rst)
|
`ifdef CLOCK_GATING
|
|
wire pc_en = fetch |
|
|
pc_sw_wr |
|
|
(i_state==I_IRQ_FETCH) |
|
|
(i_state==I_IRQ_DONE);
|
|
wire mclk_pc;
|
|
omsp_clock_gate clock_gate_pc (.gclk(mclk_pc),
|
|
.clk (mclk), .enable(pc_en), .scan_enable(scan_enable));
|
|
`else
|
|
wire mclk_pc = mclk;
|
|
`endif
|
|
|
|
always @(posedge mclk_pc or posedge puc_rst)
|
if (puc_rst) pc <= 16'h0000;
|
if (puc_rst) pc <= 16'h0000;
|
else pc <= pc_nxt;
|
else pc <= pc_nxt;
|
|
|
// Check if ROM has been busy in order to retry ROM access
|
// Check if ROM has been busy in order to retry ROM access
|
reg pmem_busy;
|
reg pmem_busy;
|
Line 332... |
Line 398... |
wire [15:0] ir = mdb_in;
|
wire [15:0] ir = mdb_in;
|
|
|
// Detect if source extension word is required
|
// Detect if source extension word is required
|
wire is_sext = (inst_as[`IDX] | inst_as[`SYMB] | inst_as[`ABS] | inst_as[`IMM]);
|
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
|
// For the Symbolic addressing mode, add -2 to the extension word in order
|
// to make up for the PC address
|
// to make up for the PC address
|
wire [15:0] ext_incr = ((i_state==I_EXT1) & inst_as[`SYMB]) |
|
wire [15:0] ext_incr = ((i_state==I_EXT1) & inst_as[`SYMB]) |
|
((i_state==I_EXT2) & inst_ad[`SYMB]) |
|
((i_state==I_EXT2) & inst_ad[`SYMB]) |
|
((i_state==I_EXT1) & ~inst_as[`SYMB] &
|
((i_state==I_EXT1) & ~inst_as[`SYMB] &
|
Line 346... |
Line 409... |
|
|
wire [15:0] ext_nxt = ir + ext_incr;
|
wire [15:0] ext_nxt = ir + ext_incr;
|
|
|
// Store source extension word
|
// Store source extension word
|
reg [15:0] inst_sext;
|
reg [15:0] inst_sext;
|
always @(posedge mclk or posedge puc_rst)
|
|
|
`ifdef CLOCK_GATING
|
|
wire inst_sext_en = (decode & is_const) |
|
|
(decode & inst_type_nxt[`INST_JMP]) |
|
|
((i_state==I_EXT1) & is_sext);
|
|
wire mclk_inst_sext;
|
|
omsp_clock_gate clock_gate_inst_sext (.gclk(mclk_inst_sext),
|
|
.clk (mclk), .enable(inst_sext_en), .scan_enable(scan_enable));
|
|
`else
|
|
wire mclk_inst_sext = mclk;
|
|
`endif
|
|
|
|
always @(posedge mclk_inst_sext or posedge puc_rst)
|
if (puc_rst) inst_sext <= 16'h0000;
|
if (puc_rst) inst_sext <= 16'h0000;
|
else if (decode & is_const) inst_sext <= sconst_nxt;
|
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 (decode & inst_type_nxt[`INST_JMP]) inst_sext <= {{5{ir[9]}},ir[9:0],1'b0};
|
|
`ifdef CLOCK_GATING
|
|
else inst_sext <= ext_nxt;
|
|
`else
|
else if ((i_state==I_EXT1) & is_sext) inst_sext <= ext_nxt;
|
else if ((i_state==I_EXT1) & is_sext) inst_sext <= ext_nxt;
|
|
`endif
|
|
|
// Source extension word is ready
|
// Source extension word is ready
|
wire inst_sext_rdy = (i_state==I_EXT1) & is_sext;
|
wire inst_sext_rdy = (i_state==I_EXT1) & is_sext;
|
|
|
|
|
// Store destination extension word
|
// Store destination extension word
|
reg [15:0] inst_dext;
|
reg [15:0] inst_dext;
|
always @(posedge mclk or posedge puc_rst)
|
|
|
`ifdef CLOCK_GATING
|
|
wire inst_dext_en = ((i_state==I_EXT1) & ~is_sext) |
|
|
(i_state==I_EXT2);
|
|
wire mclk_inst_dext;
|
|
omsp_clock_gate clock_gate_inst_dext (.gclk(mclk_inst_dext),
|
|
.clk (mclk), .enable(inst_dext_en), .scan_enable(scan_enable));
|
|
`else
|
|
wire mclk_inst_dext = mclk;
|
|
`endif
|
|
|
|
always @(posedge mclk_inst_dext or posedge puc_rst)
|
if (puc_rst) inst_dext <= 16'h0000;
|
if (puc_rst) inst_dext <= 16'h0000;
|
else if ((i_state==I_EXT1) & ~is_sext) inst_dext <= ext_nxt;
|
else if ((i_state==I_EXT1) & ~is_sext) inst_dext <= ext_nxt;
|
|
`ifdef CLOCK_GATING
|
|
else inst_dext <= ext_nxt;
|
|
`else
|
else if (i_state==I_EXT2) inst_dext <= ext_nxt;
|
else if (i_state==I_EXT2) inst_dext <= ext_nxt;
|
|
`endif
|
|
|
// Destination extension word is ready
|
// Destination extension word is ready
|
wire inst_dext_rdy = (((i_state==I_EXT1) & ~is_sext) | (i_state==I_EXT2));
|
wire inst_dext_rdy = (((i_state==I_EXT1) & ~is_sext) | (i_state==I_EXT2));
|
|
|
|
|
//=============================================================================
|
//=============================================================================
|
// 6) DECODE INSTRUCTION
|
// 6) DECODE INSTRUCTION
|
//=============================================================================
|
//=============================================================================
|
|
|
|
`ifdef CLOCK_GATING
|
|
wire mclk_decode;
|
|
omsp_clock_gate clock_gate_decode (.gclk(mclk_decode),
|
|
.clk (mclk), .enable(decode), .scan_enable(scan_enable));
|
|
`else
|
|
wire mclk_decode = mclk;
|
|
`endif
|
|
|
//
|
//
|
// 6.1) OPCODE: INSTRUCTION TYPE
|
// 6.1) OPCODE: INSTRUCTION TYPE
|
//----------------------------------------
|
//----------------------------------------
|
// Instructions type is encoded in a one hot fashion as following:
|
// Instructions type is encoded in a one hot fashion as following:
|
//
|
//
|
Line 385... |
Line 487... |
reg [2:0] inst_type;
|
reg [2:0] inst_type;
|
assign inst_type_nxt = {(ir[15:14]!=2'b00),
|
assign inst_type_nxt = {(ir[15:14]!=2'b00),
|
(ir[15:13]==3'b001),
|
(ir[15:13]==3'b001),
|
(ir[15:13]==3'b000)} & {3{~irq_detect}};
|
(ir[15:13]==3'b000)} & {3{~irq_detect}};
|
|
|
always @(posedge mclk or posedge puc_rst)
|
always @(posedge mclk_decode or posedge puc_rst)
|
if (puc_rst) inst_type <= 3'b000;
|
if (puc_rst) inst_type <= 3'b000;
|
|
`ifdef CLOCK_GATING
|
|
else inst_type <= inst_type_nxt;
|
|
`else
|
else if (decode) inst_type <= inst_type_nxt;
|
else if (decode) inst_type <= inst_type_nxt;
|
|
`endif
|
|
|
//
|
//
|
// 6.2) OPCODE: SINGLE-OPERAND ARITHMETIC
|
// 6.2) OPCODE: SINGLE-OPERAND ARITHMETIC
|
//----------------------------------------
|
//----------------------------------------
|
// Instructions are encoded in a one hot fashion as following:
|
// Instructions are encoded in a one hot fashion as following:
|
Line 406... |
Line 512... |
// 8'b10000000: IRQ
|
// 8'b10000000: IRQ
|
|
|
reg [7:0] inst_so;
|
reg [7:0] inst_so;
|
wire [7:0] inst_so_nxt = irq_detect ? 8'h80 : (one_hot8(ir[9:7]) & {8{inst_type_nxt[`INST_SO]}});
|
wire [7:0] inst_so_nxt = irq_detect ? 8'h80 : (one_hot8(ir[9:7]) & {8{inst_type_nxt[`INST_SO]}});
|
|
|
always @(posedge mclk or posedge puc_rst)
|
always @(posedge mclk_decode or posedge puc_rst)
|
if (puc_rst) inst_so <= 8'h00;
|
if (puc_rst) inst_so <= 8'h00;
|
|
`ifdef CLOCK_GATING
|
|
else inst_so <= inst_so_nxt;
|
|
`else
|
else if (decode) inst_so <= inst_so_nxt;
|
else if (decode) inst_so <= inst_so_nxt;
|
|
`endif
|
|
|
//
|
//
|
// 6.3) OPCODE: CONDITIONAL JUMP
|
// 6.3) OPCODE: CONDITIONAL JUMP
|
//--------------------------------
|
//--------------------------------
|
// Instructions are encoded in a one hot fashion as following:
|
// Instructions are encoded in a one hot fashion as following:
|
Line 425... |
Line 535... |
// 8'b00100000: JGE
|
// 8'b00100000: JGE
|
// 8'b01000000: JL
|
// 8'b01000000: JL
|
// 8'b10000000: JMP
|
// 8'b10000000: JMP
|
|
|
reg [2:0] inst_jmp_bin;
|
reg [2:0] inst_jmp_bin;
|
always @(posedge mclk or posedge puc_rst)
|
always @(posedge mclk_decode or posedge puc_rst)
|
if (puc_rst) inst_jmp_bin <= 3'h0;
|
if (puc_rst) inst_jmp_bin <= 3'h0;
|
|
`ifdef CLOCK_GATING
|
|
else inst_jmp_bin <= ir[12:10];
|
|
`else
|
else if (decode) inst_jmp_bin <= ir[12:10];
|
else if (decode) inst_jmp_bin <= ir[12:10];
|
|
`endif
|
|
|
wire [7:0] inst_jmp = one_hot8(inst_jmp_bin) & {8{inst_type[`INST_JMP]}};
|
wire [7:0] inst_jmp = one_hot8(inst_jmp_bin) & {8{inst_type[`INST_JMP]}};
|
|
|
|
|
//
|
//
|
Line 454... |
Line 568... |
|
|
wire [15:0] inst_to_1hot = one_hot16(ir[15:12]) & {16{inst_type_nxt[`INST_TO]}};
|
wire [15:0] inst_to_1hot = one_hot16(ir[15:12]) & {16{inst_type_nxt[`INST_TO]}};
|
wire [11:0] inst_to_nxt = inst_to_1hot[15:4];
|
wire [11:0] inst_to_nxt = inst_to_1hot[15:4];
|
|
|
reg inst_mov;
|
reg inst_mov;
|
always @(posedge mclk or posedge puc_rst)
|
always @(posedge mclk_decode or posedge puc_rst)
|
if (puc_rst) inst_mov <= 1'b0;
|
if (puc_rst) inst_mov <= 1'b0;
|
|
`ifdef CLOCK_GATING
|
|
else inst_mov <= inst_to_nxt[`MOV];
|
|
`else
|
else if (decode) inst_mov <= inst_to_nxt[`MOV];
|
else if (decode) inst_mov <= inst_to_nxt[`MOV];
|
|
`endif
|
|
|
|
|
//
|
//
|
// 6.5) SOURCE AND DESTINATION REGISTERS
|
// 6.5) SOURCE AND DESTINATION REGISTERS
|
//---------------------------------------
|
//---------------------------------------
|
|
|
// Destination register
|
// Destination register
|
reg [3:0] inst_dest_bin;
|
reg [3:0] inst_dest_bin;
|
always @(posedge mclk or posedge puc_rst)
|
always @(posedge mclk_decode or posedge puc_rst)
|
if (puc_rst) inst_dest_bin <= 4'h0;
|
if (puc_rst) inst_dest_bin <= 4'h0;
|
|
`ifdef CLOCK_GATING
|
|
else inst_dest_bin <= ir[3:0];
|
|
`else
|
else if (decode) inst_dest_bin <= ir[3:0];
|
else if (decode) inst_dest_bin <= ir[3:0];
|
|
`endif
|
|
|
wire [15:0] inst_dest = dbg_halt_st ? one_hot16(dbg_reg_sel) :
|
wire [15:0] inst_dest = dbg_halt_st ? one_hot16(dbg_reg_sel) :
|
inst_type[`INST_JMP] ? 16'h0001 :
|
inst_type[`INST_JMP] ? 16'h0001 :
|
inst_so[`IRQ] |
|
inst_so[`IRQ] |
|
inst_so[`PUSH] |
|
inst_so[`PUSH] |
|
Line 479... |
Line 601... |
one_hot16(inst_dest_bin);
|
one_hot16(inst_dest_bin);
|
|
|
|
|
// Source register
|
// Source register
|
reg [3:0] inst_src_bin;
|
reg [3:0] inst_src_bin;
|
always @(posedge mclk or posedge puc_rst)
|
always @(posedge mclk_decode or posedge puc_rst)
|
if (puc_rst) inst_src_bin <= 4'h0;
|
if (puc_rst) inst_src_bin <= 4'h0;
|
|
`ifdef CLOCK_GATING
|
|
else inst_src_bin <= ir[11:8];
|
|
`else
|
else if (decode) inst_src_bin <= ir[11:8];
|
else if (decode) inst_src_bin <= ir[11:8];
|
|
`endif
|
|
|
wire [15:0] inst_src = inst_type[`INST_TO] ? one_hot16(inst_src_bin) :
|
wire [15:0] inst_src = inst_type[`INST_TO] ? one_hot16(inst_src_bin) :
|
inst_so[`RETI] ? 16'h0002 :
|
inst_so[`RETI] ? 16'h0002 :
|
inst_so[`IRQ] ? 16'h0001 :
|
inst_so[`IRQ] ? 16'h0001 :
|
inst_type[`INST_SO] ? one_hot16(inst_dest_bin) : 16'h0000;
|
inst_type[`INST_SO] ? one_hot16(inst_dest_bin) : 16'h0000;
|
Line 548... |
Line 674... |
endcase
|
endcase
|
end
|
end
|
assign is_const = |inst_as_nxt[12:7];
|
assign is_const = |inst_as_nxt[12:7];
|
|
|
reg [7:0] inst_as;
|
reg [7:0] inst_as;
|
always @(posedge mclk or posedge puc_rst)
|
always @(posedge mclk_decode or posedge puc_rst)
|
if (puc_rst) inst_as <= 8'h00;
|
if (puc_rst) inst_as <= 8'h00;
|
|
`ifdef CLOCK_GATING
|
|
else inst_as <= {is_const, inst_as_nxt[6:0]};
|
|
`else
|
else if (decode) inst_as <= {is_const, inst_as_nxt[6:0]};
|
else if (decode) inst_as <= {is_const, inst_as_nxt[6:0]};
|
|
`endif
|
|
|
|
|
// 13'b0000010000000: Constant 4.
|
// 13'b0000010000000: Constant 4.
|
// 13'b0000100000000: Constant 8.
|
// 13'b0000100000000: Constant 8.
|
// 13'b0001000000000: Constant 0.
|
// 13'b0001000000000: Constant 0.
|
Line 607... |
Line 737... |
default: inst_ad_nxt = 8'b00000001;
|
default: inst_ad_nxt = 8'b00000001;
|
endcase
|
endcase
|
end
|
end
|
|
|
reg [7:0] inst_ad;
|
reg [7:0] inst_ad;
|
always @(posedge mclk or posedge puc_rst)
|
always @(posedge mclk_decode or posedge puc_rst)
|
if (puc_rst) inst_ad <= 8'h00;
|
if (puc_rst) inst_ad <= 8'h00;
|
|
`ifdef CLOCK_GATING
|
|
else inst_ad <= inst_ad_nxt;
|
|
`else
|
else if (decode) inst_ad <= inst_ad_nxt;
|
else if (decode) inst_ad <= inst_ad_nxt;
|
|
`endif
|
|
|
|
|
//
|
//
|
// 6.8) REMAINING INSTRUCTION DECODING
|
// 6.8) REMAINING INSTRUCTION DECODING
|
//-------------------------------------
|
//-------------------------------------
|
Line 625... |
Line 759... |
else if (decode) inst_bw <= ir[6] & ~inst_type_nxt[`INST_JMP] & ~irq_detect & ~cpu_halt_cmd;
|
else if (decode) inst_bw <= ir[6] & ~inst_type_nxt[`INST_JMP] & ~irq_detect & ~cpu_halt_cmd;
|
|
|
// Extended instruction size
|
// Extended instruction size
|
assign inst_sz_nxt = {1'b0, (inst_as_nxt[`IDX] | inst_as_nxt[`SYMB] | inst_as_nxt[`ABS] | inst_as_nxt[`IMM])} +
|
assign inst_sz_nxt = {1'b0, (inst_as_nxt[`IDX] | inst_as_nxt[`SYMB] | inst_as_nxt[`ABS] | inst_as_nxt[`IMM])} +
|
{1'b0, ((inst_ad_nxt[`IDX] | inst_ad_nxt[`SYMB] | inst_ad_nxt[`ABS]) & ~inst_type_nxt[`INST_SO])};
|
{1'b0, ((inst_ad_nxt[`IDX] | inst_ad_nxt[`SYMB] | inst_ad_nxt[`ABS]) & ~inst_type_nxt[`INST_SO])};
|
always @(posedge mclk or posedge puc_rst)
|
always @(posedge mclk_decode or posedge puc_rst)
|
if (puc_rst) inst_sz <= 2'b00;
|
if (puc_rst) inst_sz <= 2'b00;
|
|
`ifdef CLOCK_GATING
|
|
else inst_sz <= inst_sz_nxt;
|
|
`else
|
else if (decode) inst_sz <= inst_sz_nxt;
|
else if (decode) inst_sz <= inst_sz_nxt;
|
|
`endif
|
|
|
|
|
//=============================================================================
|
//=============================================================================
|
// 7) EXECUTION-UNIT STATE MACHINE
|
// 7) EXECUTION-UNIT STATE MACHINE
|
//=============================================================================
|
//=============================================================================
|
Line 716... |
Line 854... |
exec_src_wr ? E_SRC_WR : e_first_state;
|
exec_src_wr ? E_SRC_WR : e_first_state;
|
|
|
E_JUMP : e_state_nxt = e_first_state;
|
E_JUMP : e_state_nxt = e_first_state;
|
E_DST_WR : e_state_nxt = exec_jmp ? E_JUMP : e_first_state;
|
E_DST_WR : e_state_nxt = exec_jmp ? E_JUMP : e_first_state;
|
E_SRC_WR : e_state_nxt = e_first_state;
|
E_SRC_WR : e_state_nxt = e_first_state;
|
|
// pragma coverage off
|
default : e_state_nxt = E_IRQ_0;
|
default : e_state_nxt = E_IRQ_0;
|
|
// pragma coverage on
|
endcase
|
endcase
|
|
|
// State machine
|
// State machine
|
always @(posedge mclk or posedge puc_rst)
|
always @(posedge mclk or posedge puc_rst)
|
if (puc_rst) e_state <= E_IRQ_1;
|
if (puc_rst) e_state <= E_IRQ_1;
|
Line 794... |
Line 934... |
|
|
wire alu_shift = inst_so_nxt[`RRC] | inst_so_nxt[`RRA];
|
wire alu_shift = inst_so_nxt[`RRC] | inst_so_nxt[`RRA];
|
|
|
wire exec_no_wr = inst_to_nxt[`CMP] | inst_to_nxt[`BIT];
|
wire exec_no_wr = inst_to_nxt[`CMP] | inst_to_nxt[`BIT];
|
|
|
always @(posedge mclk or posedge puc_rst)
|
wire [11:0] inst_alu_nxt = {exec_no_wr,
|
if (puc_rst) inst_alu <= 12'h000;
|
|
else if (decode) inst_alu <= {exec_no_wr,
|
|
alu_shift,
|
alu_shift,
|
alu_stat_f,
|
alu_stat_f,
|
alu_stat_7,
|
alu_stat_7,
|
alu_dadd,
|
alu_dadd,
|
alu_xor,
|
alu_xor,
|
Line 809... |
Line 947... |
alu_add,
|
alu_add,
|
alu_inc_c,
|
alu_inc_c,
|
alu_inc,
|
alu_inc,
|
alu_src_inv};
|
alu_src_inv};
|
|
|
|
always @(posedge mclk_decode or posedge puc_rst)
|
|
if (puc_rst) inst_alu <= 12'h000;
|
|
`ifdef CLOCK_GATING
|
|
else inst_alu <= inst_alu_nxt;
|
|
`else
|
|
else if (decode) inst_alu <= inst_alu_nxt;
|
|
`endif
|
|
|
|
|
endmodule // omsp_frontend
|
endmodule // omsp_frontend
|
|
|
`ifdef OMSP_NO_INCLUDE
|
`ifdef OMSP_NO_INCLUDE
|
`else
|
`else
|