1library ieee;
2use ieee.std_logic_1164.all;
3use ieee.numeric_std.all;
4
5-- sewuence generator
6-- note: cos,sin output on negative edge before pha, sync.
7--       pha on positive edge, sync on positive edge
8entity ram_lut is
9port( nreset,clk,wstb,rstb: in std_logic;
10cmd: in std_logic_vector(2 downto 0); -- control
11din: in std_logic_vector(7 downto 0);
12dout: out std_logic_vector(7 downto 0);
13pos_ctr: out std_logic_vector(9 downto 0);
14sin,cos,indo,pha,sync:out std_logic);
15end ram_lut;
16
17architecture rtl of ram_lut is
18
19component ram2k8 is
20port( clk,WEn,CSn: in std_logic; -- clk rising edge, WEn & CSn are active low
21ADDR: in std_logic_vector(10 downto 0);
22dw: in std_logic_vector(7 downto 0); -- write data
23dr: out std_logic_vector(7 downto 0) -- read data
24);
25end component;
26
27-- signals for memory
28signal mCLK,mWEn,mCEn: std_logic;
29signal mA11: std_logic_vector(10 downto 0); -- address for the 2k mem
30signal mA: std_logic_vector(8 downto 0); -- normal address
31signal mD: std_logic_vector(7 downto 0);
32signal mQ: std_logic_vector(7 downto 0);
33signal mQr: std_logic_vector(7 downto 0); -- register to hold data
34
35-- signals for sequence generator
36signal ctr_lim: unsigned(8 downto 0); -- final byte address
37signal dib_ctr: unsigned(1 downto 0);
38signal sini,cosi,indoi,phai,synci: std_logic;
39signal pos_ctri:unsigned(9 downto 0);
40signal lut_ctl: std_logic_vector(7 downto 0); -- see below:
41
42alias lut_run: std_logic is lut_ctl(7);
43alias lut_3ph: std_logic is lut_ctl(5);
44alias indo_def: std_logic is lut_ctl(4);
45alias dib_lim: std_logic_vector(1 downto 0) is lut_ctl(2 downto 1);
46
47signal rd,csgen,csregen:std_logic; -- mem rd, controls for generator
48signal mxo:std_logic_vector(2 downto 0);-- mux of data
49
50begin
51
52pos_ctr<=std_logic_vector(pos_ctri);
53sync<=synci;
54sin<=sini;
55cos<=cosi;
56pha<=phai;
57indo<=indoi;
58
59-- dout
60dout<= mQ when cmd="000" else
61       std_logic_vector(ctr_lim(7 downto 0)) when cmd="010" else
62       lut_ctl when cmd="011" else
63       "01111110"; -- 7e
64
65mD<=din; --always
66
67-- modified controls
68-- cmd: 000 read or write mem, autoinc
69--      001 zero address - wstb
70--      010 ctr_lim(7 downto 0) - wstb, rstb
71--      011 lut_ctl - wstb,rstb
72--      101
73--
74-- lut_ctl: run,0,3pha,set_indo,0,dib_lim1,dib_lim0.ctr_lim(8)
75
76 mCEn<='0' when ((cmd="000") and ((wstb='1') or (rstb='1'))) else
77       '0' when rd='1' else
78       '1'; -- 1 cycle long
79 mWEn<='0' when ((cmd="000") and ((wstb='1')))
80           else '1';
81 mCLK<=not(clk) and not(mCEn); -- only clock when necessary
82
83process(mQ,dib_ctr) begin -- set mxo(2 downto 0) to indoi,mxo(1),mxo(0)
84  if lut_3ph='0' then
85    mxo(2)<=indo_def; -- per lut_ctl
86    case dib_ctr is
87      when "00"=>
88        mxo(0)<=mQ(0);
89        mxo(1)<=mQ(1);
90      when "01"=>
91        mxo(0)<=mQ(2);
92        mxo(1)<=mQ(3);
93      when "10"=>
94        mxo(0)<=mQ(4);
95        mxo(1)<=mQ(5);
96      when others=>
97        mxo(0)<=mQ(6);
98        mxo(1)<=mQ(7);
99     end case;
100   else -- lut_3ph='1'
101     case dib_ctr is
102       when "00"=>
103         mxo(0)<=mQ(0);
104         mxo(1)<=mQ(1);
105         mxo(2)<=mq(2);
106       when others=>
107         mxo(0)<=mQ(4);
108         mxo(1)<=mQ(5);
109         mxo(2)<=mq(6);
110     end case;
111   end if;
112end process;
113
114process (nreset,clk) -- generator
115begin
116  if nreset='0' then
117    synci<='0';
118    cosi<='0';
119    sini<='0';
120    phai<='0';
121    pos_ctri<=(others=>'0');
122    csgen<='0'; -- 1 when running
123    csregen<='0'; -- 1 when output cos,sin to register
124    dib_ctr<=(others=>'0');
125    mQr<=(others=>'0');
126    rd<='0'; -- read data byte
127  elsif clk'event and clk='1' then
128    synci<='0'; -- will give a pulse at adr 0
129    rd<='0'; -- pulse
130    if mCEn='0' then  -- always autoinc at end of access.
131      mQr<=mQ;
132      mA<=std_logic_vector(unsigned(mA) + 1);
133    end if;
134    if lut_run='0' then -- hold in reset
135      if ((cmd="001") and (wstb='1')) then -- handle table write from spi
136        mA<=(others=>'0'); -- separate or part of cycle
137      elsif (mCEn='0') then
138        mA<=std_logic_vector(unsigned(mA) + 1);
139      end if;
140      dib_ctr<=(others=>'0');
141      phai<='0';
142      pos_ctri<=(others=>'0');
143    else -- lut_run='1'
144      if csregen='1' then -- timing: pha follows cos,sin output
145        phai<=not(phai);
146      end if;
147      if rd='1' then
148        mQr<=mQ;
149        mA<=std_logic_vector(unsigned(mA) + 1);
150      end if;
151      if csgen='0' then
152        mA<=(others=>'0'); -- separate or part of cycle
153        synci<='1';
154        rd<='1';
155      else -- csgen='1';
156        dib_ctr<=dib_ctr+1;
157        if ((pos_ctri=ctr_lim) and (dib_ctr=unsigned(dib_lim))) then
158          dib_ctr<="00";
159          pos_ctri<=(others=>'0');
160          mA<=(others=>'0');
161          rd<='1';
162          synci<='1';
163        elsif dib_ctr="11" then
164          dib_ctr<="00";
165          rd<='1';
166        end if;
167      end if;
168    end if;
169  elsif clk'event and clk='0' then -- to get cos,sin on negedge
170    if lut_run='0' then
171      csregen<='0';
172    elsif csregen='0' then
173      if rd='1' then csregen<='1'; end if; -- set it once
174    else  -- normal running
175      cosi<=mxo(0);
176      sini<=mxo(1);
177      indoi<=mxo(2);
178    end if;
179  end if;
180end process;
181
182process (nreset,clk) -- handle setting things per cmd
183begin
184  if nreset='0' then
185    ctr_lim<=(others=>'0');
186    lut_ctl<=(others=>'0');
187  elsif clk'event and clk='1' then
188    if wstb='1' then
189      case cmd is
190        when "010"=> -- load ctr_lim
191          ctr_lim<=unsigned(lut_ctl(0) & din); -- so load lut ctl first
192        when "011"=> -- load cmd
193          lut_ctl<=din;
194          dib_lim<=unsigned(din(2 downto 1));
195          ctr_lim(8)<=din(0);
196        when others=>
197      end case;
198    end if;
199  end if;
200end process;
201
202-- this is based on 512 bytes so we do not need 2 upper bits
203mA11<=("00" & mA);
204
205-- based on ram2k8.vhp in vhdl_ip.
206-- need to move this RAM out so we just have ports.
207-- target -Dxfab 512x8 for asic
208--        -Dghdl model for simulation
209--        -Dxilinx model for fpga
210
211r1:ram2k8 port map(
212mCLK,mWEn,mCEn,
213mA11, mD, mQ);
214
215
216end rtl;
217