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

Первый проект на Verilog. Прошу помощи

always @(negedge SS) begin
 txbuf <= spitx;
end

always @(posedge SS) begin
 spirx <= spireg;
end

always @(negedge SCLK or posedge SS) begin
 if (SS) begin
  txld <= 1'b0;
 end else begin
  txld <= 1'b1;
 end
end

assign miso_mux = (~txld) ? txbuf[7] : spireg[7];
assign MISO = (~SS) ? miso_mux : 1'bz;

always @(negedge SCLK) begin
 if (txld) begin
  spireg <= {spireg[6:0], MOSI};
 end else begin
  spireg <= {txbuf[6:0], MOSI};
 end
end

 

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


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

На этом форуме приводил задачку синтезируемого описания многопортового триггера (те с несколькими клоками), но ветку не нашел (емнип было в ~2010г).

post.png

Изменено пользователем Leka

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


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

module spi_slave(
			input i_core_clk,	//FPGA clock
			
			input wire i_cs,
			input wire i_clk,
			input wire i_mosi,
			output reg o_miso,
				
			output reg o_irq,
			output reg [7:0]o_rx_buf,
			input wire [7:0]i_tx_buf	
);

//----------------------- MOSI -----------------------------
	
	reg [2:0]counter_rx;
	reg [7:0]sr_rx;
	
	//Детектор flag_rx
	reg flag_rx, flag_rx_1, flag_rx_2;
	wire flag_rx_pos;
	assign flag_rx_pos = flag_rx_1 & ~flag_rx_2;
		
	always @(negedge i_core_clk)
	begin
		flag_rx_1 <= flag_rx;
		flag_rx_2 <= flag_rx_1;	
	end	
		
	always @(posedge i_clk or posedge i_cs)
	begin
		if(i_cs) counter_rx <= 3'd0;
		else
		begin
			counter_rx <= counter_rx + 1'd1;
			
			if(counter_rx == 3'd7) flag_rx <= 1'd1;
			else flag_rx <= 1'd0;
		
			sr_rx <= {sr_rx[6:0], i_mosi};
		end
	end
	
	always @(posedge i_core_clk)
	begin
		if(flag_rx_pos)
		begin
			o_irq <= 1'd1;
			o_rx_buf <= sr_rx;
		end
		
		if(o_irq) o_irq <= 1'd0; 
	end
	
//-------------------------- MISO ---------------------------------	
	reg [2:0]counter_tx;
	reg [7:0]sr_tx;

	reg miso_mux, f;
	
	always @(*)
	begin
		if(i_cs) o_miso = 1'bZ;
		else o_miso = miso_mux;
		
		if(f) miso_mux = sr_tx[7]; 
		else miso_mux = i_tx_buf[7];  
	end
	
	always @(negedge i_clk or posedge i_cs)
	begin
		if(i_cs) 
		begin
			f <= 1'd0;
			counter_tx <= 1'd0;
		end	
		else 
		begin
			f <= 1'd1;
			counter_tx <= counter_tx + 1'd1;
			if(!counter_tx && !f) sr_tx <= i_tx_buf << 1'd1; 
			else if(counter_tx == 3'd7) sr_tx <= i_tx_buf;	
			else sr_tx <= sr_tx << 1'd1; 	
		end	
	end
	
endmodule

Что здесь не так? В симуляторе опять всё ОК!

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


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

Асинхронный сброс придумали мазохисты. В разные точки ПЛИС клок и асинхронный сброс могут приходить в разными относительными задержками, это означает, что могут одновременно выполняться ветви "if" и "else".

Одновременное выполнение ветвей "if" и "else" - возможный побочный эффект асинхронного дизайна, это надо учитывать.

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


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

Черновик, проверять лень.

module spi_slave(    
    input i_cs,
    input i_clk,
    input i_mosi,
    output o_miso,
    output reg [7:0] o_rx,
    input [7:0] i_tx    
);
reg p_cs, n_cs;
reg [7:0] sr_rx, sr_tx;
assign o_miso = i_cs ? 1'bz : n_cs ? i_tx[7] : sr_tx[7];  
always @(posedge i_cs) begin 
    o_rx <= sr_rx;
end    
always @(posedge i_clk) begin 
    p_cs <= i_cs;
    if(! i_cs) 
        sr_rx <= {sr_rx, i_mosi};
end
always @(negedge i_clk) begin
    n_cs <= p_cs;    
    if(! p_cs) 
        if(n_cs) 
            sr_tx <= {i_tx, 1'b0};
        else 
            sr_tx <= {sr_tx, 1'b0};
end    
endmodule
Изменено пользователем Leka

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


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

Leka, это просто частный случай некоего последовательного интерфейса, а никакой не SPI, у которого один сдвиговый регистр, данные через который проходят транзитом в следующее устройство в цепочке.

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


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

 Это м/б "SPI bus-compatible serial interface" (фраза из даташита на загрузочную флешку).

Просто хотел привести вариант кода без асинхронных гонок для конкретной задачи.

Для этого cs пропустил последовательно через "posedge i_clk" и "negedge i_clk".

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


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

Добавил к предыдущему своему коду полутактовые буферы на MOSI и параллельную загрузку, теперь это железобетонный асинхронный SPI slave:

 

always @(negedge SS) begin
 txbuf <= spitx;
end

always @(posedge SS) begin
 spirx <= spireg;
end

always @(negedge SCLK or posedge SS) begin
 if (SS) begin
  txsw <= 1'b0;
 end else begin
  txsw <= 1'b1;
 end
end

always @(posedge SCLK) begin
 txld <= txsw;
 mosibuf <= MOSI;
end

assign miso_mux = (~txsw) ? txbuf[7] : spireg[7];
assign MISO = (~SS) ? miso_mux : 1'bz;

always @(negedge SCLK) begin
 if (txld) begin
  spireg <= {spireg[6:0], mosibuf};
 end else begin
  spireg <= {txbuf[6:0], mosibuf};
 end
end

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


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

Цитата

Для этого cs пропустил последовательно через "posedge i_clk" и "negedge i_clk"

Логика работы мне немного не подходит. Ваш вариант требует обязательного наличия сигналов i_clk во время высокого уровня i_cs. Загрузка в выходной буфер o_rx из sr_rx только при фронте i_cs, а не после принятия последнего бита.   

Изменено пользователем pinchemierda

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


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

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

Если устройство одно, и клок есть только при низком уровне cs, это сильно упрощает задачу, и д/б отражено в ТЗ.

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


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

Цитата

теперь это железобетонный асинхронный SPI slave

Протокол SPI slave подразумевает загрузку принятых данных только по фронту CS? И должно ли быть так, что всё что приходит от мастера возвращается по MISO следующим байтом (эхо)?

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


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

Счетчик бит лучше не использовать, если гарантировать нужное число тактов клока при низком cs.

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


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

Просто если к примеру подчинённый один, то мастер будет всегда держать линию CS в нуле. Сигналов на линии CS вообще не будет почти никогда. Для любого устройства с SPI slave это не должно быть проблемой. 

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


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

2 минуты назад, pinchemierda сказал:

Протокол SPI slave подразумевает загрузку принятых данных только по фронту CS?

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

 

7 минут назад, pinchemierda сказал:

должно ли быть так, что всё что приходит от мастера возвращается по MISO следующим байтом (эхо)?

По стандарту, мастер в сеансе выдаёт ровно столько тактов, сколько бит в сумме у всех сдвиговых регистров, соединённых в цепочку — соответственно, все одновременно загруженные в начале сеанса по единому SS и выдвинутые из устройств биты достаются мастеру, а выдвинутые из него — устройствам, которые получают их тоже одновременно по снятию единого SS. Таким образом, счётчик битов есть лишь у мастера, чтобы во время сеанса передавать и принимать байтами, словами и т.д., как ему удобнее. Устроить "эхо", выдавая больше тактов, чем количество бит в системе, т.е. тупо гонять данные по кругу, конечно можно, но бессмысленно.

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


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

А нужна цепочка ТС? Если конечная задача - сделать spi мост между МК и конкретной схемой, не стоит усложнять.

 

|| соединение spi устройств с индивидуальными cs вроде чаще встречается.

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


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

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

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

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

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

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

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

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

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

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