Jump to content

    

Влияние смежных цепей на работу схемы.

1 minute ago, Bad0512 said:

нарезал бы всё внутренним 400 МГц клоком и жил бы припеваючи. :))

это для тех кому старшие семерки  и ультрас достаются бесплатно) такие люди, спиай давно уже не используют. Оке, уточним задачу, берем чип класса спартан6/сыклон 5, самый медленный. SPI 90 МГц.

Share this post


Link to post
Share on other sites
5 minutes ago, des00 said:

это для тех кому старшие семерки  и ультрас достаются бесплатно) такие люди, спиай давно уже не используют. Оке, уточним задачу, берем чип класса спартан6/сыклон 5, самый медленный. SPI 90 МГц.

Вот тут уже включаем голову и применяем системный подход. После беглого анализа понимаем что 90МГц SPI и дохленький чип ПЛИС как-то между собой не коррелируют. И решаем либо частоту SPI понизить, либо решить проблему сменой ПЛИС (дохленький цинк с аппаратной поддрежкой SPI в PS вполне прокатит, кстати).

P.S. А по поводу "не используют" скажу так. Эти люди иногда такое унылое говно используют, что становится страшно за будущее нашей оборонки. Из примеров - преобразователь электрика-оптика-электрика на скорости до 100 мегабит на цинке 7030. Как вам такое, Илон Маск?

Share this post


Link to post
Share on other sites
5 hours ago, des00 said:

Оке, уточним задачу, берем чип класса спартан6/сыклон 5, самый медленный. SPI 90 МГц.

Вопрос не мне, но отвечу. Когда-то делал специфический SPI на 64MHz 16 бит. Тактовый сигнал и данные держал в двух регистрах. В момент передачи оба регистра синхронно выдвигал. Выходные регистры были упакованы в IO буфферы ПЛИС. За счёт всего этого удалось добиться полного отсутствия разницы фаз между клоком и данными и достаточно простым управлением тактового сигнала в период пачки. Минус в том, что внутренняя логика должна в этом случае работать на удвоенной частоте. Но думаю, что даже 100MHz SPI (200Mhz внутренней частоты) этот дизайн бы запросто потянул, при условии согласованности линии и возможности ведомого принять такой поток. Но это если делать на чистом HDL. Не знаю как на C5, но на спартане6 есть ODDR2 (выходной буфер DDR). Думаю, что тот же фокус с двумя регистрами можно провернуть и с ним, только в этом случае удвоенная внутренняя частота уже не будет нужна.

 

А топикстартеру рекомендую изучить неблокирующие присваивания, иначе этот ад не заработает никогда.

Edited by Inanity

Share this post


Link to post
Share on other sites
20 minutes ago, Inanity said:

Вопрос не мне, но отвечу. Когда-то делал специфический SPI на 64MHz 16 бит. Тактовый сигнал и данные держал в двух регистрах. В момент передачи оба регистра синхронно выдвигал. Выходные регистры были упакованы в IO буфферы ПЛИС. За счёт всего этого удалось добиться полного отсутствия разницы фаз между клоком и данными и достаточно простым управлением тактового сигнала в период пачки. Минус в том, что внутренняя логика должна в этом случае работать на удвоенной частоте. Но думаю, что даже 100MHz SPI (200Mhz внутренней частоты) этот дизайн бы запросто потянул, при условии согласованности линии и возможности ведомого принять такой поток. Но это если делать на чистом HDL. Не знаю как на C5, но на спартане6 есть ODDR2 (выходной буфер DDR). Думаю, что тот же фокус с двумя регистрами можно провернуть и с ним, только в этом случае удвоенная внутренняя частота уже не будет нужна.

 

А топикстартеру рекомендую изучить неблокирующие присваивания, иначе этот ад не заработает никогда.

 

на передачу вообще на любой почти частоте можно сделать легко. Тут речь идёт за slave, то есть надо сделать приёмник, соответственно надо переложить всё на внутренний клок заведомо более быстрый (ну хотя бы в 3 раза быстрее) чтобы не потерять фронты.

 

Share this post


Link to post
Share on other sites
22 minutes ago, Bad0512 said:

на передачу вообще на любой почти частоте можно сделать легко. Тут речь идёт за slave, то есть надо сделать приёмник, соответственно надо переложить всё на внутренний клок заведомо более быстрый (ну хотя бы в 3 раза быстрее) чтобы не потерять фронты.

 

Какой-то странный подход. Это же не асинхронный интерфейс. Зачем тогда лишний провод на тактовый сигнал тратить?

Share this post


Link to post
Share on other sites
3 minutes ago, Inanity said:

Какой-то странный подход. Это же не асинхронный интерфейс. Зачем тогда лишний провод на тактовый сигнал тратить?

Без перехода на внутренний клок получится унылое асинхронное говнище, которое будет нестабильно работать из-за дребезга и периодически залипать наглухо по причине того, что клок SCK присутствует только в момент передачи данных, а паузах может и вообще отсутствовать.

Share this post


Link to post
Share on other sites
1 minute ago, Bad0512 said:

Без перехода на внутренний клок получится унылое асинхронное говнище, которое будет нестабильно работать из-за дребезга и периодически залипать наглухо по причине того, что клок SCK присутствует только в момент передачи данных, а паузах может и вообще отсутствовать.

Переход на внутренний клок будет в любом случае, но приёмный каскад должен работать по клоку приходящему. Это какой-то непонятный огород, который вас не спасёт, т.к. кроме фронта приходящего тактового сигнала нет никаких других способов детектировать валидные данные на шине.

Share this post


Link to post
Share on other sites
23 hours ago, des00 said:

Оке, уточним задачу, берем чип класса спартан6/сыклон 5, самый медленный. SPI 90 МГц.

 

17 hours ago, Inanity said:

Но думаю, что даже 100MHz SPI (200Mhz внутренней частоты) этот дизайн бы запросто потянул,

У меня сейчас лежит проект на Спартан 6 с клоком 200MHz. В основном всё работает без проблем, если не загружать все ненужные блоки одновременно. И при определённой сноровке можно спокойно поднять детектирование входным буффером до 300MHz, а дальше уже логику на любой частоте прикрутить. Так что не вижу необходимости заводить клок от SPI  и тактировать им внутренние ФФ. Разве что выше 100MHz  что-то будет. А может я просто ленивый и мне лень констрейнить все сопли SPI

Share this post


Link to post
Share on other sites
11 minutes ago, Inanity said:

Переход на внутренний клок будет в любом случае, но приёмный каскад должен работать по клоку приходящему. Это какой-то непонятный огород, который вас не спасёт, т.к. кроме фронта приходящего тактового сигнала нет никаких других способов детектировать валидные данные на шине.

Неизбежный дребезг как побеждать будете в этом случае?

Share this post


Link to post
Share on other sites

Собственно решил проблему, как подсказал des00Cделал срабатывание по по фронту SS. 
 


module spi_slave (rstb,ss,sck,sdin,done,rdata, sdout);
input rstb;
input ss;
input sck;
input sdin; 
output reg done;
output reg [7:0] rdata;


output reg sdout;

reg [7:0] rreg;
reg [3:0] nb;          
reg [3:0] nf;

always @(posedge sck or negedge rstb or posedge ss)
begin
if (rstb == 0)
  begin                    

  done <= 0;
  nb   <= 0;
  nf    <= 0;
  sdout <= 0;
  end
else
	if (ss)                    
		begin
		nb   <= 0;
		done <= 0;
		nf <= 0;
		sdout <= 0;
		end
	else            
		begin 
		rreg ={rreg[6:0],sdin};
		nb <= nb + 1;            
		if(nb != 7) done <= 0;
		else                    
		  begin
		  rdata=rreg;
		  done <= 1;
		  nb   <= 0;
		  nf <= nf + 1;
		  if(nf == 7) 
			begin
			sdout <= 1;
			nf    <= 0;   
			end
		  end
		end

end
endmodule

 

Share this post


Link to post
Share on other sites
49 minutes ago, Bad0512 said:

Неизбежный дребезг как побеждать будете в этом случае?

Для начала установить природу дребезга или глитча. В 90% уверен, что проблема в несогласованности линии, сигнал отражается от приёмника и гуляет по проводу, создавая внеочередные фронты, провалы, короче говоря глитчи. Решать эту проблему надо на схемотехническом уровне (согласование/экранирование и т.д.). Если все эти вопросы решены, но всё равно есть проблемы с приёмом данных ввиду внешних наводок и т.д. то проблему можно попробовать решить на уровне протокола, т.е. контрольные суммы, запрос-ответ и т.д. В худшем случае SPI как интерфейс может вам и не подойти совсем. Тогда нужен асинхронный протокол с нормальной преамбулой, ECC и т.д. Вы же, насколько я понимаю, предлагаете оверсемплингом восстанавливать клок, который поможет детектировать данные. Не могу сказать, что это не будет работать, но зачем тогда вообще применять не предназначенный для таких задач синхронный интерфейс? Стоит ли программировать навороченный гибрид SPI-приёмника и осциллографа, чтобы принять шумный SPI? Не знаю, возможно, когда другого выхода нет, то это оправданно, но во всех других ситуациях это не рационально.

Edited by Inanity

Share this post


Link to post
Share on other sites
3 hours ago, Cianid said:

Собственно решил проблему, как подсказал des00Cделал срабатывание по по фронту SS.

Что такое 《posedge sck or negedge rstb or posedge ss 》 ?

С точки зрения синтеза весьма любопытно.

Share this post


Link to post
Share on other sites
2 минуты назад, Nieve сказал:

Что такое 《posedge sck or negedge rstb or posedge ss 》 ?

С точки зрения синтеза весьма любопытно.

А это заявка записаться в расстрельный список. Чтобы начальник знал кого и за что...

Share this post


Link to post
Share on other sites
6 minutes ago, Nieve said:

Что такое 《posedge sck or negedge rstb or posedge ss 》 ?

С точки зрения синтеза весьма любопытно.

простое описание слейва (vhdl):

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

-- THE SPI SLAVE MODULE SUPPORT ONLY SPI MODE 0 (CPOL=0, CPHA=0)!!!

entity SPI_SLAVE is
    Port (
        CLK      : in  std_logic; -- system clock
        RST      : in  std_logic; -- high active synchronous reset
        -- SPI SLAVE INTERFACE
        SCLK     : in  std_logic;
        CS_N     : in  std_logic;
        MOSI     : in  std_logic;
        MISO     : out std_logic;
        -- USER INTERFACE
        READY    : out std_logic; -- when READY = 1, SPI slave is ready to accept input data
        DIN      : in  std_logic_vector(7 downto 0); -- input data for master
        DIN_VLD  : in  std_logic; -- when DIN_VLD = 1, input data are valid and can be accept
        DOUT     : out std_logic_vector(7 downto 0); -- output data from master
        DOUT_VLD : out std_logic  -- when DOUT_VLD = 1, output data are valid
    );
end SPI_SLAVE;

architecture RTL of SPI_SLAVE is

    signal spi_clk_reg        : std_logic;
    signal spi_clk_redge_en   : std_logic;
    signal spi_clk_fedge_en   : std_logic;
    signal load_data          : std_logic;
    signal data_shreg         : std_logic_vector(7 downto 0);
    signal bit_cnt            : unsigned(2 downto 0);
    signal last_bit_en        : std_logic;
    signal slave_ready        : std_logic;
    signal data_busy_reg      : std_logic;
    signal rx_data_vld        : std_logic;

begin

    load_data <= slave_ready and DIN_VLD;
    READY     <= slave_ready;
    DOUT      <= data_shreg;

    -- -------------------------------------------------------------------------
    --  SPI CLOCK REGISTER
    -- -------------------------------------------------------------------------

    spi_clk_reg_p : process (CLK)
    begin
        if (rising_edge(CLK)) then
            if (RST = '1') then
                spi_clk_reg <= '0';
            else
                spi_clk_reg <= SCLK;
            end if;
        end if;
    end process;

    -- -------------------------------------------------------------------------
    --  SPI CLOCK EDGES FLAGS
    -- -------------------------------------------------------------------------

    spi_clk_fedge_en <= not SCLK and spi_clk_reg;
    spi_clk_redge_en <= SCLK and not spi_clk_reg;

    -- -------------------------------------------------------------------------
    --  DATA BUSY REGISTER
    -- -------------------------------------------------------------------------

    data_busy_reg_p : process (CLK)
    begin
        if (rising_edge(CLK)) then
            if (RST = '1') then
                data_busy_reg <= '0';
            else
                if (DIN_VLD = '1' and CS_N = '1') then
                    data_busy_reg <= '1';
                elsif (rx_data_vld = '1') then
                    data_busy_reg <= '0';
                else
                    data_busy_reg <= data_busy_reg;
                end if;
            end if;
        end if;
    end process;

    slave_ready <= CS_N and not data_busy_reg;

    -- -------------------------------------------------------------------------
    --  MISO REGISTER
    -- -------------------------------------------------------------------------

    miso_p : process (CLK)
    begin
        if (rising_edge(CLK)) then
            if (load_data = '1') then
                MISO <= DIN(7);
            elsif (spi_clk_fedge_en = '1' and CS_N = '0') then
                MISO <= data_shreg(7);
            end if;
        end if;
    end process;

    -- -------------------------------------------------------------------------
    --  DATA SHIFT REGISTER
    -- -------------------------------------------------------------------------

    data_shreg_p : process (CLK)
    begin
        if (rising_edge(CLK)) then
            if (load_data = '1') then
                data_shreg <= DIN;
            elsif (spi_clk_redge_en = '1' and CS_N = '0') then
                data_shreg <= data_shreg(6 downto 0) & MOSI;
            end if;
        end if;
    end process;

    -- -------------------------------------------------------------------------
    --  DATA OUT VALID FLAG REGISTER
    -- -------------------------------------------------------------------------

    rx_data_vld <= spi_clk_fedge_en and last_bit_en;

    dout_vld_reg_p : process (CLK)
    begin
        if (rising_edge(CLK)) then
            if (RST = '1') then
                DOUT_VLD <= '0';
            else
                DOUT_VLD <= rx_data_vld;
            end if;
        end if;
    end process;

    -- -------------------------------------------------------------------------
    --  BIT COUNTER
    -- -------------------------------------------------------------------------

    bit_cnt_p : process (CLK)
    begin
        if (rising_edge(CLK)) then
            if (RST = '1') then
                bit_cnt <= (others => '0');
            elsif (spi_clk_fedge_en = '1' and CS_N = '0') then
                if (bit_cnt = "111") then
                    bit_cnt <= (others => '0');
                else
                    bit_cnt <= bit_cnt + 1;
                end if;
            end if;
        end if;
    end process;

    -- -------------------------------------------------------------------------
    --  LAST BIT FLAG REGISTER
    -- -------------------------------------------------------------------------

    last_bit_en_p : process (CLK)
    begin
        if (rising_edge(CLK)) then
            if (RST = '1') then
                last_bit_en <= '0';
            else
                if (bit_cnt = "111") then
                    last_bit_en <= '1';
                else
                    last_bit_en <= '0';
                end if;
            end if;
        end if;
    end process;

end RTL;

 

Share this post


Link to post
Share on other sites
30 minutes ago, iosifk said:

А это заявка записаться в расстрельный список. Чтобы начальник знал кого и за что...

И обратите внимание, если что - можно сказать, что des00 подсказал ;)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this