Plain 418 June 27, 2020 Posted June 27, 2020 · Report post 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 Quote Share this post Link to post Share on other sites More sharing options...
Leka 1 June 27, 2020 Posted June 27, 2020 (edited) · Report post На этом форуме приводил задачку синтезируемого описания многопортового триггера (те с несколькими клоками), но ветку не нашел (емнип было в ~2010г). Edited June 27, 2020 by Leka Quote Share this post Link to post Share on other sites More sharing options...
bmv89 0 June 28, 2020 Posted June 28, 2020 · Report post 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 Что здесь не так? В симуляторе опять всё ОК! Quote Share this post Link to post Share on other sites More sharing options...
Leka 1 June 28, 2020 Posted June 28, 2020 · Report post Асинхронный сброс придумали мазохисты. В разные точки ПЛИС клок и асинхронный сброс могут приходить в разными относительными задержками, это означает, что могут одновременно выполняться ветви "if" и "else". Одновременное выполнение ветвей "if" и "else" - возможный побочный эффект асинхронного дизайна, это надо учитывать. Quote Share this post Link to post Share on other sites More sharing options...
Leka 1 June 28, 2020 Posted June 28, 2020 (edited) · Report post Черновик, проверять лень. 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 Edited June 28, 2020 by Leka Quote Share this post Link to post Share on other sites More sharing options...
Plain 418 June 28, 2020 Posted June 28, 2020 · Report post Leka, это просто частный случай некоего последовательного интерфейса, а никакой не SPI, у которого один сдвиговый регистр, данные через который проходят транзитом в следующее устройство в цепочке. Quote Share this post Link to post Share on other sites More sharing options...
Leka 1 June 28, 2020 Posted June 28, 2020 · Report post Это м/б "SPI bus-compatible serial interface" (фраза из даташита на загрузочную флешку). Просто хотел привести вариант кода без асинхронных гонок для конкретной задачи. Для этого cs пропустил последовательно через "posedge i_clk" и "negedge i_clk". Quote Share this post Link to post Share on other sites More sharing options...
Plain 418 June 28, 2020 Posted June 28, 2020 · Report post Добавил к предыдущему своему коду полутактовые буферы на 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 Quote Share this post Link to post Share on other sites More sharing options...
bmv89 0 June 28, 2020 Posted June 28, 2020 (edited) · Report post Цитата Для этого cs пропустил последовательно через "posedge i_clk" и "negedge i_clk" Логика работы мне немного не подходит. Ваш вариант требует обязательного наличия сигналов i_clk во время высокого уровня i_cs. Загрузка в выходной буфер o_rx из sr_rx только при фронте i_cs, а не после принятия последнего бита. Edited June 28, 2020 by pinchemierda Quote Share this post Link to post Share on other sites More sharing options...
Leka 1 June 28, 2020 Posted June 28, 2020 · Report post Согласен, логика может не подходить. Но гарантировать отсутствие клока при высоком уровне cs можно только в случае одного устройства spi slave на шине. Надо разбираться, но сам всегда избегаю использования асинхронного сброса. Если устройство одно, и клок есть только при низком уровне cs, это сильно упрощает задачу, и д/б отражено в ТЗ. Quote Share this post Link to post Share on other sites More sharing options...
bmv89 0 June 28, 2020 Posted June 28, 2020 · Report post Цитата теперь это железобетонный асинхронный SPI slave Протокол SPI slave подразумевает загрузку принятых данных только по фронту CS? И должно ли быть так, что всё что приходит от мастера возвращается по MISO следующим байтом (эхо)? Quote Share this post Link to post Share on other sites More sharing options...
Leka 1 June 28, 2020 Posted June 28, 2020 · Report post Счетчик бит лучше не использовать, если гарантировать нужное число тактов клока при низком cs. Quote Share this post Link to post Share on other sites More sharing options...
bmv89 0 June 28, 2020 Posted June 28, 2020 · Report post Просто если к примеру подчинённый один, то мастер будет всегда держать линию CS в нуле. Сигналов на линии CS вообще не будет почти никогда. Для любого устройства с SPI slave это не должно быть проблемой. Quote Share this post Link to post Share on other sites More sharing options...
Plain 418 June 28, 2020 Posted June 28, 2020 · Report post 2 минуты назад, pinchemierda сказал: Протокол SPI slave подразумевает загрузку принятых данных только по фронту CS? По стандарту, во время сеанса, принадлежность данных, проходящих транзитом сквозь соединённые в цепочку устройства, естественно не определена, лишь по его завершении. 7 минут назад, pinchemierda сказал: должно ли быть так, что всё что приходит от мастера возвращается по MISO следующим байтом (эхо)? По стандарту, мастер в сеансе выдаёт ровно столько тактов, сколько бит в сумме у всех сдвиговых регистров, соединённых в цепочку — соответственно, все одновременно загруженные в начале сеанса по единому SS и выдвинутые из устройств биты достаются мастеру, а выдвинутые из него — устройствам, которые получают их тоже одновременно по снятию единого SS. Таким образом, счётчик битов есть лишь у мастера, чтобы во время сеанса передавать и принимать байтами, словами и т.д., как ему удобнее. Устроить "эхо", выдавая больше тактов, чем количество бит в системе, т.е. тупо гонять данные по кругу, конечно можно, но бессмысленно. Quote Share this post Link to post Share on other sites More sharing options...
Leka 1 June 28, 2020 Posted June 28, 2020 · Report post А нужна цепочка ТС? Если конечная задача - сделать spi мост между МК и конкретной схемой, не стоит усложнять. || соединение spi устройств с индивидуальными cs вроде чаще встречается. Quote Share this post Link to post Share on other sites More sharing options...