📄 regshiftmux_regshift.vhd
字号:
-- -----------------------------------------------------------------------------
-- CPU86 - VHDL CPU8088 IP core --
-- Copyright (C) 2005-2008 HT-LAB --
-- --
-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
-- Web : http://www.ht-lab.com --
-- --
-- CPU86 is released as open-source under the Aladdin Free Public License. --
-- Contact HT-Lab for commercial applications and/or support contracts. --
-- --
-- Full details of the license can be found in the file "cpu86_license.txt" --
-- which is included in the distribution zip file. --
-- -----------------------------------------------------------------------------
--
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.ALL;
USE work.cpu86pack.ALL;
USE work.cpu86instr.ALL;
ENTITY regshiftmux IS
PORT(
clk : IN std_logic;
dbus_in : IN std_logic_vector (7 DOWNTO 0);
flush_req : IN std_logic;
latchm : IN std_logic;
latcho : IN std_logic;
mux_addr : IN std_logic_vector (2 DOWNTO 0);
mux_data : IN std_logic_vector (3 DOWNTO 0);
mux_reg : IN std_logic_vector (2 DOWNTO 0);
nbreq : IN std_logic_vector (2 DOWNTO 0);
regplus1 : IN std_logic;
ldposplus1 : IN std_logic;
reset : IN std_logic;
irq : IN std_logic;
inta1 : IN std_logic; -- Added for ver 0.71
inta2_s : IN std_logic;
irq_type : IN std_logic_vector (1 DOWNTO 0);
instr : OUT instruction_type;
halt_instr : OUT std_logic;
lutbus : OUT std_logic_vector (15 DOWNTO 0);
reg1free : BUFFER std_logic;
reg1freed : BUFFER std_logic; -- Delayed version (1 clk) of reg1free
regnbok : OUT std_logic
);
-- Declarations
END regshiftmux ;
-- hds interface_end
architecture regshift of regshiftmux is
signal reg72_s : std_logic_vector(71 downto 0);
signal regcnt_s : std_logic_vector(3 downto 0); -- Note need possible 9 byte positions
signal ldpos_s : std_logic_vector(3 downto 0); -- redundant signal (=regcnt_s)
signal ireg_s : std_logic_vector(7 downto 0);
signal mod_s : std_logic_vector(1 downto 0);
signal rm_s : std_logic_vector(2 downto 0);
signal opcreg_s : std_logic_vector(2 downto 0);
signal opcdata_s: std_logic_vector(15 downto 0);
signal opcaddr_s: std_logic_vector(15 downto 0);
signal nbreq_s : std_logic_vector(2 downto 0); -- latched nbreq only for instr
signal flush_req1_s : std_logic; -- Delayed version of flush_req
signal flush_req2_s : std_logic; -- Delayed version of flush_req (address setup requires 2 clk cycle)
--pragma Synthesis_off
signal reg48_s : std_logic_vector(47 downto 0); -- Latched 6 bytes of reg72_s used for signal spy/hwmon only
--pragma Synthesis_on
begin
instr.ireg <= ireg_s;
instr.xmod <= mod_s;
instr.rm <= rm_s;
instr.reg <= opcreg_s;
instr.data <= opcdata_s(7 downto 0)&opcdata_s(15 downto 8);
instr.disp <= opcaddr_s(7 downto 0)&opcaddr_s(15 downto 8);
instr.nb <= nbreq_s; -- use latched version
halt_instr <= '1' when ireg_s=HLT else '0';
-------------------------------------------------------------------------
-- reg counter (how many bytes available in pre-fetch queue)
-- ldpos (load position in queue, if MSB=1 then ignore parts of word)
-- Don't forget resource sharing during synthesis :-)
-------------------------------------------------------------------------
process(reset,clk)
begin
if reset='1' then
regcnt_s <= (others => '0'); -- wrap around after first pulse!
ldpos_s <= (others => '1');
flush_req1_s <= '0';
flush_req2_s <= '0';
elsif rising_edge(clk) then
flush_req1_s <= flush_req; -- delay 1 cycle
flush_req2_s <= flush_req1_s; -- delay 2 cycles
if flush_req2_s='1' then
regcnt_s <= (others => '0'); -- Update during Smaxws state
elsif latcho='1' then
regcnt_s <= regcnt_s - ('0'&nbreq);
elsif regplus1='1' and reg1freed='1' then
regcnt_s <= regcnt_s + '1';
end if;
if flush_req2_s='1' then
ldpos_s <= (others => '1'); -- Result in part of dbus loaded into queue
elsif latcho='1' then
ldpos_s <= ldpos_s - ('0'&nbreq);
elsif ldposplus1='1' and reg1freed='1' then
ldpos_s <= ldpos_s + '1';
end if;
end if;
end process;
reg1free <= '1' when ldpos_s/="1000" else '0'; -- Note maxcnt=9!!
process(reset,clk)
begin
if reset='1' then
reg1freed <= '1';
elsif rising_edge(clk) then
reg1freed <= reg1free;
end if;
end process;
regnbok <= '1' when (regcnt_s>='0'&nbreq) else '0'; -- regcnt must be >= nb required
lutbus <= reg72_s(71 downto 56); -- Only for opcode LUT decoder
-------------------------------------------------------------------------
-- Load 8 bits instruction into 72 bits prefetch queue (9 bytes)
-- Latched by latchm signal (from biufsm)
-- ldpos=0 means loading at 71 downto 64 etc
-- Shiftn is connected to nbreq
-------------------------------------------------------------------------
process(reset,clk)
begin
if reset='1' then
reg72_s <= NOP & X"0000000000000000"; --(others => '0');
elsif rising_edge(clk) then
if latchm='1' then
case ldpos_s is -- Load new data, shift in lsb byte first
when "0000" => reg72_s(71 downto 64) <= dbus_in;
when "0001" => reg72_s(63 downto 56) <= dbus_in;
when "0010" => reg72_s(55 downto 48) <= dbus_in;
when "0011" => reg72_s(47 downto 40) <= dbus_in;
when "0100" => reg72_s(39 downto 32) <= dbus_in;
when "0101" => reg72_s(31 downto 24) <= dbus_in;
when "0110" => reg72_s(23 downto 16) <= dbus_in;
when "0111" => reg72_s(15 downto 8) <= dbus_in;
when "1000" => reg72_s(7 downto 0) <= dbus_in;
when others => reg72_s <= reg72_s;
-- assert FALSE report "**** Incorrect LDPOS in reg72_s " severity error;
end case;
end if;
if latcho='1' then
case nbreq is -- remove nb byte(s) when latcho is active
when "001" => reg72_s <= reg72_s(63 downto 0) & "--------"; -- smaller synth results than "00000000"
when "010" => reg72_s <= reg72_s(55 downto 0) & "----------------";
when "011" => reg72_s <= reg72_s(47 downto 0) & "------------------------";
when "100" => reg72_s <= reg72_s(39 downto 0) & "--------------------------------";
when "101" => reg72_s <= reg72_s(31 downto 0) & "----------------------------------------";
when "110" => reg72_s <= reg72_s(23 downto 0) & "------------------------------------------------";
when others => reg72_s <= reg72_s;
--assert FALSE report "**** Incorrect NBREQ in reg72_s " severity error;
end case;
end if;
end if;
end process;
-------------------------------------------------------------------------
-- Opcode Data
-- Note format LSB-MSB
-------------------------------------------------------------------------
process(reset,clk)
begin
if reset='1' then
opcdata_s <= (others => '0');
elsif rising_edge(clk) then
if latcho='1' then
case mux_data is
when "0000" => opcdata_s <= (others => '0'); -- Correct???
when "0001" => opcdata_s <= reg72_s(63 downto 56) & X"00";
when "0010" => opcdata_s <= reg72_s(63 downto 48);
when "0011" => opcdata_s <= reg72_s(55 downto 48) & X"00";
when "0100" => opcdata_s <= reg72_s(55 downto 40);
when "0101" => opcdata_s <= reg72_s(47 downto 40) & X"00";
when "0110" => opcdata_s <= reg72_s(47 downto 32);
when "0111" => opcdata_s <= reg72_s(39 downto 32) & X"00";
when "1000" => opcdata_s <= reg72_s(39 downto 24);
when others => opcdata_s <= "----------------"; -- generate Error?
--assert FALSE report "**** Incorrect mux_data in Opcode Data Register" severity error;
end case;
end if;
end if;
end process;
-------------------------------------------------------------------------
-- Opcode Address/Offset/Displacement
-- Format LSB, MSB!
-- Single Displacement byte sign extended
-------------------------------------------------------------------------
process(reset,clk)
begin
if reset='1' then
opcaddr_s <= (others => '0');
elsif rising_edge(clk) then
if inta2_s='1' then
opcaddr_s <= dbus_in & X"00"; -- Read 8 bits vector
elsif latcho='1' then
--if irq='1' then
if irq='1' or inta1='1' then -- added for ver 0.71
opcaddr_s <= "000000" & irq_type & X"00";
else
case mux_addr is
when "000" => opcaddr_s <= (others => '0'); -- Correct ????
when "001" => opcaddr_s <= reg72_s(63 downto 56) & reg72_s(63)& reg72_s(63)& reg72_s(63)& reg72_s(63)&
reg72_s(63)& reg72_s(63)& reg72_s(63)& reg72_s(63); -- MSB Sign extended
when "010" => opcaddr_s <= reg72_s(63 downto 48);
when "011" => opcaddr_s <= reg72_s(55 downto 48) & reg72_s(55)& reg72_s(55)& reg72_s(55)& reg72_s(55)&
reg72_s(55)& reg72_s(55)& reg72_s(55)& reg72_s(55); -- MSB Sign Extended
when "100" => opcaddr_s <= reg72_s(55 downto 40);
when "101" => opcaddr_s <= reg72_s(63 downto 56) & X"00"; -- No sign extend, MSB=0
when "110" => opcaddr_s <= X"0300"; -- INT3 type=3
when others => opcaddr_s <= X"0400"; -- INTO type=4
end case;
end if;
end if;
end if;
end process;
-------------------------------------------------------------------------
-- Opcode Register
-- Note : "11" is push segment reg[2]=0 reg[1..0]=reg
-- : Note reg[2]=0 if mux_reg=011
-------------------------------------------------------------------------
process(reset,clk)
begin
if reset='1' then
opcreg_s <= (others => '0');
elsif rising_edge(clk) then
if latcho='1' then
case mux_reg is
when "000" => opcreg_s <= (others => '0'); -- Correct ??
when "001" => opcreg_s <= reg72_s(61 downto 59);
when "010" => opcreg_s <= reg72_s(66 downto 64);
when "011" => opcreg_s <= '0' & reg72_s(68 downto 67); -- bit2 forced to 0
when "100" => opcreg_s <= reg72_s(58 downto 56);
when others => opcreg_s <= "---";
--assert FALSE report "**** Incorrect mux_reg in Opcode Regs Register" severity error;
end case;
end if;
end if;
end process;
-------------------------------------------------------------------------
-- Opcode, Mod R/M Register, and latched nbreq!
-- Create fake xmod and rm if offset (addr_mux) is 1,2,5,6,7. In this case
-- there is no second opcode byte. The fake xmod and rm result in an
-- EA=Displacement.
-------------------------------------------------------------------------
process(reset,clk) -- ireg
begin
if reset='1' then
ireg_s <= NOP; -- default instr
mod_s <= (others => '0'); -- default mod
rm_s <= (others => '0'); -- default rm
nbreq_s <= "001"; -- single NOP
elsif rising_edge(clk) then
if latcho='1' then
--if irq='1' then -- force INT instruction
if irq='1' or inta1='1' then -- force INT instruction, added for ver 0.71
ireg_s <= INT;
nbreq_s<= "000"; -- used in datapath to add to IP address
mod_s <= "00"; -- Fake mod (select displacement for int type
rm_s <= "110"; -- Fake rm
else
ireg_s <= reg72_s(71 downto 64);
nbreq_s<= nbreq;
if (mux_addr= "001" or mux_addr= "010" or mux_addr= "101"
or mux_addr= "110" or mux_addr= "111") then
mod_s <= "00"; -- Fake mod
rm_s <= "110"; -- Fake rm
else
mod_s <= reg72_s(63 downto 62);
rm_s <= reg72_s(58 downto 56);
end if;
end if;
end if;
end if;
end process;
--pragma Synthesis_off
---------------------------------------------------------------------------
---- Latched reg48_s signal since the BIU continous reads bytes during shift
---------------------------------------------------------------------------
process(reset,clk) -- ireg
begin
if reset='1' then
reg48_s <= (others => '0');
elsif rising_edge(clk) then
if latcho='1' then
reg48_s <= reg72_s(71 downto 24);
end if;
end if;
end process;
--pragma Synthesis_on
end regshift;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -