Сегодня у нас самая предновогодняя серия про ПЛИС и отладочную плату Френки. Предыдущие серии 1, 2.


Мы уже передавали тоновые сигналы по радио с помощью нашей платы Франкенштейн. Теперь попробуем воспроизводить звуки и музыку.


Для этого подключим к ПЛИС обычный динамик. К Френки подключен генератор на 25.175 МГц. Если поделить эту частоту до диапазона слышимых частот и подать на вывод ПЛИС, то мы можем услышать звук. Меня частоту мы можем получить разные звуки.


Тестировать качество звучания будет самый лучший слухач в доме — Маша. Диапазон частот в 60 КГц — это вам не шутки! )))



Схема подключения


Для воспроизведения звука, я использую динамик из конструктора "Знаток" (другого с ходу не нашел). Динамик подключаю к выводу ПЛИС через резистор с сопротивлением 470 Ом.



Простейший звук


В ПЛИС легко помещаются двоичные счетчики. Поэтому с такой задачей справится даже Френки. Например, 16 битный счетчик будет считать от 0 до 65535. Имея наши 25.175 МГц и 16 битный счетчик мы можем получить звук частотой 25175000 / 65536 = 384,14 Гц


module epm7064_test(clk, audio);
input wire clk;
output wire audio;

// двоичный счетчик на 16 бит
reg [15:0] counter;
always @(posedge clk) counter <= counter+1;

// выведем старший бит счетчика на динамик
assign audio = counter[15];

endmodule


Нота «ЛЯ» первой октавы (440 Гц)


Мы получили случайную частоту в звуковом диапазоне. Теперь можно попробовать получить частоту, равную 440 Гц. Это частота ноты "ЛЯ" первой октавы.


Для этого, вместо деления тактовой частоты на 65536, мы должны поделить значение частоты тактового генератора на 57216 (27175000 Гц / 440 Гц).


module epm7064_test(clk, audio);
input wire clk;
output wire audio;

// двоичный счетчик на 16 бит
reg [15:0] counter; initial counter <= 16'd0;

always @(posedge clk) begin
    if(counter==57216) begin
        counter <= 0; 
    end else begin
        counter <= counter + 1'b1;
    end
end

assign audio = counter[15];

endmodule


Но в этой реализации есть проблема. Хотя частота и равна 440 Гц, но скважность сигнала не равна 50%. Низкий уровень выводится при значениях счетчика от 0 до 32767, а высокий от 32767 до 56817. Получается, что динамик находится в единице только 42% времени. Самый простой способ получить скважность 50% — это добавить еще одно деление на два. То есть, сначала на 28608, а затем еще на 2.


module epm7064_test(clk, audio);
input wire clk;
output audio;

// двоичный счетчик на 15 бит
reg [14:0] counter; initial counter <= 15'd0;

always @(posedge clk) begin
    if(counter==28608) begin
        counter <= 0; 
    end else begin
        counter <= counter + 1'b1;
    end
end

reg audio;
always @(posedge clk) if(counter==28608) audio <= ~audio;

endmodule

Конечно, на слух это почти не отличить.



Чтобы сделать более гибкий код, можно добавить параметр clkdivider. Изменение направление счета в счетчике на обратное — это всего лишь вопрос предпочтений. Разницы в используемых ресурсах ПЛИС никакой не будет.


module epm7064_test(clk, audio);
input wire clk;
output audio;

parameter clkdivider = 25175000/440/2;

reg [14:0] counter; initial counter <= 15'd0;

always @(posedge clk) begin
    if(counter==0) begin
        counter <= clkdivider - 1'b1; 
    end else begin
        counter <= counter - 1'b1;
    end
end

reg audio;
always @(posedge clk) if(counter==0) audio <= ~audio;

endmodule

Сирена скорой помощи


Теперь давайте попробуем чередовать два разных тона. Для этого используем
счетчик (назовем его tone) на 24 бита, для получения частоты порядка 1.5 Гц.
Этот сигнал будем использовать для переключения между двумя частотами.


module epm7064_test(clk, audio);
input wire clk;
output audio;

parameter clkdivider = 25175000/440/2;

reg [14:0] counter; initial counter <= 15'd0;

reg [23:0] tone; initial tone <= 24'd0;
always @(posedge clk) tone <= tone+1;

always @(posedge clk) begin
    if(counter==0) begin
        counter <= (tone[23] ? clkdivider-1 : clkdivider/2-1); 
    end else begin
        counter <= counter - 1'b1;
    end
end

reg audio;
always @(posedge clk) if(counter==0) audio <= ~audio;

endmodule


А теперь попробуем сделать полицейскую сирену. Для начала поменяем счетчик tone так, чтобы в нем было только 23 бита, чтобы увеличить частоту вдвое (старший бит будет меняться с частотой примерно 3 Гц).


А теперь нужно придумать трюк, чтобы получить "пилу". Возьмем биты с 15 по 21 из счетчика тона. Это будет выглядеть так: tone[21:15]. Эти 7 бит дадут нам значение от 0 до 127, которые будут нарастать с определенной скоростью. Как только значение достигнет 127, оно сбросится в 0 и начнет нарастать снова. Для того, чтобы получить уменьшающееся значение, мы можем инвертировать эти биты. Это будет выглядеть так: (~tone[21:15]). Этим мы получим значения, которые идут вниз от 127 до 0, а потом все повторяется.


Для того, чтобы получить пилу, которая плавно нарастает, а потом плавно спадает,
возьем бит tone[22].


wire [6:0] ramp = (tone[22] ? tone[21:15] : ~tone[21:15]);

// это все равно, что
// "if tone[22]=1 then ramp=tone[21:15] else ramp=~tone[21:15]"

Но такая пила еще не готова к применению в нашем проекте.


Значение пилы меняется от 7'b0000000 до 7'b1111111. Для того, чтобы получить значения из которых можно было бы уже получить звук, мы добавим к слову значения пилы еще 2 бита '01' слева и шесть бит '000000' справа.


wire [14:0] clkdivider = {2'b01, ramp, 6'b000000};

Таким образом, мы получим постоянно меняющееся значение clkdivider в диапазоне от 15'b010000000000000 до 15'b011111111000000, или в шестнадцатиричной системе от 15'h2000 до 15'h3FC0, или в десятичной 8192 to 16320. При частоте генератора 25.175 МГц мы получим звук сирены от 771 Гц до 1537 Гц.


module epm7064_test(clk, audio);
input wire clk;
output audio;

reg [14:0] counter; initial counter <= 15'd0;

reg [23:0] tone; initial tone <= 24'd0;
always @(posedge clk) tone <= tone+1;

wire [6:0] ramp = (tone[22] ? tone[21:15] : ~tone[21:15]);

wire [14:0] clkdivider = {2'b01, ramp, 6'b000000};

always @(posedge clk) begin
    if(counter==0) begin
        counter <= clkdivider;
    end else begin
        counter <= counter - 1'b1;
    end
end

reg audio;
always @(posedge clk) if(counter==0) audio <= ~audio;

endmodule


И мы получили быструю сирену. Но настоящая сирена меняет свою скорость с быстрой на медленную. Мы можем взять биты tone[21:15] для быстрой пилы, и биты tone[24:18] для пилы с меньшей частотой.


wire [6:0] fastsweep = (tone[22] ? tone[21:15] : ~tone[21:15]);
wire [6:0] slowsweep = (tone[25] ? tone[24:18] : ~tone[24:18]);
wire [14:0] clkdivider = {2'b01, (tone[27] ? slowsweep : fastsweep), 6'b000000};

Для этого потребуется увеличить разрядность счетчика tone.


module epm7064_test(clk, audio);
input wire clk;
output audio;

reg [14:0] counter; initial counter <= 15'd0;

reg [27:0] tone; initial tone <= 28'd0;
always @(posedge clk) tone <= tone+1;

wire [6:0] ramp = (tone[22] ? tone[21:15] : ~tone[21:15]);

wire [6:0] fastsweep = (tone[22] ? tone[21:15] : ~tone[21:15]);
wire [6:0] slowsweep = (tone[25] ? tone[24:18] : ~tone[24:18]);
wire [14:0] clkdivider = {2'b01, (tone[27] ? slowsweep : fastsweep), 6'b000000};

always @(posedge clk) begin
    if(counter==0) begin
        counter <= clkdivider;
    end else begin
        counter <= counter - 1'b1;
    end
end

reg audio;
always @(posedge clk) if(counter==0) audio <= ~audio;

endmodule


Играем мелодию


А теперь, в честь наступающего нового года, попробуем сыграть песенку про ёлочку. Поищем ноты и видео, чтобы понять, как играется эта песенка.


Для того, чтобы играть последовательность нот, нам нужно создать секвенсор, который будет выдавать номер нужной ноты, в нужный момент времени. Это значение ноты мы преобразуем в константу для делителя частоты, чтобы получить соответствующую ноту.


Судя по видео, нам потребуется всего одна октава + 1. В принципе, все ноты нам не нужы.
А нужны только 7 нот, которые используются в песне. Поэтому, для хранения номера ноты достаточно 3 бит. Правильнее, конечно, будет сказать не номер ноты, а номер тона или частоты в мелодии.


Итак, у нас в мелодии есть ноты: до, ре, ми, фа, соль, ля и до следующей октавы. Мы их соответственно и пронумеруем. Последовательность получается такая:


соль           5
ми ми         3 3

соль           5
ми ми         3 3

соль фа ми ре до    5 4 3 2 1

ля до(+1) ля
соль ми ми
соль фа ми ре до

Нарисую временную диаграмму.




С помощью секретного табличного процессора, рассчитываем частоты нот и значения делителей, немного их округлив.




Теперь, когда все расчеты окончены, опишем логику.


Делитель частоты по номеру ноты:


wire [15:0] clkdivider = 
                         (note_num == 0) ? 16'd0 :
                         (note_num == 1) ? 16'b1011101111110000 :
                         (note_num == 2) ? 16'b1010011101110000 :
                         (note_num == 3) ? 16'b1001010100110000 :
                         (note_num == 4) ? 16'b1000110011010000 :
                         (note_num == 5) ? 16'b0111110101110000 :
                         (note_num == 6) ? 16'b0110111111000000 :
                         (note_num == 7) ? 16'b0101111000000000 : 16'd0;

Судя по картинке, секвенсор у нас получается на 64 шага. Для этого увеличиваем разрядность счетчика tone.


reg [27:0] tone; initial tone <= 28'd0;
always @(posedge clk) tone <= tone + 1'b1;

wire [5:0] step_num = tone[26:(26-5)];  // 6 бит это от 0 до 63

Преобразование из номера номера шага секвенсора в номер ноты:


wire [2:0] note_num = 
                      (step_num == 0) ? 5 :    // 1
                      (step_num == 1) ? 5 :    // 2
                      (step_num == 2) ? 0 :    // 3
                      (step_num == 3) ? 0 :    // 4
                      (step_num == 4) ? 3 :    // 5
                      (step_num == 5) ? 0 :    // 6
                      (step_num == 6) ? 3 :    // 7
                      (step_num == 7) ? 0 :    // 8
                      (step_num == 8) ? 5 :    // 9
                      (step_num == 9) ? 5 :    // 10
                      (step_num ==10) ? 0 :    // 11
                      (step_num ==11) ? 0 :    // 12
                      (step_num ==12) ? 3 :    // 13
                      (step_num ==13) ? 0 :    // 14
                      (step_num ==14) ? 3 :    // 15
                      (step_num ==15) ? 0 :    // 16
... и т. д.

полностью
module epm7064_test(clk, audio);
input wire clk;
output audio;

reg [15:0] counter; initial counter <= 16'd0;

reg [27:0] tone; initial tone <= 28'd0;
always @(posedge clk) tone <= tone + 1'b1;

wire [5:0] step_num = tone[26:(26-5)];

wire [2:0] note_num = 
                      (step_num == 0) ? 5 :    // 1
                      (step_num == 1) ? 5 :    // 2
                      (step_num == 2) ? 0 :    // 3
                      (step_num == 3) ? 0 :    // 4
                      (step_num == 4) ? 3 :    // 5
                      (step_num == 5) ? 0 :    // 6
                      (step_num == 6) ? 3 :    // 7
                      (step_num == 7) ? 0 :    // 8
                      (step_num == 8) ? 5 :    // 9
                      (step_num == 9) ? 5 :    // 10
                      (step_num ==10) ? 0 :    // 11
                      (step_num ==11) ? 0 :    // 12
                      (step_num ==12) ? 3 :    // 13
                      (step_num ==13) ? 0 :    // 14
                      (step_num ==14) ? 3 :    // 15
                      (step_num ==15) ? 0 :    // 16

                      (step_num ==16) ? 5 :    // 17
                      (step_num ==17) ? 0 :    // 18
                      (step_num ==18) ? 4 :    // 19
                      (step_num ==19) ? 0 :    // 20
                      (step_num ==20) ? 3 :    // 21
                      (step_num ==21) ? 0 :    // 22
                      (step_num ==22) ? 2 :    // 23
                      (step_num ==23) ? 0 :    // 24
                      (step_num ==24) ? 1 :    // 25
                      (step_num ==25) ? 1 :    // 26
                      (step_num ==26) ? 1 :    // 27
                      (step_num ==27) ? 1 :    // 28
                      (step_num ==28) ? 0 :    // 29
                      (step_num ==29) ? 0 :    // 30
                      (step_num ==30) ? 0 :    // 31
                      (step_num ==31) ? 0 :    // 32

                      (step_num ==32) ? 6 :    // 33
                      (step_num ==33) ? 6 :    // 34
                      (step_num ==34) ? 0 :    // 35
                      (step_num ==35) ? 0 :    // 36
                      (step_num ==36) ? 7 :    // 37
                      (step_num ==37) ? 0 :    // 38
                      (step_num ==38) ? 6 :    // 39
                      (step_num ==39) ? 0 :    // 40
                      (step_num ==40) ? 5 :    // 41
                      (step_num ==41) ? 5 :    // 42
                      (step_num ==42) ? 0 :    // 43
                      (step_num ==43) ? 0 :    // 44
                      (step_num ==44) ? 3 :    // 45
                      (step_num ==45) ? 0 :    // 46
                      (step_num ==46) ? 3 :    // 47
                      (step_num ==47) ? 0 :    // 48

                      (step_num ==48) ? 5 :    // 49
                      (step_num ==49) ? 0 :    // 50
                      (step_num ==50) ? 4 :    // 51
                      (step_num ==51) ? 0 :    // 52
                      (step_num ==52) ? 3 :    // 53
                      (step_num ==53) ? 0 :    // 54
                      (step_num ==54) ? 2 :    // 55
                      (step_num ==55) ? 0 :    // 56
                      (step_num ==56) ? 1 :    // 57
                      (step_num ==57) ? 1 :    // 58
                      (step_num ==58) ? 1 :    // 59
                      (step_num ==59) ? 1 :    // 60
                      (step_num ==60) ? 0 :    // 61
                      (step_num ==61) ? 0 :    // 62
                      (step_num ==62) ? 0 :    // 63
                      (step_num ==63) ? 0 :    // 64

                       0;

wire [15:0] clkdivider = 
                         (note_num == 0) ? 16'd0 :
                         (note_num == 1) ? 16'b1011101111110000 :
                         (note_num == 2) ? 16'b1010011101110000 :
                         (note_num == 3) ? 16'b1001010100110000 :
                         (note_num == 4) ? 16'b1000110011010000 :
                         (note_num == 5) ? 16'b0111110101110000 :
                         (note_num == 6) ? 16'b0110111111000000 :
                         (note_num == 7) ? 16'b0101111000000000 : 16'd0;

always @(posedge clk) begin
    if(counter==0) begin
        counter <= clkdivider;
    end else begin
        counter <= counter - 1'b1;
    end
end

reg audio;
always @(posedge clk) if(counter==0) audio <= ~audio;

endmodule

Начнем контрольные прослушивания



Мне кажется, Маша одобряет ;) ^_^


Выводы


Как выяснилось, ПЛИС на 64 ячейки способен выступать в роли генератора звукового сигнала для сирены сигнализации. Проект с мелодией про маленькую ёлочку, занял 61 ячейку из 64-х. А это значит, что есть еще ресурсы, их можно использовать и создать, например, музыкальный дверной звонок (привет 90е!).


Исходные коды: https://github.com/UA3MQJ/epm7064_audio


При написании статьи, использовались идеи и исходные коды статьи с сайта fpga2funMusic Box.

Поделиться с друзьями
-->

Комментарии (19)


  1. x893
    28.12.2016 11:40
    +3

    Котяра классный.


  1. AndriAnoBoTS
    28.12.2016 11:59
    +2

    Занятно видеть FPGA и аналоговый осциллограф на одной фотографии ). Смотрю ваши опыты продолжаются, это хорошо, даже очень. Надеюсь вы в курсе основного недостатка CPLD микросхем?
    MAX 7000 devices use CMOS EEPROM cells to implement logic functions, and can be programmed and
    erased up to 100 times.
    Советую быстрее перебираться на более новые семейства, они уже вполне доступны для домашнего использования.


    1. UA3MQJ
      28.12.2016 16:31

      Честно, был не в курсе. Я эту микросхему скоро передарю, мне уже в замен отдали EPM3064. А более новых семейств у меня тоже есть )) Больше отдаю предпочтение, конечно, к Cyclone от 2 по 4.

      Слева направо Altera: 2хEP4CE6, EP4CE10, 2xMAXii EPM240, EPM3064.
      Снизу Lattice LC4064V и Lattice LC4032V


      EP2C5


    1. LAutour
      28.12.2016 16:44

      Доступные для домашнего использования новые семейства это EPM240 с корпусом TQFP-100 и сложнее?


      1. UA3MQJ
        28.12.2016 16:55

        Вам доступные с точки зрения паять или с точки зрения купить? Для себя доступными считаю Altera, потому что программатор порядка 300р, и готовые платы ПЛИС от 700р до 1500р от маленьких MAX240 до Cyclone. Я больше рекомендую Cyclone, конечно. Вот ПЛИС на 10 — 20 тысяч ячеек — это уже то 10 тысяч рублей может доходить, и я их уже считаю не очень доступными. По той же причине Xilinx пока мне недоступны из за высокой цены программатора, даже китайского. Достойные платы на Lattice где-то порядка 2500 рублей.


        1. LAutour
          28.12.2016 18:25

          С точки зрения паять.


          1. UA3MQJ
            28.12.2016 18:35

            Вот плата сделана утюгом. Вполне реально паять. Это Altera EPM3000 серии. Такие же и 7000й. Добываются из старых изделий. Купить их дорого, хоть 300р не деньги, но 32 ячейки — вообще я не знаю на что можно применить. За вменяемые деньги (до 100 рублей) можно купить Altera MAXii 240. Это TQFP-100. Из обвеса потребуется только стабилизатор на 3V3, конденсаторы. Для работы — генератор. Любой, но желательно поменьше, порядка 25 МГц или ниже, чтобы половину ПЛИС не тратить на деление частоты. И разъем для подключения программатора. В 240 ячеек можно засунуть очень много, пример тому сайт — Марсоход.


            1. LAutour
              28.12.2016 20:55

              Ну так TQFP-44 это совсем не TQFP-100, с ним в самоделках работать гораздо проще. Просто 3000 и 7000 серия уже относятся к нерекомендуемым, поэтому я о TQFP-100 и вспомнил. А 32 -ячеек иногда хватает с избытком — EPM3032A применяется в одном изделии у нас на работе.


            1. LAutour
              28.12.2016 21:07

              Кстати по 7000 и 3000 серии есть одна интересная особенность. У нас на них был реализован фазовый детектор с автовыравнием фазы, который иногда глючил на определенных фазовых частотах. При этом в реализованной схеме детектора сигналы со входов шли сразу на несколько логических элементов. Глюки ушли после предварительной буферизации сигналов со входа (элемент НЕ).


  1. eugenk
    28.12.2016 15:14

    Класс! Маша просто супер! У меня лежит iCE40-HX8K Breakout Board от Lattice. Даже захотелось самому на ней прикольные звучки погонять. Хотя понимаю конечно что с таким монстром на 8К ячеек это немного не спортивно. Вам же с 64 ячейками безоговорочный респект. С Новым Годом!


    1. UA3MQJ
      28.12.2016 15:28

      Спасибо, я ей передам! Это наш охотник-защитник. В этом году на даче мы с ней не голодали. Всегда свежие мыши, хомяки и птицы. Один раз даже целую сосиску принесла.
      ПЛИСы — очень интересная для меня тема, я тоже присматриваюсь к Lattice вашей серии. Нравится то, что там количество GPIO порядка 160, можно очень много чем по управлять, при желании. При случае, обязательно куплю. А 8К ячеек — это нормально как раз. Я когда делаю декодирование MIDI сообщений, генерацию сигналов разных форм (синус, пила, итд), плюс ADSR то уже получается вполне увесисто. И это на один голос, без полифонии. Полифонический электроорган с четырьмя регистрами в лоб, вполне себе почти полностью заполняет Альтеру на 4К ячеек. Так что для целей музыки 8к — это вполне нормально. Да, пили-мили — попроще влезает и в 64 ячейки. Но тут целочисленное деление. Можно попробовать еще и DDS. В общем, не стоит стесняться использовать ресурсы.


      1. eugenk
        28.12.2016 16:40
        +1

        Блин, завидую Вам черной и белой завистью! Моя Защитница и Охотница умерла три года назад. Бусильда Укусильдовна Кошкарская. 21 год прожила. Из них 7 лет с нами. Мать с тех пор категорически против кошек, собак и прочей живности.
        ПЛИСы вообще отдельная песня. Это одна из моих больших любовей. Наряду с кошками, Eclipse(в смысле не яхта Абрамовича а среда разработки), мотоциклами и мордобойными искусствами. Занимаюсь ими уже лет 10. Эта плата была куплена для одного проекта, где плисина в итоге была забита на 98%. Сейчас постепенно дозреваю до постройки квадрокоптера с продвинутыми функциями обработки видео в реальном времени. Но там закладываюсь вот на это http://www.adapteva.com/parallella/. Это Xilinx. Вобщем очень рад, что ещё один хороший человек (и друг кошек !) этим заинтересовался. Если будут по этому какие-то вопросы, всегда буду рад помочь. Почитав Ваши статьи, понял что с базовым освоением технологии Вы и сами прекрасно справились, но когда дойдёт дело до реализации алгоритмов (например быстрого преобразования Фурье), могут возникнуть проблемы.


        1. UA3MQJ
          28.12.2016 16:51

          Да, друзей больно терять. Очень. Сам вот тоже в этом году потерял.
          Хорошо, по ПЛИСам обязательно обращусь! Есть вопросы. К примеру, тут столкнулся с такой темой, почему-то у меня Quartus не захотел к шине WOR в топ модуле, подключать N дочерних подмодулей с выходом на этот тип шины.


          1. eugenk
            28.12.2016 17:16

            Честно говоря никогда не пользовался Квартусом (работал только с Xilinx и Lattice) и никогда не использовал проводного ИЛИ. Разве что в прошлом веке, в стране которой уже нет, когда паял модули для КАМАК. Так на вскидку. Для того чтобы быть подключенным к проводному ИЛИ, подмодули должны иметь выходы с открытым коллектором (ну или с открытым стоком, если речь о современных КМОП). Поглядите у себя в настройках выходов подмодулей, какие опции для них заданы. Нужная опция должна по-идее должна называться как-то типа open-drain или похоже. Гляньте во-первых поддерживает что-либо подобное Квартус, и во-вторых установлено ли оно у Вас. Думаю если во-первых Квартус это поддерживает, во-вторых Вы её установите, то проблема решится. Однако предостерегу. Проводное ИЛИ как правило прилично увеличивает задержки. По крайней мере в дискретной ТТЛ-логике. Лучше используйте мультиплексоры.


            1. UA3MQJ
              28.12.2016 17:25

              Я хотел применить WOR внутри ПЛИС. Не выдавая наружу. Что интересно, просто внутри одного модуля на Verilog — это работает. Но если логика лежит в другом модуле и в этот он просто подключен, то нет.


              1. eugenk
                28.12.2016 17:39

                Вот это вообще странно… Я честно говоря никогда не пытался делать внутри чипа ни проводное ИЛИ, ни три состояния, а всегда использовал мультиплексоры. Так что тут не знаю. Гляньте все-таки в Квартусе на опции выходов. Наверняка если оно позволяет это делать внутри модуля, то как-то задаётся и во вне. В конце концов такой приём, немного через задницу, но по-идее должно сработать. Сделайте чисто коммуникационный модуль. В нём N подмодулей принимаются по обычным шинам, а внутри всё это передаётся на проводное ИЛИ. Блин, просто интересно стало. Жаль что сейчас довольно плотно занят другим проектом.


                1. UA3MQJ
                  28.12.2016 18:08

                  Идея была какая. Есть модуль VGA. Он генерит развертку Х, У. И есть N модулей, каждый на вход получает X, Y, и каждый выдает что-то на RGB. Ну и вот идея была в том, чтобы сделать RGB как WOR. И если кто-то из модулей выдает цвет, то оно рисуется. Если бы это получилось, то можно было бы легче организовать произвольное число элементов на экране VGA и их было бы проще добавлять/убавлять.


                  1. eugenk
                    28.12.2016 18:16

                    Ну если так, то можно R, G и B просто покомпонентно объединить выходными элементами ИЛИ. Если мне не изменяет мой склероз, LUT у Альтеры 6-входовые. Т.е. для объединения 6 модулей по RGB Вам понадобятся всего три дополнительных ячейки. А добавлять-убавлять Вы ведь всё равно будете перекомпиляцией проекта. Так что по-моему вполне допустимо.


    1. UA3MQJ
      28.12.2016 16:44

      В общем, для прототипов не важно, какой размер ПЛИС. Вот уже под конкретное устройство можно выбирать. Причем, иногда приходится выбирать по цене. К примеру если в MAX240 за 700р не влезает, а влезет в MAX на 570 или 1200, то они уже стоят больше 1000 рублей. А за 1000 — 1300 можно выбрать уже Cyclone 2-4 с количеством ячеек от 4 до 6 тысяч. Плюс там уже и PLL и аппаратные умножители, памяти больше, есть и возможность отладиться через Signal Tap.

      Вот тут, к примеру EP2C5 для экспериментов.