////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// XGATE Coprocessor - XGATE RISC Processor Core
|
// XGATE Coprocessor - XGATE RISC Processor Core
|
//
|
//
|
// Author: Bob Hayes
|
// Author: Bob Hayes
|
// rehayes@opencores.org
|
// rehayes@opencores.org
|
//
|
//
|
// Downloaded from: http://www.opencores.org/projects/xgate.....
|
// Downloaded from: http://www.opencores.org/projects/xgate.....
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
// Copyright (c) 2009, Robert Hayes
|
// Copyright (c) 2009, Robert Hayes
|
//
|
//
|
// This source file is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU Lesser General Public License as published
|
// by the Free Software Foundation, either version 3 of the License, or
|
// by the Free Software Foundation, either version 3 of the License, or
|
// (at your option) any later version.
|
// (at your option) any later version.
|
//
|
//
|
// Supplemental terms.
|
// Supplemental terms.
|
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
// * Neither the name of the <organization> nor the
|
// * Neither the name of the <organization> nor the
|
// names of its contributors may be used to endorse or promote products
|
// names of its contributors may be used to endorse or promote products
|
// derived from this software without specific prior written permission.
|
// derived from this software without specific prior written permission.
|
//
|
//
|
// THIS SOFTWARE IS PROVIDED BY Robert Hayes ''AS IS'' AND ANY
|
// THIS SOFTWARE IS PROVIDED BY Robert Hayes ''AS IS'' AND ANY
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
// DISCLAIMED. IN NO EVENT SHALL Robert Hayes BE LIABLE FOR ANY
|
// DISCLAIMED. IN NO EVENT SHALL Robert Hayes BE LIABLE FOR ANY
|
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// 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
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
//
|
//
|
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
|
|
module xgate_risc #(parameter MAX_CHANNEL = 127) // Max XGATE Interrupt Channel Number
|
module xgate_risc #(parameter MAX_CHANNEL = 127) // Max XGATE Interrupt Channel Number
|
(
|
(
|
output reg [15:0] xgr1,
|
output reg [15:0] xgr1,
|
output reg [15:0] xgr2,
|
output reg [15:0] xgr2,
|
output reg [15:0] xgr3,
|
output reg [15:0] xgr3,
|
output reg [15:0] xgr4,
|
output reg [15:0] xgr4,
|
output reg [15:0] xgr5,
|
output reg [15:0] xgr5,
|
output reg [15:0] xgr6,
|
output reg [15:0] xgr6,
|
output reg [15:0] xgr7,
|
output reg [15:0] xgr7,
|
output [15:0] xgate_address,
|
output [15:0] xgate_address,
|
output [15:0] write_mem_data, // Data for Memory write
|
output [15:0] write_mem_data, // Data for Memory write
|
output mem_access, //
|
output mem_access, //
|
output write_mem_strb_l, // Strobe for writing low data byte
|
output write_mem_strb_l, // Strobe for writing low data byte
|
output write_mem_strb_h, // Strobe for writing high data bye
|
output write_mem_strb_h, // Strobe for writing high data bye
|
output reg zero_flag,
|
output reg zero_flag,
|
output reg negative_flag,
|
output reg negative_flag,
|
output reg carry_flag,
|
output reg carry_flag,
|
output reg overflow_flag,
|
output reg overflow_flag,
|
output reg [ 6:0] xgchid,
|
output reg [ 6:0] xgchid,
|
output reg [127:0] xgif_status, // XGATE Interrupt Flag
|
output reg [127:0] xgif_status, // XGATE Interrupt Flag
|
output xg_sw_irq, // Xgate Software interrupt
|
output xg_sw_irq, // Xgate Software interrupt
|
output [ 7:0] host_semap, // Semaphore status for host
|
output [ 7:0] host_semap, // Semaphore status for host
|
output reg debug_active, // Latch to control debug mode in the RISC state machine
|
output reg debug_active, // Latch to control debug mode in the RISC state machine
|
output debug_ack, // Clear debug register
|
output debug_ack, // Clear debug register
|
output single_step, // Pulse to trigger a single instruction execution in debug mode
|
output single_step, // Pulse to trigger a single instruction execution in debug mode
|
|
|
|
|
input [15:0] read_mem_data,
|
input [15:0] read_mem_data,
|
input [15:0] perif_data,
|
input [15:0] perif_data,
|
input risc_clk,
|
input risc_clk,
|
input async_rst_b,
|
input async_rst_b,
|
input mem_req_ack, // Memory Bus available - data good
|
input mem_req_ack, // Memory Bus available - data good
|
input ss_mem_ack, // WISHBONE Bus has granted single step memory access
|
input ss_mem_ack, // WISHBONE Bus has granted single step memory access
|
input xge, // XGATE Module Enable
|
input xge, // XGATE Module Enable
|
input debug_mode_i, // Force RISC core into debug mode
|
input debug_mode_i, // Force RISC core into debug mode
|
input xgdbg_set, // Enter XGATE Debug Mode, pulse
|
input xgdbg_set, // Enter XGATE Debug Mode, pulse
|
input xgdbg_clear, // Leave XGATE Debug Mode
|
input xgdbg_clear, // Leave XGATE Debug Mode
|
input xgss, // XGATE Single Step
|
input xgss, // XGATE Single Step
|
input [15:1] xgvbr, // XGATE vector Base Address Register
|
input [15:1] xgvbr, // XGATE vector Base Address Register
|
input [ 6:0] int_req, // Encoded interrupt request
|
input [ 6:0] int_req, // Encoded interrupt request
|
input xgie, // XGATE Interrupt Enable
|
input xgie, // XGATE Interrupt Enable
|
input brk_irq_ena, // Enable BRK instruction to generate interrupt
|
input brk_irq_ena, // Enable BRK instruction to generate interrupt
|
input write_xgchid, // Write Strobe for XGCHID register
|
input write_xgchid, // Write Strobe for XGCHID register
|
input write_xgsem, // Write Strobe for XGSEM register
|
input write_xgsem, // Write Strobe for XGSEM register
|
input write_xgccr, // Write Strobe for XGATE Condition Code Register
|
input write_xgccr, // Write Strobe for XGATE Condition Code Register
|
input [ 1:0] write_xgpc, // Write Strobe for XGATE Program Counter
|
input [ 1:0] write_xgpc, // Write Strobe for XGATE Program Counter
|
input [ 1:0] write_xgr7, // Write Strobe for XGATE Data Register R7
|
input [ 1:0] write_xgr7, // Write Strobe for XGATE Data Register R7
|
input [ 1:0] write_xgr6, // Write Strobe for XGATE Data Register R6
|
input [ 1:0] write_xgr6, // Write Strobe for XGATE Data Register R6
|
input [ 1:0] write_xgr5, // Write Strobe for XGATE Data Register R5
|
input [ 1:0] write_xgr5, // Write Strobe for XGATE Data Register R5
|
input [ 1:0] write_xgr4, // Write Strobe for XGATE Data Register R4
|
input [ 1:0] write_xgr4, // Write Strobe for XGATE Data Register R4
|
input [ 1:0] write_xgr3, // Write Strobe for XGATE Data Register R3
|
input [ 1:0] write_xgr3, // Write Strobe for XGATE Data Register R3
|
input [ 1:0] write_xgr2, // Write Strobe for XGATE Data Register R2
|
input [ 1:0] write_xgr2, // Write Strobe for XGATE Data Register R2
|
input [ 1:0] write_xgr1, // Write Strobe for XGATE Data Register R1
|
input [ 1:0] write_xgr1, // Write Strobe for XGATE Data Register R1
|
input xgsweif_c, // Clear Software Flag
|
input xgsweif_c, // Clear Software Flag
|
input clear_xgif_7, // Strobe for decode to clear interrupt flag bank 7
|
input clear_xgif_7, // Strobe for decode to clear interrupt flag bank 7
|
input clear_xgif_6, // Strobe for decode to clear interrupt flag bank 6
|
input clear_xgif_6, // Strobe for decode to clear interrupt flag bank 6
|
input clear_xgif_5, // Strobe for decode to clear interrupt flag bank 5
|
input clear_xgif_5, // Strobe for decode to clear interrupt flag bank 5
|
input clear_xgif_4, // Strobe for decode to clear interrupt flag bank 4
|
input clear_xgif_4, // Strobe for decode to clear interrupt flag bank 4
|
input clear_xgif_3, // Strobe for decode to clear interrupt flag bank 3
|
input clear_xgif_3, // Strobe for decode to clear interrupt flag bank 3
|
input clear_xgif_2, // Strobe for decode to clear interrupt flag bank 2
|
input clear_xgif_2, // Strobe for decode to clear interrupt flag bank 2
|
input clear_xgif_1, // Strobe for decode to clear interrupt flag bank 1
|
input clear_xgif_1, // Strobe for decode to clear interrupt flag bank 1
|
input clear_xgif_0, // Strobe for decode to clear interrupt flag bank 0
|
input clear_xgif_0, // Strobe for decode to clear interrupt flag bank 0
|
input [15:0] clear_xgif_data // Data for decode to clear interrupt flag
|
input [15:0] clear_xgif_data // Data for decode to clear interrupt flag
|
);
|
);
|
|
|
integer j; // Loop counters for decode of XGATE Interrupt Register
|
integer j; // Loop counters for decode of XGATE Interrupt Register
|
integer k; // Loop counter for Bit Field Insert decode
|
integer k; // Loop counter for Bit Field Insert decode
|
integer bfi, bfii; // Loop counter for Bit Field Insert function
|
integer bfi, bfii; // Loop counter for Bit Field Insert function
|
|
|
// State machine sequence
|
// State machine sequence
|
parameter [3:0] //synopsys enum state_info
|
parameter [3:0] //synopsys enum state_info
|
IDLE = 4'b0000, // waiting for interrupt
|
IDLE = 4'b0000, // waiting for interrupt
|
CONT = 4'b0001, // Instruction processing state, first state
|
CONT = 4'b0001, // Instruction processing state, first state
|
S_STALL = 4'b0010, // Simple Stall while updating PC after change of flow
|
S_STALL = 4'b0010, // Simple Stall while updating PC after change of flow
|
W_STORE = 4'b1101, // Stall while doing memory word write access
|
W_STORE = 4'b1101, // Stall while doing memory word write access
|
W_LOAD = 4'b0011, // Stall while doing memory word read access
|
W_LOAD = 4'b0011, // Stall while doing memory word read access
|
B_LOAD = 4'b0100, // Stall while doing memory byte read access
|
B_LOAD = 4'b0100, // Stall while doing memory byte read access
|
BREAK = 4'b0101, // Stop in this state after BRK instruction
|
BREAK = 4'b0101, // Stop in this state after BRK instruction
|
BREAK_2 = 4'b0110, // Advance PC after Single Step command
|
BREAK_2 = 4'b0110, // Advance PC after Single Step command
|
LD_INST = 4'b0111, // Load Instruction in Debug mode
|
LD_INST = 4'b0111, // Load Instruction in Debug mode
|
DEBUG = 4'b1000, // Stop in this state while waiting for debug commands
|
DEBUG = 4'b1000, // Stop in this state while waiting for debug commands
|
BOOT_1 = 4'b1001, //
|
BOOT_1 = 4'b1001, //
|
BOOT_2 = 4'b1010, //
|
BOOT_2 = 4'b1010, //
|
BOOT_3 = 4'b1011, //
|
BOOT_3 = 4'b1011, //
|
CHG_CHID = 4'b1100;
|
CHG_CHID = 4'b1100;
|
|
|
|
|
// Semaphore states
|
// Semaphore states
|
parameter [1:0] NO_LOCK = 2'b00,
|
parameter [1:0] NO_LOCK = 2'b00,
|
RISC_LOCK = 2'b10,
|
RISC_LOCK = 2'b10,
|
HOST_LOCK = 2'b11;
|
HOST_LOCK = 2'b11;
|
|
|
|
|
reg [ 3:0] cpu_state; // State register for instruction processing
|
reg [ 3:0] cpu_state; // State register for instruction processing
|
reg [ 3:0] next_cpu_state; // Pseudo Register,
|
reg [ 3:0] next_cpu_state; // Pseudo Register,
|
wire stm_auto_advance; // State Machine increment without wait state holdoff
|
wire stm_auto_advance; // State Machine increment without wait state holdoff
|
reg load_next_inst; // Pseudo Register,
|
reg load_next_inst; // Pseudo Register,
|
reg [15:0] program_counter; // Program Counter register
|
reg [15:0] program_counter; // Program Counter register
|
wire [15:0] pc_sum; // Program Counter Adder
|
wire [15:0] pc_sum; // Program Counter Adder
|
reg [15:0] pc_incr_mux; // Pseudo Register, mux to select the Program Counter Increment value
|
reg [15:0] pc_incr_mux; // Pseudo Register, mux to select the Program Counter Increment value
|
reg [15:0] next_pc; // Pseudo Register
|
reg [15:0] next_pc; // Pseudo Register
|
wire [15:0] jump_offset; // Address offset to be added to pc on conditional branch instruction
|
wire [15:0] jump_offset; // Address offset to be added to pc on conditional branch instruction
|
wire [15:0] bra_offset; // Address offset to be added to pc on branch always instruction
|
wire [15:0] bra_offset; // Address offset to be added to pc on branch always instruction
|
reg [15:0] alu_result; // Pseudo Register,
|
reg [15:0] alu_result; // Pseudo Register,
|
reg [15:0] op_code; // Register for instruction being executed
|
reg [15:0] op_code; // Register for instruction being executed
|
reg ena_rd_low_byte; // Pseudo Register,
|
reg ena_rd_low_byte; // Pseudo Register,
|
reg ena_rd_high_byte; // Pseudo Register,
|
reg ena_rd_high_byte; // Pseudo Register,
|
|
|
reg data_access; // Pseudo Register, RAM access in proccess
|
reg data_access; // Pseudo Register, RAM access in proccess
|
reg data_write; // Pseudo Register, RAM access is write operation
|
reg data_write; // Pseudo Register, RAM access is write operation
|
reg data_word_op; // Pseudo Register, RAM access operation is 16 bits(word)
|
reg data_word_op; // Pseudo Register, RAM access operation is 16 bits(word)
|
reg [15:0] data_address; // Pseudo Register, Address for RAM data read or write
|
reg [15:0] data_address; // Pseudo Register, Address for RAM data read or write
|
reg [15:0] load_data; // Data captured from WISHBONE Master bus for Load instructions
|
reg [15:0] load_data; // Data captured from WISHBONE Master bus for Load instructions
|
|
|
reg [ 6:0] set_irq_flag; // Pseudo Register, pulse for setting irq output register
|
reg [ 6:0] set_irq_flag; // Pseudo Register, pulse for setting irq output register
|
|
|
reg next_zero; // Pseudo Register,
|
reg next_zero; // Pseudo Register,
|
reg next_negative; // Pseudo Register,
|
reg next_negative; // Pseudo Register,
|
reg next_carry; // Pseudo Register,
|
reg next_carry; // Pseudo Register,
|
reg next_overflow; // Pseudo Register,
|
reg next_overflow; // Pseudo Register,
|
|
|
reg op_code_error; // Pseudo Register,
|
reg op_code_error; // Pseudo Register,
|
reg software_error; // OP Code error, Address Error, BRK Error
|
reg software_error; // OP Code error, Address Error, BRK Error
|
wire addr_error; // Decode Addressing error
|
wire addr_error; // Decode Addressing error
|
|
|
reg set_semaph; // Pseudo Register,
|
reg set_semaph; // Pseudo Register,
|
reg clear_semaph; // Pseudo Register,
|
reg clear_semaph; // Pseudo Register,
|
reg [ 2:0] semaph_risc; // Pseudo Register,
|
reg [ 2:0] semaph_risc; // Pseudo Register,
|
reg [ 7:0] semap_risc_bit; // Pseudo Register,
|
reg [ 7:0] semap_risc_bit; // Pseudo Register,
|
wire [ 7:0] risc_semap; // Semaphore status bit for RISC
|
wire [ 7:0] risc_semap; // Semaphore status bit for RISC
|
wire semaph_stat; // Return Status of Semaphore bit
|
wire semaph_stat; // Return Status of Semaphore bit
|
|
|
reg [15:0] rd_data; // Pseudo Register,
|
reg [15:0] rd_data; // Pseudo Register,
|
reg [15:0] rs1_data; // Pseudo Register,
|
reg [15:0] rs1_data; // Pseudo Register,
|
reg [15:0] rs2_data; // Pseudo Register,
|
reg [15:0] rs2_data; // Pseudo Register,
|
|
|
wire [ 2:0] wrt_reg_sel;
|
wire [ 2:0] wrt_reg_sel;
|
reg sel_rd_field; // Pseudo Register,
|
reg sel_rd_field; // Pseudo Register,
|
reg wrt_sel_xgr1; // Pseudo Register,
|
reg wrt_sel_xgr1; // Pseudo Register,
|
reg wrt_sel_xgr2; // Pseudo Register,
|
reg wrt_sel_xgr2; // Pseudo Register,
|
reg wrt_sel_xgr3; // Pseudo Register,
|
reg wrt_sel_xgr3; // Pseudo Register,
|
reg wrt_sel_xgr4; // Pseudo Register,
|
reg wrt_sel_xgr4; // Pseudo Register,
|
reg wrt_sel_xgr5; // Pseudo Register,
|
reg wrt_sel_xgr5; // Pseudo Register,
|
reg wrt_sel_xgr6; // Pseudo Register,
|
reg wrt_sel_xgr6; // Pseudo Register,
|
reg wrt_sel_xgr7; // Pseudo Register,
|
reg wrt_sel_xgr7; // Pseudo Register,
|
|
|
reg [127:0] xgif_d;
|
reg [127:0] xgif_d;
|
|
|
reg [15:0] shift_in;
|
reg [15:0] shift_in;
|
wire [15:0] shift_out;
|
wire [15:0] shift_out;
|
wire shift_rollover;
|
wire shift_rollover;
|
reg shift_left;
|
reg shift_left;
|
reg [ 4:0] shift_ammount;
|
reg [ 4:0] shift_ammount;
|
reg [15:0] shift_filler;
|
reg [15:0] shift_filler;
|
reg [15:0] bf_mux_mask; // Mask for controlling mux's in Bit Field Insert Instructions
|
reg [15:0] bf_mux_mask; // Mask for controlling mux's in Bit Field Insert Instructions
|
|
|
wire start_thread; // Signal to pop RISC core out of IDLE State
|
wire start_thread; // Signal to pop RISC core out of IDLE State
|
|
|
wire cpu_is_idle; // Processor is in the IDLE state
|
wire cpu_is_idle; // Processor is in the IDLE state
|
wire perif_wrt_ena; // Enable for Salve writes to CPU registers
|
wire perif_wrt_ena; // Enable for Salve writes to CPU registers
|
|
|
reg xgss_edge; // Flop for edge detection
|
reg xgss_edge; // Flop for edge detection
|
reg brk_set_dbg; // Pulse to set debug_active from instruction decoder
|
reg brk_set_dbg; // Pulse to set debug_active from instruction decoder
|
reg cmd_change_pc; // Debug write to PC register
|
reg cmd_change_pc; // Debug write to PC register
|
reg debug_edge; // Reg for edge detection
|
reg debug_edge; // Reg for edge detection
|
|
|
reg cmd_dbg;
|
reg cmd_dbg;
|
|
|
reg [ 1:0] chid_sm_ns; // Pseudo Register for State Machine next state logic,
|
reg [ 1:0] chid_sm_ns; // Pseudo Register for State Machine next state logic,
|
reg [ 1:0] chid_sm; //
|
reg [ 1:0] chid_sm; //
|
wire chid_goto_idle; //
|
wire chid_goto_idle; //
|
|
|
// Debug states for change CHID
|
// Debug states for change CHID
|
parameter [1:0] CHID_IDLE = 2'b00,
|
parameter [1:0] CHID_IDLE = 2'b00,
|
CHID_TEST = 2'b10,
|
CHID_TEST = 2'b10,
|
CHID_WAIT = 2'b11;
|
CHID_WAIT = 2'b11;
|
|
|
|
|
assign jump_offset = {{6{op_code[8]}}, op_code[8:0], 1'b0};
|
assign jump_offset = {{6{op_code[8]}}, op_code[8:0], 1'b0};
|
assign bra_offset = {{5{op_code[9]}}, op_code[9:0], 1'b0};
|
assign bra_offset = {{5{op_code[9]}}, op_code[9:0], 1'b0};
|
assign pc_sum = program_counter + pc_incr_mux;
|
assign pc_sum = program_counter + pc_incr_mux;
|
|
|
assign xgate_address = data_access ? data_address : program_counter;
|
assign xgate_address = data_access ? data_address : program_counter;
|
|
|
//assign mem_access = data_access || load_next_inst || start_thread;
|
//assign mem_access = data_access || load_next_inst || start_thread;
|
assign mem_access = data_access || load_next_inst || (cpu_state == CONT) ||
|
assign mem_access = data_access || load_next_inst || (cpu_state == CONT) ||
|
(cpu_state == BREAK_2) || start_thread;
|
(cpu_state == BREAK_2) || start_thread;
|
|
|
// Generate an address for an op code fetch from an odd address or a word Load/Store from/to an odd address.
|
// Generate an address for an op code fetch from an odd address or a word Load/Store from/to an odd address.
|
assign addr_error = xgate_address[0] && (load_next_inst || (data_access && data_word_op));
|
assign addr_error = xgate_address[0] && (load_next_inst || (data_access && data_word_op));
|
|
|
assign write_mem_strb_l = data_access && data_write && (data_word_op || !data_address[0]);
|
assign write_mem_strb_l = data_access && data_write && (data_word_op || !data_address[0]);
|
assign write_mem_strb_h = data_access && data_write && (data_word_op || data_address[0]);
|
assign write_mem_strb_h = data_access && data_write && (data_word_op || data_address[0]);
|
assign write_mem_data = (write_mem_strb_l || write_mem_strb_h) ? rd_data : 16'b0;
|
assign write_mem_data = (write_mem_strb_l || write_mem_strb_h) ? rd_data : 16'b0;
|
|
|
assign start_thread = xge && (|int_req) && !debug_active;
|
assign start_thread = xge && (|int_req) && !debug_active;
|
|
|
assign cpu_is_idle = (cpu_state == IDLE);
|
assign cpu_is_idle = (cpu_state == IDLE);
|
assign perif_wrt_ena = (cpu_is_idle && ~xge) || debug_active;
|
assign perif_wrt_ena = (cpu_is_idle && ~xge) || debug_active;
|
|
|
// Decode register select for RD and RS
|
// Decode register select for RD and RS
|
always @*
|
always @*
|
begin
|
begin
|
case (op_code[10:8]) // synopsys parallel_case
|
case (op_code[10:8]) // synopsys parallel_case
|
3'b001 : rd_data = xgr1;
|
3'b001 : rd_data = xgr1;
|
3'b010 : rd_data = xgr2;
|
3'b010 : rd_data = xgr2;
|
3'b011 : rd_data = xgr3;
|
3'b011 : rd_data = xgr3;
|
3'b100 : rd_data = xgr4;
|
3'b100 : rd_data = xgr4;
|
3'b101 : rd_data = xgr5;
|
3'b101 : rd_data = xgr5;
|
3'b110 : rd_data = xgr6;
|
3'b110 : rd_data = xgr6;
|
3'b111 : rd_data = xgr7;
|
3'b111 : rd_data = xgr7;
|
default : rd_data = 16'h0; // XGR0 is always Zero
|
default : rd_data = 16'h0; // XGR0 is always Zero
|
endcase
|
endcase
|
end
|
end
|
|
|
assign wrt_reg_sel = (cpu_state == BOOT_3) ? 3'b001 :
|
assign wrt_reg_sel = (cpu_state == BOOT_3) ? 3'b001 :
|
(sel_rd_field ? op_code[10:8] : op_code[4:2]);
|
(sel_rd_field ? op_code[10:8] : op_code[4:2]);
|
|
|
// Decode register write select for eather RD or RI/RS2
|
// Decode register write select for eather RD or RI/RS2
|
always @*
|
always @*
|
begin
|
begin
|
wrt_sel_xgr1 = (wrt_reg_sel == 3'b001) && mem_req_ack;
|
wrt_sel_xgr1 = (wrt_reg_sel == 3'b001) && mem_req_ack;
|
wrt_sel_xgr2 = (wrt_reg_sel == 3'b010) && mem_req_ack;
|
wrt_sel_xgr2 = (wrt_reg_sel == 3'b010) && mem_req_ack;
|
wrt_sel_xgr3 = (wrt_reg_sel == 3'b011) && mem_req_ack;
|
wrt_sel_xgr3 = (wrt_reg_sel == 3'b011) && mem_req_ack;
|
wrt_sel_xgr4 = (wrt_reg_sel == 3'b100) && mem_req_ack;
|
wrt_sel_xgr4 = (wrt_reg_sel == 3'b100) && mem_req_ack;
|
wrt_sel_xgr5 = (wrt_reg_sel == 3'b101) && mem_req_ack;
|
wrt_sel_xgr5 = (wrt_reg_sel == 3'b101) && mem_req_ack;
|
wrt_sel_xgr6 = (wrt_reg_sel == 3'b110) && mem_req_ack;
|
wrt_sel_xgr6 = (wrt_reg_sel == 3'b110) && mem_req_ack;
|
wrt_sel_xgr7 = (wrt_reg_sel == 3'b111) && mem_req_ack;
|
wrt_sel_xgr7 = (wrt_reg_sel == 3'b111) && mem_req_ack;
|
end
|
end
|
|
|
// Decode register select for RS1 and RB
|
// Decode register select for RS1 and RB
|
always @*
|
always @*
|
case (op_code[7:5]) // synopsys parallel_case
|
case (op_code[7:5]) // synopsys parallel_case
|
3'b001 : rs1_data = xgr1;
|
3'b001 : rs1_data = xgr1;
|
3'b010 : rs1_data = xgr2;
|
3'b010 : rs1_data = xgr2;
|
3'b011 : rs1_data = xgr3;
|
3'b011 : rs1_data = xgr3;
|
3'b100 : rs1_data = xgr4;
|
3'b100 : rs1_data = xgr4;
|
3'b101 : rs1_data = xgr5;
|
3'b101 : rs1_data = xgr5;
|
3'b110 : rs1_data = xgr6;
|
3'b110 : rs1_data = xgr6;
|
3'b111 : rs1_data = xgr7;
|
3'b111 : rs1_data = xgr7;
|
default : rs1_data = 16'h0; // XGR0 is always Zero
|
default : rs1_data = 16'h0; // XGR0 is always Zero
|
endcase
|
endcase
|
|
|
// Decode register select for RS2 and RI
|
// Decode register select for RS2 and RI
|
always @*
|
always @*
|
case (op_code[4:2]) // synopsys parallel_case
|
case (op_code[4:2]) // synopsys parallel_case
|
3'b001 : rs2_data = xgr1;
|
3'b001 : rs2_data = xgr1;
|
3'b010 : rs2_data = xgr2;
|
3'b010 : rs2_data = xgr2;
|
3'b011 : rs2_data = xgr3;
|
3'b011 : rs2_data = xgr3;
|
3'b100 : rs2_data = xgr4;
|
3'b100 : rs2_data = xgr4;
|
3'b101 : rs2_data = xgr5;
|
3'b101 : rs2_data = xgr5;
|
3'b110 : rs2_data = xgr6;
|
3'b110 : rs2_data = xgr6;
|
3'b111 : rs2_data = xgr7;
|
3'b111 : rs2_data = xgr7;
|
default : rs2_data = 16'h0; // XGR0 is always Zero
|
default : rs2_data = 16'h0; // XGR0 is always Zero
|
endcase
|
endcase
|
|
|
// Decode mux select mask for Bit Field Insert Instructions
|
// Decode mux select mask for Bit Field Insert Instructions
|
always @*
|
always @*
|
begin
|
begin
|
k = 0;
|
k = 0;
|
while (k < 16)
|
while (k < 16)
|
begin
|
begin
|
bf_mux_mask[k] = 1'b0;
|
bf_mux_mask[k] = 1'b0;
|
if ((k >= rs2_data[3:0]) && (k <= rs2_data[3:0] + rs2_data[7:4]))
|
if ((k >= rs2_data[3:0]) && (k <= rs2_data[3:0] + rs2_data[7:4]))
|
bf_mux_mask[k] = 1'b1;
|
bf_mux_mask[k] = 1'b1;
|
k = k + 1;
|
k = k + 1;
|
end
|
end
|
end
|
end
|
|
|
// Software Error Interrupt Latch
|
// Software Error Interrupt Latch
|
always @(posedge risc_clk or negedge async_rst_b)
|
always @(posedge risc_clk or negedge async_rst_b)
|
if ( !async_rst_b )
|
if ( !async_rst_b )
|
software_error <= 1'b0;
|
software_error <= 1'b0;
|
else
|
else
|
software_error <= addr_error || op_code_error ||
|
software_error <= addr_error || op_code_error ||
|
(brk_set_dbg && brk_irq_ena) || (software_error && !xgsweif_c);
|
(brk_set_dbg && brk_irq_ena) || (software_error && !xgsweif_c);
|
|
|
assign xg_sw_irq = software_error && xgie;
|
assign xg_sw_irq = software_error && xgie;
|
|
|
// Latch the need to go to debug state set by xgdb
|
// Latch the need to go to debug state set by xgdb
|
always @(posedge risc_clk or negedge async_rst_b)
|
always @(posedge risc_clk or negedge async_rst_b)
|
if ( !async_rst_b )
|
if ( !async_rst_b )
|
begin
|
begin
|
cmd_dbg <= 1'b0;
|
cmd_dbg <= 1'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
cmd_dbg <= !((cpu_state == LD_INST) || (cpu_state == DEBUG)) &&
|
cmd_dbg <= !((cpu_state == LD_INST) || (cpu_state == DEBUG)) &&
|
(cmd_dbg || (xgdbg_set && mem_req_ack && (next_cpu_state == CONT)));
|
(cmd_dbg || (xgdbg_set && mem_req_ack && (next_cpu_state == CONT)));
|
end
|
end
|
|
|
// Latch the debug state, set by eather xgdb or BRK instructions
|
// Latch the debug state, set by eather xgdb or BRK instructions
|
always @(posedge risc_clk or negedge async_rst_b)
|
always @(posedge risc_clk or negedge async_rst_b)
|
if ( !async_rst_b )
|
if ( !async_rst_b )
|
begin
|
begin
|
debug_active <= 1'b0;
|
debug_active <= 1'b0;
|
debug_edge <= 0;
|
debug_edge <= 0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
debug_active <= !xgdbg_clear && (cmd_dbg ||
|
debug_active <= !xgdbg_clear && (cmd_dbg ||
|
brk_set_dbg || op_code_error || debug_active);
|
brk_set_dbg || op_code_error || debug_active);
|
debug_edge <= debug_active;
|
debug_edge <= debug_active;
|
end
|
end
|
|
|
assign debug_ack = debug_active && !debug_edge; // Posedge of debug_active
|
assign debug_ack = debug_active && !debug_edge; // Posedge of debug_active
|
|
|
// Convert xgss (Single Step Pulse) to a one risc_clk wide pulse
|
// Convert xgss (Single Step Pulse) to a one risc_clk wide pulse
|
always @(posedge risc_clk or negedge async_rst_b)
|
always @(posedge risc_clk or negedge async_rst_b)
|
if ( !async_rst_b )
|
if ( !async_rst_b )
|
xgss_edge <= 1'b0;
|
xgss_edge <= 1'b0;
|
else
|
else
|
xgss_edge <= xgss;
|
xgss_edge <= xgss;
|
|
|
assign single_step = (xgss && !xgss_edge) || (!debug_active && debug_edge);
|
assign single_step = (xgss && !xgss_edge) || (!debug_active && debug_edge);
|
|
|
assign stm_auto_advance = (chid_sm != CHID_IDLE);
|
assign stm_auto_advance = (chid_sm != CHID_IDLE);
|
|
|
// CPU State Register
|
// CPU State Register
|
always @(posedge risc_clk or negedge async_rst_b)
|
always @(posedge risc_clk or negedge async_rst_b)
|
if ( !async_rst_b )
|
if ( !async_rst_b )
|
cpu_state <= IDLE;
|
cpu_state <= IDLE;
|
else
|
else
|
cpu_state <= (mem_req_ack || stm_auto_advance) ? next_cpu_state : cpu_state;
|
cpu_state <= (mem_req_ack || stm_auto_advance) ? next_cpu_state : cpu_state;
|
|
|
// CPU Instruction Register
|
// CPU Instruction Register
|
always @(posedge risc_clk or negedge async_rst_b)
|
always @(posedge risc_clk or negedge async_rst_b)
|
if ( !async_rst_b )
|
if ( !async_rst_b )
|
op_code <= 16'h0000;
|
op_code <= 16'h0000;
|
else
|
else
|
op_code <= (load_next_inst && mem_req_ack) ? read_mem_data : op_code;
|
op_code <= (load_next_inst && mem_req_ack) ? read_mem_data : op_code;
|
|
|
// Active Channel Latch
|
// Active Channel Latch
|
always @(posedge risc_clk or negedge async_rst_b)
|
always @(posedge risc_clk or negedge async_rst_b)
|
if ( !async_rst_b )
|
if ( !async_rst_b )
|
xgchid <= 7'b0;
|
xgchid <= 7'b0;
|
else
|
else
|
xgchid <= (write_xgchid && debug_active) ? perif_data[6:0] : (cpu_is_idle ? int_req : xgchid);
|
xgchid <= (write_xgchid && debug_active) ? perif_data[6:0] : (cpu_is_idle ? int_req : xgchid);
|
|
|
// Channel Change Debug state machine register
|
// Channel Change Debug state machine register
|
always @(posedge risc_clk or negedge async_rst_b)
|
always @(posedge risc_clk or negedge async_rst_b)
|
if ( !async_rst_b )
|
if ( !async_rst_b )
|
chid_sm <= CHID_IDLE;
|
chid_sm <= CHID_IDLE;
|
else
|
else
|
chid_sm <= chid_sm_ns;
|
chid_sm <= chid_sm_ns;
|
|
|
// Channel Change Debug next state
|
// Channel Change Debug next state
|
always @*
|
always @*
|
case (chid_sm) // synopsys parallel_case
|
case (chid_sm) // synopsys parallel_case
|
CHID_IDLE:
|
CHID_IDLE:
|
if ( write_xgchid && debug_active )
|
if ( write_xgchid && debug_active )
|
chid_sm_ns = CHID_TEST;
|
chid_sm_ns = CHID_TEST;
|
CHID_TEST:
|
CHID_TEST:
|
if ( !((cpu_state == IDLE) || (cpu_state == CHG_CHID)) && (|xgchid) )
|
if ( !((cpu_state == IDLE) || (cpu_state == CHG_CHID)) && (|xgchid) )
|
chid_sm_ns = CHID_IDLE;
|
chid_sm_ns = CHID_IDLE;
|
else
|
else
|
chid_sm_ns = CHID_WAIT;
|
chid_sm_ns = CHID_WAIT;
|
CHID_WAIT:
|
CHID_WAIT:
|
if ( (cpu_state == IDLE) || (cpu_state == CHG_CHID) )
|
if ( (cpu_state == IDLE) || (cpu_state == CHG_CHID) )
|
chid_sm_ns = CHID_IDLE;
|
chid_sm_ns = CHID_IDLE;
|
else
|
else
|
chid_sm_ns = CHID_WAIT;
|
chid_sm_ns = CHID_WAIT;
|
default : chid_sm_ns = CHID_IDLE;
|
default : chid_sm_ns = CHID_IDLE;
|
endcase
|
endcase
|
|
|
assign chid_goto_idle = (chid_sm == CHID_WAIT);
|
assign chid_goto_idle = (chid_sm == CHID_WAIT);
|
|
|
// CPU Read Data Buffer Register
|
// CPU Read Data Buffer Register
|
always @(posedge risc_clk or negedge async_rst_b)
|
always @(posedge risc_clk or negedge async_rst_b)
|
if ( !async_rst_b )
|
if ( !async_rst_b )
|
load_data <= 16'h0000;
|
load_data <= 16'h0000;
|
else
|
else
|
load_data <= (data_access && !data_write && mem_req_ack) ? read_mem_data : load_data;
|
load_data <= (data_access && !data_write && mem_req_ack) ? read_mem_data : load_data;
|
|
|
// Program Counter Register
|
// Program Counter Register
|
always @(posedge risc_clk or negedge async_rst_b)
|
always @(posedge risc_clk or negedge async_rst_b)
|
if ( !async_rst_b )
|
if ( !async_rst_b )
|
program_counter <= 16'h0000;
|
program_counter <= 16'h0000;
|
else
|
else
|
program_counter <= (|write_xgpc && perif_wrt_ena) ?
|
program_counter <= (|write_xgpc && perif_wrt_ena) ?
|
{(write_xgpc[1] ? perif_data[15:8]: program_counter[15:8]),
|
{(write_xgpc[1] ? perif_data[15:8]: program_counter[15:8]),
|
(write_xgpc[0] ? perif_data[ 7:0]: program_counter[ 7:0])} :
|
(write_xgpc[0] ? perif_data[ 7:0]: program_counter[ 7:0])} :
|
(mem_req_ack ? next_pc : program_counter);
|
(mem_req_ack ? next_pc : program_counter);
|
|
|
// Debug Change Program Counter Register
|
// Debug Change Program Counter Register
|
always @(posedge risc_clk or negedge async_rst_b)
|
always @(posedge risc_clk or negedge async_rst_b)
|
if ( !async_rst_b )
|
if ( !async_rst_b )
|
cmd_change_pc <= 1'b0;
|
cmd_change_pc <= 1'b0;
|
else
|
else
|
cmd_change_pc <= (|write_xgpc && perif_wrt_ena) || (cmd_change_pc && !mem_req_ack);
|
cmd_change_pc <= (|write_xgpc && perif_wrt_ena) || (cmd_change_pc && !mem_req_ack);
|
|
|
// ALU Flag Bits
|
// ALU Flag Bits
|
always @(posedge risc_clk or negedge async_rst_b)
|
always @(posedge risc_clk or negedge async_rst_b)
|
if ( !async_rst_b )
|
if ( !async_rst_b )
|
begin
|
begin
|
carry_flag <= 1'b0;
|
carry_flag <= 1'b0;
|
overflow_flag <= 1'b0;
|
overflow_flag <= 1'b0;
|
zero_flag <= 1'b0;
|
zero_flag <= 1'b0;
|
negative_flag <= 1'b0;
|
negative_flag <= 1'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
carry_flag <= (write_xgccr && perif_wrt_ena) ? perif_data[0] : (mem_req_ack ? next_carry : carry_flag);
|
carry_flag <= (write_xgccr && perif_wrt_ena) ? perif_data[0] : (mem_req_ack ? next_carry : carry_flag);
|
overflow_flag <= (write_xgccr && perif_wrt_ena) ? perif_data[1] : (mem_req_ack ? next_overflow : overflow_flag);
|
overflow_flag <= (write_xgccr && perif_wrt_ena) ? perif_data[1] : (mem_req_ack ? next_overflow : overflow_flag);
|
zero_flag <= (write_xgccr && perif_wrt_ena) ? perif_data[2] : (mem_req_ack ? next_zero : zero_flag);
|
zero_flag <= (write_xgccr && perif_wrt_ena) ? perif_data[2] : (mem_req_ack ? next_zero : zero_flag);
|
negative_flag <= (write_xgccr && perif_wrt_ena) ? perif_data[3] : (mem_req_ack ? next_negative : negative_flag);
|
negative_flag <= (write_xgccr && perif_wrt_ena) ? perif_data[3] : (mem_req_ack ? next_negative : negative_flag);
|
end
|
end
|
|
|
// Interrupt Flag next value
|
// Interrupt Flag next value
|
always @*
|
always @*
|
begin
|
begin
|
xgif_d = 0;
|
xgif_d = 0;
|
j = 0;
|
j = 0;
|
while (j <= MAX_CHANNEL)
|
while (j <= MAX_CHANNEL)
|
begin
|
begin
|
xgif_d[j] = xgif_status[j] || (set_irq_flag == j);
|
xgif_d[j] = xgif_status[j] || (set_irq_flag == j);
|
j = j + 1;
|
j = j + 1;
|
end
|
end
|
if (clear_xgif_0)
|
if (clear_xgif_0)
|
xgif_d[15: 0] = ~clear_xgif_data & xgif_status[15: 0];
|
xgif_d[15: 0] = ~clear_xgif_data & xgif_status[15: 0];
|
if (clear_xgif_1)
|
if (clear_xgif_1)
|
xgif_d[31:16] = ~clear_xgif_data & xgif_status[31:16];
|
xgif_d[31:16] = ~clear_xgif_data & xgif_status[31:16];
|
if (clear_xgif_2)
|
if (clear_xgif_2)
|
xgif_d[47:32] = ~clear_xgif_data & xgif_status[47:32];
|
xgif_d[47:32] = ~clear_xgif_data & xgif_status[47:32];
|
if (clear_xgif_3)
|
if (clear_xgif_3)
|
xgif_d[63:48] = ~clear_xgif_data & xgif_status[63:48];
|
xgif_d[63:48] = ~clear_xgif_data & xgif_status[63:48];
|
if (clear_xgif_4)
|
if (clear_xgif_4)
|
xgif_d[79:64] = ~clear_xgif_data & xgif_status[79:64];
|
xgif_d[79:64] = ~clear_xgif_data & xgif_status[79:64];
|
if (clear_xgif_5)
|
if (clear_xgif_5)
|
xgif_d[95:80] = ~clear_xgif_data & xgif_status[95:80];
|
xgif_d[95:80] = ~clear_xgif_data & xgif_status[95:80];
|
if (clear_xgif_6)
|
if (clear_xgif_6)
|
xgif_d[111:96] = ~clear_xgif_data & xgif_status[111:96];
|
xgif_d[111:96] = ~clear_xgif_data & xgif_status[111:96];
|
if (clear_xgif_7)
|
if (clear_xgif_7)
|
xgif_d[127:112] = ~clear_xgif_data & xgif_status[127:112];
|
xgif_d[127:112] = ~clear_xgif_data & xgif_status[127:112];
|
end
|
end
|
|
|
// Interrupt Flag Registers
|
// Interrupt Flag Registers
|
always @(posedge risc_clk or negedge async_rst_b)
|
always @(posedge risc_clk or negedge async_rst_b)
|
if ( !async_rst_b )
|
if ( !async_rst_b )
|
xgif_status <= 0;
|
xgif_status <= 0;
|
else
|
else
|
xgif_status <= xgif_d;
|
xgif_status <= xgif_d;
|
|
|
|
|
// RISC Data Registers
|
// RISC Data Registers
|
always @(posedge risc_clk or negedge async_rst_b)
|
always @(posedge risc_clk or negedge async_rst_b)
|
if ( !async_rst_b )
|
if ( !async_rst_b )
|
begin
|
begin
|
xgr1 <= 16'b0;
|
xgr1 <= 16'b0;
|
xgr2 <= 16'b0;
|
xgr2 <= 16'b0;
|
xgr3 <= 16'b0;
|
xgr3 <= 16'b0;
|
xgr4 <= 16'b0;
|
xgr4 <= 16'b0;
|
xgr5 <= 16'b0;
|
xgr5 <= 16'b0;
|
xgr6 <= 16'b0;
|
xgr6 <= 16'b0;
|
xgr7 <= 16'b0;
|
xgr7 <= 16'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
xgr1 <= (|write_xgr1 && perif_wrt_ena) ?
|
xgr1 <= (|write_xgr1 && perif_wrt_ena) ?
|
{(write_xgr1[1] ? perif_data[15:8]: xgr1[15:8]),
|
{(write_xgr1[1] ? perif_data[15:8]: xgr1[15:8]),
|
(write_xgr1[0] ? perif_data[ 7:0]: xgr1[ 7:0])} :
|
(write_xgr1[0] ? perif_data[ 7:0]: xgr1[ 7:0])} :
|
{((wrt_sel_xgr1 && ena_rd_high_byte) ? alu_result[15:8] : xgr1[15:8]),
|
{((wrt_sel_xgr1 && ena_rd_high_byte) ? alu_result[15:8] : xgr1[15:8]),
|
((wrt_sel_xgr1 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr1[ 7:0])};
|
((wrt_sel_xgr1 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr1[ 7:0])};
|
xgr2 <= (|write_xgr2 && perif_wrt_ena) ?
|
xgr2 <= (|write_xgr2 && perif_wrt_ena) ?
|
{(write_xgr2[1] ? perif_data[15:8]: xgr2[15:8]),
|
{(write_xgr2[1] ? perif_data[15:8]: xgr2[15:8]),
|
(write_xgr2[0] ? perif_data[ 7:0]: xgr2[ 7:0])} :
|
(write_xgr2[0] ? perif_data[ 7:0]: xgr2[ 7:0])} :
|
{((wrt_sel_xgr2 && ena_rd_high_byte) ? alu_result[15:8] : xgr2[15:8]),
|
{((wrt_sel_xgr2 && ena_rd_high_byte) ? alu_result[15:8] : xgr2[15:8]),
|
((wrt_sel_xgr2 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr2[ 7:0])};
|
((wrt_sel_xgr2 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr2[ 7:0])};
|
xgr3 <= (|write_xgr3 && perif_wrt_ena) ?
|
xgr3 <= (|write_xgr3 && perif_wrt_ena) ?
|
{(write_xgr3[1] ? perif_data[15:8]: xgr3[15:8]),
|
{(write_xgr3[1] ? perif_data[15:8]: xgr3[15:8]),
|
(write_xgr3[0] ? perif_data[ 7:0]: xgr3[ 7:0])} :
|
(write_xgr3[0] ? perif_data[ 7:0]: xgr3[ 7:0])} :
|
{((wrt_sel_xgr3 && ena_rd_high_byte) ? alu_result[15:8] : xgr3[15:8]),
|
{((wrt_sel_xgr3 && ena_rd_high_byte) ? alu_result[15:8] : xgr3[15:8]),
|
((wrt_sel_xgr3 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr3[ 7:0])};
|
((wrt_sel_xgr3 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr3[ 7:0])};
|
xgr4 <= (|write_xgr4 && perif_wrt_ena) ?
|
xgr4 <= (|write_xgr4 && perif_wrt_ena) ?
|
{(write_xgr4[1] ? perif_data[15:8]: xgr4[15:8]),
|
{(write_xgr4[1] ? perif_data[15:8]: xgr4[15:8]),
|
(write_xgr4[0] ? perif_data[ 7:0]: xgr4[ 7:0])} :
|
(write_xgr4[0] ? perif_data[ 7:0]: xgr4[ 7:0])} :
|
{((wrt_sel_xgr4 && ena_rd_high_byte) ? alu_result[15:8] : xgr4[15:8]),
|
{((wrt_sel_xgr4 && ena_rd_high_byte) ? alu_result[15:8] : xgr4[15:8]),
|
((wrt_sel_xgr4 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr4[ 7:0])};
|
((wrt_sel_xgr4 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr4[ 7:0])};
|
xgr5 <= (|write_xgr5 && perif_wrt_ena) ?
|
xgr5 <= (|write_xgr5 && perif_wrt_ena) ?
|
{(write_xgr5[1] ? perif_data[15:8]: xgr5[15:8]),
|
{(write_xgr5[1] ? perif_data[15:8]: xgr5[15:8]),
|
(write_xgr5[0] ? perif_data[ 7:0]: xgr5[ 7:0])} :
|
(write_xgr5[0] ? perif_data[ 7:0]: xgr5[ 7:0])} :
|
{((wrt_sel_xgr5 && ena_rd_high_byte) ? alu_result[15:8] : xgr5[15:8]),
|
{((wrt_sel_xgr5 && ena_rd_high_byte) ? alu_result[15:8] : xgr5[15:8]),
|
((wrt_sel_xgr5 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr5[ 7:0])};
|
((wrt_sel_xgr5 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr5[ 7:0])};
|
xgr6 <= (|write_xgr6 && perif_wrt_ena) ?
|
xgr6 <= (|write_xgr6 && perif_wrt_ena) ?
|
{(write_xgr6[1] ? perif_data[15:8]: xgr6[15:8]),
|
{(write_xgr6[1] ? perif_data[15:8]: xgr6[15:8]),
|
(write_xgr6[0] ? perif_data[ 7:0]: xgr6[ 7:0])} :
|
(write_xgr6[0] ? perif_data[ 7:0]: xgr6[ 7:0])} :
|
{((wrt_sel_xgr6 && ena_rd_high_byte) ? alu_result[15:8] : xgr6[15:8]),
|
{((wrt_sel_xgr6 && ena_rd_high_byte) ? alu_result[15:8] : xgr6[15:8]),
|
((wrt_sel_xgr6 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr6[ 7:0])};
|
((wrt_sel_xgr6 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr6[ 7:0])};
|
xgr7 <= (|write_xgr7 && perif_wrt_ena) ?
|
xgr7 <= (|write_xgr7 && perif_wrt_ena) ?
|
{(write_xgr7[1] ? perif_data[15:8]: xgr7[15:8]),
|
{(write_xgr7[1] ? perif_data[15:8]: xgr7[15:8]),
|
(write_xgr7[0] ? perif_data[ 7:0]: xgr7[ 7:0])} :
|
(write_xgr7[0] ? perif_data[ 7:0]: xgr7[ 7:0])} :
|
{((wrt_sel_xgr7 && ena_rd_high_byte) ? alu_result[15:8] : xgr7[15:8]),
|
{((wrt_sel_xgr7 && ena_rd_high_byte) ? alu_result[15:8] : xgr7[15:8]),
|
((wrt_sel_xgr7 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr7[ 7:0])};
|
((wrt_sel_xgr7 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr7[ 7:0])};
|
end
|
end
|
|
|
// V Ñ Vector fetch: always an aligned word read, lasts for at least one RISC core cycle
|
// V Ñ Vector fetch: always an aligned word read, lasts for at least one RISC core cycle
|
// P Ñ Program word fetch: always an aligned word read, lasts for at least one RISC core cycle
|
// P Ñ Program word fetch: always an aligned word read, lasts for at least one RISC core cycle
|
// r Ñ 8-bit data read: lasts for at least one RISC core cycle
|
// r Ñ 8-bit data read: lasts for at least one RISC core cycle
|
// R Ñ 16-bit data read: lasts for at least one RISC core cycle
|
// R Ñ 16-bit data read: lasts for at least one RISC core cycle
|
// w Ñ 8-bit data write: lasts for at least one RISC core cycle
|
// w Ñ 8-bit data write: lasts for at least one RISC core cycle
|
// W Ñ 16-bit data write: lasts for at least one RISC core cycle
|
// W Ñ 16-bit data write: lasts for at least one RISC core cycle
|
// A Ñ Alignment cycle: no read or write, lasts for zero or one RISC core cycles
|
// A Ñ Alignment cycle: no read or write, lasts for zero or one RISC core cycles
|
// f Ñ Free cycle: no read or write, lasts for one RISC core cycles
|
// f Ñ Free cycle: no read or write, lasts for one RISC core cycles
|
// Special Cases
|
// Special Cases
|
// PP/P Ñ Branch: PP if branch taken, P if not taken
|
// PP/P Ñ Branch: PP if branch taken, P if not taken
|
|
|
always @*
|
always @*
|
begin
|
begin
|
ena_rd_low_byte = 1'b0;
|
ena_rd_low_byte = 1'b0;
|
ena_rd_high_byte = 1'b0;
|
ena_rd_high_byte = 1'b0;
|
|
|
next_cpu_state = (debug_active || cmd_dbg) ? LD_INST : CONT;
|
next_cpu_state = (debug_active || cmd_dbg) ? LD_INST : CONT;
|
load_next_inst = 1'b1;
|
load_next_inst = 1'b1;
|
pc_incr_mux = cmd_dbg ? 16'h0000: 16'h0002; // Verilog Instruction order dependent
|
pc_incr_mux = cmd_dbg ? 16'h0000: 16'h0002; // Verilog Instruction order dependent
|
next_pc = pc_sum; // ""
|
next_pc = pc_sum; // ""
|
|
|
next_zero = zero_flag;
|
next_zero = zero_flag;
|
next_negative = negative_flag;
|
next_negative = negative_flag;
|
next_carry = carry_flag;
|
next_carry = carry_flag;
|
next_overflow = overflow_flag;
|
next_overflow = overflow_flag;
|
|
|
brk_set_dbg = 1'b0;
|
brk_set_dbg = 1'b0;
|
op_code_error = 1'b0;
|
op_code_error = 1'b0;
|
|
|
alu_result = 16'h0000;
|
alu_result = 16'h0000;
|
sel_rd_field = 1'b1;
|
sel_rd_field = 1'b1;
|
|
|
data_access = 1'b0;
|
data_access = 1'b0;
|
data_word_op = 1'b0;
|
data_word_op = 1'b0;
|
data_write = 1'b0;
|
data_write = 1'b0;
|
data_address = 16'h0000;
|
data_address = 16'h0000;
|
|
|
shift_left = 1'b0;
|
shift_left = 1'b0;
|
shift_ammount = 5'b0_0000;
|
shift_ammount = 5'b0_0000;
|
shift_filler = 16'h0000;
|
shift_filler = 16'h0000;
|
shift_in = rd_data;
|
shift_in = rd_data;
|
|
|
set_irq_flag = 7'b0;
|
set_irq_flag = 7'b0;
|
|
|
set_semaph = 1'b0;
|
set_semaph = 1'b0;
|
clear_semaph = 1'b0;
|
clear_semaph = 1'b0;
|
semaph_risc = 3'b0;
|
semaph_risc = 3'b0;
|
|
|
casez ({cpu_state, op_code})
|
casez ({cpu_state, op_code})
|
|
|
{IDLE, 16'b????????????????} :
|
{IDLE, 16'b????????????????} :
|
begin
|
begin
|
next_cpu_state = start_thread ? BOOT_1 : IDLE;
|
next_cpu_state = start_thread ? BOOT_1 : IDLE;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
end
|
end
|
|
|
{CHG_CHID, 16'b????????????????} :
|
{CHG_CHID, 16'b????????????????} :
|
begin
|
begin
|
if (!xge)
|
if (!xge)
|
next_cpu_state = IDLE;
|
next_cpu_state = IDLE;
|
else if (ss_mem_ack || !debug_active)
|
else if (ss_mem_ack || !debug_active)
|
next_cpu_state = BOOT_1;
|
next_cpu_state = BOOT_1;
|
else
|
else
|
next_cpu_state = CHG_CHID;
|
next_cpu_state = CHG_CHID;
|
|
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
end
|
end
|
|
|
// Output RAM address for Program Counter
|
// Output RAM address for Program Counter
|
{BOOT_1, 16'b????????????????} :
|
{BOOT_1, 16'b????????????????} :
|
begin
|
begin
|
next_cpu_state = BOOT_2;
|
next_cpu_state = BOOT_2;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
data_access = 1'b1;
|
data_access = 1'b1;
|
data_word_op = 1'b1;
|
data_word_op = 1'b1;
|
data_address = {xgvbr, 1'b0} + {7'b0, xgchid, 2'b0};
|
data_address = {xgvbr, 1'b0} + {7'b0, xgchid, 2'b0};
|
end
|
end
|
|
|
// Load PC value from data buffer register
|
// Load PC value from data buffer register
|
// Output RAM address for initial variable pointer
|
// Output RAM address for initial variable pointer
|
{BOOT_2, 16'b????????????????} :
|
{BOOT_2, 16'b????????????????} :
|
begin
|
begin
|
next_cpu_state = BOOT_3;
|
next_cpu_state = BOOT_3;
|
next_pc = load_data;
|
next_pc = load_data;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
data_access = 1'b1;
|
data_access = 1'b1;
|
data_word_op = 1'b1;
|
data_word_op = 1'b1;
|
data_address = {xgvbr, 1'b0} + {7'b0, xgchid, 2'b0} + 2;
|
data_address = {xgvbr, 1'b0} + {7'b0, xgchid, 2'b0} + 2;
|
end
|
end
|
|
|
// Load R1 with initial variable pointer from data buffer register
|
// Load R1 with initial variable pointer from data buffer register
|
// Load first instruction to op_code register
|
// Load first instruction to op_code register
|
// Increment Program Counter
|
// Increment Program Counter
|
{BOOT_3, 16'b????????????????} :
|
{BOOT_3, 16'b????????????????} :
|
begin
|
begin
|
next_cpu_state = CONT;
|
next_cpu_state = CONT;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
alu_result = load_data;
|
alu_result = load_data;
|
end
|
end
|
|
|
{BREAK, 16'b????????????????} :
|
{BREAK, 16'b????????????????} :
|
begin
|
begin
|
if (!xge)
|
if (!xge)
|
next_cpu_state = IDLE;
|
next_cpu_state = IDLE;
|
else if (ss_mem_ack || !debug_active)
|
else if (ss_mem_ack || !debug_active)
|
next_cpu_state = BREAK_2;
|
next_cpu_state = BREAK_2;
|
else if (chid_goto_idle)
|
else if (chid_goto_idle)
|
next_cpu_state = CHG_CHID;
|
next_cpu_state = CHG_CHID;
|
else
|
else
|
next_cpu_state = BREAK;
|
next_cpu_state = BREAK;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
end
|
end
|
|
|
{BREAK_2, 16'b????????????????} :
|
{BREAK_2, 16'b????????????????} :
|
begin
|
begin
|
next_cpu_state = LD_INST;
|
next_cpu_state = LD_INST;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
end
|
end
|
|
|
{LD_INST, 16'b????????????????} :
|
{LD_INST, 16'b????????????????} :
|
begin
|
begin
|
next_cpu_state = DEBUG;
|
next_cpu_state = DEBUG;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
end
|
end
|
|
|
{DEBUG, 16'b????????????????} :
|
{DEBUG, 16'b????????????????} :
|
begin
|
begin
|
if (!xge)
|
if (!xge)
|
next_cpu_state = IDLE;
|
next_cpu_state = IDLE;
|
else if (ss_mem_ack || !debug_active)
|
else if (ss_mem_ack || !debug_active)
|
next_cpu_state = CONT;
|
next_cpu_state = CONT;
|
else if (cmd_change_pc)
|
else if (cmd_change_pc)
|
next_cpu_state = LD_INST;
|
next_cpu_state = LD_INST;
|
else if (chid_goto_idle)
|
else if (chid_goto_idle)
|
next_cpu_state = CHG_CHID;
|
next_cpu_state = CHG_CHID;
|
else
|
else
|
next_cpu_state = DEBUG;
|
next_cpu_state = DEBUG;
|
|
|
load_next_inst = cmd_change_pc;
|
load_next_inst = cmd_change_pc;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
end
|
end
|
|
|
// Pause here for program counter change of flow or memory write access
|
// Pause here for program counter change of flow or memory write access
|
// Load next instruction and increment PC
|
// Load next instruction and increment PC
|
// Default next_cpu_state is CONT
|
// Default next_cpu_state is CONT
|
{S_STALL, 16'b????????????????} :
|
{S_STALL, 16'b????????????????} :
|
begin
|
begin
|
end
|
end
|
|
|
// Pause here for memory read word access
|
// Pause here for memory read word access
|
// Load next instruction and increment PC
|
// Load next instruction and increment PC
|
{W_LOAD, 16'b????????????????} :
|
{W_LOAD, 16'b????????????????} :
|
begin
|
begin
|
alu_result = load_data;
|
alu_result = load_data;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
end
|
end
|
|
|
// Pause here for memory read byte access
|
// Pause here for memory read byte access
|
// Load next instruction and increment PC
|
// Load next instruction and increment PC
|
{B_LOAD, 16'b????????????????} :
|
{B_LOAD, 16'b????????????????} :
|
begin
|
begin
|
alu_result = {8'h00, load_data[15:8]};
|
alu_result = {8'h00, load_data[15:8]};
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
end
|
end
|
|
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
// Instruction Group -- Return to Scheduler and Others
|
// Instruction Group -- Return to Scheduler and Others
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
|
|
// Instruction = BRK, Op Code = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
// Instruction = BRK, Op Code = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
// Cycles - PAff
|
// Cycles - PAff
|
{CONT, 16'b0000000000000000} :
|
{CONT, 16'b0000000000000000} :
|
begin
|
begin
|
next_cpu_state = BREAK;
|
next_cpu_state = BREAK;
|
pc_incr_mux = 16'hfffe; // equals -2
|
pc_incr_mux = 16'hfffe; // equals -2
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
brk_set_dbg = 1'b1;
|
brk_set_dbg = 1'b1;
|
end
|
end
|
|
|
// Instruction = NOP, Op Code = 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
|
// Instruction = NOP, Op Code = 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
|
{CONT, 16'b0000000100000000} :
|
{CONT, 16'b0000000100000000} :
|
begin
|
begin
|
end
|
end
|
|
|
// Instruction = RTS, Op Code = 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
|
// Instruction = RTS, Op Code = 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
|
// Cycles - PA
|
// Cycles - PA
|
{CONT, 16'b0000001000000000} :
|
{CONT, 16'b0000001000000000} :
|
begin
|
begin
|
next_cpu_state = IDLE;
|
next_cpu_state = IDLE;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
end
|
end
|
|
|
// Instruction = SIF, Op Code = 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0
|
// Instruction = SIF, Op Code = 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0
|
// Sets the Interrupt Flag of the current channel (XGCHID) will be set.
|
// Sets the Interrupt Flag of the current channel (XGCHID) will be set.
|
// Cycles - PA
|
// Cycles - PA
|
{CONT, 16'b0000001100000000} :
|
{CONT, 16'b0000001100000000} :
|
begin
|
begin
|
set_irq_flag = xgchid;
|
set_irq_flag = xgchid;
|
end
|
end
|
|
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
// Instruction Group -- Semaphore Instructions
|
// Instruction Group -- Semaphore Instructions
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
|
|
// Instruction = CSEM IMM3, Op Code = 0 0 0 0 0 IMM3 1 1 1 1 0 0 0 0
|
// Instruction = CSEM IMM3, Op Code = 0 0 0 0 0 IMM3 1 1 1 1 0 0 0 0
|
// Unlocks a semaphore that was locked by the RISC core.
|
// Unlocks a semaphore that was locked by the RISC core.
|
// Cycles - PA
|
// Cycles - PA
|
{CONT, 16'b00000???11110000} :
|
{CONT, 16'b00000???11110000} :
|
begin
|
begin
|
clear_semaph = 1'b1;
|
clear_semaph = 1'b1;
|
semaph_risc = op_code[10:8];
|
semaph_risc = op_code[10:8];
|
end
|
end
|
|
|
// Instruction = CSEM RS, Op Code = 0 0 0 0 0 RS 1 1 1 1 0 0 0 1
|
// Instruction = CSEM RS, Op Code = 0 0 0 0 0 RS 1 1 1 1 0 0 0 1
|
// Unlocks a semaphore that was locked by the RISC core.
|
// Unlocks a semaphore that was locked by the RISC core.
|
// In monadic address mode, bits RS[2:0] select the semaphore to be cleared.
|
// In monadic address mode, bits RS[2:0] select the semaphore to be cleared.
|
// Cycles - PA
|
// Cycles - PA
|
{CONT, 16'b00000???11110001} :
|
{CONT, 16'b00000???11110001} :
|
begin
|
begin
|
clear_semaph = 1'b1;
|
clear_semaph = 1'b1;
|
semaph_risc = rd_data[2:0];
|
semaph_risc = rd_data[2:0];
|
end
|
end
|
|
|
// Instruction = SSEM IMM3, Op Code = 0 0 0 0 0 IMM3 1 1 1 1 0 0 1 0
|
// Instruction = SSEM IMM3, Op Code = 0 0 0 0 0 IMM3 1 1 1 1 0 0 1 0
|
// Attempts to set a semaphore. The state of the semaphore will be stored in the Carry-Flag:
|
// Attempts to set a semaphore. The state of the semaphore will be stored in the Carry-Flag:
|
// 1 = Semaphore is locked by the RISC core
|
// 1 = Semaphore is locked by the RISC core
|
// 0 = Semaphore is locked by the S12X_CPU
|
// 0 = Semaphore is locked by the S12X_CPU
|
// Cycles - PA
|
// Cycles - PA
|
{CONT, 16'b00000???11110010} :
|
{CONT, 16'b00000???11110010} :
|
begin
|
begin
|
set_semaph = 1'b1;
|
set_semaph = 1'b1;
|
semaph_risc = op_code[10:8];
|
semaph_risc = op_code[10:8];
|
|
|
next_carry = semaph_stat;
|
next_carry = semaph_stat;
|
end
|
end
|
|
|
// Instruction = SSEM RS, Op Code = 0 0 0 0 0 RS 1 1 1 1 0 0 1 1
|
// Instruction = SSEM RS, Op Code = 0 0 0 0 0 RS 1 1 1 1 0 0 1 1
|
// Attempts to set a semaphore. The state of the semaphore will be stored in the Carry-Flag:
|
// Attempts to set a semaphore. The state of the semaphore will be stored in the Carry-Flag:
|
// 1 = Semaphore is locked by the RISC core
|
// 1 = Semaphore is locked by the RISC core
|
// 0 = Semaphore is locked by the S12X_CPU
|
// 0 = Semaphore is locked by the S12X_CPU
|
// In monadic address mode, bits RS[2:0] select the semaphore to be set.
|
// In monadic address mode, bits RS[2:0] select the semaphore to be set.
|
// Cycles - PA
|
// Cycles - PA
|
{CONT, 16'b00000???11110011} :
|
{CONT, 16'b00000???11110011} :
|
begin
|
begin
|
set_semaph = 1'b1;
|
set_semaph = 1'b1;
|
semaph_risc = rd_data[2:0];
|
semaph_risc = rd_data[2:0];
|
|
|
next_carry = semaph_stat;
|
next_carry = semaph_stat;
|
end
|
end
|
|
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
// Instruction Group -- Single Register Instructions
|
// Instruction Group -- Single Register Instructions
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
|
|
// Instruction = SEX RD, Op Code = 0 0 0 0 0 RD 1 1 1 1 0 1 0 0
|
// Instruction = SEX RD, Op Code = 0 0 0 0 0 RD 1 1 1 1 0 1 0 0
|
// SEX - Sign Extend Byte to Word
|
// SEX - Sign Extend Byte to Word
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00000???11110100} :
|
{CONT, 16'b00000???11110100} :
|
begin
|
begin
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
|
|
alu_result = {{8{rd_data[7]}}, rd_data[7:0]};
|
alu_result = {{8{rd_data[7]}}, rd_data[7:0]};
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// Instruction = PAR RD, Op Code = 0 0 0 0 0 RD 1 1 1 1 0 1 0 1
|
// Instruction = PAR RD, Op Code = 0 0 0 0 0 RD 1 1 1 1 0 1 0 1
|
// PAR - Calculate Parity
|
// PAR - Calculate Parity
|
// Set Carry Flag on odd number of bits
|
// Set Carry Flag on odd number of bits
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00000???11110101} :
|
{CONT, 16'b00000???11110101} :
|
begin
|
begin
|
next_zero = !(|rd_data);
|
next_zero = !(|rd_data);
|
next_negative = 1'b0;
|
next_negative = 1'b0;
|
next_carry = ^rd_data;
|
next_carry = ^rd_data;
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// Instruction = JAL RD, Op Code = 0 0 0 0 0 RD 1 1 1 1 0 1 1 0
|
// Instruction = JAL RD, Op Code = 0 0 0 0 0 RD 1 1 1 1 0 1 1 0
|
// Jump And Link
|
// Jump And Link
|
// PC + $0002 => RD; RD => PC
|
// PC + $0002 => RD; RD => PC
|
// Jumps to the address stored in RD and saves the return address in RD.
|
// Jumps to the address stored in RD and saves the return address in RD.
|
// Cycles - PP
|
// Cycles - PP
|
{CONT, 16'b00000???11110110} :
|
{CONT, 16'b00000???11110110} :
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
alu_result = program_counter;
|
alu_result = program_counter;
|
next_pc = rd_data;
|
next_pc = rd_data;
|
end
|
end
|
|
|
// Instruction = SIF RS, Op Code = 0 0 0 0 0 RS 1 1 1 1 0 1 1 1
|
// Instruction = SIF RS, Op Code = 0 0 0 0 0 RS 1 1 1 1 0 1 1 1
|
// Sets the Interrupt Flag associated with the channel id number
|
// Sets the Interrupt Flag associated with the channel id number
|
// contained in RS[6:0] is set. The content of RS[15:7] is ignored
|
// contained in RS[6:0] is set. The content of RS[15:7] is ignored
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00000???11110111} :
|
{CONT, 16'b00000???11110111} :
|
begin
|
begin
|
set_irq_flag = rd_data[6:0];
|
set_irq_flag = rd_data[6:0];
|
end
|
end
|
|
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
// Instruction Group -- Special Move instructions
|
// Instruction Group -- Special Move instructions
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
|
|
// Instruction = TFR RD,CCR, Op Code = 0 0 0 0 0 RD 1 1 1 1 1 0 0 0
|
// Instruction = TFR RD,CCR, Op Code = 0 0 0 0 0 RD 1 1 1 1 1 0 0 0
|
// Transfer from and to Special Registers
|
// Transfer from and to Special Registers
|
// TFR RD,CCR: CCR => RD[3:0], 0 => RD[15:4]
|
// TFR RD,CCR: CCR => RD[3:0], 0 => RD[15:4]
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00000???11111000} :
|
{CONT, 16'b00000???11111000} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
alu_result = {12'b0, negative_flag, zero_flag, overflow_flag, carry_flag};
|
alu_result = {12'b0, negative_flag, zero_flag, overflow_flag, carry_flag};
|
end
|
end
|
|
|
// Instruction = TFR CCR,RS, Op Code = 0 0 0 0 0 RS 1 1 1 1 1 0 0 1
|
// Instruction = TFR CCR,RS, Op Code = 0 0 0 0 0 RS 1 1 1 1 1 0 0 1
|
// Transfer from and to Special Registers
|
// Transfer from and to Special Registers
|
// TFR CCR,RD: RD[3:0] => CCR
|
// TFR CCR,RD: RD[3:0] => CCR
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00000???11111001} :
|
{CONT, 16'b00000???11111001} :
|
begin
|
begin
|
next_negative = rd_data[3];
|
next_negative = rd_data[3];
|
next_zero = rd_data[2];
|
next_zero = rd_data[2];
|
next_overflow = rd_data[1];
|
next_overflow = rd_data[1];
|
next_carry = rd_data[0];
|
next_carry = rd_data[0];
|
end
|
end
|
|
|
// Instruction = TFR RD,PC, Op Code = 0 0 0 0 0 RD 1 1 1 1 1 0 1 0
|
// Instruction = TFR RD,PC, Op Code = 0 0 0 0 0 RD 1 1 1 1 1 0 1 0
|
// Transfer from and to Special Registers
|
// Transfer from and to Special Registers
|
// TFR RD,PC: PC+4 => RD
|
// TFR RD,PC: PC+4 => RD
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00000???11111010} :
|
{CONT, 16'b00000???11111010} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
alu_result = next_pc;
|
alu_result = next_pc;
|
end
|
end
|
|
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
// Instruction Group -- Shift instructions Dyadic
|
// Instruction Group -- Shift instructions Dyadic
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
|
|
// Instruction = BFFO RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 0 0 0
|
// Instruction = BFFO RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 0 0 0
|
// BFFO - Bit Field Find First One
|
// BFFO - Bit Field Find First One
|
// FirstOne (RS) => RD
|
// FirstOne (RS) => RD
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00001??????10000} :
|
{CONT, 16'b00001??????10000} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
|
|
casez (rs1_data) // synopsys parallel_case
|
casez (rs1_data) // synopsys parallel_case
|
16'b1???_????_????_???? : alu_result = 16'h000f;
|
16'b1???_????_????_???? : alu_result = 16'h000f;
|
16'b01??_????_????_???? : alu_result = 16'h000e;
|
16'b01??_????_????_???? : alu_result = 16'h000e;
|
16'b001?_????_????_???? : alu_result = 16'h000d;
|
16'b001?_????_????_???? : alu_result = 16'h000d;
|
16'b0001_????_????_???? : alu_result = 16'h000c;
|
16'b0001_????_????_???? : alu_result = 16'h000c;
|
16'b0000_1???_????_???? : alu_result = 16'h000b;
|
16'b0000_1???_????_???? : alu_result = 16'h000b;
|
16'b0000_01??_????_???? : alu_result = 16'h000a;
|
16'b0000_01??_????_???? : alu_result = 16'h000a;
|
16'b0000_001?_????_???? : alu_result = 16'h0009;
|
16'b0000_001?_????_???? : alu_result = 16'h0009;
|
16'b0000_0001_????_???? : alu_result = 16'h0008;
|
16'b0000_0001_????_???? : alu_result = 16'h0008;
|
16'b0000_0000_1???_???? : alu_result = 16'h0007;
|
16'b0000_0000_1???_???? : alu_result = 16'h0007;
|
16'b0000_0000_01??_???? : alu_result = 16'h0006;
|
16'b0000_0000_01??_???? : alu_result = 16'h0006;
|
16'b0000_0000_001?_???? : alu_result = 16'h0005;
|
16'b0000_0000_001?_???? : alu_result = 16'h0005;
|
16'b0000_0000_0001_???? : alu_result = 16'h0004;
|
16'b0000_0000_0001_???? : alu_result = 16'h0004;
|
16'b0000_0000_0000_1??? : alu_result = 16'h0003;
|
16'b0000_0000_0000_1??? : alu_result = 16'h0003;
|
16'b0000_0000_0000_01?? : alu_result = 16'h0002;
|
16'b0000_0000_0000_01?? : alu_result = 16'h0002;
|
16'b0000_0000_0000_001? : alu_result = 16'h0001;
|
16'b0000_0000_0000_001? : alu_result = 16'h0001;
|
16'b0000_0000_0000_0001 : alu_result = 16'h0000;
|
16'b0000_0000_0000_0001 : alu_result = 16'h0000;
|
endcase
|
endcase
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = 1'b0;
|
next_negative = 1'b0;
|
next_carry = !(|rs1_data);
|
next_carry = !(|rs1_data);
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// Instruction = ASR RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 0 0 1
|
// Instruction = ASR RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 0 0 1
|
// ASR - Arithmetic Shift Right
|
// ASR - Arithmetic Shift Right
|
// n = RS
|
// n = RS
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00001??????10001} :
|
{CONT, 16'b00001??????10001} :
|
begin
|
begin
|
shift_ammount = {|rs1_data[15:4], rs1_data[3:0]};
|
shift_ammount = {|rs1_data[15:4], rs1_data[3:0]};
|
shift_filler = {16{rd_data[15]}};
|
shift_filler = {16{rd_data[15]}};
|
|
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
alu_result = shift_out;
|
alu_result = shift_out;
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_carry = |rs1_data ? shift_rollover : carry_flag;
|
next_carry = |rs1_data ? shift_rollover : carry_flag;
|
next_overflow = rd_data[15] ^ alu_result[15]; // Table and text disagree
|
next_overflow = rd_data[15] ^ alu_result[15]; // Table and text disagree
|
end
|
end
|
|
|
// Instruction = CSL RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 0 1 0
|
// Instruction = CSL RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 0 1 0
|
// CSL - Logical Shift Left with Carry
|
// CSL - Logical Shift Left with Carry
|
// n = RS
|
// n = RS
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00001??????10010} :
|
{CONT, 16'b00001??????10010} :
|
begin
|
begin
|
shift_left = 1'b1;
|
shift_left = 1'b1;
|
shift_ammount = {|rs1_data[15:4], rs1_data[3:0]};
|
shift_ammount = {|rs1_data[15:4], rs1_data[3:0]};
|
shift_filler = {16{carry_flag}};
|
shift_filler = {16{carry_flag}};
|
|
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
alu_result = shift_out;
|
alu_result = shift_out;
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_carry = |rs1_data ? shift_rollover : carry_flag;
|
next_carry = |rs1_data ? shift_rollover : carry_flag;
|
next_overflow = rd_data[15] ^ alu_result[15];
|
next_overflow = rd_data[15] ^ alu_result[15];
|
end
|
end
|
|
|
// Instruction = CSR RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 0 1 1
|
// Instruction = CSR RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 0 1 1
|
// Logical Shift Right with Carry
|
// Logical Shift Right with Carry
|
// n = RS
|
// n = RS
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00001??????10011} :
|
{CONT, 16'b00001??????10011} :
|
begin
|
begin
|
shift_ammount = {|rs1_data[15:4], rs1_data[3:0]};
|
shift_ammount = {|rs1_data[15:4], rs1_data[3:0]};
|
shift_filler = {16{carry_flag}};
|
shift_filler = {16{carry_flag}};
|
|
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
alu_result = shift_out;
|
alu_result = shift_out;
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_carry = |rs1_data ? shift_rollover : carry_flag;
|
next_carry = |rs1_data ? shift_rollover : carry_flag;
|
next_overflow = rd_data[15] ^ alu_result[15];
|
next_overflow = rd_data[15] ^ alu_result[15];
|
end
|
end
|
|
|
// Instruction = LSL RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 1 0 0
|
// Instruction = LSL RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 1 0 0
|
// Logical Shift Left
|
// Logical Shift Left
|
// n = RS
|
// n = RS
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00001??????10100} :
|
{CONT, 16'b00001??????10100} :
|
begin
|
begin
|
shift_left = 1'b1;
|
shift_left = 1'b1;
|
shift_ammount = {|rs1_data[15:4], rs1_data[3:0]};
|
shift_ammount = {|rs1_data[15:4], rs1_data[3:0]};
|
shift_filler = 16'h0000;
|
shift_filler = 16'h0000;
|
|
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
alu_result = shift_out;
|
alu_result = shift_out;
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_carry = |rs1_data ? shift_rollover : carry_flag;
|
next_carry = |rs1_data ? shift_rollover : carry_flag;
|
next_overflow = rd_data[15] ^ alu_result[15];
|
next_overflow = rd_data[15] ^ alu_result[15];
|
end
|
end
|
|
|
// Instruction = LSR RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 1 0 1
|
// Instruction = LSR RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 1 0 1
|
// Logical Shift Right
|
// Logical Shift Right
|
// n = RS
|
// n = RS
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00001??????10101} :
|
{CONT, 16'b00001??????10101} :
|
begin
|
begin
|
shift_ammount = {|rs1_data[15:4], rs1_data[3:0]};
|
shift_ammount = {|rs1_data[15:4], rs1_data[3:0]};
|
shift_filler = 16'h0000;
|
shift_filler = 16'h0000;
|
|
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
alu_result = shift_out;
|
alu_result = shift_out;
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_carry = |rs1_data ? shift_rollover : carry_flag;
|
next_carry = |rs1_data ? shift_rollover : carry_flag;
|
next_overflow = rd_data[15] ^ alu_result[15];
|
next_overflow = rd_data[15] ^ alu_result[15];
|
end
|
end
|
|
|
// Instruction = ROL RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 1 1 0
|
// Instruction = ROL RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 1 1 0
|
// Rotate Left
|
// Rotate Left
|
// n = RS
|
// n = RS
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00001??????10110} :
|
{CONT, 16'b00001??????10110} :
|
begin
|
begin
|
shift_left = 1'b1;
|
shift_left = 1'b1;
|
shift_ammount = {1'b0, rs1_data[3:0]};
|
shift_ammount = {1'b0, rs1_data[3:0]};
|
shift_filler = rd_data;
|
shift_filler = rd_data;
|
|
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
alu_result = shift_out;
|
alu_result = shift_out;
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// Instruction = ROR RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 1 1 1
|
// Instruction = ROR RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 1 1 1
|
// Rotate Right
|
// Rotate Right
|
// n = RS
|
// n = RS
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00001??????10111} :
|
{CONT, 16'b00001??????10111} :
|
begin
|
begin
|
shift_ammount = {1'b0, rs1_data[3:0]};
|
shift_ammount = {1'b0, rs1_data[3:0]};
|
shift_filler = rd_data;
|
shift_filler = rd_data;
|
|
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
alu_result = shift_out;
|
alu_result = shift_out;
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
// Instruction Group -- Shift instructions immediate
|
// Instruction Group -- Shift instructions immediate
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
|
|
// Instruction = ASR RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 0 0 1
|
// Instruction = ASR RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 0 0 1
|
// ASR - Arithmetic Shift Right
|
// ASR - Arithmetic Shift Right
|
// n = IMM4
|
// n = IMM4
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00001???????1001} :
|
{CONT, 16'b00001???????1001} :
|
begin
|
begin
|
shift_ammount = {!(|op_code[7:4]), op_code[7:4]};
|
shift_ammount = {!(|op_code[7:4]), op_code[7:4]};
|
shift_filler = {16{rd_data[15]}};
|
shift_filler = {16{rd_data[15]}};
|
|
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
alu_result = shift_out;
|
alu_result = shift_out;
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_carry = shift_rollover;
|
next_carry = shift_rollover;
|
next_overflow = rd_data[15] ^ alu_result[15]; // Table and text disagree
|
next_overflow = rd_data[15] ^ alu_result[15]; // Table and text disagree
|
end
|
end
|
|
|
// Instruction = CSL RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 0 1 0
|
// Instruction = CSL RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 0 1 0
|
// CSL - Logical Shift Left with Carry
|
// CSL - Logical Shift Left with Carry
|
// n = IMM4
|
// n = IMM4
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00001???????1010} :
|
{CONT, 16'b00001???????1010} :
|
begin
|
begin
|
shift_left = 1'b1;
|
shift_left = 1'b1;
|
shift_ammount = {!(|op_code[7:4]), op_code[7:4]};
|
shift_ammount = {!(|op_code[7:4]), op_code[7:4]};
|
shift_filler = {16{carry_flag}};
|
shift_filler = {16{carry_flag}};
|
|
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
alu_result = shift_out;
|
alu_result = shift_out;
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_carry = shift_rollover;
|
next_carry = shift_rollover;
|
next_overflow = rd_data[15] ^ alu_result[15];
|
next_overflow = rd_data[15] ^ alu_result[15];
|
end
|
end
|
|
|
// Instruction = CSR RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 0 1 1
|
// Instruction = CSR RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 0 1 1
|
// CSR - Logical Shift Right with Carry
|
// CSR - Logical Shift Right with Carry
|
// n = IMM4
|
// n = IMM4
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00001???????1011} :
|
{CONT, 16'b00001???????1011} :
|
begin
|
begin
|
shift_ammount = {!(|op_code[7:4]), op_code[7:4]};
|
shift_ammount = {!(|op_code[7:4]), op_code[7:4]};
|
shift_filler = {16{carry_flag}};
|
shift_filler = {16{carry_flag}};
|
|
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
alu_result = shift_out;
|
alu_result = shift_out;
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_carry = shift_rollover;
|
next_carry = shift_rollover;
|
next_overflow = rd_data[15] ^ alu_result[15];
|
next_overflow = rd_data[15] ^ alu_result[15];
|
end
|
end
|
|
|
// Instruction = LSL RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 1 0 0
|
// Instruction = LSL RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 1 0 0
|
// LSL - Logical Shift Left
|
// LSL - Logical Shift Left
|
// n = IMM4
|
// n = IMM4
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00001???????1100} :
|
{CONT, 16'b00001???????1100} :
|
begin
|
begin
|
shift_left = 1'b1;
|
shift_left = 1'b1;
|
shift_ammount = {!(|op_code[7:4]), op_code[7:4]};
|
shift_ammount = {!(|op_code[7:4]), op_code[7:4]};
|
shift_filler = 16'h0000;
|
shift_filler = 16'h0000;
|
|
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
alu_result = shift_out;
|
alu_result = shift_out;
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_carry = shift_rollover;
|
next_carry = shift_rollover;
|
next_overflow = rd_data[15] ^ alu_result[15];
|
next_overflow = rd_data[15] ^ alu_result[15];
|
end
|
end
|
|
|
// Instruction = LSR RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 1 0 1
|
// Instruction = LSR RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 1 0 1
|
// LSR - Logical Shift Right
|
// LSR - Logical Shift Right
|
// n = IMM4
|
// n = IMM4
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00001???????1101} :
|
{CONT, 16'b00001???????1101} :
|
begin
|
begin
|
shift_ammount = {!(|op_code[7:4]), op_code[7:4]};
|
shift_ammount = {!(|op_code[7:4]), op_code[7:4]};
|
shift_filler = 16'h0000;
|
shift_filler = 16'h0000;
|
|
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
alu_result = shift_out;
|
alu_result = shift_out;
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_carry = shift_rollover;
|
next_carry = shift_rollover;
|
next_overflow = rd_data[15] ^ alu_result[15];
|
next_overflow = rd_data[15] ^ alu_result[15];
|
end
|
end
|
|
|
// Instruction = ROL RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 1 1 0
|
// Instruction = ROL RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 1 1 0
|
// ROL - Rotate Left
|
// ROL - Rotate Left
|
// n = IMM4
|
// n = IMM4
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00001???????1110} :
|
{CONT, 16'b00001???????1110} :
|
begin
|
begin
|
shift_left = 1'b1;
|
shift_left = 1'b1;
|
shift_ammount = {1'b0, op_code[7:4]};
|
shift_ammount = {1'b0, op_code[7:4]};
|
shift_filler = rd_data;
|
shift_filler = rd_data;
|
|
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
alu_result = shift_out;
|
alu_result = shift_out;
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// Instruction = ROR RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 1 1 1
|
// Instruction = ROR RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 1 1 1
|
// ROR - Rotate Right
|
// ROR - Rotate Right
|
// n = IMM4
|
// n = IMM4
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00001???????1111} :
|
{CONT, 16'b00001???????1111} :
|
begin
|
begin
|
shift_ammount = {1'b0, op_code[7:4]};
|
shift_ammount = {1'b0, op_code[7:4]};
|
shift_filler = rd_data;
|
shift_filler = rd_data;
|
|
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
alu_result = shift_out;
|
alu_result = shift_out;
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
// Instruction Group -- Logical Triadic
|
// Instruction Group -- Logical Triadic
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
|
|
// Instruction = AND RD, RS1, RS2, Op Code = 0 0 0 1 0 RD RS1 RS2 0 0
|
// Instruction = AND RD, RS1, RS2, Op Code = 0 0 0 1 0 RD RS1 RS2 0 0
|
// AND - Logical AND
|
// AND - Logical AND
|
// RS1 & RS2 => RD
|
// RS1 & RS2 => RD
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00010?????????00} :
|
{CONT, 16'b00010?????????00} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
|
|
alu_result = rs1_data & rs2_data;
|
alu_result = rs1_data & rs2_data;
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// Instruction = OR RD, RS1, RS2, Op Code = 0 0 0 1 0 RD RS1 RS2 1 0
|
// Instruction = OR RD, RS1, RS2, Op Code = 0 0 0 1 0 RD RS1 RS2 1 0
|
// OR - Logical OR
|
// OR - Logical OR
|
// RS1 | RS2 => RD
|
// RS1 | RS2 => RD
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00010?????????10} :
|
{CONT, 16'b00010?????????10} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
|
|
alu_result = rs1_data | rs2_data;
|
alu_result = rs1_data | rs2_data;
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// Instruction = XNOR RD, RS1, RS2, Op Code = 0 0 0 1 0 RD RS1 RS2 1 1
|
// Instruction = XNOR RD, RS1, RS2, Op Code = 0 0 0 1 0 RD RS1 RS2 1 1
|
// XNOR - Logical Exclusive NOR
|
// XNOR - Logical Exclusive NOR
|
// ~(RS1 ^ RS2) => RD
|
// ~(RS1 ^ RS2) => RD
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00010?????????11} :
|
{CONT, 16'b00010?????????11} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
|
|
alu_result = ~(rs1_data ^ rs2_data);
|
alu_result = ~(rs1_data ^ rs2_data);
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
// Instruction Group -- Arithmetic Triadic
|
// Instruction Group -- Arithmetic Triadic
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
|
|
// Instruction = SUB RD, RS1, RS2, Op Code = 0 0 0 1 1 RD RS1 RS2 0 0
|
// Instruction = SUB RD, RS1, RS2, Op Code = 0 0 0 1 1 RD RS1 RS2 0 0
|
// SUB - Subtract without Carry
|
// SUB - Subtract without Carry
|
// RS1 - RS2 => RD
|
// RS1 - RS2 => RD
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00011?????????00} :
|
{CONT, 16'b00011?????????00} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
|
|
{next_carry, alu_result} = rs1_data - rs2_data;
|
{next_carry, alu_result} = rs1_data - rs2_data;
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = (rs1_data[15] && !rs2_data[15] && !alu_result[15]) || (!rs1_data[15] && rs2_data[15] && alu_result[15]);
|
next_overflow = (rs1_data[15] && !rs2_data[15] && !alu_result[15]) || (!rs1_data[15] && rs2_data[15] && alu_result[15]);
|
end
|
end
|
|
|
// Instruction = SBC RD, RS1, RS2, Op Code = 0 0 0 1 1 RD RS1 RS2 0 1
|
// Instruction = SBC RD, RS1, RS2, Op Code = 0 0 0 1 1 RD RS1 RS2 0 1
|
// SBC - Subtract with Carry
|
// SBC - Subtract with Carry
|
// RS1 - RS2 - C => RD
|
// RS1 - RS2 - C => RD
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00011?????????01} :
|
{CONT, 16'b00011?????????01} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
|
|
{next_carry, alu_result} = rs1_data - rs2_data - {15'b0, carry_flag};
|
{next_carry, alu_result} = rs1_data - rs2_data - {15'b0, carry_flag};
|
next_zero = !(|alu_result) && zero_flag;
|
next_zero = !(|alu_result) && zero_flag;
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = (rs1_data[15] && !rs2_data[15] && !alu_result[15]) || (!rs1_data[15] && rs2_data[15] && alu_result[15]);
|
next_overflow = (rs1_data[15] && !rs2_data[15] && !alu_result[15]) || (!rs1_data[15] && rs2_data[15] && alu_result[15]);
|
end
|
end
|
|
|
// Instruction = ADD RD, RS1, RS2, Op Code = 0 0 0 1 1 RD RS1 RS2 1 0
|
// Instruction = ADD RD, RS1, RS2, Op Code = 0 0 0 1 1 RD RS1 RS2 1 0
|
// ADD - ADD without carry
|
// ADD - ADD without carry
|
// RS1 + RS2 => RD
|
// RS1 + RS2 => RD
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00011?????????10} :
|
{CONT, 16'b00011?????????10} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
|
|
{next_carry, alu_result} = rs1_data + rs2_data;
|
{next_carry, alu_result} = rs1_data + rs2_data;
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = (rs1_data[15] && rs2_data[15] && !alu_result[15]) || (!rs1_data[15] && !rs2_data[15] && alu_result[15]);
|
next_overflow = (rs1_data[15] && rs2_data[15] && !alu_result[15]) || (!rs1_data[15] && !rs2_data[15] && alu_result[15]);
|
end
|
end
|
|
|
// Instruction = ADC RD, RS1, RS2, Op Code = 0 0 0 1 1 RD RS1 RS2 1 1
|
// Instruction = ADC RD, RS1, RS2, Op Code = 0 0 0 1 1 RD RS1 RS2 1 1
|
// ADC - add with carry
|
// ADC - add with carry
|
// RS1 + RS2 + C => RD
|
// RS1 + RS2 + C => RD
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b00011?????????11} :
|
{CONT, 16'b00011?????????11} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
|
|
{next_carry, alu_result} = rs1_data + rs2_data + {15'b0, carry_flag};
|
{next_carry, alu_result} = rs1_data + rs2_data + {15'b0, carry_flag};
|
next_zero = !(|alu_result) && zero_flag;
|
next_zero = !(|alu_result) && zero_flag;
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = (rs1_data[15] && rs2_data[15] && !alu_result[15]) || (!rs1_data[15] && !rs2_data[15] && alu_result[15]);
|
next_overflow = (rs1_data[15] && rs2_data[15] && !alu_result[15]) || (!rs1_data[15] && !rs2_data[15] && alu_result[15]);
|
end
|
end
|
|
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
// Instruction Group -- Branches
|
// Instruction Group -- Branches
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
|
|
// Instruction = BCC REL9, Op Code = 0 0 1 0 0 0 0 REL9
|
// Instruction = BCC REL9, Op Code = 0 0 1 0 0 0 0 REL9
|
// Branch if Carry Cleared
|
// Branch if Carry Cleared
|
// If C = 0, then PC + $0002 + (REL9 << 1) => PC
|
// If C = 0, then PC + $0002 + (REL9 << 1) => PC
|
// Cycles - PP/P
|
// Cycles - PP/P
|
{CONT, 16'b0010000?????????} :
|
{CONT, 16'b0010000?????????} :
|
begin
|
begin
|
if (!carry_flag)
|
if (!carry_flag)
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = jump_offset;
|
pc_incr_mux = jump_offset;
|
next_pc = pc_sum; // There is a race condition when the default declaration is used
|
next_pc = pc_sum; // There is a race condition when the default declaration is used
|
end
|
end
|
end
|
end
|
|
|
// Instruction = BCS REL9, Op Code = 0 0 1 0 0 0 1 REL9
|
// Instruction = BCS REL9, Op Code = 0 0 1 0 0 0 1 REL9
|
// Branch if Carry Set
|
// Branch if Carry Set
|
// If C = 1, then PC + $0002 + (REL9 << 1) => PC
|
// If C = 1, then PC + $0002 + (REL9 << 1) => PC
|
// Cycles - PP/P
|
// Cycles - PP/P
|
{CONT, 16'b0010001?????????} :
|
{CONT, 16'b0010001?????????} :
|
begin
|
begin
|
if (carry_flag)
|
if (carry_flag)
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = jump_offset;
|
pc_incr_mux = jump_offset;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
end
|
end
|
end
|
end
|
|
|
// Instruction = BNE REL9, Op Code = 0 0 1 0 0 1 0 REL9
|
// Instruction = BNE REL9, Op Code = 0 0 1 0 0 1 0 REL9
|
// Branch if Not Equal
|
// Branch if Not Equal
|
// If Z = 0, then PC + $0002 + (REL9 << 1) => PC
|
// If Z = 0, then PC + $0002 + (REL9 << 1) => PC
|
// Cycles - PP/P
|
// Cycles - PP/P
|
{CONT, 16'b0010010?????????} :
|
{CONT, 16'b0010010?????????} :
|
begin
|
begin
|
if (!zero_flag)
|
if (!zero_flag)
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = jump_offset;
|
pc_incr_mux = jump_offset;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
end
|
end
|
end
|
end
|
|
|
// Instruction = BEQ REL9, Op Code = 0 0 1 0 0 1 1 REL9
|
// Instruction = BEQ REL9, Op Code = 0 0 1 0 0 1 1 REL9
|
// Branch if Equal
|
// Branch if Equal
|
// If Z = 1, then PC + $0002 + (REL9 << 1) => PC
|
// If Z = 1, then PC + $0002 + (REL9 << 1) => PC
|
// Cycles - PP/P
|
// Cycles - PP/P
|
{CONT, 16'b0010011?????????} :
|
{CONT, 16'b0010011?????????} :
|
begin
|
begin
|
if (zero_flag)
|
if (zero_flag)
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = jump_offset;
|
pc_incr_mux = jump_offset;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
end
|
end
|
end
|
end
|
|
|
// Instruction = BPL REL9, Op Code = 0 0 1 0 1 0 0 REL9
|
// Instruction = BPL REL9, Op Code = 0 0 1 0 1 0 0 REL9
|
// Branch if Plus
|
// Branch if Plus
|
// If N = 0, then PC + $0002 + (REL9 << 1) => PC
|
// If N = 0, then PC + $0002 + (REL9 << 1) => PC
|
// Cycles - PP/P
|
// Cycles - PP/P
|
{CONT, 16'b0010100?????????} :
|
{CONT, 16'b0010100?????????} :
|
begin
|
begin
|
if (!negative_flag)
|
if (!negative_flag)
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = jump_offset;
|
pc_incr_mux = jump_offset;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
end
|
end
|
end
|
end
|
|
|
// Instruction = BMI REL9, Op Code = 0 0 1 0 1 0 1 REL9
|
// Instruction = BMI REL9, Op Code = 0 0 1 0 1 0 1 REL9
|
// Branch if Minus
|
// Branch if Minus
|
// If N = 1, then PC + $0002 + (REL9 << 1) => PC
|
// If N = 1, then PC + $0002 + (REL9 << 1) => PC
|
// Cycles - PP/P
|
// Cycles - PP/P
|
{CONT, 16'b0010101?????????} :
|
{CONT, 16'b0010101?????????} :
|
begin
|
begin
|
if (negative_flag)
|
if (negative_flag)
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = jump_offset;
|
pc_incr_mux = jump_offset;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
end
|
end
|
end
|
end
|
|
|
// Instruction = BVC REL9, Op Code = 0 0 1 0 1 1 0 REL9
|
// Instruction = BVC REL9, Op Code = 0 0 1 0 1 1 0 REL9
|
// Branch if Overflow Cleared
|
// Branch if Overflow Cleared
|
// If V = 0, then PC + $0002 + (REL9 << 1) => PC
|
// If V = 0, then PC + $0002 + (REL9 << 1) => PC
|
// Cycles - PP/P
|
// Cycles - PP/P
|
{CONT, 16'b0010110?????????} :
|
{CONT, 16'b0010110?????????} :
|
begin
|
begin
|
if (!overflow_flag)
|
if (!overflow_flag)
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = jump_offset;
|
pc_incr_mux = jump_offset;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
end
|
end
|
end
|
end
|
|
|
// Instruction = BVS REL9, Op Code = 0 0 1 0 1 1 1 REL9
|
// Instruction = BVS REL9, Op Code = 0 0 1 0 1 1 1 REL9
|
// Branch if Overflow Set
|
// Branch if Overflow Set
|
// If V = 1, then PC + $0002 + (REL9 << 1) => PC
|
// If V = 1, then PC + $0002 + (REL9 << 1) => PC
|
// Cycles - PP/P
|
// Cycles - PP/P
|
{CONT, 16'b0010111?????????} :
|
{CONT, 16'b0010111?????????} :
|
begin
|
begin
|
if (overflow_flag)
|
if (overflow_flag)
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = jump_offset;
|
pc_incr_mux = jump_offset;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
end
|
end
|
end
|
end
|
|
|
// Instruction = BHI REL9, Op Code = 0 0 1 1 0 0 0 REL9
|
// Instruction = BHI REL9, Op Code = 0 0 1 1 0 0 0 REL9
|
// Branch if Higher
|
// Branch if Higher
|
// If C | Z = 0, then PC + $0002 + (REL9 << 1) => PC
|
// If C | Z = 0, then PC + $0002 + (REL9 << 1) => PC
|
// Cycles - PP/P
|
// Cycles - PP/P
|
{CONT, 16'b0011000?????????} :
|
{CONT, 16'b0011000?????????} :
|
begin
|
begin
|
if (!(carry_flag || zero_flag))
|
if (!(carry_flag || zero_flag))
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = jump_offset;
|
pc_incr_mux = jump_offset;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
end
|
end
|
end
|
end
|
|
|
// Instruction = BLS REL9, Op Code = 0 0 1 1 0 0 1 REL9
|
// Instruction = BLS REL9, Op Code = 0 0 1 1 0 0 1 REL9
|
// Branch if Lower or Same
|
// Branch if Lower or Same
|
// If C | Z = 1, then PC + $0002 + (REL9 << 1) => PC
|
// If C | Z = 1, then PC + $0002 + (REL9 << 1) => PC
|
// Cycles - PP/P
|
// Cycles - PP/P
|
{CONT, 16'b0011001?????????} :
|
{CONT, 16'b0011001?????????} :
|
begin
|
begin
|
if (carry_flag || zero_flag)
|
if (carry_flag || zero_flag)
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = jump_offset;
|
pc_incr_mux = jump_offset;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
end
|
end
|
end
|
end
|
|
|
// Instruction = BGE REL9, Op Code = 0 0 1 1 0 1 0 REL9
|
// Instruction = BGE REL9, Op Code = 0 0 1 1 0 1 0 REL9
|
// Branch if Greater than or Equal to Zero
|
// Branch if Greater than or Equal to Zero
|
// If N ^ V = 0, then PC + $0002 + (REL9 << 1) => PC
|
// If N ^ V = 0, then PC + $0002 + (REL9 << 1) => PC
|
// Cycles - PP/P
|
// Cycles - PP/P
|
{CONT, 16'b0011010?????????} :
|
{CONT, 16'b0011010?????????} :
|
begin
|
begin
|
if (!(negative_flag ^ overflow_flag))
|
if (!(negative_flag ^ overflow_flag))
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = jump_offset;
|
pc_incr_mux = jump_offset;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
end
|
end
|
end
|
end
|
|
|
// Instruction = BLT REL9, Op Code = 0 0 1 1 0 1 1 REL9
|
// Instruction = BLT REL9, Op Code = 0 0 1 1 0 1 1 REL9
|
// Branch if Lower than Zero
|
// Branch if Lower than Zero
|
// If N ^ V = 1, then PC + $0002 + (REL9 << 1) => PC
|
// If N ^ V = 1, then PC + $0002 + (REL9 << 1) => PC
|
// Cycles - PP/P
|
// Cycles - PP/P
|
{CONT, 16'b0011011?????????} :
|
{CONT, 16'b0011011?????????} :
|
begin
|
begin
|
if (negative_flag ^ overflow_flag)
|
if (negative_flag ^ overflow_flag)
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = jump_offset;
|
pc_incr_mux = jump_offset;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
end
|
end
|
end
|
end
|
|
|
// Instruction = BGT REL9, Op Code = 0 0 1 1 1 0 0 REL9
|
// Instruction = BGT REL9, Op Code = 0 0 1 1 1 0 0 REL9
|
// Branch if Greater than Zero
|
// Branch if Greater than Zero
|
// If Z | (N ^ V) = 0, then PC + $0002 + (REL9 << 1) => PC
|
// If Z | (N ^ V) = 0, then PC + $0002 + (REL9 << 1) => PC
|
// Cycles - PP/P
|
// Cycles - PP/P
|
{CONT, 16'b0011100?????????} :
|
{CONT, 16'b0011100?????????} :
|
begin
|
begin
|
if (!(zero_flag || (negative_flag ^ overflow_flag)))
|
if (!(zero_flag || (negative_flag ^ overflow_flag)))
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = jump_offset;
|
pc_incr_mux = jump_offset;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
end
|
end
|
end
|
end
|
|
|
// Instruction = BLE REL9, Op Code = 0 0 1 1 1 0 1 REL9
|
// Instruction = BLE REL9, Op Code = 0 0 1 1 1 0 1 REL9
|
// Branch if Less or Equal to Zero
|
// Branch if Less or Equal to Zero
|
// If Z | (N ^ V) = 1, then PC + $0002 + (REL9 << 1) => PC
|
// If Z | (N ^ V) = 1, then PC + $0002 + (REL9 << 1) => PC
|
// Cycles - PP/P
|
// Cycles - PP/P
|
{CONT, 16'b0011101?????????} :
|
{CONT, 16'b0011101?????????} :
|
begin
|
begin
|
if (zero_flag || (negative_flag ^ overflow_flag))
|
if (zero_flag || (negative_flag ^ overflow_flag))
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = jump_offset;
|
pc_incr_mux = jump_offset;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
end
|
end
|
end
|
end
|
|
|
// Instruction = BRA REL10, Op Code = 0 0 1 1 1 1 REL10
|
// Instruction = BRA REL10, Op Code = 0 0 1 1 1 1 REL10
|
// Branch Always, signed offset
|
// Branch Always, signed offset
|
// PC + $0002 + (REL10 << 1) => PC
|
// PC + $0002 + (REL10 << 1) => PC
|
// Cycles - PP
|
// Cycles - PP
|
{CONT, 16'b001111??????????} :
|
{CONT, 16'b001111??????????} :
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = bra_offset;
|
pc_incr_mux = bra_offset;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
end
|
end
|
|
|
|
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
// Instruction Group -- Load and Store Instructions
|
// Instruction Group -- Load and Store Instructions
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
|
|
// Instruction = LDB RD, (RB, #OFFS5), Op Code = 0 1 0 0 0 RD RB OFFS5
|
// Instruction = LDB RD, (RB, #OFFS5), Op Code = 0 1 0 0 0 RD RB OFFS5
|
// Load Byte from Memory, unsigned offset
|
// Load Byte from Memory, unsigned offset
|
// M[RB, #OFFS5] => RD.L; $00 => RD.H
|
// M[RB, #OFFS5] => RD.L; $00 => RD.H
|
// RB field == RS1 field
|
// RB field == RS1 field
|
// Cycles - Pr
|
// Cycles - Pr
|
{CONT, 16'b01000???????????} :
|
{CONT, 16'b01000???????????} :
|
begin
|
begin
|
next_cpu_state = B_LOAD;
|
next_cpu_state = B_LOAD;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
data_access = 1'b1;
|
data_access = 1'b1;
|
data_address = rs1_data + {11'b0, op_code[4:0]};
|
data_address = rs1_data + {11'b0, op_code[4:0]};
|
end
|
end
|
|
|
// Instruction = LDW RD, (RB, #OFFS5), Op Code = 0 1 0 0 1 RD RB OFFS5
|
// Instruction = LDW RD, (RB, #OFFS5), Op Code = 0 1 0 0 1 RD RB OFFS5
|
// Load Word from Memory, unsigned offset
|
// Load Word from Memory, unsigned offset
|
// M[RB, #OFFS5] => RD
|
// M[RB, #OFFS5] => RD
|
// RB field == RS1 field
|
// RB field == RS1 field
|
// Cycles - PR
|
// Cycles - PR
|
{CONT, 16'b01001???????????} :
|
{CONT, 16'b01001???????????} :
|
begin
|
begin
|
next_cpu_state = W_LOAD;
|
next_cpu_state = W_LOAD;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
data_access = 1'b1;
|
data_access = 1'b1;
|
data_address = rs1_data + {11'b0, op_code[4:0]};
|
data_address = rs1_data + {11'b0, op_code[4:0]};
|
data_word_op = 1'b1;
|
data_word_op = 1'b1;
|
end
|
end
|
|
|
// Instruction = STB RS, (RB, #OFFS5), Op Code = 0 1 0 1 0 RS RB OFFS5
|
// Instruction = STB RS, (RB, #OFFS5), Op Code = 0 1 0 1 0 RS RB OFFS5
|
// Store Byte to Memory, unsigned offset
|
// Store Byte to Memory, unsigned offset
|
// RS.L => M[RB, #OFFS5]
|
// RS.L => M[RB, #OFFS5]
|
// RS field == RD fieild, RB field == RS1 field
|
// RS field == RD fieild, RB field == RS1 field
|
// Cycles - Pw
|
// Cycles - Pw
|
{CONT, 16'b01010???????????} :
|
{CONT, 16'b01010???????????} :
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
data_access = 1'b1;
|
data_access = 1'b1;
|
data_write = 1'b1;
|
data_write = 1'b1;
|
data_address = rs1_data + {11'b0, op_code[4:0]};
|
data_address = rs1_data + {11'b0, op_code[4:0]};
|
end
|
end
|
|
|
// Instruction = STW RS, (RB, #OFFS5), Op Code = 0 1 0 1 1 RS RB OFFS5
|
// Instruction = STW RS, (RB, #OFFS5), Op Code = 0 1 0 1 1 RS RB OFFS5
|
// Store Word to Memory, unsigned offset
|
// Store Word to Memory, unsigned offset
|
// RS => M[RB, #OFFS5]
|
// RS => M[RB, #OFFS5]
|
// RS field == RD fieild, RB field == RS1 field
|
// RS field == RD fieild, RB field == RS1 field
|
// Cycles - PW
|
// Cycles - PW
|
{CONT, 16'b01011???????????} :
|
{CONT, 16'b01011???????????} :
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
data_access = 1'b1;
|
data_access = 1'b1;
|
data_write = 1'b1;
|
data_write = 1'b1;
|
data_address = rs1_data + {11'b0, op_code[4:0]};
|
data_address = rs1_data + {11'b0, op_code[4:0]};
|
data_word_op = 1'b1;
|
data_word_op = 1'b1;
|
end
|
end
|
|
|
// Instruction = LDB RD, (RB, RI), Op Code = 0 1 1 0 0 RD RB RI 0 0
|
// Instruction = LDB RD, (RB, RI), Op Code = 0 1 1 0 0 RD RB RI 0 0
|
// Load Byte from Memory
|
// Load Byte from Memory
|
// M[RB, RI] => RD.L; $00 => RD.H
|
// M[RB, RI] => RD.L; $00 => RD.H
|
// RB field == RS1 field, RI field == RS2 field
|
// RB field == RS1 field, RI field == RS2 field
|
// Cycles - Pr
|
// Cycles - Pr
|
{CONT, 16'b01100?????????00} :
|
{CONT, 16'b01100?????????00} :
|
begin
|
begin
|
next_cpu_state = B_LOAD;
|
next_cpu_state = B_LOAD;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
data_access = 1'b1;
|
data_access = 1'b1;
|
data_address = rs1_data + rs2_data;
|
data_address = rs1_data + rs2_data;
|
end
|
end
|
|
|
// Instruction = LDW RD, (RB, RI), Op Code = 0 1 1 0 1 RD RB RI 0 0
|
// Instruction = LDW RD, (RB, RI), Op Code = 0 1 1 0 1 RD RB RI 0 0
|
// Load Word from Memory
|
// Load Word from Memory
|
// M[RB, RI] => RD
|
// M[RB, RI] => RD
|
// RB field == RS1 field, RI field == RS2 field
|
// RB field == RS1 field, RI field == RS2 field
|
// Cycles - PR
|
// Cycles - PR
|
{CONT, 16'b01101?????????00} :
|
{CONT, 16'b01101?????????00} :
|
begin
|
begin
|
next_cpu_state = W_LOAD;
|
next_cpu_state = W_LOAD;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
data_access = 1'b1;
|
data_access = 1'b1;
|
data_address = rs1_data + rs2_data;
|
data_address = rs1_data + rs2_data;
|
data_word_op = 1'b1;
|
data_word_op = 1'b1;
|
end
|
end
|
|
|
// Instruction = STB RS, (RB, RI), Op Code = 0 1 1 1 0 RS RB RI 0 0
|
// Instruction = STB RS, (RB, RI), Op Code = 0 1 1 1 0 RS RB RI 0 0
|
// RS.L => M[RB, RI]
|
// RS.L => M[RB, RI]
|
// Store Byte to Memory
|
// Store Byte to Memory
|
// RS field == RD fieild, RB field == RS1 field, RI field == RS2 field
|
// RS field == RD fieild, RB field == RS1 field, RI field == RS2 field
|
// Cycles - Pw
|
// Cycles - Pw
|
{CONT, 16'b01110?????????00} :
|
{CONT, 16'b01110?????????00} :
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
data_access = 1'b1;
|
data_access = 1'b1;
|
data_write = 1'b1;
|
data_write = 1'b1;
|
data_address = rs1_data + rs2_data;
|
data_address = rs1_data + rs2_data;
|
end
|
end
|
|
|
// Instruction = STW RS, (RB, RI), Op Code = 0 1 1 1 1 RS RB RI 0 0
|
// Instruction = STW RS, (RB, RI), Op Code = 0 1 1 1 1 RS RB RI 0 0
|
// Store Word to Memory
|
// Store Word to Memory
|
// RS => M[RB, RI]
|
// RS => M[RB, RI]
|
// RS field == RD fieild, RB field == RS1 field, RI field == RS2 field
|
// RS field == RD fieild, RB field == RS1 field, RI field == RS2 field
|
// Cycles - PW
|
// Cycles - PW
|
{CONT, 16'b01111?????????00} :
|
{CONT, 16'b01111?????????00} :
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
data_access = 1'b1;
|
data_access = 1'b1;
|
data_write = 1'b1;
|
data_write = 1'b1;
|
data_address = rs1_data + rs2_data;
|
data_address = rs1_data + rs2_data;
|
data_word_op = 1'b1;
|
data_word_op = 1'b1;
|
end
|
end
|
|
|
// Instruction = LDB RD, (RB, RI+), Op Code = 0 1 1 0 0 RD RB RI 0 1
|
// Instruction = LDB RD, (RB, RI+), Op Code = 0 1 1 0 0 RD RB RI 0 1
|
// Load Byte from Memory
|
// Load Byte from Memory
|
// M[RB, RI] => RD.L; $00 => RD.H; RI+1 => RI
|
// M[RB, RI] => RD.L; $00 => RD.H; RI+1 => RI
|
// If the same general purpose register is used as index (RI) and destination register (RD),
|
// If the same general purpose register is used as index (RI) and destination register (RD),
|
// the content of the register will not be incremented after the data move: M[RB, RI] => RD.L; $00 => RD.H
|
// the content of the register will not be incremented after the data move: M[RB, RI] => RD.L; $00 => RD.H
|
// RB field == RS1 field, RI field == RS2 field
|
// RB field == RS1 field, RI field == RS2 field
|
// Cycles - Pr
|
// Cycles - Pr
|
{CONT, 16'b01100?????????01} :
|
{CONT, 16'b01100?????????01} :
|
begin
|
begin
|
next_cpu_state = B_LOAD;
|
next_cpu_state = B_LOAD;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
data_access = 1'b1;
|
data_access = 1'b1;
|
data_address = rs1_data + rs2_data;
|
data_address = rs1_data + rs2_data;
|
alu_result = rs2_data + 16'h0001;
|
alu_result = rs2_data + 16'h0001;
|
sel_rd_field = 1'b0;
|
sel_rd_field = 1'b0;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
end
|
end
|
|
|
// Instruction = LDW RD, (RB, RI+), Op Code = 0 1 1 0 1 RD RB RI 0 1
|
// Instruction = LDW RD, (RB, RI+), Op Code = 0 1 1 0 1 RD RB RI 0 1
|
// Load Word from Memory
|
// Load Word from Memory
|
// M[RB, RI] => RD; RI+2 => RI
|
// M[RB, RI] => RD; RI+2 => RI
|
// If the same general purpose register is used as index (RI) and destination register (RD),
|
// If the same general purpose register is used as index (RI) and destination register (RD),
|
// the content of the register will not be incremented after the data move: M[RB, RI] => RD
|
// the content of the register will not be incremented after the data move: M[RB, RI] => RD
|
// RB field == RS1 field, RI field == RS2 field
|
// RB field == RS1 field, RI field == RS2 field
|
// Cycles - PR
|
// Cycles - PR
|
{CONT, 16'b01101?????????01} :
|
{CONT, 16'b01101?????????01} :
|
begin
|
begin
|
next_cpu_state = W_LOAD;
|
next_cpu_state = W_LOAD;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
data_access = 1'b1;
|
data_access = 1'b1;
|
data_address = rs1_data + rs2_data;
|
data_address = rs1_data + rs2_data;
|
data_word_op = 1'b1;
|
data_word_op = 1'b1;
|
alu_result = rs2_data + 16'h0002;
|
alu_result = rs2_data + 16'h0002;
|
sel_rd_field = 1'b0;
|
sel_rd_field = 1'b0;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
end
|
end
|
|
|
// Instruction = STB RS, (RB, RI+), Op Code = 0 1 1 1 0 RS RB RI 0 1
|
// Instruction = STB RS, (RB, RI+), Op Code = 0 1 1 1 0 RS RB RI 0 1
|
// Store Byte to Memory
|
// Store Byte to Memory
|
// RS.L => M[RB, RI]; RI+1 => RI
|
// RS.L => M[RB, RI]; RI+1 => RI
|
// RS field == RD fieild, RB field == RS1 field, RI field == RS2 field
|
// RS field == RD fieild, RB field == RS1 field, RI field == RS2 field
|
// Cycles - Pw
|
// Cycles - Pw
|
{CONT, 16'b01110?????????01} :
|
{CONT, 16'b01110?????????01} :
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
data_access = 1'b1;
|
data_access = 1'b1;
|
data_write = 1'b1;
|
data_write = 1'b1;
|
data_address = rs1_data + rs2_data;
|
data_address = rs1_data + rs2_data;
|
alu_result = rs2_data + 16'h0001;
|
alu_result = rs2_data + 16'h0001;
|
sel_rd_field = 1'b0;
|
sel_rd_field = 1'b0;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
end
|
end
|
|
|
// Instruction = STW RS, (RB, RI+), Op Code = 0 1 1 1 1 RS RB RI 0 1
|
// Instruction = STW RS, (RB, RI+), Op Code = 0 1 1 1 1 RS RB RI 0 1
|
// Store Word to Memory
|
// Store Word to Memory
|
// RS => M[RB, RI]; RI+2 => RI
|
// RS => M[RB, RI]; RI+2 => RI
|
// RS field == RD fieild, RB field == RS1 field, RI field == RS2 field
|
// RS field == RD fieild, RB field == RS1 field, RI field == RS2 field
|
// Cycles - PW
|
// Cycles - PW
|
{CONT, 16'b01111?????????01} :
|
{CONT, 16'b01111?????????01} :
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
data_access = 1'b1;
|
data_access = 1'b1;
|
data_write = 1'b1;
|
data_write = 1'b1;
|
data_word_op = 1'b1;
|
data_word_op = 1'b1;
|
data_address = rs1_data + rs2_data;
|
data_address = rs1_data + rs2_data;
|
alu_result = rs2_data + 16'h0002;
|
alu_result = rs2_data + 16'h0002;
|
sel_rd_field = 1'b0;
|
sel_rd_field = 1'b0;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
end
|
end
|
|
|
// Instruction = LDB RD, (RB, -RI), Op Code = 0 1 1 0 0 RD RB RI 1 0
|
// Instruction = LDB RD, (RB, -RI), Op Code = 0 1 1 0 0 RD RB RI 1 0
|
// Load Byte from Memory
|
// Load Byte from Memory
|
// RI-1 => RI; M[RS, RI] => RD.L; $00 => RD.H
|
// RI-1 => RI; M[RS, RI] => RD.L; $00 => RD.H
|
// RB field == RS1 field, RI field == RS2 field
|
// RB field == RS1 field, RI field == RS2 field
|
// Cycles - Pr
|
// Cycles - Pr
|
{CONT, 16'b01100?????????10} :
|
{CONT, 16'b01100?????????10} :
|
begin
|
begin
|
next_cpu_state = B_LOAD;
|
next_cpu_state = B_LOAD;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
data_access = 1'b1;
|
data_access = 1'b1;
|
alu_result = rs2_data + 16'hffff;
|
alu_result = rs2_data + 16'hffff;
|
data_address = rs1_data + alu_result;
|
data_address = rs1_data + alu_result;
|
sel_rd_field = 1'b0;
|
sel_rd_field = 1'b0;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
end
|
end
|
|
|
// Instruction = LDW RD, (RB, -RI), Op Code = 0 1 1 0 1 RD RB RI 1 0
|
// Instruction = LDW RD, (RB, -RI), Op Code = 0 1 1 0 1 RD RB RI 1 0
|
// Load Word from Memory
|
// Load Word from Memory
|
// RI-2 => RI; M[RS, RI] => RD
|
// RI-2 => RI; M[RS, RI] => RD
|
// RB field == RS1 field, RI field == RS2 field
|
// RB field == RS1 field, RI field == RS2 field
|
// Cycles - PR
|
// Cycles - PR
|
{CONT, 16'b01101?????????10} :
|
{CONT, 16'b01101?????????10} :
|
begin
|
begin
|
next_cpu_state = W_LOAD;
|
next_cpu_state = W_LOAD;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
data_access = 1'b1;
|
data_access = 1'b1;
|
alu_result = rs2_data + 16'hfffe;
|
alu_result = rs2_data + 16'hfffe;
|
data_address = rs1_data + alu_result;
|
data_address = rs1_data + alu_result;
|
data_word_op = 1'b1;
|
data_word_op = 1'b1;
|
sel_rd_field = 1'b0;
|
sel_rd_field = 1'b0;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
end
|
end
|
|
|
// Instruction = STB RS, (RB, -RI), Op Code = 0 1 1 1 0 RS RB RI 1 0
|
// Instruction = STB RS, (RB, -RI), Op Code = 0 1 1 1 0 RS RB RI 1 0
|
// Store Byte to Memory
|
// Store Byte to Memory
|
// RI-1 => RI; RS.L => M[RB, RI]
|
// RI-1 => RI; RS.L => M[RB, RI]
|
// If the same general purpose register is used as index (RI) and source register (RS),
|
// If the same general purpose register is used as index (RI) and source register (RS),
|
// the unmodified content of the source register is written to the memory: RS.L => M[RB, RS-1]; RS-1 => RS
|
// the unmodified content of the source register is written to the memory: RS.L => M[RB, RS-1]; RS-1 => RS
|
// RS field == RD fieild, RB field == RS1 field, RI field == RS2 field
|
// RS field == RD fieild, RB field == RS1 field, RI field == RS2 field
|
// Cycles - Pw
|
// Cycles - Pw
|
{CONT, 16'b01110?????????10} :
|
{CONT, 16'b01110?????????10} :
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
data_access = 1'b1;
|
data_access = 1'b1;
|
data_write = 1'b1;
|
data_write = 1'b1;
|
alu_result = rs2_data + 16'hffff;
|
alu_result = rs2_data + 16'hffff;
|
data_address = rs1_data + alu_result;
|
data_address = rs1_data + alu_result;
|
sel_rd_field = 1'b0;
|
sel_rd_field = 1'b0;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
end
|
end
|
|
|
// Instruction = STW RS, (RB, -RI), Op Code = 0 1 1 1 1 RS RB RI 1 0
|
// Instruction = STW RS, (RB, -RI), Op Code = 0 1 1 1 1 RS RB RI 1 0
|
// Store Word to Memory
|
// Store Word to Memory
|
// RI-2 => RI; RS => M[RB, RI]
|
// RI-2 => RI; RS => M[RB, RI]
|
// If the same general purpose register is used as index (RI) and source register (RS),
|
// If the same general purpose register is used as index (RI) and source register (RS),
|
// the unmodified content of the source register is written to the memory: RS => M[RB, RS-2]; RS-2 => RS
|
// the unmodified content of the source register is written to the memory: RS => M[RB, RS-2]; RS-2 => RS
|
// RS field == RD fieild, RB field == RS1 field, RI field == RS2 field
|
// RS field == RD fieild, RB field == RS1 field, RI field == RS2 field
|
// Cycles - PW
|
// Cycles - PW
|
{CONT, 16'b01111?????????10} :
|
{CONT, 16'b01111?????????10} :
|
begin
|
begin
|
next_cpu_state = S_STALL;
|
next_cpu_state = S_STALL;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
data_access = 1'b1;
|
data_access = 1'b1;
|
data_write = 1'b1;
|
data_write = 1'b1;
|
data_word_op = 1'b1;
|
data_word_op = 1'b1;
|
alu_result = rs2_data + 16'hfffe;
|
alu_result = rs2_data + 16'hfffe;
|
data_address = rs1_data + alu_result;
|
data_address = rs1_data + alu_result;
|
sel_rd_field = 1'b0;
|
sel_rd_field = 1'b0;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
end
|
end
|
|
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
// Instruction Group -- Bit Field Instructions
|
// Instruction Group -- Bit Field Instructions
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
|
|
// Instruction = BFEXT RD, RS1, RS2, Op Code = 0 1 1 0 0 RD RS1 RS2 1 1
|
// Instruction = BFEXT RD, RS1, RS2, Op Code = 0 1 1 0 0 RD RS1 RS2 1 1
|
// BFEXT - Bit Field Extract
|
// BFEXT - Bit Field Extract
|
// RS1[(o+w):o] => RD[w:0]; 0 => RD[15:(w+1)]
|
// RS1[(o+w):o] => RD[w:0]; 0 => RD[15:(w+1)]
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b01100?????????11} :
|
{CONT, 16'b01100?????????11} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
shift_ammount = {1'b0, rs2_data[3:0]};
|
shift_ammount = {1'b0, rs2_data[3:0]};
|
for (bfi = 0; bfi <= 15; bfi = bfi + 1)
|
for (bfi = 0; bfi <= 15; bfi = bfi + 1)
|
shift_in[bfi] = bf_mux_mask[bfi] ? rs1_data[bfi] : 1'b0;
|
shift_in[bfi] = bf_mux_mask[bfi] ? rs1_data[bfi] : 1'b0;
|
|
|
alu_result = shift_out;
|
alu_result = shift_out;
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// Instruction = BFINS RD, RS1, RS2, Op Code = 0 1 1 0 1 RD RS1 RS2 1 1
|
// Instruction = BFINS RD, RS1, RS2, Op Code = 0 1 1 0 1 RD RS1 RS2 1 1
|
// BFINS - Bit Field Insert
|
// BFINS - Bit Field Insert
|
// RS1[w:0] => RD[(w+o):o
|
// RS1[w:0] => RD[(w+o):o
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b01101?????????11} :
|
{CONT, 16'b01101?????????11} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
shift_left = 1'b1;
|
shift_left = 1'b1;
|
shift_ammount = {1'b0, rs2_data[3:0]};
|
shift_ammount = {1'b0, rs2_data[3:0]};
|
shift_in = rs1_data;
|
shift_in = rs1_data;
|
|
|
for (bfi = 0; bfi <= 15; bfi = bfi + 1)
|
for (bfi = 0; bfi <= 15; bfi = bfi + 1)
|
alu_result[bfi] = bf_mux_mask[bfi] ? shift_out[bfi] : rd_data[bfi];
|
alu_result[bfi] = bf_mux_mask[bfi] ? shift_out[bfi] : rd_data[bfi];
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// Instruction = BFINSI RD, RS1, RS2, Op Code = 0 1 1 1 0 RD RS1 RS2 1 1
|
// Instruction = BFINSI RD, RS1, RS2, Op Code = 0 1 1 1 0 RD RS1 RS2 1 1
|
// BFINSI - Bit Field Insert and Invert
|
// BFINSI - Bit Field Insert and Invert
|
// !RS1[w:0] => RD[w+o:o]
|
// !RS1[w:0] => RD[w+o:o]
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b01110?????????11} :
|
{CONT, 16'b01110?????????11} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
shift_left = 1'b1;
|
shift_left = 1'b1;
|
shift_ammount = {1'b0, rs2_data[3:0]};
|
shift_ammount = {1'b0, rs2_data[3:0]};
|
shift_in = rs1_data;
|
shift_in = rs1_data;
|
|
|
for (bfi = 0; bfi <= 15; bfi = bfi + 1)
|
for (bfi = 0; bfi <= 15; bfi = bfi + 1)
|
alu_result[bfi] = bf_mux_mask[bfi] ? !shift_out[bfi] : rd_data[bfi];
|
alu_result[bfi] = bf_mux_mask[bfi] ? !shift_out[bfi] : rd_data[bfi];
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// Instruction = BFINSX RD, RS1, RS2, Op Code = 0 1 1 1 1 RD RS1 RS2 1 1
|
// Instruction = BFINSX RD, RS1, RS2, Op Code = 0 1 1 1 1 RD RS1 RS2 1 1
|
// BFINSX - Bit Field Insert and XNOR
|
// BFINSX - Bit Field Insert and XNOR
|
// !(RS1[w:0] ^ RD[w+o:o]) => RD[w+o:o]
|
// !(RS1[w:0] ^ RD[w+o:o]) => RD[w+o:o]
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b01111?????????11} :
|
{CONT, 16'b01111?????????11} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
shift_left = 1'b1;
|
shift_left = 1'b1;
|
shift_ammount = {1'b0, rs2_data[3:0]};
|
shift_ammount = {1'b0, rs2_data[3:0]};
|
shift_in = rs1_data;
|
shift_in = rs1_data;
|
|
|
for (bfii = 0; bfii <= 15; bfii = bfii + 1)
|
for (bfii = 0; bfii <= 15; bfii = bfii + 1)
|
alu_result[bfii] = bf_mux_mask[bfii] ? !(shift_out[bfii] ^ rd_data[bfii]) : rd_data[bfii];
|
alu_result[bfii] = bf_mux_mask[bfii] ? !(shift_out[bfii] ^ rd_data[bfii]) : rd_data[bfii];
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
// Instruction Group -- Logic Immediate Instructions
|
// Instruction Group -- Logic Immediate Instructions
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
|
|
// Instruction = ANDL RD, #IMM8, Op Code = 1 0 0 0 0 RD IMM8
|
// Instruction = ANDL RD, #IMM8, Op Code = 1 0 0 0 0 RD IMM8
|
// AND - Logical AND
|
// AND - Logical AND
|
// RD.L & IMM8 => RD.L
|
// RD.L & IMM8 => RD.L
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b10000???????????} :
|
{CONT, 16'b10000???????????} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
|
|
alu_result = rd_data & {8'b0, op_code[7:0]};
|
alu_result = rd_data & {8'b0, op_code[7:0]};
|
next_zero = !(|alu_result[7:0]);
|
next_zero = !(|alu_result[7:0]);
|
next_negative = alu_result[7];
|
next_negative = alu_result[7];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// Instruction = ANDH RD, #IMM8, Op Code = 1 0 0 0 1 RD IMM8
|
// Instruction = ANDH RD, #IMM8, Op Code = 1 0 0 0 1 RD IMM8
|
// AND - Logical AND
|
// AND - Logical AND
|
// RD.H & IMM8 => RD.H
|
// RD.H & IMM8 => RD.H
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b10001???????????} :
|
{CONT, 16'b10001???????????} :
|
begin
|
begin
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
|
|
alu_result = rd_data & {op_code[7:0], 8'b0};
|
alu_result = rd_data & {op_code[7:0], 8'b0};
|
next_zero = !(|alu_result[15:8]);
|
next_zero = !(|alu_result[15:8]);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// Instruction = BITL RD, #IMM8, Op Code = 1 0 0 1 0 RD IMM8
|
// Instruction = BITL RD, #IMM8, Op Code = 1 0 0 1 0 RD IMM8
|
// RD.L & IMM8 => NONE
|
// RD.L & IMM8 => NONE
|
{CONT, 16'b10010???????????} :
|
{CONT, 16'b10010???????????} :
|
begin
|
begin
|
|
|
next_zero = !(|(rd_data[7:0] & op_code[7:0]));
|
next_zero = !(|(rd_data[7:0] & op_code[7:0]));
|
next_negative = rd_data[7] && op_code[7];
|
next_negative = rd_data[7] && op_code[7];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// Instruction = BITH RD, #IMM8, Op Code = 1 0 0 1 1 RD IMM8
|
// Instruction = BITH RD, #IMM8, Op Code = 1 0 0 1 1 RD IMM8
|
// RD.H & IMM8 => NONE
|
// RD.H & IMM8 => NONE
|
{CONT, 16'b10011???????????} :
|
{CONT, 16'b10011???????????} :
|
begin
|
begin
|
|
|
next_zero = !(|(rd_data[15:8] & op_code[7:0]));
|
next_zero = !(|(rd_data[15:8] & op_code[7:0]));
|
next_negative = rd_data[15] && op_code[7];
|
next_negative = rd_data[15] && op_code[7];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// Instruction = ORL RD, #IMM8, Op Code = 1 0 1 0 0 RD IMM8
|
// Instruction = ORL RD, #IMM8, Op Code = 1 0 1 0 0 RD IMM8
|
// OR - Logical OR
|
// OR - Logical OR
|
// RD.L | IMM8 => RD.L
|
// RD.L | IMM8 => RD.L
|
{CONT, 16'b10100???????????} :
|
{CONT, 16'b10100???????????} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
|
|
alu_result = rd_data | {8'b0, op_code[7:0]};
|
alu_result = rd_data | {8'b0, op_code[7:0]};
|
next_zero = !(|alu_result[7:0]);
|
next_zero = !(|alu_result[7:0]);
|
next_negative = alu_result[7];
|
next_negative = alu_result[7];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// Instruction = ORH RD, #IMM8, Op Code = 1 0 1 0 1 RD IMM8
|
// Instruction = ORH RD, #IMM8, Op Code = 1 0 1 0 1 RD IMM8
|
// OR - Logical OR
|
// OR - Logical OR
|
// RD.H | IMM8 => RD.H
|
// RD.H | IMM8 => RD.H
|
{CONT, 16'b10101???????????} :
|
{CONT, 16'b10101???????????} :
|
begin
|
begin
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
|
|
alu_result = rd_data | {op_code[7:0], 8'b0};
|
alu_result = rd_data | {op_code[7:0], 8'b0};
|
next_zero = !(|alu_result[15:8]);
|
next_zero = !(|alu_result[15:8]);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// Instruction = XNORL RD, #IMM8, Op Code = 1 0 1 1 0 RD IMM8
|
// Instruction = XNORL RD, #IMM8, Op Code = 1 0 1 1 0 RD IMM8
|
// XNOR - Logical Exclusive NOR
|
// XNOR - Logical Exclusive NOR
|
// ~(RD.L ^ IMM8) => RD.L
|
// ~(RD.L ^ IMM8) => RD.L
|
{CONT, 16'b10110???????????} :
|
{CONT, 16'b10110???????????} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
|
|
alu_result = ~(rd_data ^ {8'b0, op_code[7:0]});
|
alu_result = ~(rd_data ^ {8'b0, op_code[7:0]});
|
next_zero = !(|alu_result[7:0]);
|
next_zero = !(|alu_result[7:0]);
|
next_negative = alu_result[7];
|
next_negative = alu_result[7];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// Instruction = XNORH RD, #IMM8, Op Code = 1 0 1 1 1 RD IMM8
|
// Instruction = XNORH RD, #IMM8, Op Code = 1 0 1 1 1 RD IMM8
|
// XNOR - Logical Exclusive NOR
|
// XNOR - Logical Exclusive NOR
|
// ~(RD.H ^ IMM8) => RD.H
|
// ~(RD.H ^ IMM8) => RD.H
|
{CONT, 16'b10111???????????} :
|
{CONT, 16'b10111???????????} :
|
begin
|
begin
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
|
|
alu_result = ~(rd_data ^ {op_code[7:0], 8'b0});
|
alu_result = ~(rd_data ^ {op_code[7:0], 8'b0});
|
next_zero = !(|alu_result[15:8]);
|
next_zero = !(|alu_result[15:8]);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = 1'b0;
|
next_overflow = 1'b0;
|
end
|
end
|
|
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
// Instruction Group -- Arithmetic Immediate Instructions
|
// Instruction Group -- Arithmetic Immediate Instructions
|
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
|
|
// Instruction = SUBL RD, #IMM8, Op Code = 1 1 0 0 0 RD IMM8
|
// Instruction = SUBL RD, #IMM8, Op Code = 1 1 0 0 0 RD IMM8
|
// SUB - Subtract without Carry
|
// SUB - Subtract without Carry
|
// RD - $00:IMM8 => RD
|
// RD - $00:IMM8 => RD
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b11000???????????} :
|
{CONT, 16'b11000???????????} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
|
|
alu_result = rd_data - {8'b0, op_code[7:0]};
|
alu_result = rd_data - {8'b0, op_code[7:0]};
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_carry = (!rd_data[7] && op_code[7]) || (!rd_data[7] && alu_result[7]) || (op_code[7] && alu_result[7]);
|
next_carry = (!rd_data[7] && op_code[7]) || (!rd_data[7] && alu_result[7]) || (op_code[7] && alu_result[7]);
|
next_overflow = (rd_data[7] && !op_code[7] && !alu_result[7]) || (!rd_data[7] && op_code[7] && alu_result[7]);
|
next_overflow = (rd_data[7] && !op_code[7] && !alu_result[7]) || (!rd_data[7] && op_code[7] && alu_result[7]);
|
end
|
end
|
|
|
// Instruction = SUBH RD, #IMM8, Op Code = 1 1 0 0 1 RD IMM8
|
// Instruction = SUBH RD, #IMM8, Op Code = 1 1 0 0 1 RD IMM8
|
// SUB - Subtract without Carry
|
// SUB - Subtract without Carry
|
// RD - IMM8:$00 => RD
|
// RD - IMM8:$00 => RD
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b11001???????????} :
|
{CONT, 16'b11001???????????} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
|
|
{next_carry, alu_result} = rd_data - {op_code[7:0], 8'b0};
|
{next_carry, alu_result} = rd_data - {op_code[7:0], 8'b0};
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = (rd_data[15] && !op_code[7] && !alu_result[15]) || (!rd_data[15] && op_code[7] && alu_result[15]);
|
next_overflow = (rd_data[15] && !op_code[7] && !alu_result[15]) || (!rd_data[15] && op_code[7] && alu_result[15]);
|
end
|
end
|
|
|
// Instruction = CMPL RS, #IMM8, Op Code = 1 1 0 1 0 RS IMM8
|
// Instruction = CMPL RS, #IMM8, Op Code = 1 1 0 1 0 RS IMM8
|
// RS.L - IMM8 => NONE, only condition code flags get updated
|
// RS.L - IMM8 => NONE, only condition code flags get updated
|
// RS field == RD field
|
// RS field == RD field
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b11010???????????} :
|
{CONT, 16'b11010???????????} :
|
begin
|
begin
|
|
|
alu_result = {8'b0, rd_data[7:0] - op_code[7:0]};
|
alu_result = {8'b0, rd_data[7:0] - op_code[7:0]};
|
next_zero = !(|alu_result[7:0]);
|
next_zero = !(|alu_result[7:0]);
|
next_negative = alu_result[7];
|
next_negative = alu_result[7];
|
next_carry = (!rd_data[7] && op_code[7]) || (!rd_data[7] && alu_result[7]) || (op_code[7] && alu_result[7]);
|
next_carry = (!rd_data[7] && op_code[7]) || (!rd_data[7] && alu_result[7]) || (op_code[7] && alu_result[7]);
|
next_overflow = (rd_data[7] && !op_code[7] && !alu_result[7]) || (!rd_data[7] && op_code[7] && alu_result[7]);
|
next_overflow = (rd_data[7] && !op_code[7] && !alu_result[7]) || (!rd_data[7] && op_code[7] && alu_result[7]);
|
end
|
end
|
|
|
// Instruction = CPCH RS, #IMM8, Op Code = 1 1 0 1 1 RS IMM8
|
// Instruction = CPCH RS, #IMM8, Op Code = 1 1 0 1 1 RS IMM8
|
// RS.H - IMM8 - C => NONE, only condition code flags get updated
|
// RS.H - IMM8 - C => NONE, only condition code flags get updated
|
// RS field == RD field
|
// RS field == RD field
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b11011???????????} :
|
{CONT, 16'b11011???????????} :
|
begin
|
begin
|
|
|
alu_result = {rd_data[15:8], 8'b0} - {op_code[7:0], 8'b0} - {7'b0, carry_flag, 8'b0};
|
alu_result = {rd_data[15:8], 8'b0} - {op_code[7:0], 8'b0} - {7'b0, carry_flag, 8'b0};
|
next_zero = !(|alu_result[15:8]) && zero_flag;
|
next_zero = !(|alu_result[15:8]) && zero_flag;
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_carry = (!rd_data[15] && op_code[7]) || (!rd_data[15] && alu_result[15]) || (op_code[7] && alu_result[15]);
|
next_carry = (!rd_data[15] && op_code[7]) || (!rd_data[15] && alu_result[15]) || (op_code[7] && alu_result[15]);
|
next_overflow = (rd_data[15] && !op_code[7] && !alu_result[15]) || (!rd_data[15] && op_code[7] && alu_result[15]);
|
next_overflow = (rd_data[15] && !op_code[7] && !alu_result[15]) || (!rd_data[15] && op_code[7] && alu_result[15]);
|
end
|
end
|
|
|
// Instruction = ADDL RD, #IMM8, Op Code = 1 1 1 0 0 RD IMM8
|
// Instruction = ADDL RD, #IMM8, Op Code = 1 1 1 0 0 RD IMM8
|
// ADD - ADD without carry
|
// ADD - ADD without carry
|
// RD + $00:IMM8 => RD
|
// RD + $00:IMM8 => RD
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b11100???????????} :
|
{CONT, 16'b11100???????????} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
|
|
alu_result = rd_data + {8'b0, op_code[7:0]};
|
alu_result = rd_data + {8'b0, op_code[7:0]};
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_carry = (rd_data[7] && op_code[7]) || (rd_data[7] && !alu_result[7]) || (op_code[7] && !alu_result[7]);
|
next_carry = (rd_data[7] && op_code[7]) || (rd_data[7] && !alu_result[7]) || (op_code[7] && !alu_result[7]);
|
next_overflow = (!rd_data[7] && !op_code[7] && alu_result[7]) || (rd_data[7] && op_code[7] && !alu_result[7]);
|
next_overflow = (!rd_data[7] && !op_code[7] && alu_result[7]) || (rd_data[7] && op_code[7] && !alu_result[7]);
|
end
|
end
|
|
|
// Instruction = ADDH RD, #IMM8, Op Code = 1 1 1 0 1 RD IMM8
|
// Instruction = ADDH RD, #IMM8, Op Code = 1 1 1 0 1 RD IMM8
|
// ADD - ADD without carry
|
// ADD - ADD without carry
|
// RD + IMM8:$00 => RD
|
// RD + IMM8:$00 => RD
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b11101???????????} :
|
{CONT, 16'b11101???????????} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
|
|
{next_carry, alu_result} = rd_data + {op_code[7:0], 8'b0};
|
{next_carry, alu_result} = rd_data + {op_code[7:0], 8'b0};
|
next_zero = !(|alu_result);
|
next_zero = !(|alu_result);
|
next_negative = alu_result[15];
|
next_negative = alu_result[15];
|
next_overflow = (rd_data[15] && op_code[7] && !alu_result[15]) || (!rd_data[15] && !op_code[7] && alu_result[15]);
|
next_overflow = (rd_data[15] && op_code[7] && !alu_result[15]) || (!rd_data[15] && !op_code[7] && alu_result[15]);
|
end
|
end
|
|
|
// Instruction = LDL RD, #IMM8, Op Code = 1 1 1 1 0 RD IMM8
|
// Instruction = LDL RD, #IMM8, Op Code = 1 1 1 1 0 RD IMM8
|
// IMM8 => RD.L; $00 => RD.H, High Byte is cleared
|
// IMM8 => RD.L; $00 => RD.H, High Byte is cleared
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b11110???????????} :
|
{CONT, 16'b11110???????????} :
|
begin
|
begin
|
ena_rd_low_byte = 1'b1;
|
ena_rd_low_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
|
|
alu_result = {8'b0, op_code[7:0]};
|
alu_result = {8'b0, op_code[7:0]};
|
end
|
end
|
|
|
// Instruction = LDH RD, #IMM8, Op Code = 1 1 1 1 1 RD IMM8
|
// Instruction = LDH RD, #IMM8, Op Code = 1 1 1 1 1 RD IMM8
|
// IMM8 => RD.H, Low Byte is unchanged
|
// IMM8 => RD.H, Low Byte is unchanged
|
// Cycles - P
|
// Cycles - P
|
{CONT, 16'b11111???????????} :
|
{CONT, 16'b11111???????????} :
|
begin
|
begin
|
ena_rd_high_byte = 1'b1;
|
ena_rd_high_byte = 1'b1;
|
|
|
alu_result = {op_code[7:0], 8'b0};
|
alu_result = {op_code[7:0], 8'b0};
|
end
|
end
|
default :
|
default :
|
begin
|
begin
|
// synopsys translate_off
|
// synopsys translate_off
|
$display("\nOP Code Error\n");
|
$display("\nOP Code Error\n");
|
// synopsys translate_on
|
// synopsys translate_on
|
next_cpu_state = DEBUG;
|
next_cpu_state = DEBUG;
|
pc_incr_mux = 16'h0000;
|
pc_incr_mux = 16'h0000;
|
next_pc = pc_sum;
|
next_pc = pc_sum;
|
load_next_inst = 1'b0;
|
load_next_inst = 1'b0;
|
op_code_error = 1'b1;
|
op_code_error = 1'b1;
|
end
|
end
|
endcase
|
endcase
|
|
|
end // always
|
end // always
|
|
|
xgate_barrel_shift barrel_shift(
|
xgate_barrel_shift barrel_shift(
|
// outputs
|
// outputs
|
.shift_out( shift_out ),
|
.shift_out( shift_out ),
|
.shift_rollover( shift_rollover ),
|
.shift_rollover( shift_rollover ),
|
// inputs
|
// inputs
|
.shift_left( shift_left ),
|
.shift_left( shift_left ),
|
.shift_ammount( shift_ammount ),
|
.shift_ammount( shift_ammount ),
|
.shift_in( shift_in ),
|
.shift_in( shift_in ),
|
.shift_filler( shift_filler )
|
.shift_filler( shift_filler )
|
);
|
);
|
|
|
// Three to Eight line decoder
|
// Three to Eight line decoder
|
always @*
|
always @*
|
case (semaph_risc) // synopsys parallel_case
|
case (semaph_risc) // synopsys parallel_case
|
4'h0 : semap_risc_bit = 8'b0000_0001;
|
4'h0 : semap_risc_bit = 8'b0000_0001;
|
4'h1 : semap_risc_bit = 8'b0000_0010;
|
4'h1 : semap_risc_bit = 8'b0000_0010;
|
4'h2 : semap_risc_bit = 8'b0000_0100;
|
4'h2 : semap_risc_bit = 8'b0000_0100;
|
4'h3 : semap_risc_bit = 8'b0000_1000;
|
4'h3 : semap_risc_bit = 8'b0000_1000;
|
4'h4 : semap_risc_bit = 8'b0001_0000;
|
4'h4 : semap_risc_bit = 8'b0001_0000;
|
4'h5 : semap_risc_bit = 8'b0010_0000;
|
4'h5 : semap_risc_bit = 8'b0010_0000;
|
4'h6 : semap_risc_bit = 8'b0100_0000;
|
4'h6 : semap_risc_bit = 8'b0100_0000;
|
4'h7 : semap_risc_bit = 8'b1000_0000;
|
4'h7 : semap_risc_bit = 8'b1000_0000;
|
endcase
|
endcase
|
|
|
assign semaph_stat = |risc_semap;
|
assign semaph_stat = |risc_semap;
|
|
|
// Semaphore Bits
|
// Semaphore Bits
|
genvar sem_gen_count;
|
genvar sem_gen_count;
|
generate
|
generate
|
for (sem_gen_count = 0; sem_gen_count < 8; sem_gen_count = sem_gen_count + 1)
|
for (sem_gen_count = 0; sem_gen_count < 8; sem_gen_count = sem_gen_count + 1)
|
begin:semaphore_
|
begin:semaphore_
|
semaphore_bit bit(
|
semaphore_bit bit(
|
// outputs
|
// outputs
|
.host_status( host_semap[sem_gen_count] ),
|
.host_status( host_semap[sem_gen_count] ),
|
.risc_status( risc_semap[sem_gen_count] ),
|
.risc_status( risc_semap[sem_gen_count] ),
|
// inputs
|
// inputs
|
.risc_clk( risc_clk ),
|
.risc_clk( risc_clk ),
|
.async_rst_b( async_rst_b ),
|
.async_rst_b( async_rst_b ),
|
.risc_bit_sel( semap_risc_bit[sem_gen_count] ),
|
.risc_bit_sel( semap_risc_bit[sem_gen_count] ),
|
.csem( clear_semaph ),
|
.csem( clear_semaph ),
|
.ssem( set_semaph ),
|
.ssem( set_semaph ),
|
.host_wrt( write_xgsem ),
|
.host_wrt( write_xgsem ),
|
.host_bit_mask( perif_data[sem_gen_count+8] ),
|
.host_bit_mask( perif_data[sem_gen_count+8] ),
|
.host_bit( perif_data[sem_gen_count] )
|
.host_bit( perif_data[sem_gen_count] )
|
);
|
);
|
end
|
end
|
endgenerate
|
endgenerate
|
|
|
endmodule // xgate_inst_decode
|
endmodule // xgate_inst_decode
|
|
|
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
|
|
module xgate_barrel_shift (
|
module xgate_barrel_shift (
|
output reg [15:0] shift_out,
|
output reg [15:0] shift_out,
|
output reg shift_rollover,
|
output reg shift_rollover,
|
|
|
input shift_left,
|
input shift_left,
|
input [ 4:0] shift_ammount,
|
input [ 4:0] shift_ammount,
|
input [15:0] shift_in,
|
input [15:0] shift_in,
|
input [15:0] shift_filler
|
input [15:0] shift_filler
|
);
|
);
|
|
|
always @*
|
always @*
|
casez ({shift_left, shift_ammount}) // synopsys parallel_case
|
casez ({shift_left, shift_ammount}) // synopsys parallel_case
|
// Start Right Shifts
|
// Start Right Shifts
|
6'b0_0_0000 :
|
6'b0_0_0000 :
|
begin
|
begin
|
shift_out = shift_in;
|
shift_out = shift_in;
|
shift_rollover = 1'b0;
|
shift_rollover = 1'b0;
|
end
|
end
|
6'b0_0_0001 :
|
6'b0_0_0001 :
|
begin
|
begin
|
shift_out = {shift_filler[ 0], shift_in[15: 1]};
|
shift_out = {shift_filler[ 0], shift_in[15: 1]};
|
shift_rollover = shift_in[ 0];
|
shift_rollover = shift_in[ 0];
|
end
|
end
|
6'b0_0_0010 :
|
6'b0_0_0010 :
|
begin
|
begin
|
shift_out = {shift_filler[ 1:0], shift_in[15: 2]};
|
shift_out = {shift_filler[ 1:0], shift_in[15: 2]};
|
shift_rollover = shift_in[ 1];
|
shift_rollover = shift_in[ 1];
|
end
|
end
|
6'b0_0_0011 :
|
6'b0_0_0011 :
|
begin
|
begin
|
shift_out = {shift_filler[ 2:0], shift_in[15: 3]};
|
shift_out = {shift_filler[ 2:0], shift_in[15: 3]};
|
shift_rollover = shift_in[ 2];
|
shift_rollover = shift_in[ 2];
|
end
|
end
|
6'b0_0_0100 :
|
6'b0_0_0100 :
|
begin
|
begin
|
shift_out = {shift_filler[ 3:0], shift_in[15: 4]};
|
shift_out = {shift_filler[ 3:0], shift_in[15: 4]};
|
shift_rollover = shift_in[ 3];
|
shift_rollover = shift_in[ 3];
|
end
|
end
|
6'b0_0_0101 :
|
6'b0_0_0101 :
|
begin
|
begin
|
shift_out = {shift_filler[ 4:0], shift_in[15: 5]};
|
shift_out = {shift_filler[ 4:0], shift_in[15: 5]};
|
shift_rollover = shift_in[ 4];
|
shift_rollover = shift_in[ 4];
|
end
|
end
|
6'b0_0_0110 :
|
6'b0_0_0110 :
|
begin
|
begin
|
shift_out = {shift_filler[ 5:0], shift_in[15: 6]};
|
shift_out = {shift_filler[ 5:0], shift_in[15: 6]};
|
shift_rollover = shift_in[ 5];
|
shift_rollover = shift_in[ 5];
|
end
|
end
|
6'b0_0_0111 :
|
6'b0_0_0111 :
|
begin
|
begin
|
shift_out = {shift_filler[ 6:0], shift_in[15: 7]};
|
shift_out = {shift_filler[ 6:0], shift_in[15: 7]};
|
shift_rollover = shift_in[ 6];
|
shift_rollover = shift_in[ 6];
|
end
|
end
|
6'b0_0_1000 :
|
6'b0_0_1000 :
|
begin
|
begin
|
shift_out = {shift_filler[ 7:0], shift_in[15: 8]};
|
shift_out = {shift_filler[ 7:0], shift_in[15: 8]};
|
shift_rollover = shift_in[ 7];
|
shift_rollover = shift_in[ 7];
|
end
|
end
|
6'b0_0_1001 :
|
6'b0_0_1001 :
|
begin
|
begin
|
shift_out = {shift_filler[ 8:0], shift_in[15: 9]};
|
shift_out = {shift_filler[ 8:0], shift_in[15: 9]};
|
shift_rollover = shift_in[ 8];
|
shift_rollover = shift_in[ 8];
|
end
|
end
|
6'b0_0_1010 :
|
6'b0_0_1010 :
|
begin
|
begin
|
shift_out = {shift_filler[ 9:0], shift_in[15:10]};
|
shift_out = {shift_filler[ 9:0], shift_in[15:10]};
|
shift_rollover = shift_in[ 9];
|
shift_rollover = shift_in[ 9];
|
end
|
end
|
6'b0_0_1011 :
|
6'b0_0_1011 :
|
begin
|
begin
|
shift_out = {shift_filler[10:0], shift_in[15:11]};
|
shift_out = {shift_filler[10:0], shift_in[15:11]};
|
shift_rollover = shift_in[10];
|
shift_rollover = shift_in[10];
|
end
|
end
|
6'b0_0_1100 :
|
6'b0_0_1100 :
|
begin
|
begin
|
shift_out = {shift_filler[11:0], shift_in[15:12]};
|
shift_out = {shift_filler[11:0], shift_in[15:12]};
|
shift_rollover = shift_in[11];
|
shift_rollover = shift_in[11];
|
end
|
end
|
6'b0_0_1101 :
|
6'b0_0_1101 :
|
begin
|
begin
|
shift_out = {shift_filler[12:0], shift_in[15:13]};
|
shift_out = {shift_filler[12:0], shift_in[15:13]};
|
shift_rollover = shift_in[12];
|
shift_rollover = shift_in[12];
|
end
|
end
|
6'b0_0_1110 :
|
6'b0_0_1110 :
|
begin
|
begin
|
shift_out = {shift_filler[13:0], shift_in[15:14]};
|
shift_out = {shift_filler[13:0], shift_in[15:14]};
|
shift_rollover = shift_in[13];
|
shift_rollover = shift_in[13];
|
end
|
end
|
6'b0_0_1111 :
|
6'b0_0_1111 :
|
begin
|
begin
|
shift_out = {shift_filler[14:0], shift_in[15]};
|
shift_out = {shift_filler[14:0], shift_in[15]};
|
shift_rollover = shift_in[14];
|
shift_rollover = shift_in[14];
|
end
|
end
|
6'b0_1_???? :
|
6'b0_1_???? :
|
begin
|
begin
|
shift_out = shift_filler[15:0];
|
shift_out = shift_filler[15:0];
|
shift_rollover = shift_in[15];
|
shift_rollover = shift_in[15];
|
end
|
end
|
|
|
// Start Left Shifts
|
// Start Left Shifts
|
|
|
6'b1_0_0000 :
|
6'b1_0_0000 :
|
begin
|
begin
|
shift_out = shift_in;
|
shift_out = shift_in;
|
shift_rollover = 1'b0;
|
shift_rollover = 1'b0;
|
end
|
end
|
6'b1_0_0001 :
|
6'b1_0_0001 :
|
begin
|
begin
|
shift_out = {shift_in[14:0], shift_filler[15]};
|
shift_out = {shift_in[14:0], shift_filler[15]};
|
shift_rollover = shift_in[15];
|
shift_rollover = shift_in[15];
|
end
|
end
|
6'b1_0_0010 :
|
6'b1_0_0010 :
|
begin
|
begin
|
shift_out = {shift_in[13:0], shift_filler[15:14]};
|
shift_out = {shift_in[13:0], shift_filler[15:14]};
|
shift_rollover = shift_in[14];
|
shift_rollover = shift_in[14];
|
end
|
end
|
6'b1_0_0011 :
|
6'b1_0_0011 :
|
begin
|
begin
|
shift_out = {shift_in[12:0], shift_filler[15:13]};
|
shift_out = {shift_in[12:0], shift_filler[15:13]};
|
shift_rollover = shift_in[13];
|
shift_rollover = shift_in[13];
|
end
|
end
|
6'b1_0_0100 :
|
6'b1_0_0100 :
|
begin
|
begin
|
shift_out = {shift_in[11:0], shift_filler[15:12]};
|
shift_out = {shift_in[11:0], shift_filler[15:12]};
|
shift_rollover = shift_in[12];
|
shift_rollover = shift_in[12];
|
end
|
end
|
6'b1_0_0101 :
|
6'b1_0_0101 :
|
begin
|
begin
|
shift_out = {shift_in[10:0], shift_filler[15:11]};
|
shift_out = {shift_in[10:0], shift_filler[15:11]};
|
shift_rollover = shift_in[11];
|
shift_rollover = shift_in[11];
|
end
|
end
|
6'b1_0_0110 :
|
6'b1_0_0110 :
|
begin
|
begin
|
shift_out = {shift_in[ 9:0], shift_filler[15:10]};
|
shift_out = {shift_in[ 9:0], shift_filler[15:10]};
|
shift_rollover = shift_in[10];
|
shift_rollover = shift_in[10];
|
end
|
end
|
6'b1_0_0111 :
|
6'b1_0_0111 :
|
begin
|
begin
|
shift_out = {shift_in[ 8:0], shift_filler[15: 9]};
|
shift_out = {shift_in[ 8:0], shift_filler[15: 9]};
|
shift_rollover = shift_in[ 9];
|
shift_rollover = shift_in[ 9];
|
end
|
end
|
6'b1_0_1000 :
|
6'b1_0_1000 :
|
begin
|
begin
|
shift_out = {shift_in[ 7:0], shift_filler[15: 8]};
|
shift_out = {shift_in[ 7:0], shift_filler[15: 8]};
|
shift_rollover = shift_in[ 8];
|
shift_rollover = shift_in[ 8];
|
end
|
end
|
6'b1_0_1001 :
|
6'b1_0_1001 :
|
begin
|
begin
|
shift_out = {shift_in[ 6:0], shift_filler[15: 7]};
|
shift_out = {shift_in[ 6:0], shift_filler[15: 7]};
|
shift_rollover = shift_in[ 7];
|
shift_rollover = shift_in[ 7];
|
end
|
end
|
6'b1_0_1010 :
|
6'b1_0_1010 :
|
begin
|
begin
|
shift_out = {shift_in[ 5:0], shift_filler[15: 6]};
|
shift_out = {shift_in[ 5:0], shift_filler[15: 6]};
|
shift_rollover = shift_in[ 6];
|
shift_rollover = shift_in[ 6];
|
end
|
end
|
6'b1_0_1011 :
|
6'b1_0_1011 :
|
begin
|
begin
|
shift_out = {shift_in[ 4:0], shift_filler[15: 5]};
|
shift_out = {shift_in[ 4:0], shift_filler[15: 5]};
|
shift_rollover = shift_in[ 5];
|
shift_rollover = shift_in[ 5];
|
end
|
end
|
6'b1_0_1100 :
|
6'b1_0_1100 :
|
begin
|
begin
|
shift_out = {shift_in[ 3:0], shift_filler[15 :4]};
|
shift_out = {shift_in[ 3:0], shift_filler[15 :4]};
|
shift_rollover = shift_in[ 4];
|
shift_rollover = shift_in[ 4];
|
end
|
end
|
6'b1_0_1101 :
|
6'b1_0_1101 :
|
begin
|
begin
|
shift_out = {shift_in[ 2:0], shift_filler[15: 3]};
|
shift_out = {shift_in[ 2:0], shift_filler[15: 3]};
|
shift_rollover = shift_in[ 3];
|
shift_rollover = shift_in[ 3];
|
end
|
end
|
6'b1_0_1110 :
|
6'b1_0_1110 :
|
begin
|
begin
|
shift_out = {shift_in[ 1:0], shift_filler[15: 2]};
|
shift_out = {shift_in[ 1:0], shift_filler[15: 2]};
|
shift_rollover = shift_in[ 2];
|
shift_rollover = shift_in[ 2];
|
end
|
end
|
6'b1_0_1111 :
|
6'b1_0_1111 :
|
begin
|
begin
|
shift_out = {shift_in[ 0], shift_filler[15: 1]};
|
shift_out = {shift_in[ 0], shift_filler[15: 1]};
|
shift_rollover = shift_in[ 1];
|
shift_rollover = shift_in[ 1];
|
end
|
end
|
6'b1_1_???? :
|
6'b1_1_???? :
|
begin
|
begin
|
shift_out = shift_filler[15: 0];
|
shift_out = shift_filler[15: 0];
|
shift_rollover = shift_in[ 0];
|
shift_rollover = shift_in[ 0];
|
end
|
end
|
endcase
|
endcase
|
|
|
|
|
endmodule // xgate_barrel_shift
|
endmodule // xgate_barrel_shift
|
|
|
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
|
|
module semaphore_bit #(parameter NO_LOCK = 2'b00,
|
module semaphore_bit #(parameter NO_LOCK = 2'b00,
|
parameter RISC_LOCK = 2'b10,
|
parameter RISC_LOCK = 2'b10,
|
parameter HOST_LOCK = 2'b11)
|
parameter HOST_LOCK = 2'b11)
|
(
|
(
|
output host_status, // Return status for Host processor
|
output host_status, // Return status for Host processor
|
output risc_status, // Return Status for RISC processor
|
output risc_status, // Return Status for RISC processor
|
|
|
input risc_clk, // Semaphore register clock
|
input risc_clk, // Semaphore register clock
|
input async_rst_b, // Async reset signal
|
input async_rst_b, // Async reset signal
|
input risc_bit_sel, // Bit selected by RISC
|
input risc_bit_sel, // Bit selected by RISC
|
input csem, // RISC Clear Semaphore Bit
|
input csem, // RISC Clear Semaphore Bit
|
input ssem, // RISC Set Semaphore Bit
|
input ssem, // RISC Set Semaphore Bit
|
input host_wrt, // Host write to the Semaphore Register
|
input host_wrt, // Host write to the Semaphore Register
|
input host_bit_mask, // Host mask bit written to the Semaphore bit
|
input host_bit_mask, // Host mask bit written to the Semaphore bit
|
input host_bit // Host bit written to the Semaphore bit
|
input host_bit // Host bit written to the Semaphore bit
|
);
|
);
|
|
|
reg [1:0] next_semap_state;
|
reg [1:0] next_semap_state;
|
reg [1:0] semap_state;
|
reg [1:0] semap_state;
|
|
|
assign host_status = semap_state == HOST_LOCK;
|
assign host_status = semap_state == HOST_LOCK;
|
assign risc_status = ssem && risc_bit_sel && ((semap_state == RISC_LOCK) || (next_semap_state == RISC_LOCK));
|
assign risc_status = ssem && risc_bit_sel && ((semap_state == RISC_LOCK) || (next_semap_state == RISC_LOCK));
|
|
|
always @(posedge risc_clk or negedge async_rst_b)
|
always @(posedge risc_clk or negedge async_rst_b)
|
if (!async_rst_b)
|
if (!async_rst_b)
|
semap_state <= NO_LOCK;
|
semap_state <= NO_LOCK;
|
else
|
else
|
semap_state <= next_semap_state;
|
semap_state <= next_semap_state;
|
|
|
always @*
|
always @*
|
begin
|
begin
|
case(semap_state)
|
case(semap_state)
|
NO_LOCK:
|
NO_LOCK:
|
begin
|
begin
|
if (host_wrt && host_bit_mask && host_bit)
|
if (host_wrt && host_bit_mask && host_bit)
|
next_semap_state = HOST_LOCK;
|
next_semap_state = HOST_LOCK;
|
else if (ssem && risc_bit_sel)
|
else if (ssem && risc_bit_sel)
|
next_semap_state = RISC_LOCK;
|
next_semap_state = RISC_LOCK;
|
else
|
else
|
next_semap_state = NO_LOCK;
|
next_semap_state = NO_LOCK;
|
end
|
end
|
RISC_LOCK:
|
RISC_LOCK:
|
begin
|
begin
|
if (csem && risc_bit_sel)
|
if (csem && risc_bit_sel)
|
next_semap_state = NO_LOCK;
|
next_semap_state = NO_LOCK;
|
else
|
else
|
next_semap_state = RISC_LOCK;
|
next_semap_state = RISC_LOCK;
|
end
|
end
|
HOST_LOCK:
|
HOST_LOCK:
|
begin
|
begin
|
if (host_wrt && host_bit_mask && !host_bit)
|
if (host_wrt && host_bit_mask && !host_bit)
|
next_semap_state = NO_LOCK;
|
next_semap_state = NO_LOCK;
|
else
|
else
|
next_semap_state = HOST_LOCK;
|
next_semap_state = HOST_LOCK;
|
end
|
end
|
default:
|
default:
|
next_semap_state = NO_LOCK;
|
next_semap_state = NO_LOCK;
|
endcase
|
endcase
|
end
|
end
|
|
|
endmodule // semaphore_bit
|
endmodule // semaphore_bit
|
|
|
|
|
|
|