library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- sewuence generator -- note: cos,sin output on negative edge before pha, sync. -- pha on positive edge, sync on positive edge entity ram_lut is port( nreset,clk,wstb,rstb: in std_logic; cmd: in std_logic_vector(2 downto 0); -- control din: in std_logic_vector(7 downto 0); dout: out std_logic_vector(7 downto 0); pos_ctr: out std_logic_vector(9 downto 0); sin,cos,indo,pha,sync:out std_logic); end ram_lut; architecture rtl of ram_lut is component ram2k8 is port( clk,WEn,CSn: in std_logic; -- clk rising edge, WEn & CSn are active low ADDR: in std_logic_vector(10 downto 0); dw: in std_logic_vector(7 downto 0); -- write data dr: out std_logic_vector(7 downto 0) -- read data ); end component; -- signals for memory signal mCLK,mWEn,mCEn: std_logic; signal mA11: std_logic_vector(10 downto 0); -- address for the 2k mem signal mA: std_logic_vector(8 downto 0); -- normal address signal mD: std_logic_vector(7 downto 0); signal mQ: std_logic_vector(7 downto 0); signal mQr: std_logic_vector(7 downto 0); -- register to hold data -- signals for sequence generator signal ctr_lim: unsigned(8 downto 0); -- final byte address signal dib_ctr: unsigned(1 downto 0); signal sini,cosi,indoi,phai,synci: std_logic; signal pos_ctri:unsigned(9 downto 0); signal lut_ctl: std_logic_vector(7 downto 0); -- see below: alias lut_run: std_logic is lut_ctl(7); alias lut_3ph: std_logic is lut_ctl(5); alias indo_def: std_logic is lut_ctl(4); alias dib_lim: std_logic_vector(1 downto 0) is lut_ctl(2 downto 1); signal rd,csgen,csregen:std_logic; -- mem rd, controls for generator signal mxo:std_logic_vector(2 downto 0);-- mux of data begin pos_ctr<=std_logic_vector(pos_ctri); sync<=synci; sin<=sini; cos<=cosi; pha<=phai; indo<=indoi; -- dout dout<= mQ when cmd="000" else std_logic_vector(ctr_lim(7 downto 0)) when cmd="010" else lut_ctl when cmd="011" else "01111110"; -- 7e mD<=din; --always -- modified controls -- cmd: 000 read or write mem, autoinc -- 001 zero address - wstb -- 010 ctr_lim(7 downto 0) - wstb, rstb -- 011 lut_ctl - wstb,rstb -- 101 -- -- lut_ctl: run,0,3pha,set_indo,0,dib_lim1,dib_lim0.ctr_lim(8) mCEn<='0' when ((cmd="000") and ((wstb='1') or (rstb='1'))) else '0' when rd='1' else '1'; -- 1 cycle long mWEn<='0' when ((cmd="000") and ((wstb='1'))) else '1'; mCLK<=not(clk) and not(mCEn); -- only clock when necessary process(mQ,dib_ctr) begin -- set mxo(2 downto 0) to indoi,mxo(1),mxo(0) if lut_3ph='0' then mxo(2)<=indo_def; -- per lut_ctl case dib_ctr is when "00"=> mxo(0)<=mQ(0); mxo(1)<=mQ(1); when "01"=> mxo(0)<=mQ(2); mxo(1)<=mQ(3); when "10"=> mxo(0)<=mQ(4); mxo(1)<=mQ(5); when others=> mxo(0)<=mQ(6); mxo(1)<=mQ(7); end case; else -- lut_3ph='1' case dib_ctr is when "00"=> mxo(0)<=mQ(0); mxo(1)<=mQ(1); mxo(2)<=mq(2); when others=> mxo(0)<=mQ(4); mxo(1)<=mQ(5); mxo(2)<=mq(6); end case; end if; end process; process (nreset,clk) -- generator begin if nreset='0' then synci<='0'; cosi<='0'; sini<='0'; phai<='0'; pos_ctri<=(others=>'0'); csgen<='0'; -- 1 when running csregen<='0'; -- 1 when output cos,sin to register dib_ctr<=(others=>'0'); mQr<=(others=>'0'); rd<='0'; -- read data byte elsif clk'event and clk='1' then synci<='0'; -- will give a pulse at adr 0 rd<='0'; -- pulse if mCEn='0' then -- always autoinc at end of access. mQr<=mQ; mA<=std_logic_vector(unsigned(mA) + 1); end if; if lut_run='0' then -- hold in reset if ((cmd="001") and (wstb='1')) then -- handle table write from spi mA<=(others=>'0'); -- separate or part of cycle elsif (mCEn='0') then mA<=std_logic_vector(unsigned(mA) + 1); end if; dib_ctr<=(others=>'0'); phai<='0'; pos_ctri<=(others=>'0'); else -- lut_run='1' if csregen='1' then -- timing: pha follows cos,sin output phai<=not(phai); end if; if rd='1' then mQr<=mQ; mA<=std_logic_vector(unsigned(mA) + 1); end if; if csgen='0' then mA<=(others=>'0'); -- separate or part of cycle synci<='1'; rd<='1'; else -- csgen='1'; dib_ctr<=dib_ctr+1; if ((pos_ctri=ctr_lim) and (dib_ctr=unsigned(dib_lim))) then dib_ctr<="00"; pos_ctri<=(others=>'0'); mA<=(others=>'0'); rd<='1'; synci<='1'; elsif dib_ctr="11" then dib_ctr<="00"; rd<='1'; end if; end if; end if; elsif clk'event and clk='0' then -- to get cos,sin on negedge if lut_run='0' then csregen<='0'; elsif csregen='0' then if rd='1' then csregen<='1'; end if; -- set it once else -- normal running cosi<=mxo(0); sini<=mxo(1); indoi<=mxo(2); end if; end if; end process; process (nreset,clk) -- handle setting things per cmd begin if nreset='0' then ctr_lim<=(others=>'0'); lut_ctl<=(others=>'0'); elsif clk'event and clk='1' then if wstb='1' then case cmd is when "010"=> -- load ctr_lim ctr_lim<=unsigned(lut_ctl(0) & din); -- so load lut ctl first when "011"=> -- load cmd lut_ctl<=din; dib_lim<=unsigned(din(2 downto 1)); ctr_lim(8)<=din(0); when others=> end case; end if; end if; end process; -- this is based on 512 bytes so we do not need 2 upper bits mA11<=("00" & mA); -- based on ram2k8.vhp in vhdl_ip. -- need to move this RAM out so we just have ports. -- target -Dxfab 512x8 for asic -- -Dghdl model for simulation -- -Dxilinx model for fpga r1:ram2k8 port map( mCLK,mWEn,mCEn, mA11, mD, mQ); end rtl;