Пример двустороннего рукопожатия Verilog
Я заканчиваю проект, и требование-двустороннее рукопожатие между функциональными блоками внутри нашего процессора. Я знаю, что это такое, но есть ли какой-нибудь "стандарт" или хороший простой пример этого?
Единственное, что я могу придумать между двумя блоками, когда между ними есть линия передачи данных и когда X посылает Y, дается отдельный сигнал "отправлено". Когда Y получает сигнал "принято", он передается X по другому проводу. Как только X считывает полученный сигнал, он прекращает передачу данных по линии передачи данных и наборы отправлено провод к 0 или З. Ы затем полученный сигнал 0 или Z, а также.
Все это синхронно (на одних и тех же часах).
Является ли это допустимым способом сделать это? Я думаю, что это может быть очень грязно в больших масштабах, но я работаю только на простом процессоре на основе аккумулятора.
3 ответа:
Наиболее распространенным простым рукопожатием для одного домена часов было бы действительное/готовое рукопожатие.
Если 'X' передает 'Y', то X имеет выходы
data
иvalid
, а Y имеет выходready
.Когда у X есть данные для отправки, он утверждает, что они действительны, и смотрит на ready. Если действителен и готов на posedge часов, тогда Х будет рассматривать данные, которые будут отправлены, и y будем рассматривать сведения, которые будут получены.
Преимущество этой схемы заключается в том, что вы можете отправлять одни данные за такт без какого-либо времени простоя. Если valid по-прежнему высока, то следующий цикл после valid/ready был высоким, то это считается вторым пакетом.
Также нет требования, что Y ждет, чтобы увидеть действительный, прежде чем он утверждает ready, Y может утверждать ready в любое время, когда он доступен для получения данных.
Схема, которую вы описываете, является тем, что я бы назвал "req / ack 4-фазное рукопожатие", в котором требуется четыре такта для передачи одной информации
1. req=1 ack=0 2. req=1 ack=1 3. req=0 ack=1 4. req=0 ack=0
Такой интерфейс был бы лучше при выполнении асинхронного запроса через тактовую границу, так как это исключает любую возможность интерпретации пакета дважды. Но вам это не нужно для полностью синхронного интерфейса.
Я часто использую схемы, подобные предложению Tims, для того, чтобы FSMs запускали/приостанавливали друг друга. Сигнал go (req) может инициировать обработку в Нижнем или вторичном модуле, который подтверждает, когда она завершена.
reg go; reg complete; //abstracted FSM1 always @(posedge clk) begin case( fsm1_state ) START_SUB : begin go <= 1'b1; fsm1_next_state <= WAIT_SUB; end WAIT_SUB: begin if (complete == 1'b1) begin go <= 1'b0; fsm1_next_state <= COMPLETED_SUB; end else begin go <= 1'b1; //Might not be required to hold high in Synch design fsm1_next_state <= WAIT_SUB; // Holds state end end default: begin go <= 1'b0; fsm1_next_state <= fsm1_state; end endcase end //fsm2 always @(posedge clk) begin case( fsm2_state ) WAITING : begin complete <= 1'b0; if (go ==1'b1) begin fsm2_next_state <= DOSOMETHING; end else begin fsm2_next_state <= WAITING; end end DOSOMETHING : begin complete <= 1'b1; fsm2_next_state <= WAITING; // if an async system wait until go is deasserted // rather than pulse complete for 1 cycle end endcase end
Государственные машины всегда должны быть инициализированы или сброшены и использовать случай по умолчанию для удаления непреднамеренных состояний блокировки.
Я думаю, что вы хотите создать арбитра. Существует множество различных арбитражных схем. Самая простая-это круговая схема. Если кто-то хочет получить доступ к ресурсу (например, к процессору или памяти и т. д.), то этот модуль будет утверждать строку запроса. Он ждет, пока арбитр не утвердит линию Гранта, после чего ему разрешается продолжить обработку, зная, что он имеет выделенный доступ к интерфейсу, который контролируется арбитром.