Перейти к содержанию
    

SPI Verilog

Пытаюсь совокупить Atmega8 и EPM240, конечная цель генератор DDS, авр задает, плис молотит. Делаю исключительно just for fun, чтобы получить немного опыта. В общем все завелось и фурычит, но через одно место. Проблема очевидно в SPI модуле, суть такова что аврка пересчитывает частоту в переменную размерностью 32 бита, толкает их по spi, плисина должна принять стартовый бит '*', а затем 4 байта и использовать их. После Си верилог для меня в целом понятен, но читать чужие куски просто нереально, поэтому я решил написать свой модуль spi.

///---------------------------------------/////
///			SPI RECEIVE DATA
///---------------------------------------/////		
   //если чип селект не равен 0, т.е. данные не передаются
	if(ss)
	begin
		nBit <= 0;	//обнуляем счетчик принятых битов
	end

	//если данные передаются
	else
	begin
		//нужно поймать восходящий фронт, тактовых импульсов spi
                       //при этом смотрим читали ли мы уже на этом импульсе
		if((s_clk == 1) && (bit_readed == 0))
		begin
			//читаем данные
			spi_data[7:0] <= {spi_data[6:0],mosi};
			//увеличиваем счетчик
                               nBit <= nBit + 1'b1;
                               //выставляем флаг что на этом импульсе данные уже прочитаны
			bit_readed <= 1;
		end

		//по спадающему фронту, сбрасываем флаг того что данные прочитаны
		if(s_clk == 0)
		begin
			bit_readed <= 0;
		end

		//если прочитали 8 бит
		if(nBit == 8)
		begin
                               //выставляем флаг что байт готов к обработке
			byte_readed <= 1;
                               //обнуляем биты
			nBit <= 0;
		end	

	end

 

Дальше идет разбор байтов

//если байт прочитан
if(byte_readed == 1)
begin
                       //выставляем флаг
		byte_readed <= 0;

                       //смотрим номер прочитанного байта
		case(n_Byte)
		1: begin
			temp_resByte[7:0]  <= spi_data[7:0];
			n_Byte <= 2;
			end
		2:	begin
			temp_resByte[15:8] <= spi_data[7:0];
			n_Byte <= 3;
			end
		3:	begin
			temp_resByte[23:16]<= spi_data[7:0];
			n_Byte <= 4;
			end
		4:	begin
			temp_resByte[31:24]<= spi_data[7:0];
			n_Byte <= 0;
			add_Counter[31:0] <= temp_resByte[31:0];
			end
		0: begin
			n_Byte <= 0; // do nothing
			end
		endcase

		//если прочитанный байт '*', то читаем остальные байты
		if(spi_data[7:0] == 8'b00101010)
		begin
			n_Byte <= 1;
		end
end	

 

 

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Жестко. Вам надо работать по фронтам клока. Либо спи либо отдельного. А так это слишком все шатко.

Ключевое слово

Always @(posedge clk)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Жестко. Вам надо работать по фронтам клока. Либо спи либо отдельного. А так это слишком все шатко.

Ключевое слово

Always @(posedge clk)

 

нене весь этот код засунут в Always @(posedge clk), просто там есть еще логика, которая не относится к делу, т.е. я проверяю каждый такт генератора, установленного на плисине 100мгц. К клокам spi никак не могу привязаться, ибо если я выставляю какие то флаги в допустим Always @(posedge s_clk), то их нельзя сбрасывать в так назовем основном цикле Always @(posedge clk). Думаю есть способы обойти это, но гугль ничего не выдает толкового.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ага. А вы уверены что во всех частях схемы событие s_clk = 0 наступает одновременно?

Ответ в общем случае нет. И так може получится что у вас срабатываю оба if

 

Ловите фронт клока

 

Sclk2 <= sclk1

Sclk1 <= sclk

 

If(( sclk2 = 0)&&(sclk1 = 1))

 

Это будет фронт и будет он 1 раз по нему и сохраняйте данные. А чтобы защититься от метастабильности хорошо бы еще sclk3 <= sclk2 добавить и if делать по 3 и 2

П.с. Простите пишу с планшета и он сам буквы заглавные ставит, бороться сил нет:)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ага. А вы уверены что во всех частях схемы событие s_clk = 0 наступает одновременно?

Ответ в общем случае нет. И так може получится что у вас срабатываю оба if

 

Ловите фронт клока

 

Sclk2 <= sclk1

Sclk1 <= sclk

 

If(( sclk2 = 0)&&(sclk1 = 1))

 

Это будет фронт и будет он 1 раз по нему и сохраняйте данные. А чтобы защититься от метастабильности хорошо бы еще sclk3 <= sclk2 добавить и if делать по 3 и 2

П.с. Простите пишу с планшета и он сам буквы заглавные ставит, бороться сил нет:)

 

Спасибо огромное, сделал по Вашему, с sclk3. Если раньше данные принимались 1 раз из 5 попыток, то сейчас наоборот за 5 раз, 1 не уходят. Попробую еще поковырять

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ну теперь вы можете обобщить полученный опыт на другие сигналы%) У вас же не один клок асинхронный основному клоку

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...