___sergey___ 0 8 декабря, 2011 Опубликовано 8 декабря, 2011 · Жалоба Столкнулся с непонятной проблемой, выглядит так, что иногда на выходе получаю либо нули, либо мусор. Подключил СигналТар, обнаружилась проблема в стейтмашине, из состояния NEXT_BIT она переходит в неопределенное когда все пины в 0 или поднимается пин WAIT_4_CLK и при этом NEXT_BIT остается поднятым и потом происходит переход в состояние WAIT_4_CS и данные портятся. Клок на spi 1Mhz, внутренний 50MHz. Может кто то подсказать, в какой стороне копать проблему? код компелируется в Quartus 11.0 под Cyclon lll library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity spi_slave is Port ( clk_50MHz : in std_logic; -- internal clock spi_cs : in std_logic; -- spi bus slave select line spi_clk : in std_logic; -- spi bus sck clock spi_mosi : in std_logic; -- spi bus mosi input spi_miso : out std_logic; -- spi bus miso output status_reg : in std_logic_vector(15 downto 0); -- parallel input status rate_l_reg : in std_logic_vector(15 downto 0); -- parallel input rate low bit rate_h_reg : in std_logic_vector(15 downto 0); -- parallel input rate hi bit uscale_reg : in std_logic_vector(15 downto 0); -- parallel input scale temper_reg : in std_logic_vector(15 downto 0) -- parallel input temperature ); end spi_slave; architecture rtl of spi_slave is type SPI_SM_Type is ( WAIT_4_CS, WAIT_4_CLK, SHIFT_BIT, NEXT_BIT ); signal spi_sm_state : SPI_SM_Type := WAIT_4_CS; signal shift_register_out : std_logic_vector(111 downto 0); BEGIN SPI_SM : process (clk_50MHz) begin if falling_edge (clk_50MHz) then case spi_sm_state is ---------WAIT_4_CS-------- when WAIT_4_CS => if spi_cs = '0' then spi_sm_state <= WAIT_4_CLK; shift_register_out( 15 downto 0) <= "0000000000000000"; shift_register_out( 31 downto 16) <= temper_reg; shift_register_out( 47 downto 32) <= uscale_reg; shift_register_out( 63 downto 48) <= rate_l_reg; shift_register_out( 79 downto 64) <= rate_h_reg; shift_register_out( 95 downto 80) <= status_reg; shift_register_out(111 downto 96) <= "0101010110101010"; end if; -------------WAIT_4_CLK---------- when WAIT_4_CLK => if spi_cs = '0' then spi_miso <= shift_register_out(111); if spi_clk = '1' then spi_sm_state <= SHIFT_BIT; end if; else spi_sm_state <= WAIT_4_CS; end if; -------------SHIFT_BIT---------- when SHIFT_BIT => if spi_cs = '0' then spi_sm_state <= NEXT_BIT; shift_register_out <= shift_register_out(110 downto 0) & '0'; else spi_sm_state <= WAIT_4_CS; end if; -------------NEXT_BIT---------- when NEXT_BIT => if spi_cs = '0' then if spi_clk = '0' then spi_sm_state <= WAIT_4_CLK; end if; else spi_sm_state <= WAIT_4_CS; end if; ----------------------- when others => null; ----------------------- end case; end if; end process SPI_SM; end architecture rtl; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 8 декабря, 2011 Опубликовано 8 декабря, 2011 · Жалоба поиском по форуму, за последний месяц темы две были. асинхра у вас %) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sazh 3 9 декабря, 2011 Опубликовано 9 декабря, 2011 · Жалоба Может кто Наверно надо описать состояние ожидания spi_cs = '1' Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sisuprun 0 9 декабря, 2011 Опубликовано 9 декабря, 2011 (изменено) · Жалоба Столкнулся с непонятной проблемой, выглядит так, что иногда на выходе получаю либо нули, либо мусор. Подключил СигналТар, обнаружилась проблема в стейтмашине, из состояния NEXT_BIT она переходит в неопределенное когда все пины в 0 или поднимается пин WAIT_4_CLK и при этом NEXT_BIT остается поднятым и потом происходит переход в состояние WAIT_4_CS и данные портятся. Клок на spi 1Mhz, внутренний 50MHz. Может кто то подсказать, в какой стороне копать проблему? код компелируется в Quartus 11.0 под Cyclon lll library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity spi_slave is Port ( clk_50MHz : in std_logic; -- internal clock spi_cs : in std_logic; -- spi bus slave select line spi_clk : in std_logic; -- spi bus sck clock spi_mosi : in std_logic; -- spi bus mosi input spi_miso : out std_logic; -- spi bus miso output status_reg : in std_logic_vector(15 downto 0); -- parallel input status rate_l_reg : in std_logic_vector(15 downto 0); -- parallel input rate low bit rate_h_reg : in std_logic_vector(15 downto 0); -- parallel input rate hi bit uscale_reg : in std_logic_vector(15 downto 0); -- parallel input scale temper_reg : in std_logic_vector(15 downto 0) -- parallel input temperature ); end spi_slave; architecture rtl of spi_slave is type SPI_SM_Type is ( WAIT_4_CS, WAIT_4_CLK, SHIFT_BIT, NEXT_BIT ); signal spi_sm_state : SPI_SM_Type := WAIT_4_CS; signal shift_register_out : std_logic_vector(111 downto 0); BEGIN SPI_SM : process (clk_50MHz) begin if falling_edge (clk_50MHz) then case spi_sm_state is ---------WAIT_4_CS-------- when WAIT_4_CS => if spi_cs = '0' then spi_sm_state <= WAIT_4_CLK; shift_register_out( 15 downto 0) <= "0000000000000000"; shift_register_out( 31 downto 16) <= temper_reg; shift_register_out( 47 downto 32) <= uscale_reg; shift_register_out( 63 downto 48) <= rate_l_reg; shift_register_out( 79 downto 64) <= rate_h_reg; shift_register_out( 95 downto 80) <= status_reg; shift_register_out(111 downto 96) <= "0101010110101010"; end if; -------------WAIT_4_CLK---------- when WAIT_4_CLK => if spi_cs = '0' then spi_miso <= shift_register_out(111); if spi_clk = '1' then spi_sm_state <= SHIFT_BIT; end if; else spi_sm_state <= WAIT_4_CS; end if; -------------SHIFT_BIT---------- when SHIFT_BIT => if spi_cs = '0' then spi_sm_state <= NEXT_BIT; shift_register_out <= shift_register_out(110 downto 0) & '0'; else spi_sm_state <= WAIT_4_CS; end if; -------------NEXT_BIT---------- when NEXT_BIT => if spi_cs = '0' then if spi_clk = '0' then spi_sm_state <= WAIT_4_CLK; end if; else spi_sm_state <= WAIT_4_CS; end if; ----------------------- when others => null; ----------------------- end case; end if; end process SPI_SM; end architecture rtl; Прав ой как прав des00. Почитайте о синхронизации данных при их передаче между двумя разными клоковыми доменами, например на сайте уважаемого iosifk CDC Изменено 9 декабря, 2011 пользователем artix Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Bad0512 2 9 декабря, 2011 Опубликовано 9 декабря, 2011 · Жалоба Ну и кроме очевидного косяка с асинхронным управлением FSM тут ещё антиглитч напрашивается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
___sergey___ 0 9 декабря, 2011 Опубликовано 9 декабря, 2011 · Жалоба всем спасибо за помощь, дело в том, что на входных сигналах перед блоком стоят триггеры на внутреннем клоке, хотя может конечно этого не достаточно. на сигналтапе, внешний клок приходит ровно каждые 50 клоков внутреннего, без сбоев. дата сигнал тоже поднимается без проблем, вовремя. но вот раз в 10-30 передач, зависимости я не уловил, в момент перехода (переход в нужный момент) стейтмашина становится в два состояния одновременно (остатется поднятым бит предыдущего состояния и поднимается бит нового состояния) или опускает все состояния, соответственно передача сбивается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sisuprun 0 10 декабря, 2011 Опубликовано 10 декабря, 2011 · Жалоба всем спасибо за помощь, дело в том, что на входных сигналах перед блоком стоят триггеры на внутреннем клоке, хотя может конечно этого не достаточно. дабы избежать метастабильного состояния их как минимум должно быть 2 :laughing: причина такого поведения именно в метастабильности. К бабке не ходи :laughing: ИМХО:На Вашем месте я бы завел spi_clk на PLL и на этой частоте принимал бы данные. Приняв,например, байт перекидывал бы в домен работающий на системном клоке. B) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
___sergey___ 0 10 декабря, 2011 Опубликовано 10 декабря, 2011 · Жалоба дабы избежать метастабильного состояния их как минимум должно быть 2 :laughing: причина такого поведения именно в метастабильности. К бабке не ходи :laughing: ИМХО:На Вашем месте я бы завел spi_clk на PLL и на этой частоте принимал бы данные. Приняв,например, байт перекидывал бы в домен работающий на системном клоке. B) спасибо за совет, попробую реализовать Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sazh 3 11 декабря, 2011 Опубликовано 11 декабря, 2011 · Жалоба но вот раз в 10-30 передач Свой тестбенч покажите. Чтоб ясно было, чего Вы от схемы своей хотите. library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity spi_slave is Port ( clk_50MHz : in std_logic; -- internal clock spi_cs : in std_logic; -- spi bus slave select line spi_clk : in std_logic; -- spi bus sck clock spi_miso : out std_logic; -- spi bus miso output status_reg : in std_logic_vector(15 downto 0); -- parallel input status rate_l_reg : in std_logic_vector(15 downto 0); -- parallel input rate low bit rate_h_reg : in std_logic_vector(15 downto 0); -- parallel input rate hi bit uscale_reg : in std_logic_vector(15 downto 0); -- parallel input scale temper_reg : in std_logic_vector(15 downto 0) -- parallel input temperature ); end spi_slave; architecture rtl of spi_slave is signal meta_cs : std_logic_vector(2 downto 0); signal meta_clk : std_logic_vector(4 downto 0); signal shift_register_out : std_logic_vector(95 downto 0); signal ena_cs, ena_clk : std_logic; begin process (clk_50MHz) begin if (clk_50MHz'event and clk_50MHz = '1') then meta_cs <= meta_cs(1 downto 0) & spi_cs; meta_clk <= meta_clk(3 downto 0) & spi_clk; if (ena_cs = '1') then --shift_register_out( 15 downto 0) <= "0000000000000000"; shift_register_out( 15 downto 0) <= temper_reg; shift_register_out( 31 downto 16) <= uscale_reg; shift_register_out( 47 downto 32) <= rate_l_reg; shift_register_out( 63 downto 48) <= rate_h_reg; shift_register_out( 79 downto 64) <= status_reg; shift_register_out( 95 downto 80) <= "0101010110101010"; elsif (ena_clk = '1') then shift_register_out <= shift_register_out(94 downto 0) & '0'; end if; if (ena_clk = '1') then spi_miso <= shift_register_out(95); end if; end if; end process; ena_cs <= not meta_cs(1) and meta_cs(2); ena_clk <= not meta_clk(3) and meta_clk(4); end architecture rtl; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Bad0512 2 11 декабря, 2011 Опубликовано 11 декабря, 2011 · Жалоба дабы избежать метастабильного состояния их как минимум должно быть 2 :laughing: причина такого поведения именно в метастабильности. К бабке не ходи :laughing: ИМХО:На Вашем месте я бы завел spi_clk на PLL и на этой частоте принимал бы данные. Приняв,например, байт перекидывал бы в домен работающий на системном клоке. B) Плохой совет. SPI CLK - медленный клок, не факт что от него PLL заведётся. Кроме того в зависимости от источника этого клока он может иметь джиттер, глитчи и кучу других непонятных проблем. Он может вообще пропасть - тогда PLLка тупо встанет и потом придётся долго плясать с бубном чтобы её завести. Делайте как советует вам большинство : переводите все принятые с SPI сигналы в домен ваших внутренних клоков с помощью двойной защёлки (можно и больше сделать, попутно туда же запихать глитчедавилку). Вся схема - синхронная, работает от внутреннего клока. Фронты сигналов от SPI выделяются на этой же частоте, далее при необходимости подаются на CE входы разрешения триггеров вашей FSM. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
___sergey___ 0 11 декабря, 2011 Опубликовано 11 декабря, 2011 · Жалоба c PLL не работает, наверное из-за того что SPI CLK появляется только на время передачи а вот с двойным триггером все вроде стало на свои места, поставил на все входные spi сигналы, 10 Мб передались без единой ошибки. всем большое спасибо за помощь. еще только вопрос на счет гличедавилки, как ее реализовать и как правильно разместить? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
van_de_luxe 0 14 декабря, 2011 Опубликовано 14 декабря, 2011 · Жалоба ___Sergey___, выложи плиз конечный вариант. Я сейчас только начинаю с ПЛИС работать и тоже нужно spi slave реализовать Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Bad0512 2 14 декабря, 2011 Опубликовано 14 декабря, 2011 · Жалоба c PLL не работает, наверное из-за того что SPI CLK появляется только на время передачи а вот с двойным триггером все вроде стало на свои места, поставил на все входные spi сигналы, 10 Мб передались без единой ошибки. всем большое спасибо за помощь. еще только вопрос на счет гличедавилки, как ее реализовать и как правильно разместить? Ну например можно так : задвигаете входные данные в сдвиговый регистр, и выдаёте на выход 0 только тогда когда все биты этого регистра равны 0, точно также с единицами. Во всех промежуточных состояниях на выход выдаётся то, что было ранее. Имеются некоторые противопоказания : глитчедавилка вносит задержку, это может пагубно повлиять если вам надо не только читать по SPI, но и писать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
___sergey___ 0 14 декабря, 2011 Опубликовано 14 декабря, 2011 · Жалоба ___Sergey___, выложи плиз конечный вариант. Я сейчас только начинаю с ПЛИС работать и тоже нужно spi slave реализовать то что я выкладывал и есть конечный вариант, только к нему на входные сигналы spi поставил по двойному триггеру. и еще один ньюанс, девайс по запросу выдает значения сразу нескольких регистров и битовых поле, поэтому регистр такой длинный Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 15 декабря, 2011 Опубликовано 15 декабря, 2011 · Жалоба то что я выкладывал и есть конечный вариант, только к нему на входные сигналы spi поставил по двойному триггеру. и еще один ньюанс, девайс по запросу выдает значения сразу нескольких регистров и битовых поле, поэтому регистр такой длинный так вроде здесь все описанное реализовано (код от sazh) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться