- added
git-svn-id: http://moon:8086/svn/vhdl/trunk@1423 cc03376c-175c-47c8-b038-4cd826a8556b
This commit is contained in:
@@ -0,0 +1,854 @@
|
||||
--------------------------------------------------------------------------
|
||||
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
||||
-- This file: Types, constants and functions for JCPU
|
||||
--
|
||||
-- Copyright (C) 2007 J. Ahrensfeld
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
--
|
||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.numeric_std.ALL;
|
||||
|
||||
|
||||
package cpu_pkg is
|
||||
|
||||
-- Revision of the CPU
|
||||
constant REVISION : integer := 2;
|
||||
|
||||
-- Chipram depth (can be tweaked)
|
||||
constant CHIPRAM_SIZE_BITS : integer := 10;
|
||||
|
||||
-- Chipregister file depth
|
||||
constant CHIPREG_SIZE_BITS : integer := 8;
|
||||
|
||||
-- Number of registers (can be tweaked)
|
||||
constant REG_SIZE_BITS : integer := 4;
|
||||
|
||||
-- Instruction memory
|
||||
constant IMEM_ADDR_WIDTH : integer := 12;
|
||||
|
||||
-- Data memory
|
||||
constant DMEM_DATA_WIDTH : integer := 8;
|
||||
constant DMEM_ADDR_WIDTH : integer := 8;
|
||||
|
||||
-- Instruction format
|
||||
constant INST_OPCODE_WIDTH : integer := 6;
|
||||
constant IMEM_DATA_WIDTH : integer := INST_OPCODE_WIDTH + DMEM_DATA_WIDTH + REG_SIZE_BITS;
|
||||
|
||||
-- Microcode ROM
|
||||
constant MUCODE_ADDR_WIDTH : integer := 9;
|
||||
|
||||
-- Stack depth
|
||||
constant STACK_SIZE_BITS : integer := CHIPRAM_SIZE_BITS-1;
|
||||
|
||||
--Types
|
||||
subtype iphase_t is integer range 0 to 1;
|
||||
type mem_access_t is (cmem_access, xmem_access, cio_access, xio_access);
|
||||
type reg_src_t is (alu_src, stk_src, cmem_src, xmem_src);
|
||||
type alu_src_t is (reg_a, reg_b, const);
|
||||
type ddata_src_t is (reg_a, reg_b, const);
|
||||
type daddr_src_t is (reg_a, reg_b, const);
|
||||
subtype instr_name_t is string(1 to 12);
|
||||
type instr_name_array_t is array (0 to 63) of instr_name_t;
|
||||
subtype opcode_t is unsigned (INST_OPCODE_WIDTH-1 downto 0);
|
||||
subtype inst_data_t is unsigned (IMEM_ADDR_WIDTH-1 downto 0);
|
||||
subtype inst_addr_t is unsigned (IMEM_ADDR_WIDTH-1 downto 0);
|
||||
subtype inst_t is unsigned (IMEM_DATA_WIDTH-1 downto 0);
|
||||
subtype dmem_data_t is unsigned (DMEM_DATA_WIDTH-1 downto 0);
|
||||
subtype dmem_addr_t is unsigned (DMEM_DATA_WIDTH-1 downto 0);
|
||||
subtype reg_ptr_t is unsigned (3 downto 0);
|
||||
type dmem_array_t is array (natural range <>) of dmem_data_t;
|
||||
type instr_addr_array is array (integer range <>) of inst_addr_t;
|
||||
subtype page_sel_t is unsigned (CHIPRAM_SIZE_BITS-DMEM_DATA_WIDTH-2 downto 0);
|
||||
|
||||
type alu_op_t is
|
||||
(
|
||||
pass_op2,
|
||||
op1_add_op2,
|
||||
op1_sub_op2,
|
||||
op1_addc_op2,
|
||||
op1_subc_op2,
|
||||
op1_and_op2,
|
||||
op1_or_op2,
|
||||
op1_xor_op2,
|
||||
swap_op,
|
||||
shl_op,
|
||||
shr_op,
|
||||
rol_op,
|
||||
ror_op,
|
||||
rolc_op,
|
||||
rorc_op
|
||||
);
|
||||
|
||||
type alu_status_t is record
|
||||
zero : STD_LOGIC;
|
||||
carry : STD_LOGIC;
|
||||
end record;
|
||||
|
||||
type cpu_status_t is record
|
||||
alu : alu_status_t;
|
||||
end record;
|
||||
|
||||
type ctrl_lines_t is record
|
||||
reg_we : STD_LOGIC;
|
||||
reg_src_sel : reg_src_t;
|
||||
alu_op1_src_sel : alu_src_t;
|
||||
alu_op2_src_sel : alu_src_t;
|
||||
alu_opsel : alu_op_t;
|
||||
alu_load : STD_LOGIC;
|
||||
ddata_src_sel : ddata_src_t;
|
||||
daddr_src_sel : daddr_src_t;
|
||||
pc_load : STD_LOGIC;
|
||||
pc_inc : STD_LOGIC;
|
||||
stk_push : STD_LOGIC;
|
||||
stk_pop : STD_LOGIC;
|
||||
stk_pushd : STD_LOGIC;
|
||||
stk_popd : STD_LOGIC;
|
||||
mem_access : mem_access_t;
|
||||
mem_read : STD_LOGIC;
|
||||
mem_write : STD_LOGIC;
|
||||
int_exit : STD_LOGIC;
|
||||
end record;
|
||||
|
||||
type dpath_ctrl_out_t is record
|
||||
lines : ctrl_lines_t;
|
||||
reg_a_ptr : reg_ptr_t;
|
||||
reg_b_ptr : reg_ptr_t;
|
||||
end record;
|
||||
|
||||
type int_ctrl_in_t is record
|
||||
enable : std_logic;
|
||||
polarity : std_logic;
|
||||
edge_sens : std_logic;
|
||||
request : std_logic;
|
||||
end record;
|
||||
|
||||
type creg_ctrl_out_t is record
|
||||
page_sel : page_sel_t;
|
||||
int_ctrl : int_ctrl_in_t;
|
||||
stk_high : unsigned(IMEM_ADDR_WIDTH-DMEM_ADDR_WIDTH-1 downto 0);
|
||||
cmem_high : unsigned(IMEM_ADDR_WIDTH-DMEM_ADDR_WIDTH-1 downto 0);
|
||||
end record;
|
||||
|
||||
type creg_ctrl_in_t is record
|
||||
alu : alu_status_t;
|
||||
end record;
|
||||
|
||||
|
||||
type murom_t is array (0 to integer(2**MUCODE_ADDR_WIDTH)-1) of ctrl_lines_t;
|
||||
|
||||
constant instr_name_array : instr_name_array_t :=
|
||||
(
|
||||
"NOP ", -- 00
|
||||
"HALT ", -- 01
|
||||
"MOV|R|R ", -- 02
|
||||
"MOV|R|K ", -- 03
|
||||
"MOVX|R|Ri ", -- 04
|
||||
"MOVX|R|Ki ", -- 05
|
||||
"MOVX|Ri|R ", -- 06
|
||||
"MOVX|Ri|K ", -- 07
|
||||
"MOVX|Ki|R ", -- 08
|
||||
"MOVC|R|Ri ", -- 09
|
||||
"MOVC|R|Ki ", -- 0A
|
||||
"MOVC|Ri|R ", -- 0B
|
||||
"MOVC|Ri|K ", -- 0C
|
||||
"MOVC|Ki|R ", -- 0D
|
||||
"CMP|R|R ", -- 0E
|
||||
"CMP|R|K ", -- 0F
|
||||
"ADD|R|R ", -- 10
|
||||
"ADD|R|K ", -- 11
|
||||
"ADDC|R|R ", -- 12
|
||||
"ADDC|R|K ", -- 13
|
||||
"SUB|R|R ", -- 14
|
||||
"SUB|R|K ", -- 15
|
||||
"SUBC|R|R ", -- 16
|
||||
"SUBC|R|K ", -- 17
|
||||
"AND|R|R ", -- 18
|
||||
"AND|R|K ", -- 19
|
||||
"OR|R|R ", -- 1A
|
||||
"OR|R|K ", -- 1B
|
||||
"XOR|R|R ", -- 1C
|
||||
"XOR|R|K ", -- 1D
|
||||
"SHL|R ", -- 1E
|
||||
"SHR|R ", -- 1F
|
||||
"ROL|R ", -- 20
|
||||
"ROR|R ", -- 21
|
||||
"ROLC|R ", -- 22
|
||||
"RORC|R ", -- 23
|
||||
"XOUT|Ki|R ", -- 24
|
||||
"XOUT|Ri|K ", -- 25
|
||||
"COUT|Ki|R ", -- 26
|
||||
"COUT|Ri|K ", -- 27
|
||||
"XIN|R|Ki ", -- 28
|
||||
"CIN|R|Ki ", -- 29
|
||||
"SWAP|R ", -- 2A
|
||||
"UNDEF ", -- 2B
|
||||
"UNDEF ", -- 2C
|
||||
"UNDEF ", -- 2D
|
||||
"SUB|K|R ", -- 2E
|
||||
"SUBC|K|R ", -- 2F
|
||||
"JMP|K ", -- 30
|
||||
"JZ|K ", -- 31
|
||||
"JNZ|K ", -- 32
|
||||
"JC|K ", -- 33
|
||||
"JNC|K ", -- 34
|
||||
"JLT|K ", -- 35
|
||||
"JGT|K ", -- 36
|
||||
"JLE|K ", -- 37
|
||||
"JGE|K ", -- 38
|
||||
"JEQ|K ", -- 39
|
||||
"JNE|K ", -- 3A
|
||||
"CALL|K ", -- 3B
|
||||
"PUSH|R ", -- 3C
|
||||
"POP|R ", -- 3D
|
||||
"RET ", -- 3E
|
||||
"RETI " -- 3F
|
||||
);
|
||||
-- Functions
|
||||
function Instr(opcode : opcode_t) return inst_t;
|
||||
function Instr(opcode : opcode_t; data : inst_data_t) return inst_t;
|
||||
function Instr(opcode : opcode_t; data : inst_data_t; reg : integer) return inst_t;
|
||||
function Instr(opcode : opcode_t; reg_a : integer) return inst_t;
|
||||
function Instr(opcode : opcode_t; reg_a, reg_b : integer) return inst_t;
|
||||
function Instr(opcode : opcode_t; reg_a, reg_b, reg_c : integer) return inst_t;
|
||||
function ctrl_lines_default return ctrl_lines_t;
|
||||
function idecoder(instr_name : instr_name_t; iphase : iphase_t; alu_status : alu_status_t) return ctrl_lines_t;
|
||||
function idecoder(opcode : opcode_t; iphase : iphase_t; alu_status : alu_status_t) return ctrl_lines_t;
|
||||
function gen_murom return murom_t;
|
||||
function get_muromaddr (opcode : opcode_t; iphase : iphase_t; alu_status : alu_status_t) return unsigned;
|
||||
function MIN (X, Y: INTEGER) return INTEGER;
|
||||
function MAX (X, Y: INTEGER) return INTEGER;
|
||||
|
||||
end cpu_pkg;
|
||||
|
||||
package body cpu_pkg is
|
||||
|
||||
function Instr(opcode : opcode_t) return inst_t is
|
||||
variable inst : inst_t := (others => '0');
|
||||
begin
|
||||
inst(inst_t'length-1 downto inst_t'length-opcode_t'length) := opcode;
|
||||
return inst;
|
||||
|
||||
end Instr;
|
||||
|
||||
function Instr(opcode : opcode_t; data : inst_data_t) return inst_t is
|
||||
variable inst : inst_t := (others => '0');
|
||||
begin
|
||||
inst(inst_t'length-1 downto inst_t'length-opcode_t'length) := opcode;
|
||||
inst(inst_t'length-opcode_t'length-1 downto inst_t'length-opcode_t'length-inst_addr_t'length) := data;
|
||||
return inst;
|
||||
|
||||
end Instr;
|
||||
|
||||
function Instr(opcode : opcode_t; data : inst_data_t; reg : integer) return inst_t is
|
||||
variable inst : inst_t := (others => '0');
|
||||
begin
|
||||
inst(inst_t'length-1 downto inst_t'length-opcode_t'length) := opcode;
|
||||
inst(inst_t'length-opcode_t'length-1 downto inst_t'length-opcode_t'length-inst_data_t'length) := data;
|
||||
inst(reg_ptr_t'length-1 downto 0) := reg_ptr_t(to_unsigned(reg, reg_ptr_t'length));
|
||||
|
||||
return inst;
|
||||
|
||||
end Instr;
|
||||
|
||||
function Instr(opcode : opcode_t; reg_a : integer) return inst_t is
|
||||
variable inst : inst_t := (others => '0');
|
||||
begin
|
||||
inst(inst_t'length-1 downto inst_t'length-opcode_t'length) := opcode;
|
||||
inst(reg_ptr_t'length-1 downto 0) := reg_ptr_t(to_unsigned(reg_a, reg_ptr_t'length));
|
||||
|
||||
return inst;
|
||||
|
||||
end Instr;
|
||||
|
||||
function Instr(opcode : opcode_t; reg_a, reg_b : integer) return inst_t is
|
||||
variable inst : inst_t := (others => '0');
|
||||
begin
|
||||
inst(inst_t'length-1 downto inst_t'length-opcode_t'length) := opcode;
|
||||
inst(2*(reg_ptr_t'length)-1 downto reg_ptr_t'length) := reg_ptr_t(to_unsigned(reg_b, reg_ptr_t'length));
|
||||
inst(reg_ptr_t'length-1 downto 0) := reg_ptr_t(to_unsigned(reg_a, reg_ptr_t'length));
|
||||
|
||||
return inst;
|
||||
|
||||
end Instr;
|
||||
|
||||
function Instr(opcode : opcode_t; reg_a, reg_b, reg_c : integer) return inst_t is
|
||||
variable inst : inst_t := (others => '0');
|
||||
begin
|
||||
inst(inst_t'length-1 downto inst_t'length-opcode_t'length) := opcode;
|
||||
inst(3*(reg_ptr_t'length)-1 downto 2*reg_ptr_t'length) := reg_ptr_t(to_unsigned(reg_c, reg_ptr_t'length));
|
||||
inst(2*(reg_ptr_t'length)-1 downto reg_ptr_t'length) := reg_ptr_t(to_unsigned(reg_b, reg_ptr_t'length));
|
||||
inst(reg_ptr_t'length-1 downto 0) := reg_ptr_t(to_unsigned(reg_a, reg_ptr_t'length));
|
||||
|
||||
return inst;
|
||||
|
||||
end Instr;
|
||||
|
||||
function ctrl_lines_default return ctrl_lines_t is
|
||||
variable result : ctrl_lines_t;
|
||||
begin
|
||||
result.pc_load := '0';
|
||||
result.pc_inc := '0';
|
||||
result.stk_push := '0';
|
||||
result.stk_pop := '0';
|
||||
result.stk_pushd := '0';
|
||||
result.stk_popd := '0';
|
||||
result.reg_we := '0';
|
||||
result.reg_src_sel := alu_src;
|
||||
result.ddata_src_sel := reg_a;
|
||||
result.daddr_src_sel := reg_b;
|
||||
result.alu_opsel := pass_op2;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_op2_src_sel := reg_b;
|
||||
result.alu_load := '0';
|
||||
result.mem_access := cmem_access;
|
||||
result.mem_read := '0';
|
||||
result.mem_write := '0';
|
||||
result.int_exit := '0';
|
||||
return result;
|
||||
|
||||
end ctrl_lines_default;
|
||||
|
||||
function idecoder(opcode : opcode_t; iphase : iphase_t; alu_status : alu_status_t) return ctrl_lines_t is
|
||||
variable instr_name : instr_name_t;
|
||||
begin
|
||||
instr_name := instr_name_array(to_integer(opcode));
|
||||
return idecoder(instr_name, iphase, alu_status);
|
||||
end idecoder;
|
||||
|
||||
function idecoder(instr_name : instr_name_t; iphase : iphase_t; alu_status : alu_status_t) return ctrl_lines_t is
|
||||
variable result : ctrl_lines_t;
|
||||
variable ze, cy : STD_LOGIC;
|
||||
|
||||
begin
|
||||
ze := alu_status.zero;
|
||||
cy := alu_status.carry;
|
||||
|
||||
result := ctrl_lines_default;
|
||||
if iphase = 0 then
|
||||
result.pc_inc := '1';
|
||||
end if;
|
||||
|
||||
case instr_name is
|
||||
|
||||
when "HALT " =>
|
||||
result.pc_inc := '0';
|
||||
when "MOV|R|R " => -- R(a) <= R(b)
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_opsel := pass_op2;
|
||||
result.alu_op2_src_sel := reg_b;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "MOV|R|K " => -- R(a) <= #kk
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_opsel := pass_op2;
|
||||
result.alu_op2_src_sel := const;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "MOVC|Ri|R " => -- [R(b)] <= R(a)
|
||||
result.mem_access := cmem_access;
|
||||
result.daddr_src_sel := reg_b;
|
||||
result.ddata_src_sel := reg_a;
|
||||
if iphase = 0 then
|
||||
result.mem_write := '1';
|
||||
end if;
|
||||
when "MOVC|Ri|K " => -- [R(a)] <= kk
|
||||
result.mem_access := cmem_access;
|
||||
result.daddr_src_sel := reg_a;
|
||||
result.ddata_src_sel := const;
|
||||
if iphase = 0 then
|
||||
result.mem_write := '1';
|
||||
end if;
|
||||
when "COUT|Ri|K " => -- [R(a)] <= kk
|
||||
result.mem_access := cio_access;
|
||||
result.daddr_src_sel := reg_a;
|
||||
result.ddata_src_sel := const;
|
||||
if iphase = 0 then
|
||||
result.mem_write := '1';
|
||||
end if;
|
||||
when "MOVC|R|Ri " => -- R(a) <= [R(b)]
|
||||
result.mem_access := cmem_access;
|
||||
result.reg_src_sel := cmem_src;
|
||||
result.daddr_src_sel := reg_b;
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "MOVC|R|Ki " => -- R(a) <= [#addr]
|
||||
result.mem_access := cmem_access;
|
||||
result.reg_src_sel := cmem_src;
|
||||
result.daddr_src_sel := const;
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "CIN|R|Ki " => -- R(a) <= [#addr]
|
||||
result.mem_access := cio_access;
|
||||
result.reg_src_sel := cmem_src;
|
||||
result.daddr_src_sel := const;
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "MOVC|Ki|R " => -- [#addr] <= R(a)
|
||||
result.mem_access := cmem_access;
|
||||
result.daddr_src_sel := const;
|
||||
result.ddata_src_sel := reg_a;
|
||||
if iphase = 0 then
|
||||
result.mem_write := '1';
|
||||
end if;
|
||||
when "COUT|Ki|R " => -- [#addr] <= R(a)
|
||||
result.mem_access := cio_access;
|
||||
result.daddr_src_sel := const;
|
||||
result.ddata_src_sel := reg_a;
|
||||
if iphase = 0 then
|
||||
result.mem_write := '1';
|
||||
end if;
|
||||
when "MOVX|Ri|R " => -- [R(b)] <= R(a)
|
||||
result.mem_access := xmem_access;
|
||||
result.daddr_src_sel := reg_b;
|
||||
result.ddata_src_sel := reg_a;
|
||||
if iphase = 0 then
|
||||
result.mem_write := '1';
|
||||
end if;
|
||||
when "MOVX|Ri|K " => -- [R(a)] <= kk
|
||||
result.mem_access := xmem_access;
|
||||
result.daddr_src_sel := reg_a;
|
||||
result.ddata_src_sel := const;
|
||||
if iphase = 0 then
|
||||
result.mem_write := '1';
|
||||
end if;
|
||||
when "XOUT|Ri|K " => -- [R(a)] <= kk
|
||||
result.mem_access := xio_access;
|
||||
result.daddr_src_sel := reg_a;
|
||||
result.ddata_src_sel := const;
|
||||
if iphase = 0 then
|
||||
result.mem_write := '1';
|
||||
end if;
|
||||
when "MOVX|R|Ri " => -- R(a) <= [R(b)]
|
||||
result.mem_access := xmem_access;
|
||||
result.reg_src_sel := xmem_src;
|
||||
result.daddr_src_sel := reg_b;
|
||||
if iphase = 0 then
|
||||
result.mem_read := '1';
|
||||
elsif iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "MOVX|R|Ki " => -- R(a) <= [#addr]
|
||||
result.mem_access := xmem_access;
|
||||
result.reg_src_sel := xmem_src;
|
||||
result.daddr_src_sel := const;
|
||||
if iphase = 0 then
|
||||
result.mem_read := '1';
|
||||
elsif iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "XIN|R|Ki " => -- R(a) <= [#addr]
|
||||
result.mem_access := xio_access;
|
||||
result.reg_src_sel := xmem_src;
|
||||
result.daddr_src_sel := const;
|
||||
if iphase = 0 then
|
||||
result.mem_read := '1';
|
||||
elsif iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "MOVX|Ki|R " => -- [#addr] <= R(a)
|
||||
result.mem_access := xmem_access;
|
||||
result.daddr_src_sel := const;
|
||||
result.ddata_src_sel := reg_a;
|
||||
if iphase = 0 then
|
||||
result.mem_write := '1';
|
||||
end if;
|
||||
when "XOUT|Ki|R " => -- [#addr] <= R(a)
|
||||
result.mem_access := xio_access;
|
||||
result.daddr_src_sel := const;
|
||||
result.ddata_src_sel := reg_a;
|
||||
if iphase = 0 then
|
||||
result.mem_write := '1';
|
||||
end if;
|
||||
when "ADD|R|R " => -- R(a) <= R(a) + R(b)
|
||||
result.alu_opsel := op1_add_op2;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_op2_src_sel := reg_b;
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "ADD|R|K " => -- R(a) <= R(a) + k
|
||||
result.alu_opsel := op1_add_op2;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_op2_src_sel := const;
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "ADDC|R|R " => -- R(a) <= R(a) + R(b)
|
||||
result.alu_opsel := op1_addc_op2;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_op2_src_sel := reg_b;
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "ADDC|R|K " => -- R(a) <= R(a) + k
|
||||
result.alu_opsel := op1_addc_op2;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_op2_src_sel := const;
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "SUB|R|R " => -- R(a) <= R(a) + R(b)
|
||||
result.alu_opsel := op1_sub_op2;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_op2_src_sel := reg_b;
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "SUB|R|K " => -- R(a) <= R(a) + k
|
||||
result.alu_opsel := op1_sub_op2;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_op2_src_sel := const;
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "SUB|K|R " => -- R(a) <= k - R(a)
|
||||
result.alu_opsel := op1_sub_op2;
|
||||
result.alu_op1_src_sel := const;
|
||||
result.alu_op2_src_sel := reg_a;
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "SUBC|R|R " => -- R(a) <= R(a) + R(b)
|
||||
result.alu_opsel := op1_subc_op2;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_op2_src_sel := reg_b;
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "SUBC|R|K " => -- R(a) <= R(a) + k
|
||||
result.alu_opsel := op1_subc_op2;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_op2_src_sel := const;
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "SUBC|K|R " => -- R(a) <= K - R(a)
|
||||
result.alu_opsel := op1_subc_op2;
|
||||
result.alu_op1_src_sel := const;
|
||||
result.alu_op2_src_sel := reg_a;
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "AND|R|R " => -- R(a) <= R(a) and R(b)
|
||||
result.alu_opsel := op1_and_op2;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_op2_src_sel := reg_b;
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "AND|R|K " => -- R(a) <= R(a) and k
|
||||
result.alu_opsel := op1_and_op2;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_op2_src_sel := const;
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "OR|R|R " => -- R(a) <= R(a) or R(b)
|
||||
result.alu_opsel := op1_or_op2;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_op2_src_sel := reg_b;
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "OR|R|K " => -- R(a) <= R(a) or R(b)
|
||||
result.alu_opsel := op1_or_op2;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_op2_src_sel := const;
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "XOR|R|R " => -- R(a) <= R(a) xor R(b)
|
||||
result.alu_opsel := op1_xor_op2;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_op2_src_sel := reg_b;
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "XOR|R|K " => -- R(a) <= R(a) xor R(b)
|
||||
result.alu_opsel := op1_xor_op2;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_op2_src_sel := const;
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "SWAP|R " => -- R(a) <= R(b)
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_opsel := swap_op;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "SHL|R " => -- R(a) <= R(a) xor R(b)
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_opsel := shl_op;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "SHR|R " => -- R(a) <= R(a) xor R(b)
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_opsel := shr_op;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "ROL|R " => -- R(a) <= R(a) xor R(b)
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_opsel := rol_op;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "ROR|R " => -- R(a) <= R(a) xor R(b)
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_opsel := ror_op;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "ROLC|R " => -- R(a) <= R(a) xor R(b)
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_opsel := rolc_op;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "RORC|R " => -- R(a) <= R(a) xor R(b)
|
||||
result.reg_src_sel := alu_src;
|
||||
result.alu_opsel := rorc_op;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_load := '1';
|
||||
if iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "CMP|R|R " => --
|
||||
result.alu_opsel := op1_sub_op2;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_op2_src_sel := reg_b;
|
||||
result.alu_load := '1';
|
||||
when "CMP|R|K " => --
|
||||
result.alu_opsel := op1_sub_op2;
|
||||
result.alu_op1_src_sel := reg_a;
|
||||
result.alu_op2_src_sel := const;
|
||||
result.alu_load := '1';
|
||||
when "JMP|K " => -- PC <= #addr
|
||||
if iphase = 0 then
|
||||
result.pc_load := '1';
|
||||
end if;
|
||||
when "JZ|K " => -- PC <= #addr, zero
|
||||
if iphase = 0 then
|
||||
if ze = '1' then
|
||||
result.pc_load := '1';
|
||||
end if;
|
||||
end if;
|
||||
when "JNZ|K " => -- PC <= #addr, !zero
|
||||
if iphase = 0 then
|
||||
if ze = '0' then
|
||||
result.pc_load := '1';
|
||||
end if;
|
||||
end if;
|
||||
when "JC|K " => -- PC <= #addr, carry
|
||||
if iphase = 0 then
|
||||
if cy = '1' then
|
||||
result.pc_load := '1';
|
||||
end if;
|
||||
end if;
|
||||
when "JNC|K " => -- PC <= #addr, !carry
|
||||
if iphase = 0 then
|
||||
if cy = '0' then
|
||||
result.pc_load := '1';
|
||||
end if;
|
||||
end if;
|
||||
when "JLT|K " => -- PC <= #addr, !carry
|
||||
if iphase = 0 then
|
||||
if cy = '1' then
|
||||
result.pc_load := '1';
|
||||
end if;
|
||||
end if;
|
||||
when "JGT|K " => --
|
||||
if iphase = 0 then
|
||||
if (cy or ze) = '0' then
|
||||
result.pc_load := '1';
|
||||
end if;
|
||||
end if;
|
||||
when "JLE|K " => --
|
||||
if iphase = 0 then
|
||||
if (cy xor ze) = '1' then
|
||||
result.pc_load := '1';
|
||||
end if;
|
||||
end if;
|
||||
when "JGE|K " => --
|
||||
if iphase = 0 then
|
||||
if (not cy or ze) = '1' then
|
||||
result.pc_load := '1';
|
||||
end if;
|
||||
end if;
|
||||
when "JEQ|K " => --
|
||||
if iphase = 0 then
|
||||
if ze = '1' then
|
||||
result.pc_load := '1';
|
||||
end if;
|
||||
end if;
|
||||
when "JNE|K " => --
|
||||
if iphase = 0 then
|
||||
if ze = '0' then
|
||||
result.pc_load := '1';
|
||||
end if;
|
||||
end if;
|
||||
when "PUSH|R " => -- push
|
||||
if iphase = 0 then
|
||||
result.stk_pushd := '1';
|
||||
end if;
|
||||
when "POP|R " => -- pop
|
||||
result.reg_src_sel := stk_src;
|
||||
if iphase = 0 then
|
||||
result.stk_popd := '1';
|
||||
elsif iphase = 1 then
|
||||
result.reg_we := '1';
|
||||
end if;
|
||||
when "CALL|K " => -- call
|
||||
if iphase = 0 then
|
||||
result.pc_load := '1';
|
||||
result.stk_push := '1';
|
||||
end if;
|
||||
when "RET " => -- return
|
||||
if iphase = 0 then
|
||||
result.pc_load := '1';
|
||||
result.stk_pop := '1';
|
||||
end if;
|
||||
when "RETI " => -- return
|
||||
result.pc_inc := '0';
|
||||
result.int_exit := '1';
|
||||
|
||||
when others => null; -- nop
|
||||
end case;
|
||||
|
||||
return result;
|
||||
|
||||
end idecoder;
|
||||
|
||||
function gen_murom return murom_t is
|
||||
variable result : murom_t;
|
||||
variable opcode : opcode_t;
|
||||
variable iphase : iphase_t;
|
||||
variable addr : unsigned(MUCODE_ADDR_WIDTH-1 downto 0);
|
||||
variable alu_status : alu_status_t;
|
||||
variable pos : integer := 0;
|
||||
|
||||
begin
|
||||
for i in 0 to 2**addr'length-1 loop
|
||||
addr := to_unsigned(i, addr'length);
|
||||
opcode := addr(opcode'length-1 downto 0);
|
||||
pos := opcode'length;
|
||||
iphase := 0;
|
||||
if addr(pos) = '1' then
|
||||
iphase := 1;
|
||||
end if;
|
||||
pos := pos + 1;
|
||||
alu_status.zero := addr(pos);
|
||||
pos := pos + 1;
|
||||
alu_status.carry := addr(pos);
|
||||
|
||||
result(i) := idecoder(opcode, iphase, alu_status);
|
||||
end loop;
|
||||
|
||||
return result;
|
||||
end gen_murom;
|
||||
|
||||
function get_muromaddr (opcode : opcode_t; iphase : iphase_t; alu_status : alu_status_t) return unsigned is
|
||||
variable addr : unsigned(MUCODE_ADDR_WIDTH-1 downto 0);
|
||||
begin
|
||||
addr := alu_status.carry & alu_status.zero & to_unsigned(iphase, 1) & opcode;
|
||||
return addr;
|
||||
|
||||
end get_muromaddr;
|
||||
|
||||
-------------------------------------------------------------
|
||||
function MIN (X, Y: INTEGER) return INTEGER is
|
||||
variable res : integer := X;
|
||||
begin
|
||||
if Y < X then
|
||||
res := Y;
|
||||
end if;
|
||||
|
||||
return res;
|
||||
|
||||
end MIN;
|
||||
|
||||
-------------------------------------------------------------
|
||||
function MAX (X, Y: INTEGER) return INTEGER is
|
||||
variable res : integer := X;
|
||||
begin
|
||||
if Y > X then
|
||||
res := Y;
|
||||
end if;
|
||||
|
||||
return res;
|
||||
|
||||
end MAX;
|
||||
|
||||
|
||||
end cpu_pkg;
|
||||
|
||||
Reference in New Issue
Block a user