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: out std_logic; -- RTS
26 gpio18: out std_logic; -- PWM0/PCMCLK
27 gpio27: out std_logic; -- SD1DAT3
28 gpio22: out std_logic; -- SD1CLK
29 gpio23: out std_logic; -- SD1CMD
30 gpio24: out std_logic; -- SD1DAT0
31 gpio10: in std_logic; -- SPI0MOSI
32 gpio9: out std_logic; -- SPI0MISO
33 gpio25: out 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,reset);
117 signal state : state_type;
118 signal adc_data: std_logic_vector(11 downto 0); --ADC income data
119 signal adc_reset : std_logic;
120 signal adc_rst_old : std_logic_vector(1 downto 0);
121 signal adc_address: std_logic_vector(8 downto 0);
122 signal adc_channels: std_logic_vector(35 downto 0);
124 signal spiclk_old: std_logic_vector(1 downto 0); --pro detekci hrany SPI hodin
125 signal pwm_in, pwm_dir_in: std_logic;
126 signal gpio_clk: std_logic;
127 signal dat_reg : STD_LOGIC_VECTOR (95 downto 0); --shift register for spi
128 signal position: std_logic_vector(31 downto 0); --pozice z qcounteru
129 signal ce0_old: std_logic_vector(1 downto 0);
133 -- attribute syn_noprune of gpio2 : signal is true;
134 -- attribute syn_preserve of gpio2 : signal is true;
135 -- attribute syn_keep of gpio2 : signal is true;
136 -- attribute syn_hier of gpio2 : signal is true;
139 -- PLL as a reset generator
141 --zesileni signalu GPIO CLK
168 -- clka => pll_clkin,
169 -- gla => pll_clkout,
170 -- lock => pll_lock);
171 -- -- reset <= not pll_lock;
172 -- reset <= '0'; -- TODO: apply reset for good failsafe
176 dummy_unused <= gpio2 and gpio3 and gpio4 and
178 gpio12 and gpio13 and gpio14 and
179 gpio15 and gpio16 and gpio19 and
180 gpio20 and gpio21 and gpio26 and
181 stat(1) and stat(2) and stat(3) and
182 hal_in(1) and hal_in(2) and hal_in(3) and
183 irc_i and power_stat and
186 can_rx and can_tx and
187 dip_sw(1) and dip_sw(2) and dip_sw(3) and
189 -- gpio17 and gpio18 and gpio27 and gpio22 and
190 gpio8 and gpio11 and gpio7 and gpio10 and
191 ext_scs1 and ext_scs2 and ext_miso and ext_mosi and ext_sclk and ext_scs0;
208 --position is obtained on rising edge -> we should write it on next cycle
209 wait until (gpio_clk'event and gpio_clk='1');
211 --SCLK edge detection
212 spiclk_old(0)<=gpio11;
213 spiclk_old(1)<=spiclk_old(0);
217 ce0_old(1)<=ce0_old(0);
219 if (spiclk_old="01") then --rising edge, faze cteni
220 if (gpio7 = '0') then -- SPI CS must be selected
221 -- shift serial data into dat_reg on each rising edge
223 dat_reg(95 downto 0) <= dat_reg(94 downto 0) & gpio10;
225 elsif (spiclk_old="10" ) then --falling edge, faze zapisu
226 if (gpio7 = '0') then
227 gpio9 <= dat_reg(95); --zapisujeme nejdriv MSB
232 --sestupna hrana SS, pripravime data pro prenos
233 if (ce0_old = "10" ) then
234 dat_reg(95 downto 64) <= position(31 downto 0); --pozice
235 dat_reg(63 downto 61) <= hal_in(1 to 3); --halovy sondy
236 dat_reg(60 downto 36) <= (others => '1'); --let the rest fill with ones
237 dat_reg(35 downto 0) <= adc_channels(35 downto 0); --current mesurments
238 elsif (ce0_old = "01") then --rising edge of SS, we should read the data
239 adc_reset<=dat_reg(95);
244 variable data_ready : std_logic;
245 variable channel: std_logic_vector(1 downto 0);
247 wait until (gpio_clk'event and gpio_clk='1');
250 adc_scs<='0'; --active-high SS
252 --addresse are CH(A2,A1,A0): CH0:(0,0,1),CH1:(1,0,1),CH2:(0,1,0)
253 adc_address<="001101010";
257 adc_mosi<='1'; --start bit
258 state<=r1; --next state
259 when r1=> --rising edge
261 adc_data(5)<=adc_miso;
263 when f2=> --2nd falling edge
265 adc_mosi<=adc_address(8); --A2 address
267 when r2=> --rising edge
269 adc_data(4)<=adc_miso;
271 when f3=> --3rd falling edge
273 adc_mosi<=adc_address(7); --A1 address
275 when r3=> --rising edge
277 adc_data(3)<=adc_miso;
279 when f4=> --4th falling edge
281 adc_mosi<=adc_address(6); --A0 address
282 --shift the addresses
283 adc_address(8 downto 0)<=adc_address(5 downto 0) & adc_address(8 downto 6);
285 when r4=> --rising edge
287 adc_data(2)<=adc_miso;
289 when f5=> --5th falling edge
291 adc_mosi<='0'; --MODE (LOW -12bit)
293 when r5=> --rising edge
295 adc_data(1)<=adc_miso;
297 when f6=> --6th falling edge
299 adc_mosi<='1'; --SGL/DIF (HIGH - SGL=Single Ended)
301 when r6=> --rising edge
303 adc_data(0)<=adc_miso;
305 when f7=> -- 7th falling edge
307 adc_mosi<='0'; --PD1 (power down - PD1=PD0=0 -> power down between conversion)
309 when r7=> --rising edge, data ready
311 if (data_ready='1') then
314 adc_channels(35 downto 24)<=adc_data(11 downto 0);
317 adc_channels(23 downto 12)<=adc_data(11 downto 0);
320 adc_channels(11 downto 0)<=adc_data(11 downto 0);
326 when f8=> --8th falling edge
330 when r8=> --rising edge
333 when f9=> --busy state between conversion, 9th falling edge
336 when r9=> --10th rising edge
338 adc_data(11)<=adc_miso;
343 when r10=> --11th rising edge
345 adc_data(10)<=adc_miso;
350 when r11=> --12th rising edge
352 adc_data(9)<=adc_miso;
357 when r12=> --13th rising edge
359 adc_data(8)<=adc_miso;
364 when r13=> --14th rising edge
366 adc_data(7)<=adc_miso;
371 when r14=> --15th rising edge
373 adc_data(6)<=adc_miso;
374 adc_rst_old(0)<=adc_reset;
375 adc_rst_old(1)<=adc_rst_old(0);
376 if (adc_rst_old="01") then --we check rising edge of reset