nabbla (nabbla1) wrote,
nabbla
nabbla1

Categories:

Счётчик в кодах Грея - окончание

Начало, продолжение

Осталось за малым: всё-таки реализовать "обычный режим", где дойдя до крайнего значения, счётчик сразу перескакивает в начальное, без хитрого реверса, который мы наблюдали вчера. А ещё сделать разрешение работы clk_en и вход синхронной загрузки. И проверить, что всё работает и при другом количестве бит.


Изменения, в общем-то, не очень большие:

module GrayCodeCounter (input clk, input clk_en, input sload, input [Width-1:0] D,
			output reg [Width-1:0] Q = 1'b0,
			output Ddummy);
parameter Width = 4;
parameter NoReverse = 1'b1;	//если 1, то за 1000..000 идёт сразу 0000..000,
//в противном случае ещё на такт застревает в 1000..000 и начинает идти в обратную сторону,
//затем на 2 такта застревает на 0000..000 и снова вперёд

reg dummy = 1'b0;	//вводим дополнительный бит справа, "контрольная сумма", такая, что сумма всех битов всегда должна быть чётной
assign Ddummy = dummy;

wire [Width-1:0] carryChain;

assign carryChain[0] = ~dummy;

genvar i;
generate
  for (i=1; i<Width; i=i+1) begin	:take_your_stupid_name
    assign carryChain[i] = carryChain[i-1] | Q[i-1];
  end
endgenerate

wire [Width-1:0] T_input;

assign T_input[0] = ~dummy;
assign T_input[Width-2:1] = Q[Width-3:0] & (~carryChain[Width-3:0]);
assign T_input[Width-1] = (Q[Width-2] | NoReverse) & (~carryChain[Width-2]);

always @(posedge clk) if (clk_en) begin
	dummy <= sload? ^D : ~dummy;
	Q <= sload? D : Q^T_input;
end

endmodule


Вход clk_en позволяет запретить любое изменение на выходе, будь то счёт или параллельная загрузка.
Когда sload=1, то вместо счёта загружается значение с входа D.

Главная хитрость в том, что нужно правильно инициализировать бит dummy, иначе можем "случайно" начать считать не в ту сторону.

Не так давно узнал о таком вот синтаксисе верилога:
^D


Где D - это шина. Это означает "горизонтальный" XOR, т.е D[Width-1]^D[Width-2]^...D[1]^D[0]. Удобно, не нужно городить очередной for или generate хотя бы здесь :)

Не стал начисто "убивать" свой старый вариант с реверсом, вместо этого ввёл параметр NoReverse и значение по умолчанию: "1". Как это реализовано - видно, когда NoReverse=1, старший разряд больше не обращает внимание на значение второго по старшинству, поэтому и при "нолике", и при "единичке" переключится, главное, чтобы все остальные разряды, включая dummy, содержали нули.

Теперь при Width=4 этот модуль синтезируется в 10 ЛЭ. Многовато, можно было при правильном использовании добиться 5N/4+1 для N разрядов (N ЛЭ на N бит, плюс фиктивный бит, плюс "горизонтальный XOR" для него), но увы.


Проверим для начала работу clk_en и режим "без реверса":


Всё верно: пока clk_en=0, вообще ничего не делаем, потом приступаем. Дойдя до 8 = 4'b1000, сразу переключаемся в 0 = 4'b0000, и повторяем всё то же самое, как ни в чём не бывало.

Теперь ещё опробуем синхронную загрузку:


Видно, что dummy, вместо того, чтобы переключиться в очередной раз, стал равным "чётности" поступившего значения E = 4'1110, т.е 1. И как видно, счёт продолжился в правильном направлении, что не может не радовать.

И глянем Width=8. Увы, отсинтезировалось оно в 25 ЛЭ, слишком много на мой вкус. Ну хорошо, не смог один бит вместить в 1 ЛЭ, вместил в 2 ЛЭ, это было бы 16, плюс "фиктивный бит" dummy, это 17. Плюс логика "горизонтального XOR" между 8 значениями - это ещё 3 ЛЭ, итого 20. Как так-то?? Но хотя бы работает правильно:

И предельная частота для моей ПЛИС 5576ХС4Т: 76,92 МГц, худо-бедно.

Главного достигли: получили параметризуемый модуль. Можно задавать Width от 3 и вверх. Вообще, могли бы сюда включить очередной generate, чтобы отдельно рассмотреть случаи 1 и 2, "оставим это читателю в качестве упражнения".

Остаётся вопрос: а нафига вообще он нужен? Ну, я хочу с ним один опыт провернуть, но возможно чуть позже...
Tags: ПЛИС, работа, странные девайсы
Subscribe

  • Так ли страшно 0,99969 вместо 1?

    В размышлениях о DMA, о возможных последствиях "смешивания" старых и новых значений при выдаче целевой информации, опять выполз вопрос: насколько…

  • Как продлить агонию велотрансмиссии на 1500+ км

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

  • DMA для QuatCore

    Вот фрагмент схемы нашего "процессорного ядра" QuatCore: Справа сверху "притаилась" оперативная память. На той ПЛИС, что у меня есть сейчас…

  • "МКО через UART" в железе - 2

    Продолжим проверять этот модулёк. "Для закрепления пройденного", снова запрашиваем телеметрию, сначала 1 слово данных (командное слово 0x3701, и…

  • "МКО через UART" в железе

    Долго мучали эту штуковину на симуляции, пора уже в макет это прошить и посмотреть, как оно себя поведёт. Оставлю "основную схему" (процессор, SPI,…

  • "Ошибка на единицу" при передаче CRC

    В прошлый раз обнаружили нехорошую вещь: при передаче данных от нашего устройства, CRC начинает работать одним словом раньше, чем надо, и результат…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments