Nemos760 0 25 ноября, 2020 Опубликовано 25 ноября, 2020 (изменено) · Жалоба 1 hour ago, Flip-fl0p said: Я предпочитаю преобразователь из двоичного в семи сегментный держать в виде отдельного модуля с параметром каким логичесим уровнем зажигать сегмент. Хотя все чаще и чаще я стал в своём коде применять различного рода функции, хоть раньше этого и не любил. Не cразу понял, что у меня лишнее звено to_integer(DATA) с последующим преобразованием в hex, когда можно было сразу писать x"integer", надо избавляться от старых привычек. Изменено 25 ноября, 2020 пользователем Nemos760 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
agathodaimon 0 27 ноября, 2020 Опубликовано 27 ноября, 2020 · Жалоба В общем, подправил немного код. Теперь он выглядит так: module helloworlds ( input [3:0]btn, output [3:0]led , output reg [3:0] digits, output reg [7:0] dots, output speaker, output reg strobe, input clk); assign led[0] = btn[0]; reg [23:0]CTCQ; reg [16:0]CTFQ; reg [16:0]freq; reg [1:0]dig = 2'd0; reg [3:0]curr_digit; reg [15:0]CNT = 16'ha5a5; //reg strobe = 1; reg [7:0]strobe_ct = 0; always @(posedge clk) begin CTCQ <= CTCQ + 1'd1; strobe_ct <= strobe_ct + 1'd1; if(strobe_ct > 8'hf0) begin strobe <= 0; end else begin strobe <= 1; end // // ___ // b | g | f // |___| // | a | // c |___| e // d if (strobe) begin case(curr_digit)// ABCDEFG 4'h0: dots = ~7'b0111111; 4'h1: dots = ~7'b0000110; 4'h2: dots = ~7'b1011011; 4'h3: dots = ~7'b1001111; 4'h4: dots = ~7'b1100110; 4'h5: dots = ~7'b1101101; 4'h6: dots = ~7'b1111101; 4'h7: dots = ~7'b0000111; 4'h8: dots = ~7'b1111111; 4'h9: dots = ~7'b1101111; 4'ha: dots = ~7'b1110111; 4'hb: dots = ~7'b1111100; 4'hc: dots = ~7'b0111001; 4'hd: dots = ~7'b1011110; 4'he: dots = ~7'b1111001; 4'hf: dots = ~7'b1110001; endcase end else begin dots = ~7'b0000000; end end always @(posedge strobe) begin dig <= dig + 1'd1; curr_digit <= CNT >> (dig * 4); case(dig) 2'd0: digits = ~4'd1; 2'd1: digits = ~4'd2; 2'd2: digits = ~4'd4; 2'd3: digits = ~4'd8; endcase end always @(posedge CTCQ[23]) CNT <= CNT + 1'd1; endmodule По временной диаграмме должно быть все хорошо и наложения должны пропасть: Однако реально нажелезяке продолжаю видеть старое поведение. Сегодня попробую пример тов. Flip-fl0p. Может что-то проясниться у меня. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 27 ноября, 2020 Опубликовано 27 ноября, 2020 · Жалоба 10 часов назад, agathodaimon сказал: В общем, подправил немного код. Теперь он выглядит так: По временной диаграмме должно быть все хорошо и наложения должны пропасть: Однако реально нажелезяке продолжаю видеть старое поведение. Сегодня попробую пример тов. Flip-fl0p. Может что-то проясниться у меня. В Вашем коде много недостатков. 1. Есть сигналы, которые не используются. Долой из рабочего кода мусор. Код должен быть максимально чистым. 2. Нет нормальных названий сигналов. Сигналы должны быть понятными. Вот что значит регистр CTCQ ? По коду видно, что это счетчик, а что он считает. Зачем он нужен ? 3. Смешано все в одной куче. Разбейте схему на логически законченные блоки. 4. На вход тактовой частоты подается сигнал с счетчика. Думаю в Вашем случае это ошибка.... Хотите правильно делать ? Начинайте проектирование не с написание кода, а с рисования карандашом на бумаге. Нарисуйте функциональную схему Вашего устройства. Тогда все станет понятным и простым. Ну и самое главное - пользуйтесь симулятором. Пока не заработает на симуляторе - в железе работать не будет. Чтобы дойти до уровня, когда можно написать код без симулятора - надо потратить не один десяток часов, а то и сотню. При этом Все-равно на более-менее сложных блоках без симулятора не обойтись. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Plain 165 28 ноября, 2020 Опубликовано 28 ноября, 2020 · Жалоба Ничего не изменилось, потому что ничего не меняли. Требуемые для отображения данные по-прежнему отсутствуют в заголовке модуля и создаются внутри него асинхронным генератором случайных чисел. Таким же кривым остался и строб, с F1 по 00 включительно, т.е. на выходе гашение данных соответственно с F2 по 01 включительно, что прекрасно видно даже на такой картинке. А уж частота 200 кГц для выводов ПЛИС, нагруженных на ёмкости слонового размера светодиодов на другой стороне платы — ну это запредельно круто. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
agathodaimon 0 29 ноября, 2020 Опубликовано 29 ноября, 2020 · Жалоба On 11/28/2020 at 12:59 AM, Flip-fl0p said: В Вашем коде много недостатков. издержки С программиста Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 29 ноября, 2020 Опубликовано 29 ноября, 2020 · Жалоба 15 минут назад, agathodaimon сказал: издержки С программиста Так FPGA - это больше схемотехника. И думать надо по-другому. А когда рисуете схемы на бумаге карандашом - становится сразу проще. Советую. У меня обычно уходит много бумаги времени прежде чем я приступаю к написанию кода. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
agathodaimon 0 29 ноября, 2020 Опубликовано 29 ноября, 2020 · Жалоба On 11/28/2020 at 9:59 AM, Plain said: Требуемые для отображения данные по-прежнему отсутствуют в заголовке модуля и создаются внутри него асинхронным генератором случайных чисел почему отсутствуют-то? Данные для отображения содержаться в регистре CNT, который путем сдвига на 4 бита, преобразуется в число для каждого сегмента. Изначальное значение этого регистра задается при его объявлении, а инекремент происходит при просчете счетчика CTCQ. On 11/28/2020 at 9:59 AM, Plain said: А уж частота 200 кГц для выводов ПЛИС, нагруженных на ёмкости слонового размера светодиодов на другой стороне платы — ну это запредельно круто. Вы предлагаете понизить частоту смены переключения индикаторов? Звучит логично.... надо попробовать. 14 minutes ago, Flip-fl0p said: У меня обычно уходит много бумаги времени прежде чем я приступаю к написанию кода. А на сколько детально вы рисуете схемы? Наверное, если бы я рисовал схему сейчас, то в моей схеме бы присутствовал один блок, с входим тактовой частоты и выходом на семисегментный индикатор) 16 minutes ago, Flip-fl0p said: Так FPGA - это больше схемотехника. И думать надо по-другому. Да, когда начинал изучать эту тему, сложно было свыкнуться, что в ПЛИС все процессы происходят одновременно Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Plain 165 29 ноября, 2020 Опубликовано 29 ноября, 2020 · Жалоба 15 минут назад, agathodaimon сказал: Данные для отображения содержаться в регистре CNT, который Вы не знаете, в каком месте кристалла синтезатор положил curr_digit, а в каком dots, и какие задержки получились между их тактовыми — так вот, в худшем случае, данные на входах dots могут исчезать раньше, чем требуется, и вперемешку, в зависимости от тепловых волн, пульсаций питания и т.п., поэтому на его выходах будет случайное число. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 29 ноября, 2020 Опубликовано 29 ноября, 2020 · Жалоба 40 минут назад, agathodaimon сказал: почему отсутствуют-то? Данные для отображения содержаться в регистре CNT, который путем сдвига на 4 бита, преобразуется в число для каждого сегмента. Изначальное значение этого регистра задается при его объявлении, а инекремент происходит при просчете счетчика CTCQ. Вы предлагаете понизить частоту смены переключения индикаторов? Звучит логично.... надо попробовать. А на сколько детально вы рисуете схемы? Наверное, если бы я рисовал схему сейчас, то в моей схеме бы присутствовал один блок, с входим тактовой частоты и выходом на семисегментный индикатор) Да, когда начинал изучать эту тему, сложно было свыкнуться, что в ПЛИС все процессы происходят одновременно Детальность зависит только от полноты описания модуля, которое мне нужно для документирования. В случае вывода на семисегментный индикатор с 4 разрядами я бы ограничился таким описанием: Модуль верхнего уровня CONTROLLER_4X_7SEGM, который имеет 4 входа данных (каждый вход данные для соответствующего сегмента) и 2 выхода данных. Один выход - код семисегментного индикатора. Второй - выбор индикатора. Этот модуль состоит из 2 других модулей: 7SEGM_CTRL_FSM - модуль который определяет в какое время включить нужный сегмент и что на этот сегмент подать. По сути - это простейший цифровой автомат. Возможно туда имело бы смысл добавить небольшой блок, который формирует из системной частоты нужную частоту для своей работы, чтобы обеспечить необходимую скорость переключения сегментов. Или же счетчик, который держит включенным разряд нужное нам время. Но это мелочи, которые обычно определяются когда полная схема устройства перед глазами. И второй модуль - это BINARY_TO_7SEGM_CODER кодер из 4 битового двоичного числа в код семисегментного индикатора. В итоге мы имеем блок CONTROLLER_4X_7SEGM которому достаточно подать на входы данные, которые мы хотим зажечь на соответствующих сегментах. Ему все равно каким образом эти данные формируются. Он полностью автономен. Стараюсь модули делать с минимальной связностью. Каждый модуль максимально "тупой" и не знает о существовании других модулей. Ему подали данные на вход, он их обработал и выдал дальше. Это в идеале. Обычно получается чуть сложнее и частенько приходится добавлять доплнительные сигнал в виде ready, busy, done. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Plain 165 29 ноября, 2020 Опубликовано 29 ноября, 2020 · Жалоба 8 часов назад, Flip-fl0p сказал: я бы ограничился таким описанием: До полноценных модулей по-моему ещё далеко, а неполноценными задача решается примерно так: always @(posedge clk) begin // делаем три стробированных переноса, т.е. каждый "1" 10 нс, если 100 МГц, // когда его счётчик, и все до него, равны нулю cnt0r <= (cnt0 == 16'd1); cnt1r <= (cnt0 == 16'd1) && (cnt1 == 8'd0); cnt2r <= (cnt0 == 16'd1) && (cnt1 == 8'd0) && (cnt2 == 2'd0); // младший счётчик считает всегда cnt0 <= cnt0 - 1'b1; // когда он упёрся, загружаем в него его период и дёргаем следующий счётчик if (cnt0r) begin cnt0 <= prd0; cnt1 <= cnt1 - 1'b1; end // аналогично следующий if (cnt1r) begin cnt1 <= prd1; cnt2 <= cnt2 - 1'b1; end // аналогично, но дальше счётчиков нет, поэтому лишь загрузка последнего if (cnt2r) begin cnt2 <= prd2; end // второй счётчик создаёт развёртку интервала гашения if (cnt0r) begin // включаем индикацию спустя один его такт после смены разряда дисплея if (cnt1 == prd1) begin case (mem0[cnt2]) 4'h0: dots <= 7'b1111111; ... 4'hf: dots <= 7'b1111111; endcase end // выключаем индикацию за один его такт до смены разряда дисплея if (cnt1 == 8'd1) begin dots <= 7'b0000000; end end // делаем синхронный дешифратор позиции дисплея, учитывая, // что в третьем счётчике сейчас предыдущее её значение if (cnt1r) begin case (cnt2) 2'b00 : digits <= 4'b1000; 2'b01 : digits <= 4'b0001; 2'b10 : digits <= 4'b0010; 2'b11 : digits <= 4'b0100; endcase end end Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться