2 -- * LXPWR slave part *
3 -- common sioreg & common counter for several ADC&PWM blocks
5 -- part of LXPWR motion control board (c) PiKRON Ltd
6 -- idea by Pavel Pisa PiKRON Ltd <pisa@cmp.felk.cvut.cz>
7 -- code by Marek Peca <mp@duch.cz>
14 use ieee.std_logic_1164.all;
15 use ieee.numeric_std.all;
18 entity rpi_mc_simple_dc is
20 gpio2: in std_logic; -- SDA
21 gpio3: in std_logic; -- SCL
22 gpio4: in std_logic; -- CLK
23 gpio14: in std_logic; -- Tx
24 gpio15: in std_logic; -- Rx
25 gpio17: in std_logic; -- RTS
26 gpio18: in std_logic; -- PWM0/PCMCLK
27 gpio27: in std_logic; -- SD1DAT3
28 gpio22: in std_logic; -- SD1CLK
29 gpio23: in std_logic; -- SD1CMD
30 gpio24: in std_logic; -- SD1DAT0
31 gpio10: in std_logic; -- SPI0MOSI
32 gpio9: out std_logic; -- SPI0MISO
33 gpio25: in std_logic; -- SD1DAT1
34 gpio11: in std_logic; -- SPI0SCLK
35 gpio8: in std_logic; -- SPI0CE0
36 gpio7: in std_logic; -- SPI0CE1
37 gpio5: in std_logic; -- GPCLK1
38 gpio6: in std_logic; -- GPCLK2
39 gpio12: in std_logic; -- PWM0
40 gpio13: in std_logic; -- PWM1
41 gpio19: in std_logic; -- PWM1/SPI1MISO/PCMFS
42 gpio16: in std_logic; -- SPI1CE2
43 gpio26: in std_logic; -- SD1DAT2
44 gpio20: in std_logic; -- SPI1MOSI/PCMDIN/GPCLK0
45 gpio21: in std_logic; -- SPI1SCLK/PCMDOUT/GPCLK1
48 -- Each PWM signal has cooresponding shutdown
49 pwm: out std_logic_vector (1 to 3);
50 shdn: out std_logic_vector (1 to 3);
51 -- Fault/power stage status
52 stat: in std_logic_vector (1 to 3);
54 hal_in: in std_logic_vector (1 to 3);
60 power_stat: in std_logic;
62 adc_miso: in std_logic;
63 adc_mosi: out std_logic;
64 adc_sclk: out std_logic;
65 adc_scs: out std_logic;
67 ext_miso: in std_logic; --master in slave out
68 ext_mosi: in std_logic; --master out slave in
69 ext_sclk: in std_logic;
70 ext_scs0: in std_logic;
71 ext_scs1: in std_logic;
72 ext_scs2: in std_logic;
74 rs485_rxd: in std_logic;
75 rs485_txd: out std_logic;
76 rs485_dir: out std_logic;
81 dip_sw: in std_logic_vector (1 to 3); --na desce je prohozene cislovanni
82 -- Unused terminal to keep design tools silent
83 dummy_unused : out std_logic
88 architecture behavioral of rpi_mc_simple_dc is
89 attribute syn_noprune :boolean;
90 attribute syn_preserve :boolean;
91 attribute syn_keep :boolean;
92 attribute syn_hier :boolean;
94 -- component pll50to200
96 -- powerdown, clka: in std_logic;
97 -- lock, gla: out std_logic
102 port (A: in std_logic; Y: out std_logic);
109 a0, b0: in std_logic;
110 qcount: out std_logic_vector (31 downto 0);
111 a_rise, a_fall, b_rise, b_fall, ab_event: out std_logic;
112 ab_error: out std_logic
116 type state_type is (f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,f15,r15,reset,rst_wait);
117 signal state : state_type;
119 type channel_type is (ch0, ch1, ch2);
121 signal adc_data: std_logic_vector(11 downto 0); --ADC income data
122 signal adc_reset : std_logic;
123 signal adc_rst_old : std_logic_vector(1 downto 0);
124 signal adc_address: std_logic_vector(8 downto 0);
125 signal adc_channels: std_logic_vector(35 downto 0);
127 signal spiclk_old: std_logic_vector(1 downto 0); --pro detekci hrany SPI hodin
128 --signal pwm_in, pwm_dir_in: std_logic;
129 signal gpio_clk: std_logic;
130 signal dat_reg : STD_LOGIC_VECTOR (95 downto 0); --shift register for spi
131 signal position: std_logic_vector(31 downto 0); --pozice z qcounteru
132 signal ce0_old: std_logic_vector(1 downto 0);
136 -- attribute syn_noprune of gpio2 : signal is true;
137 -- attribute syn_preserve of gpio2 : signal is true;
138 -- attribute syn_keep of gpio2 : signal is true;
139 -- attribute syn_hier of gpio2 : signal is true;
142 -- PLL as a reset generator
144 --zesileni signalu GPIO CLK
171 -- clka => pll_clkin,
172 -- gla => pll_clkout,
173 -- lock => pll_lock);
174 -- -- reset <= not pll_lock;
175 -- reset <= '0'; -- TODO: apply reset for good failsafe
179 dummy_unused <= gpio2 and gpio3 and gpio4 and
181 gpio12 and gpio13 and gpio14 and
182 gpio15 and gpio16 and gpio19 and
183 gpio20 and gpio21 and gpio26 and
184 stat(1) and stat(2) and stat(3) and
185 hal_in(1) and hal_in(2) and hal_in(3) and
186 irc_i and power_stat and
189 can_rx and can_tx and
190 dip_sw(1) and dip_sw(2) and dip_sw(3) and
192 gpio17 and gpio18 and gpio27 and gpio22 and gpio23 and gpio24 and gpio25 and
193 gpio8 and gpio11 and gpio7 and gpio10 and
194 ext_scs1 and ext_scs2 and ext_miso and ext_mosi and ext_sclk and ext_scs0;
211 --position is obtained on rising edge -> we should write it on next cycle
212 wait until (gpio_clk'event and gpio_clk='1');
214 --SCLK edge detection
215 spiclk_old(0)<=gpio11;
216 spiclk_old(1)<=spiclk_old(0);
220 ce0_old(1)<=ce0_old(0);
222 if (spiclk_old="01") then --rising edge, faze cteni
223 if (gpio7 = '0') then -- SPI CS must be selected
224 -- shift serial data into dat_reg on each rising edge
226 dat_reg(95 downto 0) <= dat_reg(94 downto 0) & gpio10;
228 elsif (spiclk_old="10" ) then --falling edge, faze zapisu
229 if (gpio7 = '0') then
230 gpio9 <= dat_reg(95); --zapisujeme nejdriv MSB
235 --sestupna hrana SS, pripravime data pro prenos
236 if (ce0_old = "10" ) then
237 dat_reg(95 downto 64) <= position(31 downto 0); --pozice
238 dat_reg(63 downto 61) <= hal_in(1 to 3); --halovy sondy
239 dat_reg(60 downto 36) <= (others => '1'); --let the rest fill with ones
240 dat_reg(35 downto 0) <= adc_channels(35 downto 0); --current mesurments
241 adc_reset<='0'; --remove reset flag, and wait on its rising edge
242 elsif (ce0_old = "01") then --rising edge of SS, we should read the data
243 adc_reset<=dat_reg(95);
248 variable data_ready : std_logic;
249 variable channel: channel_type;
250 variable reset_re: std_logic:='0';
251 variable reset_count: integer:=0;
253 wait until (gpio_clk'event and gpio_clk='1');
255 --reset rising edge detection
256 adc_rst_old(0)<=adc_reset;
257 adc_rst_old(1)<=adc_rst_old(0);
259 if (adc_rst_old="01") then
265 reset_re:='0'; --clear reset flag
266 adc_scs<='1'; --active-low SS
267 adc_sclk<='0'; --lower clock
269 --addresse are CH(A2,A1,A0): CH0:(0,0,1),CH1:(1,0,1),CH2:(0,1,0)
270 adc_address<="001101010";
272 adc_channels(35 downto 0)<=(others=>'1'); --for debug only - remove this line!
273 adc_data(11 downto 0)<=(others=>'1');
277 if (reset_count<10) then
278 reset_count:=reset_count+1;
279 if (reset_count=7) then
280 adc_scs<='0'; --give the adc some time to prepare before trensfer
285 when f1=> --1st 'fallin edge' - its not falling edge in any case-if rst clock is low before
287 adc_mosi<='1'; --start bit
288 state<=r1; --next state
289 when r1=> --1st rising edge (adc gets the start bit, we get date..)
291 adc_data(5)<=adc_miso;
293 when f2=> --2nd falling edge
295 adc_mosi<=adc_address(8); --A2 address
297 when r2=> --2nd rising edge (adc gets A2 address)
299 adc_data(4)<=adc_miso;
301 when f3=> --3rd falling edge
303 adc_mosi<=adc_address(7); --A1 address
305 when r3=> --rising edge
307 adc_data(3)<=adc_miso;
309 when f4=> --4th falling edge
311 adc_mosi<=adc_address(6); --A0 address
312 --shift the addresses
313 adc_address(8 downto 0)<=adc_address(5 downto 0) & adc_address(8 downto 6);
315 when r4=> --rising edge
317 adc_data(2)<=adc_miso;
319 when f5=> --5th falling edge
321 adc_mosi<='0'; --MODE (LOW -12bit)
323 when r5=> --rising edge
325 adc_data(1)<=adc_miso;
327 when f6=> --6th falling edge
329 adc_mosi<='1'; --SGL/DIF (HIGH - SGL=Single Ended)
331 when r6=> --6th rising edge (we read last bit of conversion, adc gets SGL/DIF)
333 adc_data(0)<=adc_miso;
335 when f7=> -- 7th falling edge
337 adc_mosi<='0'; --PD1 (power down - PD1=PD0=0 -> power down between conversion)
339 when r7=> --7th rising edge, data ready
341 if (data_ready='1') then
344 adc_channels(35 downto 24)<=adc_data(11 downto 0);
345 --adc_channels(35 downto 24)<=(others=>'0');
348 adc_channels(23 downto 12)<=adc_data(11 downto 0);
349 --adc_channels(23 downto 12)<=(others=>'1');
352 adc_channels(11 downto 0)<=adc_data(11 downto 0);
353 --adc_channels(11 downto 0)<=(others=>'0');
359 when f8=> --8th falling edge
363 when r8=> --8th rising edge (adc gets PD0)
366 when f9=> --9th falling edge busy state between conversion (we write nothing)
369 when r9=> --9th rising edge (we nor ads get nothing)
372 when f10=> --10th falling edge
375 when r10=> --10th rising edge (we read 1. bit of conversion)
377 adc_data(11)<=adc_miso;
382 when r11=> --11th rising edge
384 adc_data(10)<=adc_miso;
389 when r12=> --12th rising edge
391 adc_data(9)<=adc_miso;
396 when r13=> --13th rising edge
398 adc_data(8)<=adc_miso;
403 when r14=> --14th rising edge
405 adc_data(7)<=adc_miso;
409 --for rising edge detection in next cycle
411 when r15=> --15th rising edge
413 adc_data(6)<=adc_miso;
414 if (reset_re='1') then --we check rising edge of reset