library ieee; use ieee.std_logic_1164.all; use work.DMEM_PKG.all; package OISC_SUBLEQ_PKG is component OISC_SUBLEQ is generic ( log2PADDR : integer range 0 to integer'high := 8; log2DADDR : integer range 0 to integer'high := 4; DW : integer range 1 to integer'high := 8; ZERO : boolean := false; LVT_DMEM : boolean := true; ASYNC : boolean := false ); port ( iPCLK : in std_logic; iPWE : in std_logic; iPADDR : in integer range 0 to 2**log2PADDR-1; iPINST : in std_logic_vector(log2DADDR+log2DADDR+log2PADDR-1 downto 0); oPINST : out std_logic_vector(log2DADDR+log2DADDR+log2PADDR-1 downto 0); iDCLK : in std_logic; iDWE : in std_logic; iDADDR : in integer range 0 to 2**log2DADDR-1; iDDATA : in std_logic_vector(DW-1 downto 0); oDDATA : out std_logic_vector(DW-1 downto 0); iCLR : in std_logic; iCLK : in std_logic; iACT : in std_logic; oACT : out std_logic; oPC : out integer range 0 to 2**log2PADDR-1; oLEQ : out std_logic ); end component OISC_SUBLEQ; constant cOISC_SUBLEQ_PW_LATENCY : integer := 1; constant cOISC_SUBLEQ_PR_LATENCY : integer := 0; constant cOISC_SUBLEQ_LATENCY : integer := 1; pure function fOISC_SUBLEQ_DW_LATENCY ( iLVT_DMEM : boolean ) return integer; pure function fOISC_SUBLEQ_DR_LATENCY ( iLVT_DMEM : boolean ) return integer; end package OISC_SUBLEQ_PKG; package body OISC_SUBLEQ_PKG is pure function fOISC_SUBLEQ_DW_LATENCY ( iLVT_DMEM : boolean ) return integer is begin if (iLVT_DMEM = true) then return cDMEM_DW_LATENCY; else return 1; end if; end function fOISC_SUBLEQ_DW_LATENCY; pure function fOISC_SUBLEQ_DR_LATENCY ( iLVT_DMEM : boolean ) return integer is begin if (iLVT_DMEM = true) then return cDMEM_DR_LATENCY; else return 0; end if; end function fOISC_SUBLEQ_DR_LATENCY; end package body OISC_SUBLEQ_PKG; library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.DMEM_PKG.all; entity OISC_SUBLEQ is generic ( log2PADDR : integer range 0 to integer'high := 8; log2DADDR : integer range 0 to integer'high := 4; DW : integer range 1 to integer'high := 8; ZERO : boolean := true; LVT_DMEM : boolean := true; ASYNC : boolean := false ); port ( iPCLK : in std_logic; iPWE : in std_logic; iPADDR : in integer range 0 to 2**log2PADDR-1; iPINST : in std_logic_vector(log2DADDR+log2DADDR+log2PADDR-1 downto 0); oPINST : out std_logic_vector(log2DADDR+log2DADDR+log2PADDR-1 downto 0); iDCLK : in std_logic; iDWE : in std_logic; iDADDR : in integer range 0 to 2**log2DADDR-1; iDDATA : in std_logic_vector(DW-1 downto 0); oDDATA : out std_logic_vector(DW-1 downto 0); iCLR : in std_logic; iCLK : in std_logic; iACT : in std_logic; oACT : out std_logic; oPC : out integer range 0 to 2**log2PADDR-1; oLEQ : out std_logic ); begin -- RTL_SYNTHESIS OFF A_DMEM_AR_LATENCY : assert (not (LVT_DMEM = true and cDMEM_AR_LATENCY /= 0)) report OISC_SUBLEQ'instance_name & "cDMEM_AR_LATENCY =" & integer'image(cDMEM_AR_LATENCY) severity warning; A_DMEM_BW_LATENCY : assert (not (LVT_DMEM = true and cDMEM_BW_LATENCY /= 1)) report OISC_SUBLEQ'instance_name & "cDMEM_BW_LATENCY =" & integer'image(cDMEM_BW_LATENCY) severity warning; A_DMEM_BR_LATENCY : assert (not (LVT_DMEM = true and cDMEM_BR_LATENCY /= 0)) report OISC_SUBLEQ'instance_name & "cDMEM_BR_LATENCY =" & integer'image(cDMEM_BR_LATENCY) severity warning; -- RTL_SYNTHESIS ON end entity OISC_SUBLEQ; architecture TP of OISC_SUBLEQ is type tIF is record PMEM_oA : integer range 0 to 2**log2DADDR-1; PMEM_oB : integer range 0 to 2**log2DADDR-1; PMEM_oC : integer range 0 to 2**log2PADDR-1; DMEM_oA : std_logic_vector(DW-1 downto 0); DMEM_oB : std_logic_vector(DW-1 downto 0); end record tIF; signal s : tIF; type t is record ACT : std_logic; SUB : std_logic_vector(DW-1 downto 0); PC : integer range 0 to 2**log2PADDR-1; LEQ : std_logic; end record t; constant c : t := ( ACT => '0', SUB => (DW-1 downto 0 => '0'), PC => 0, LEQ => '0' ); signal g : t; signal r : t := c; begin B_BLOB : block is type tPMEM is array (0 to 2**log2PADDR-1) of std_logic_vector(log2DADDR+log2DADDR+log2PADDR-1 downto 0); signal aPMEM : tPMEM := (0 to 2**log2PADDR-1 => (log2DADDR+log2DADDR+log2PADDR-1 downto 0 => '0')); signal gPMEM_oINST : std_logic_vector(log2DADDR+log2DADDR+log2PADDR-1 downto 0); signal gPMEM_oA : std_logic_vector(log2DADDR-1 downto 0); signal gPMEM_oB : std_logic_vector(log2DADDR-1 downto 0); signal gPMEM_oC : std_logic_vector(log2PADDR-1 downto 0); begin P_PMEM_P : process (iPCLK) begin if (rising_edge(iPCLK)) then if (iPWE = '1') then aPMEM(iPADDR) <= iPINST; end if; end if; end process P_PMEM_P; oPINST <= aPMEM(iPADDR); gPMEM_oINST <= aPMEM(r.PC); gPMEM_oA <= gPMEM_oINST(log2DADDR+log2DADDR+log2PADDR-1 downto log2DADDR+log2PADDR); gPMEM_oB <= gPMEM_oINST( log2DADDR+log2PADDR-1 downto log2PADDR); gPMEM_oC <= gPMEM_oINST( log2PADDR-1 downto 0); s.PMEM_oA <= to_integer(unsigned(gPMEM_oA)); s.PMEM_oB <= to_integer(unsigned(gPMEM_oB)); s.PMEM_oC <= to_integer(unsigned(gPMEM_oC)); G_LVT_DMEM : if (LVT_DMEM = true) generate begin U_DMEM : DMEM generic map ( log2DADDR => log2DADDR, DW => DW, ZERO => ZERO ) port map ( iDCLK => iDCLK, iDWE => iDWE, iDADDR => iDADDR, iDDATA => iDDATA, oDDATA => oDDATA, iCLK => iCLK, iAADDR => s.PMEM_oA, oADATA => s.DMEM_oA, iBWE => iACT, iBADDR => s.PMEM_oB, iBDATA => g.SUB, oBDATA => s.DMEM_oB ); end generate G_LVT_DMEM; G_2W3R_DMEM : if (LVT_DMEM = false) generate -- FIXME: ISE 13.2 does not support "protected"... :( --type tDMEM is protected -- procedure pWRITE( -- iADDR : in integer range 0 to 2**log2DADDR-1; -- iDATA : in std_logic_vector(DW-1 downto 0) -- ); -- impure function fREAD( -- iADDR : integer range 0 to 2**log2DADDR-1 -- ) return std_logic_vector; --end protected tDMEM; --type tDMEM is protected body -- type tDMEM_PRIM is array (0 to 2**log2DADDR-1) of std_logic_vector(DW-1 downto 0); -- variable aDMEM_PRIM : tDMEM_PRIM := (0 to 2**log2DADDR-1 => (DW-1 downto 0 => '0')); -- procedure pWRITE( -- iADDR : in integer range 0 to 2**log2DADDR-1; -- iDATA : in std_logic_vector(DW-1 downto 0) -- ) is -- begin -- aDMEM_PRIM(iADDR) := iDATA; -- end procedure pWRITE; -- impure function fREAD( -- iADDR : integer range 0 to 2**log2DADDR-1 -- ) return std_logic_vector is -- begin -- return aDMEM_PRIM(iADDR); -- end function fREAD; --end protected body tDMEM; --shared variable aDMEM : tDMEM; -- FIXME: VHDL-93 shared variable does not provide mutex... :( type tDMEM is array (0 to 2**log2DADDR-1) of std_logic_vector(DW-1 downto 0); shared variable aDMEM : tDMEM := (0 to 2**log2DADDR-1 => (DW-1 downto 0 => '0')); begin P_DMEM_D : process (iDCLK) begin if (rising_edge(iDCLK)) then if (iDWE = '1') then --aDMEM.pWRITE(iDADDR, iDDATA); aDMEM(iDADDR) := iDDATA; end if; end if; end process P_DMEM_D; --oDDATA <= (DW-1 downto 0 => '0') when (ZERO = true and iDADDR = 0) else aDMEM.fREAD(iDADDR); --s.DMEM_oA <= (DW-1 downto 0 => '0') when (ZERO = true and s.PMEM_oA = 0) else aDMEM.fREAD(s.PMEM_oA); --s.DMEM_oB <= (DW-1 downto 0 => '0') when (ZERO = true and s.PMEM_oB = 0) else aDMEM.fREAD(s.PMEM_oB); oDDATA <= (DW-1 downto 0 => '0') when (ZERO = true and iDADDR = 0) else aDMEM(iDADDR); s.DMEM_oA <= (DW-1 downto 0 => '0') when (ZERO = true and s.PMEM_oA = 0) else aDMEM(s.PMEM_oA); s.DMEM_oB <= (DW-1 downto 0 => '0') when (ZERO = true and s.PMEM_oB = 0) else aDMEM(s.PMEM_oB); -- FIXME: This DMEM write back is kludge... :( P_DMEM_WRITE_BACK : process (iCLK) begin if (rising_edge(iCLK)) then if (iACT = '1') then --aDMEM.pWRITE(s.PMEM_oB, g.SUB); aDMEM(s.PMEM_oB) := g.SUB; end if; end if; end process P_DMEM_WRITE_BACK; end generate G_2W3R_DMEM; end block B_BLOB; P_COMB : process (iACT, r, s) variable v : t := c; pure function fSUB ( iA : std_logic_vector(DW-1 downto 0); iB : std_logic_vector(DW-1 downto 0) ) return std_logic_vector is variable vSUB : signed(DW-1 downto 0); begin -- FIXME: Consider th3 borrow? vSUB := signed(iB) - signed(iA); return std_logic_vector(vSUB); end function fSUB; begin if (iACT = '1') then v.ACT := '1'; v.SUB := fSUB(s.DMEM_oA, s.DMEM_oB); if (signed(v.SUB) <= 0) then v.PC := s.PMEM_oC; v.LEQ := '1'; else if (r.PC >= 2**log2PADDR-1) then v.PC := 0; else v.PC := r.PC + 1; end if; v.LEQ := '0'; end if; else v.ACT := '0'; v.SUB := r.SUB; v.PC := r.PC; v.LEQ := r.LEQ; end if; g <= v; oACT <= r.ACT; oPC <= r.PC; oLEQ <= r.LEQ; end process P_COMB; G_ASYNC : if (ASYNC = true) generate begin P_SEQ : process (iCLR, iCLK) begin if (iCLR = '1') then r <= c; elsif (rising_edge(iCLK)) then r <= g; end if; end process P_SEQ; end generate G_ASYNC; G_SYNC : if (ASYNC = false) generate begin P_SEQ : process (iCLK) begin if (rising_edge(iCLK)) then if (iCLR = '1') then r <= c; else r <= g; end if; end if; end process P_SEQ; end generate G_SYNC; end architecture TP;