nabbla (nabbla1) wrote,
nabbla
nabbla1

Categories:

Мучаем 5576ХС4Т - часть 'h37 - ускоренные счётчики, работа над ошибками

[Оглавление (ссылки на остальные части)]Часть 0 - покупаем, паяем, ставим драйвера и софт
Часть 1 - что это вообще за зверь?
Часть 2 - наша первая схема!
Часть 3 - кнопочки и лампочки
Часть 4 - делитель частоты
Часть 5 - подавление дребезга кнопки
Часть 6 - заканчиваем кнопочки и лампочки
Часть 7 - счетчики и жаба
Часть 8 - передатчик UART
Часть 9 - Hello, wolf!
Часть 'hA - приёмник UART
Часть 'hB - UART и жаба
Часть 'hC - полудуплексный UART.
Часть 'hD - МКО (МКИО, Mil-Std 1553) для бедных, введение.
Часть 'hE - приёмопередатчик МКО "из подручных материалов" (в процессе)
Часть 'hF - модуль передатчика МКО
Часть 'h10 - передатчик сообщений МКО
Часть 'h20 - работа с АЦП ADC124s051
Часть 'h21 - преобразование двоичного кода в двоично-десятичный (BCD)
Часть 'h22 - Bin2Bcd с последовательной выдачей данных
Часть 'h23 - перемножитель беззнаковых чисел с округлением
Часть 'h24 - перемножитель беззнаковых чисел, реализация
Часть 'h25 - передаём показания АЦП на компьютер
Часть 'h26 - работа над ошибками (быстрый UART)
Часть 'h27 - PNG и коды коррекции ошибок CRC32
Часть 'h28 - передатчик изображения PNG
Часть 'h29 - принимаем с ПЛИС изображение PNG
Часть 'h2A - ZLIB и коды коррекции ошибок Adler32
Часть 'h2B - ускоряем Adler32
Часть 'h2C - формирователь потока Zlib
Часть 'h2D - передаём сгенерированное PNG-изображение
Часть 'h2E - делим отрезок на равные части
Часть 'h2F - знаковые умножители, тысячи их!
Часть 'h30 - вычислитель множества Мандельброта
Часть 'h31 - ускоренные сумматоры
Часть 'h32 - ускоренные счётчики (делаем часы)
Часть 'h33 - ускоряем ВСЁ
Часть 'h34 - ускоренные перемножители
Часть 'h35 - умножители совсем просто
Часть 'h36 - уравновешенный четверичный умножитель
Часть 'h37 - ускоренные счётчики, работа над ошибками


Модули "быстрых" счётчиков из части 'h32, которые способны корректно работать на медленных кристаллах (Flex10ke speed grade "-3", ну или наши 5576ХС4Т), имеют один "изъян", который надо поскорее локализовать и исправить!

А именно, иногда они неправильно реагируют на сигнал сброса...

Вот, наверное, самая простая схема, на которой можно продемонстрировать нехорошее поведение:



Это схема счёта до 60: верхний по схеме счётчик идёт от 0 до 9, и когда он доходит до 9, формируется сигнал ceo, который на единичку прибавляет нижний счётчик, идущий от 0 до 5. "Фрагмент часов".

Также у нас тут стоит схема сброса, которая должна "безусловно" устанавливать оба счётчика в ноль.

Посмотрим, что получается на деле:


Здесь мы два раза "жмём" сброс. Во второй раз всё получается правильно - ровно к следующему такту (у нас это синхронный сброс) получаем два нуля, после чего возобновляется обычный счёт.

А вот в первый раз происходит бяка: первоначально как будто всё правильно, мы получили два нуля. Но затем, вместо того, чтобы единица прибавилась в "младшем" счётчике, она прибавилась в "старшем", т.е следующим за 00 у нас получилось не 01, а 10. Затем правильный счёт продолжился с этого места.

Объяснение очень простое: мы забыли сбросить регистр переноса!

Чтобы не нужно было "впопыхах" проверять, что мы досчитали до 9, а значит, нужно выдать сброс на наш собственный счётчик и сформировать импульс счёта на следующий, мы решили делать проверку одним шагом ранее (того, что досчитали до 8) и сохранять её в регистре, чтобы к следующему такту сигнал переноса появлялся "сразу", не дожидаясь, пока выходы регистров пройдут через ГФ (LUT) и сформируют правильное значение.

И как мы видим, если ровно за такт до конца счёта подать сигнал сброса, то он укажет самому счётчику со следующего такта выдавать ноль, а вот наш регистр ничего не знает об этом, всё, что он "видит" - это текущий выход счётчика, восьмёрку. Поэтому на следующем такте он как не в чём ни бывало выдаёт единичку, которая заставляет к следующему такту сбросить младший счётчик (ПОВТОРНО!) и прибавить единичку в старшем разряде.

"Лечение" очень простое, регистр переноса также должен обнуляться при подаче сброса:

`include "math.v"

module FastCounter (	input ce,  	//clock enable
			input clk, 	//clock
			input sclr, //synchronous clear
			output [Width - 1 : 0] Q,
			output reg TC = 1'b0,
			output ceo); //clock enable - output

	parameter Fin = 80_000_000;
	parameter Fout = 1000;
	parameter Width = 17;
	
	localparam DivideBy = (Fin + Fout / 2) / Fout; //rounding to nearest integer
	localparam Limit = DivideBy - 2; //when dividing by 10, Limit is 8
	localparam IntWidth = `CLOG2(DivideBy);
	localparam MaxInt = 1 << IntWidth;

	
	wire cout; //carry-out of lpm_counter
	wire [IntWidth - 1 : 0] IntQ;
	wire combTC = ((IntQ & Limit) == Limit) & (IntQ[0] == (Limit & 1'b1)); //Terminal Count

	lpm_counter	lpm_counter_component (
				.clock (clk),
				.cnt_en (ce),
				.sclr (ceo | sclr),
				.q (IntQ));
	defparam
		lpm_counter_component.lpm_direction = "UP",
		lpm_counter_component.lpm_port_updown = "PORT_UNUSED",
		lpm_counter_component.lpm_type = "LPM_COUNTER",
		lpm_counter_component.lpm_width = IntWidth;

	
	always @(posedge clk)
		TC <= sclr? 1'b0 : ce? combTC : TC;
		
	assign ceo = TC & ce;
	assign Q = IntQ;
	
endmodule


Зелёным обозначена исправленная строка, раньше здесь было просто
if (ce) TC <= combTC;


После этого исправления всё работает правильно:



"Детская" ошибка, наподобие этой:

но весьма характерная - мы неявно сделали "конвейер" и забыли его сбросить, если что-то начинает идти "не по плану". И сразу огребли.
Tags: ПЛИС, работа, странные девайсы
Subscribe

  • О вытягивании себя из болота по методу Мюнхгаузена

    Всё готовлюсь к встрече с представителями РКК Энергия, нужно убедить их в моём способе определения положения ВидеоИзмерителя Параметров Сближения на…

  • Ремонт лыжных мостиков

    Вернулся с сегодняшнего субботника. Очень продуктивно: отремонтировали все ТРИ мостика! Правда, для этого надо было разделиться, благо народу…

  • Гетто-байк

    В субботу во время Великой Октябрьской резни бензопилой умудрился петуха сломать в велосипеде. По счастью, уже на следующий день удалось купить…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 4 comments