yaghtn 0 19 июня, 2015 Опубликовано 19 июня, 2015 · Жалоба Здравствуйте. Для связи между CPLD epm570 и MCU atsam3u задумано использовать SPI, проц - мастер, плис - слейв. Микроконтроллер должен управлять светодиодами посредством ПЛИС и считывать состояние входов ПЛИС. Регистров в ПЛИС несколько, поэтому в дополнение к сигналам SPI (mosi/miso/sck/ncs), используются три линии адреса, управляемые микроконтроллером в режиме PIO. Обмен происходит изредка и не быстрее мегагерца, поэтому мне показалось неоптимальным постоянно тактовать модуль SPI от быстрого системного клока ПЛИС. Та же шина должна использоваться для контроля внешнего ЦАП, поэтому формат SPI выбран самый обычный (CPHA=0, CPOL=0), когда данные на mosi/miso появляются сразу после падения NCS, а сигнальный клок SCK появляется позже. MCU не генерит SCK, когда NCS в единице, и эти сигналы не меняют своё состояние одновременно. Код модуля и тестбенча - ниже. Основная идея - клочить приёмопередатчик сигналом ck, получаемый объединением логическим ИЛИ сигналов SCK и NCS шины. Что нужно защелкивать в сдвиговый регистр интерфейса - выходные данные MOSI или параллельные данные состояния ПЛИС, держится в регистре state. Если по фронту объединенного клока видим положительный NCS - будем загружать данные ПЛИС. Если был SCK - значит будем загружать побитно MOSI. В итоге, проц нормально управляет регистрами ПЛИС - лампочки загораются как надо, но, хотя в симуляторе всё работает, в реальном устройстве ПЛИС не выдаёт на MISO своё состояние, а лишь повторяет прошлые пришедшие в MOSI данные. Подскажите пожалуйста, в чем я мог тут ошибиться. Или я уже готов плюнуть и сделать синхронный дизайн на мастерклоке в 20МГц с детекторами фронтов клоков шины, как во всех примерах гугла, но это не то, что хотелось. module spislave( spcki,ncsi,mosi,miso,addri, pdati, pdat1o,pdat2o); //spi IO input spcki,ncsi,mosi; output miso; input [2:0]addri; //parallel IO input [7:0]pdati; output [7:0]pdat1o; output [7:0]pdat2o; parameter PDATI=0,MOSI=1; //что защелкивать в spishiftreg reg state=PDATI; wire ck = spcki | ncsi; always@(posedge ck) begin if(ncsi) state <= PDATI; else //(ncs==0 && spcki==1) state <= MOSI; end reg mosi_prelatch=0; always@(posedge spcki) mosi_prelatch<=mosi; reg [7:0]spishiftreg=0; always@(negedge ck) begin if(state == PDATI) spishiftreg<=pdati; else//(state == MOSI) spishiftreg<={spishiftreg[6:0],mosi_prelatch}; end assign miso=spishiftreg[7]&(~ncsi); reg [7:0]pdat1o; reg [7:0]pdat2o; always@(posedge ncsi) begin if(addri==0) pdat1o<=spishiftreg; else if(addri==1) pdat2o<=spishiftreg; end endmodule `timescale 1ps/1ps parameter ps=1;parameter ns=1000*ps; module tbspi(); integer bitnum=0; reg [2:0]addr=7; reg ncs=1; reg spck=0; wire mosi; reg [7:0]spi_reg=0; assign mosi=spi_reg[7]; initial begin #(50*ns)ncs=1; for(addr=0;addr<4;addr=addr+1) begin spi_reg<=8'b01010101; #(50*ns)ncs=0; for(bitnum=0; bitnum<8; bitnum=bitnum+1) begin #(10*ns) spck=1; #(10*ns) spck=0; spi_reg<={spi_reg[6:0],1'b0}; end #(50*ns)ncs=1; #(50*ns)ncs=1; end end wire miso; wire [7:0]pdati=8'b11100111; wire [7:0]pdat1o; wire [7:0]pdat2o; spislave DUT(.spcki(spck),.ncsi(ncs),.mosi(mosi),.miso(miso),.addri(addr), .pdati(pdati), .pdat1o(pdat1o),.pdat2o(pdat2o)); endmodule Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Mad_kvmg 0 19 июня, 2015 Опубликовано 19 июня, 2015 · Жалоба Или я уже готов плюнуть и сделать синхронный дизайн на мастерклоке в 20МГц с детекторами фронтов клоков шины, как во всех примерах гугла, но это не то, что хотелось. Именно это и нужно сделать! Потому что то, что у Вас сейчас это тихий ужас. И еще не мешайте в testbench блокирующее и не блокирующее присваивание, а то на race condition напоритесь Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexRayne 7 19 июня, 2015 Опубликовано 19 июня, 2015 · Жалоба у вас в проекте используется 3 разных клока - это уже занимает хилые ресурсы CPLD заметно. я делал такие дизайны, их надо очень подробно отлаживать чтоб заработало, но всеравно их скорость будет уступать синхронным просто потому что она не может быть адекватна посчитана симуляторами. ваш проект скорее всего заработает если вы сведете количество доменов клоков к 2м, и это потребует довольно серьезных размышлений над междоменной синхронизацией. проще всего конечно сделать чисто синхронный дизайн с одним клоком. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yaghtn 0 19 июня, 2015 Опубликовано 19 июня, 2015 · Жалоба Спасибо большое за ответы. сейчас это тихий ужас. Как, по вашему, будет смотреться дизайн с мастерклоком модуля, разрешаемым декодером адреса (трех входных пинов плис)? Просто не хотелось бы "шевелить" эту часть вхолостую, если фактически работа с нею происходит раз в сутки. скорость будет уступать синхронным просто потому что она не может быть адекватна посчитана симуляторами. ваш проект скорее всего заработает если вы сведете количество доменов клоков к 2м, и это потребует довольно серьезных размышлений над междоменной синхронизацией. Да в том и дело, что скорость высокая совсем не требуется. Клоки в реале - не более чем 1МГц. Т.е времена - микросекундные. Рассинхронизация тут, по идее, влиять на должна. Я грешил на ошибки в алгоритме, которые почему-то не могу увидеть сам. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Mad_kvmg 0 19 июня, 2015 Опубликовано 19 июня, 2015 · Жалоба Как, по вашему, будет смотреться дизайн с мастерклоком модуля, разрешаемым декодером адреса (трех входных пинов плис)? Так и будет смотреться, пересадите все асинхронные входные сигналы на системный клок, далее спокойно работайте в одном домене и будет у вас синхронный дизайн без состояний когда работает, но не совсем. А ужас это вот это wire ck = spcki | ncsi; always@(posedge ck) Вы берете по или два сигнала и используете как клок. А что синтехатор сделает из этого, вообще сложно представить always@(posedge ncsi) begin Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yaghtn 0 19 июня, 2015 Опубликовано 19 июня, 2015 · Жалоба Так и будет смотреться, пересадите все асинхронные входные сигналы на системный клок, далее спокойно работайте в одном домене и будет у вас синхронный дизайн без состояний когда работает, но не совсем. Вы правы, так написать проще всего. Но появятся дополнительные цепочки реклока трех входных сигналов и детекта фронтов, это дополнительные 8..12 LE, которых и так маловато. Поэтому, для начала, хотелось бы попробовать асинхронный дизайн. А ужас это вот это wire ck = spcki | ncsi; always@(posedge ck) Вы берете по или два сигнала и используете как клок. Возможно, глупый вопрос, но почему это ужас? Ведь на этом клоке работает единственный регистр, выход которого используется гарантированно больше, чем 500ns, по другому фронту этого же клока. А что синтехатор сделает из этого, вообще сложно представить always@(posedge ncsi) begin Я надеялся, что сделает параллельные регистры, берущие данные с шины из сдвигового регистра приёма mosi, работающие по клоку ncsi, и с энейблами, декодированными из трехбитного адреса. И судя по post-fitting map квартуса, пока синтезируется так. Подозреваю что, аналогичная синхронная логика будет не сильно проще. Нужно переписать конструкцию if-else-if как switch-case? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 19 июня, 2015 Опубликовано 19 июня, 2015 · Жалоба Вот что-то такое можно оформить в виде таска, и потом при отладке менять адреса и данные... Ну а "адреса и данные" сделать входами для таска... #(50*ns)ncs=1; for(addr=0;addr<4;addr=addr+1) begin spi_reg<=8'b01010101; #(50*ns)ncs=0; for(bitnum=0; bitnum<8; bitnum=bitnum+1) begin #(10*ns) spck=1; #(10*ns) spck=0; spi_reg<={spi_reg[6:0],1'b0}; end #(50*ns)ncs=1; #(50*ns)ncs=1; end Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 20 июня, 2015 Опубликовано 20 июня, 2015 · Жалоба Подскажите пожалуйста, в чем я мог тут ошибиться. Или я уже готов плюнуть и сделать синхронный дизайн на мастерклоке в 20МГц с детекторами фронтов клоков шины, как во всех примерах гугла, но это не то, что хотелось. Можно сделать и асинхронный (т.е. на клоке от spi) если четко понимаете что вам нужно. В вашем коде мне показалось странным вот что : 1. По хорошему MISO при неактивном CS должен быть в Z состоянии. 2. Т.к. у вас читается только регистр состояния, так и сделайте что бы он читался на каждой транзакции. Т.е. берете компонент dffeas (а ваш макс это сыклон 2 по сути), на сигнал aload вешаете CS, по спаду загружаете свой регистр ну и дальше банальная транзакция записи/чтения, т.е. сдвиговый регистр). А отличать запись от чтения, судя по вашему коду, вы будете по адресам (маскируя "лишную" запись). Логика упростится и будет надежно работать (пока наводочки с левыми фронтами на сигналах не появятся ;)) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
topor_topor 0 20 июня, 2015 Опубликовано 20 июня, 2015 · Жалоба Обмен происходит изредка и не быстрее мегагерца, поэтому мне показалось неоптимальным постоянно тактовать модуль SPI от быстрого системного клока ПЛИС. А чем по Вашему такое решение неоптимально в этом случае если есть такая возможность? Делать SPI от внешнего клока имеет смысл только если нет возможности привязатть к внутреннему клоку (напр. он сравним по скорости с SPI, или его нет ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yaghtn 0 22 июня, 2015 Опубликовано 22 июня, 2015 · Жалоба А чем по Вашему такое решение неоптимально Характер потребления плис по питанию будет мягче для асинхронного дизайна за счёт разновременности переключения отдельных логических элементов. Хотелось бы иметь поменьше побочного взаимовлияния между компонентами системы. И прежде чем сильнее фильтровать питание и экранировать чувствительные места, сначала можно попробовать поменьше шуметь. Ну и для ресинхронизации и детекта фронтов требуются дополнительные ресурсы (по два-три Dff в каждую линию), которые хочется сэкономить. dffeas на сигнал aload вешаете CS Элемент dffeas не решает задачу, потому что он работает не по фронту, а по уровню aload. Ему необходим детектор фронта. Суть задачи именно в этом и состоит: нужен D-триггер с двумя защелкивающими входами (и с двумя входами данных, соответствующих им). Возможен ли такой элемент вообще? И чтобы а)без явных детекторов фронтов на элементах задержки(на Д-триггерах синхронных мастерклоку, либо на цепочках lcell) б)без дополнительной внутренней памяти некоего автоматного состояния в)без использования аппаратно-специфичных примитивов (на синтезируемом Верилоге, например) Можете ли посоветовать литературу на эту тему? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 22 июня, 2015 Опубликовано 22 июня, 2015 · Жалоба Элемент dffeas не решает задачу, потому что он работает не по фронту, а по уровню aload. Ему необходим детектор фронта. Вашу задачу решает прекрасно. Вы читаете один регистр статуса. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yaghtn 0 22 июня, 2015 Опубликовано 22 июня, 2015 · Жалоба Вашу задачу решает прекрасно. Вы читаете один регистр статуса. Простите, я не понимаю, как. (Сколько регистров передаём - не суть, пусть даже всего один читаем, и всего один пишем, я согласен на это) Но Dffeas, судя по таблице истинности описания примитива в /modelsim_ase/.../maxii_atoms.v при установленном Aload становится в режим прозрачности, повторяя Adata на выходе. И не реагирует на D и Clk, пока Aload не снимется. Если подать CS на Aload, то регистр проигнорирует любое остальное шевеление на шине SPI, хотя именно тогда идут нужные данные. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 22 июня, 2015 Опубликовано 22 июня, 2015 · Жалоба Простите, я не понимаю, как. Может быть я вашу задачу не понял, но сами смотрите : `timescale 1ns/1ns module pipa (input clk, input cs_n, sclk, mosi, output miso, input [1 : 0] addr, output logic [1 : 0] leds [2]); logic [7 : 0] sreg, sreg_next; logic [7 : 0] status_cnt; //------------------------------------------------------------------------------------------------------ // spi //------------------------------------------------------------------------------------------------------ /* always_ff @(posedge sclk or posedge cs_n) begin // not correctly dffeas (!!!!) if (cs_n) sreg <= status_cnt; else sreg <= (sreg << 1) | mosi; end */ assign sreg_next = {sreg[6:0], mosi}; generate genvar i; for (i = 0; i < 8; i++) begin : popa_inst dffeas popa ( .clk ( sclk ) , .d ( sreg_next [i] ) , .ena ( 1'b1 ) , .asdata ( status_cnt [i] ) , .aload ( cs_n ) , .q ( sreg [i] ) ); end endgenerate assign miso = !cs_n ? sreg[7] : 1'bz; //------------------------------------------------------------------------------------------------------ // spi decode //------------------------------------------------------------------------------------------------------ always_ff @(posedge cs_n) begin leds[addr] <= sreg[1:0]; end //------------------------------------------------------------------------------------------------------ // status cnt //------------------------------------------------------------------------------------------------------ always_ff @(posedge clk) begin status_cnt <= status_cnt + 1'b1; end endmodule // synthesis translate_off module tb ; bit clk, cs_n, sclk, mosi, miso; bit [1 : 0] addr; logic [1 : 0] leds [2]; pipa popa (.*); initial begin forever #50ns clk = ~clk; end const int N = 5; initial begin bit [7 : 0] rtmp; init_spi(100ns); for (int i = 0; i < N; i++) begin do_spi(10+i, i, rtmp, 50ns); $display("%0d write %0d read %0d", i, 10+i, rtmp); end $stop; end //------------------------------------------------------------------------------------------------------ // //------------------------------------------------------------------------------------------------------ time T = 10ns; task init_spi (time delay = T); cs_n <= 1'b1; sclk <= 1'b0; mosi <= 1'b0; #delay; endtask task do_spi (bit [7 :0] wdat = 0, addr = 0, output bit [7:0] rdat, input time delay = T); cs_n <= 1'b0; addr <= addr; #(T/2); for (int i = 0; i < 8; i++) begin sclk <= 1'b0; mosi <= wdat[7-i]; rdat <= (rdat << 1) | miso; #(T/2); sclk <= 1'b1; #(T/2); end #(T/2); sclk <= 1'b0; cs_n <= 1'b1; #delay; endtask endmodule // synthesis translate_on Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yaghtn 0 23 июня, 2015 Опубликовано 23 июня, 2015 · Жалоба смотрите : Сразу стало ясно. Прозрачность рабочего регистра spi для выходных данных слейва по ald=nCS=1 в покое и сдвигание данных по slck при транзакции. Просто блестящая в своей простоте идея. Спасибо. Моя проблема в том, что я хотел описать на верилоге, чтобы тот же код использовать ещё и для max3000/7000. но теперь стало ясно, для начала надо вдумчиво изучить Алтеровский "Coding Guidelines" Вот было интересное обсуждение около года назад на тему "dffea -- verilog" http://electronix.ru/forum/index.php?s=&am...t&p=1276608 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kefalle 0 26 июня, 2015 Опубликовано 26 июня, 2015 · Жалоба Товарищи, подскажите, у меня есть проект SPI синхронного от внутреннего генератора. Регитр состояния и регистр значения (4 байта) сделан на verilog обычным reg [7:0]. На MAX II работает нормально. А вот при портирования проекта на Lattice дурят значения регистров, если вставляю в CASE четыре альтернативы все плывет, а если две то работате нормально... В симуляции смотрел все отлично, да и до этого на MAX II все проверял... в чем может быть загвоздка? Такое ощущение, что разводке что-то оптимизируется или усекается... под словои "дурит" понимается, что когда в коде написано data_sent <= 32'hDEADBEEF; на порт выходит что-то не понятное, а когда работает, то нормально на порту выходит это значение Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться