FPGA. Динамическая мета-логика (Dynamic meta-logics)

Как программиста меня всегда привлекала возможность производить вычисления со скоростью работы аппаратной логики. Но для этого потребовалось бы перестраивать логическую схему компьютера программным способом. Когда я узнал в середине 1990-х, что есть такие микросхемы -- программируемой логики ПЛИС (FPGA), то я сразу понял, что пройдёт некоторое время и у меня появится такая возможность.

И вот, начав изучать язык описания аппаратной логики Verilog, я сразу же вспомнил об этой своей мечте, так что оставалось только изобрести, как это воплотить. В данной статье рассказывается, как это делается.

Универсальный функциональный модуль

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

В чём-то универсальный функциональный модуль напоминает арифметическо-логическое устройство АЛУ (MCU), хотя я сравнил бы его с микросхемой стандартной логики, функциональную начинку которой можно переключать, подавая на её контрольные выводы значения "включить AND, включить XOR и т.п.".

Вот как выглядит универсальный функциональный модуль unifunc (скачать), имеющий 2 входа, 2 выхода и умеющий выполнять 8 различных функций:

module unifunc(

input [1:0] IN,

input [2:0] ctrlIN,

output reg [1:0] OUT

);


always @ (IN)

case (ctrlIN)

3'b000: // Hi-Z

OUT <= 2'bzz;

3'b001: // Pass Through

begin

OUT[0] <= IN[0];

OUT[1] <= IN[1];

end

3'b010: // 2 NOT

begin

OUT[0] <= ~IN[0];

OUT[1] <= ~IN[1];

end

3'b011: // AND and AND-NOT

begin

OUT[0] <= IN[0] & IN[1];

OUT[1] <= ~ (IN[0] & IN[1]);

end

3'b100: // OR and OR-NOT

begin

OUT[0] <= IN[0] | IN[1];

OUT[1] <= ~ (IN[0] | IN[1]);

end

3'b101: // XOR and XOR-NOT

begin

OUT[0] <= IN[0] | IN[1];

OUT[1] <= ~ (IN[0] | IN[1]);

end

3'b110: // Sum

begin

OUT[0] <= IN[0] + IN[1];

OUT[1] <= IN[0] & IN[1];

end

3'b111: // Difference

begin

OUT[0] <= IN[1] - IN[0];

OUT[1] <= IN[1] < IN[0];

end

endcase


endmodule

Динамически конфигурируемый коммутатор сигналов

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

Схема динамически конфигурируемого коммутатора сигналов (Dynamic Reconfigurable Signal Switch)

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

Вот как выглядит код модуля на 16 входов и 16 выходов comm16to16 (скачать) на языке Verilog:

module comm16to16(

input wire [15:0] IN,

input wire [3:0] ctrlIN0,

input wire [3:0] ctrlIN1,

input wire [3:0] ctrlIN2,

input wire [3:0] ctrlIN3,

input wire [3:0] ctrlIN4,

input wire [3:0] ctrlIN5,

input wire [3:0] ctrlIN6,

input wire [3:0] ctrlIN7,

input wire [3:0] ctrlIN8,

input wire [3:0] ctrlIN9,

input wire [3:0] ctrlINA,

input wire [3:0] ctrlINB,

input wire [3:0] ctrlINC,

input wire [3:0] ctrlIND,

input wire [3:0] ctrlINE,

input wire [3:0] ctrlINF,

output reg [15:0] OUT

);


always @ (IN or ctrlIN0 or ctrlIN1 or ctrlIN2 or ctrlIN3

or ctrlIN4 or ctrlIN5 or ctrlIN6 or ctrlIN7

or ctrlIN8 or ctrlIN9 or ctrlINA or ctrlINB

or ctrlINC or ctrlIND or ctrlINE or ctrlINF)

begin

OUT[0] <= IN[ctrlIN0];

OUT[1] <= IN[ctrlIN1];

OUT[2] <= IN[ctrlIN2];

OUT[3] <= IN[ctrlIN3];

OUT[4] <= IN[ctrlIN4];

OUT[5] <= IN[ctrlIN5];

OUT[6] <= IN[ctrlIN6];

OUT[7] <= IN[ctrlIN7];

OUT[8] <= IN[ctrlIN8];

OUT[9] <= IN[ctrlIN9];

OUT[10] <= IN[ctrlINA];

OUT[11] <= IN[ctrlINB];

OUT[12] <= IN[ctrlINC];

OUT[13] <= IN[ctrlIND];

OUT[14] <= IN[ctrlINE];

OUT[15] <= IN[ctrlINF];

end

endmodule

Обработка данных

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

Схема динамической обработки данных в процессоре динамической логики

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

Данная схема позволяет использовать вместо распараллеливания вычислений их аппаратное ускорение с квантованием по времени.

Автор: Андрей Шаройко <vanyamboe@gmail.com>