Результат сравнения различных методов построения модулярных умножителей (индексный метод, разность квадратов, метод Espresso) — различия между версиями

Материал из Модулярная арифметики
Перейти к: навигация, поиск
 
(не показано 10 промежуточных версии 2 участников)
Строка 1: Строка 1:
 
Было проведено сравнение модулярных умножителей. Рассматриваемые методы:
 
Было проведено сравнение модулярных умножителей. Рассматриваемые методы:
# Метод минимизации логических функций на базе [http://vscripts.ru/w/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_Espresso алгоритма Espresso]
+
* Метод минимизации логических функций на базе [http://vscripts.ru/w/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_Espresso алгоритма Espresso]
# [http://vscripts.ru/2012/index-modulo-multiplication-sqr.php Метод разности квадратов]
+
* [http://vscripts.ru/2012/index-modulo-multiplication-sqr.php Метод разности квадратов]
# [http://vscripts.ru/2012/index-modulo-multiplication.php Индексная реализация умножителя]
+
* [http://vscripts.ru/2012/index-modulo-multiplication.php Индексная реализация умножителя]
 
   
 
   
    Метод Espresso заключается в построении таблицы истинности для операции модулярного умножения, и дальнейшей минимизации получившейся булевой функции [http://vscripts.ru/w/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_Espresso методом Espresso]. Сравнение проводилось для расширенного набора оснований в диапазоне 3-149. Индексный метод работает только для простых чисел, метод, основанный на разности квадратов допускает любые нечетные числа, а метод Espresso работает для любых целых чисел. Маршрут проектирования для схем Espresso включал минимизацию булевых функций с помощью программного средства Logic Friday. Для автоматизации запуска Logic Friday использовался язык автоматизации AutoIt. Для остальных двух схем использовался стандартный подход с реализацией автоматизироанных генераторов.
+
Метод Espresso заключается в построении таблицы истинности для операции модулярного умножения, и дальнейшей минимизации получившейся булевой функции [http://vscripts.ru/w/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_Espresso методом Espresso]. Сравнение проводилось для расширенного набора оснований в диапазоне 3-149. Индексный метод работает только для простых чисел, метод, основанный на разности квадратов допускает любые нечетные числа, а метод Espresso работает для любых целых чисел. Маршрут проектирования для схем Espresso включал минимизацию булевых функций с помощью программного средства Logic Friday. Для автоматизации запуска Logic Friday использовался язык автоматизации AutoIt. Для остальных двух схем использовался стандартный подход с реализацией автоматизироанных генераторов.
  
 
== Типовые Verilog-модули ==
 
== Типовые Verilog-модули ==
  
1. Стандартный модулярный сумматор (на примере модуля 11)
 
<pre>
 
// Sum modulo 11
 
module sum_modulo_11 (A, B, S);
 
input [3:0] A;
 
input [3:0] B;
 
output reg[3:0] S;
 
  
always @(A or B)  
+
1. Индексный модулярный умножитель (на примере модуля 7)
begin  
+
<pre class="mw-collapsible mw-collapsed">
if ({1'b0, A} + {1'b0, B} < 11) S <= {1'b0, A} + {1'b0, B};  
+
module multiplication_mod_7(inp1, inp2, out);
else S <= {1'b0, A} + {1'b0, B} - (11);  
+
input [2:0] inp1;
// else S <= {1'b0, A} + {1'b0, B} + (5);  
+
input [2:0] inp2;
end  
+
output reg [2:0] out;
endmodule  
+
wire [2:0] out_pre;
 +
wire [1:0] w_1_0;
 +
wire [1:0] w_2_0;
 +
wire [1:0] wout_0;
 +
wire [1:0] w_1_1;
 +
wire [1:0] w_2_1;
 +
wire [1:0] wout_1;
 +
lut_input_7 lut1(inp1, w_1_0, w_1_1);
 +
lut_input_7 lut2(inp2, w_2_0, w_2_1);
 +
sum_modulo_2 sm0(w_1_0, w_2_0, wout_0);
 +
sum_modulo_3 sm1(w_1_1, w_2_1, wout_1);
 +
lut_output_7 lut3(wout_0, wout_1, out_pre);
 +
always @ (*)
 +
begin
 +
if (inp1 == 0 || inp2 == 0)
 +
begin
 +
out = 0;
 +
end
 +
else
 +
begin
 +
out = out_pre;
 +
end
 +
end
 +
endmodule
 +
 
 +
module sum_modulo_2(inp1, inp2, out);
 +
input [1:0] inp1;
 +
input [1:0] inp2;
 +
output reg [1:0] out;
 +
wire [2:0] int;
 +
assign int = inp1 + inp2;
 +
always @ (*)
 +
begin
 +
if (int < 2)
 +
begin
 +
out = int;
 +
end
 +
else
 +
begin
 +
out = int - 2;
 +
end
 +
end
 +
endmodule
 +
 
 +
module sum_modulo_3(inp1, inp2, out);
 +
input [1:0] inp1;
 +
input [1:0] inp2;
 +
output reg [1:0] out;
 +
wire [2:0] int;
 +
assign int = inp1 + inp2;
 +
always @ (*)
 +
begin
 +
if (int < 3)
 +
begin
 +
out = int;
 +
end
 +
else
 +
begin
 +
out = int - 3;
 +
end
 +
end
 +
endmodule
 +
 
 +
module lut_output_7(inp0, inp1, out);
 +
output reg [2:0] out;
 +
input [1:0] inp0;
 +
input [1:0] inp1;
 +
always @ (*)
 +
begin
 +
if (inp0 == 0 && inp1 == 0)
 +
begin
 +
out <= 1;
 +
end
 +
else if (inp0 == 0 && inp1 == 2)
 +
begin
 +
out <= 2;
 +
end
 +
else if (inp0 == 1 && inp1 == 1)
 +
begin
 +
out <= 3;
 +
end
 +
else if (inp0 == 0 && inp1 == 1)
 +
begin
 +
out <= 4;
 +
end
 +
else if (inp0 == 1 && inp1 == 2)
 +
begin
 +
out <= 5;
 +
end
 +
else if (inp0 == 1 && inp1 == 0)
 +
begin
 +
out <= 6;
 +
end
 +
else
 +
begin
 +
out <= 0;
 +
end
 +
end
 +
endmodule
 +
 
 +
module lut_input_7(inp, out0, out1);
 +
input [2:0] inp;
 +
output reg [1:0] out0;
 +
output reg [1:0] out1;
 +
always @ (inp)
 +
begin
 +
case(inp)
 +
1:
 +
begin
 +
out0 <= 0;
 +
out1 <= 0;
 +
end
 +
2:
 +
begin
 +
out0 <= 0;
 +
out1 <= 2;
 +
end
 +
3:
 +
begin
 +
out0 <= 1;
 +
out1 <= 1;
 +
end
 +
4:
 +
begin
 +
out0 <= 0;
 +
out1 <= 1;
 +
end
 +
5:
 +
begin
 +
out0 <= 1;
 +
out1 <= 2;
 +
end
 +
6:
 +
begin
 +
out0 <= 1;
 +
out1 <= 0;
 +
end
 +
default:
 +
begin
 +
out0 <= 0;
 +
out1 <= 0;
 +
end
 +
endcase
 +
end
 +
endmodule
 +
 
 +
module atop_testbench();
 +
reg [2:0] inp1;
 +
reg [2:0] inp2;
 +
wire [2:0] out;
 +
 
 +
integer i, j, l, m, k, t;
 +
reg dummy;
 +
integer fori, forj;
 +
multiplication_mod_7 mul1(inp1, inp2, out);
 +
initial
 +
begin
 +
k = 1;
 +
for (fori = 0; fori < 7; fori = fori + 1)
 +
begin
 +
for (forj = 0; forj < 7; forj = forj + 1)
 +
begin
 +
inp1 = fori;
 +
inp2 = forj;
 +
#1 dummy = 1;
 +
i = (fori*forj)%7;
 +
$display ("!!! OP1 = (%d) OP2 = (%d) RES = (%d) EXPECT = (%d)", fori, forj, out, i);
 +
l = out;
 +
if (l != i)
 +
begin
 +
$display ("!!! Error (%d, %d)!!!", i, l);
 +
end
 +
#1 dummy = 1;
 +
end
 +
end
 +
end
 +
endmodule
 +
 
 +
 
 
</pre>
 
</pre>
  
2. Модулярный сумматор по методу Espresso (на примере модуля 7)
+
2. Модулярный умножитель на базе формулы разности квадратов (на примере модуля 7)
<pre>
+
<pre class="mw-collapsible mw-collapsed">
module adder_mod7 (out, a, b); // Сумматор
+
module multiplication_mod_7(inp1, inp2, out);
 +
input [2:0] inp1;
 +
input [2:0] inp2;
 +
output [2:0] out;
 +
wire [3:0] plus;
 +
wire [3:0] minus;
 +
wire [2:0] plout;
 +
wire [2:0] miout;
 +
assign plus = inp1 + inp2; // [0; 12]
 +
assign minus = 6 + inp1 - inp2; // [0; 12]
 +
lut_sqr_sum ls1(plus, plout);
 +
lut_sqr_sub ls2(minus, miout);
 +
sub_mod_7 sub1(plout, miout, out);
 +
endmodule
 +
 
 +
module lut_sqr_sum (in, out);
 +
input [3:0] in;
 +
output reg [2:0] out;
 +
always @ (in)
 +
begin
 +
case (in)
 +
0: out = 0;
 +
1: out = 2;
 +
2: out = 1;
 +
3: out = 4;
 +
4: out = 4;
 +
5: out = 1;
 +
6: out = 2;
 +
7: out = 0;
 +
8: out = 2;
 +
9: out = 1;
 +
10: out = 4;
 +
11: out = 4;
 +
12: out = 1;
 +
default: out = 0;
 +
endcase
 +
end
 +
endmodule
 +
 
 +
module lut_sqr_sub (in, out);
 +
input [3:0] in;
 +
output reg [2:0] out;
 +
always @ (in)
 +
begin
 +
case (in)
 +
0: out = 2;
 +
1: out = 1;
 +
2: out = 4;
 +
3: out = 4;
 +
4: out = 1;
 +
5: out = 2;
 +
6: out = 0;
 +
7: out = 2;
 +
8: out = 1;
 +
9: out = 4;
 +
10: out = 4;
 +
11: out = 1;
 +
12: out = 2;
 +
default: out = 0;
 +
endcase
 +
end
 +
endmodule
 +
 
 +
module sub_mod_7 (in1, in2, out);
 +
input [2:0] in1, in2;
 +
output [2:0] out;
 +
wire [3:0] data;
 +
 
 +
assign data = 7 + in1 - in2;
 +
mod_7_13 mdval(data, out);
 +
endmodule
 +
 
 +
module mod_7_13 (in, out);
 +
input [3:0] in;
 +
output reg [2:0] out;
 +
always @ (in)
 +
begin
 +
// we have small max value so we can use table here
 +
case (in)
 +
0: out = 0;
 +
1: out = 1;
 +
2: out = 2;
 +
3: out = 3;
 +
4: out = 4;
 +
5: out = 5;
 +
6: out = 6;
 +
7: out = 0;
 +
8: out = 1;
 +
9: out = 2;
 +
10: out = 3;
 +
11: out = 4;
 +
12: out = 5;
 +
13: out = 6;
 +
default: out = 0;
 +
endcase
 +
end
 +
endmodule
 +
 
 +
module atop_testbench();
 +
reg [2:0] inp1;
 +
reg [2:0] inp2;
 +
wire [2:0] out;
 +
 
 +
integer i, j, l, m, k, t;
 +
reg dummy;
 +
integer fori, forj;
 +
multiplication_mod_7 mul1(inp1, inp2, out);
 +
initial
 +
begin
 +
k = 1;
 +
for (fori = 0; fori < 7; fori = fori + 1)
 +
begin
 +
for (forj = 0; forj < 7; forj = forj + 1)
 +
begin
 +
inp1 = fori;
 +
inp2 = forj;
 +
#1 dummy = 1;
 +
i = (fori*forj)%7;
 +
$display ("!!! OP1 = (%d) OP2 = (%d) RES = (%d) EXPECT = (%d)", fori, forj, out, i);
 +
l = out;
 +
if (l != i)
 +
begin
 +
$display ("!!! Error (%d, %d)!!!", i, l);
 +
end
 +
#1 dummy = 1;
 +
end
 +
end
 +
end
 +
endmodule
 +
 
 +
</pre>
 +
 
 +
2. Модулярный сумматор по методу Espresso (на примере модуля 10)
 +
<pre class="mw-collapsible mw-collapsed">
 +
module mul_mod10 (out, a, b);  
 
   
 
   
input  [2:0]  a, b;  
+
input  [3:0]  a, b;  
output  [2:0]  out;  
+
output  [3:0]  out;  
 
   
 
   
 
   
 
   
assign out[2] = (~a[2]&~a[1]&~a[0]&b[2]) | (a[2]&a[1]&b[2]&b[1]) | (a[2]&a[0]&b[2]&b[1]) | (~a[2]&a[1]&~b[2]&b[1]) |
+
assign out[3] = (~a[3]&~a[2]&~a[1]&a[0]&b[3]) | (~a[2]&a[1]&~a[0]&b[3]&b[0]) | (a[3]&~b[3]&~b[2]&~b[1]&b[0]) |  
(~a[2]&~a[1]&b[2]&~b[1]) | (a[2]&~a[1]&~b[2]&~b[1]) | (a[2]&a[1]&b[2]&b[0]) | (a[1]&a[0]&~b[2]&b[0]) | (~a[2]&a[0]&b[1]&b[0]) |  
+
(a[2]&a[1]&~a[0]&b[3]&~b[0]) | (a[3]&~a[0]&b[2]&b[1]&~b[0]) | (a[3]&a[0]&~b[2]&b[1]&~b[0]) | (a[2]&a[1]&a[0]&b[2]&b[1]&b[0]) |  
(a[2]&~b[2]&~b[1]&~b[0]) | (a[2]&~a[1]&~a[0]&~b[2]&~b[0]) | (~a[2]&~a[0]&b[2]&~b[1]&~b[0]);  
+
(a[2]&~a[1]&~a[0]&b[2]&b[1]&b[0]) | (~a[2]&a[1]&a[0]&~b[2]&b[1]&b[0]) | (a[2]&a[1]&~a[0]&~b[2]&b[1]&b[0]) |  
assign out[1] = (~a[2]&~a[1]&~a[0]&b[1]) | (a[1]&a[0]&b[2]&b[1]) | (a[2]&a[0]&b[2]&~b[1]) | (a[2]&~a[1]&b[2]&b[0]) |  
+
(~a[2]&a[1]&a[0]&b[2]&b[1]&~b[0]) | (a[2]&~a[1]&~a[0]&~b[2]&b[1]&~b[0]) | (a[2]&a[1]&a[0]&b[2]&~b[1]&~b[0]) |  
(a[2]&a[1]&b[1]&b[0]) | (a[1]&a[0]&b[1]&b[0]) | (~a[1]&a[0]&~b[1]&b[0]) | (~a[1]&~a[0]&b[1]&~b[0]) | (a[1]&~a[0]&~b[1]&~b[0]) |  
+
(~a[2]&a[1]&~a[0]&b[2]&~b[1]&~b[0]);  
(a[1]&~b[2]&~b[1]&~b[0]) | (~a[2]&a[1]&~a[0]&~b[2]&~b[1]) | (~a[2]&~a[1]&~b[2]&b[1]&~b[0]);  
+
 
assign out[0] = (a[1]&~a[0]&b[2]&b[1]) | (~a[2]&~a[1]&~a[0]&b[0]) | (a[2]&a[0]&b[2]&b[0]) | (a[1]&a[0]&b[2]&b[0]) |  
+
assign out[2] = (~a[2]&a[1]&a[0]&b[3]) | (a[3]&~a[0]&~b[2]&b[1]) | (a[2]&~a[1]&a[0]&b[0]) | (a[3]&~a[0]&b[1]&b[0]) |  
(~a[2]&~a[0]&~b[2]&b[0]) | (a[2]&a[0]&b[1]&b[0]) | (a[2]&~a[0]&b[2]&~b[0]) | (~a[2]&a[0]&~b[2]&~b[0]) | (a[2]&a[1]&b[1]&~b[0]) |  
+
(a[3]&~b[2]&b[1]&b[0]) | (a[0]&b[2]&~b[1]&b[0]) | (~a[2]&a[1]&b[3]&~b[0]) | (a[1]&a[0]&b[3]&~b[0]) | (a[3]&~a[0]&b[3]&~b[0]) |
(a[0]&~b[2]&~b[1]&~b[0]) | (~a[1]&~a[0]&~b[2]&~b[1]&b[0]) | (~a[2]&~a[1]&a[0]&~b[1]&~b[0]);  
+
(a[2]&~a[0]&b[2]&~b[0]) | (~a[2]&a[1]&~a[0]&b[1]&b[0]) | (a[1]&a[0]&~b[2]&b[1]&~b[0]) | (~a[3]&~a[2]&~a[1]&a[0]&b[2]) |
 +
(a[2]&~a[0]&~b[2]&~b[1]&b[0]) | (a[2]&~b[3]&~b[2]&~b[1]&b[0]) | (~a[2]&~a[1]&a[0]&b[2]&~b[0]) | (~a[2]&a[1]&~b[2]&b[1]&~b[0]);  
 +
 
 +
assign out[1] = (a[2]&a[1]&a[0]&b[3]) | (a[2]&~a[1]&~a[0]&b[3]) | (a[3]&~a[0]&b[3]&b[0]) | (a[3]&b[2]&b[1]&b[0]) |  
 +
(a[3]&a[0]&b[3]&~b[0]) | (a[3]&b[2]&~b[1]&~b[0]) | (~a[3]&~a[2]&~a[1]&a[0]&b[1]) | (a[2]&a[1]&~a[0]&b[2]&b[1]) |
 +
(a[1]&~b[3]&~b[2]&~b[1]&b[0]) | (~a[2]&a[1]&~a[0]&b[3]&~b[0]) | (a[2]&a[1]&~a[0]&b[1]&~b[0]) | (a[2]&a[1]&b[2]&b[1]&~b[0]) |  
 +
(a[1]&~a[0]&b[2]&b[1]&~b[0]) | (a[3]&~a[0]&~b[2]&b[1]&~b[0]) | (a[2]&~a[1]&~a[0]&~b[2]&b[1]&b[0]) |  
 +
(~a[2]&a[1]&a[0]&b[2]&~b[1]&~b[0]) | (a[2]&~a[1]&~a[0]&b[2]&~b[1]&~b[0]) | (~a[2]&~a[1]&a[0]&b[1]&b[0]) |  
 +
(a[1]&a[0]&~b[2]&~b[1]&b[0]) | (~a[2]&a[1]&~a[0]&~b[2]&b[1]&b[0]) | (~a[2]&a[1]&a[0]&~b[2]&b[1]&~b[0]);
 +
 
 +
assign out[0] = (a[0]&b[0]);  
 
   
 
   
 
 
 
 
Строка 76: Строка 391:
  
 
== Файлы для эксперимента ==
 
== Файлы для эксперимента ==
* [http://vscripts.ru/res/files/Truth-table-sum-by-mod-450MB.7z Несжатые таблицы истинности для сумматоров (.csv, 2MB)]
+
* [http://vscripts.ru/res/files/Truth-table-mul-by-mod-450MB.7z Несжатые таблицы истинности для умножителей (.csv, 8MB)]
* [http://vscripts.ru/res/files/Truth-table-sum-by-mod-minimized.zip Сжатые Espresso таблицы истинности для сумматоров (.csv, 3MB)]
+
* [http://vscripts.ru/res/files/Truth-table-mul-by-mod-minimized.zip Сжатые Espresso таблицы истинности для умножителей (.csv, 4MB)]
* [http://vscripts.ru/res/files/Truth-table-sum-by-mod-minimized-verilog.zip Verilog на основе таблиц истинности для сумматоров (.csv, 3MB)]
+
* [http://vscripts.ru/res/files/Truth-table-mul-by-mod-minimized-verilog.zip Verilog на основе таблиц истинности для умножителей (.v, 4.3MB)]
  
 
== Результаты эксперимента ==
 
== Результаты эксперимента ==
[[Изображение:Espresso1.JPG]]
+
[[Изображение:boolean.JPG]]
[[Изображение:Espresso2.JPG]]
+
[[Изображение:sqr.JPG]]
 
+
[[Изображение:index.JPG]]
* [http://vscripts.ru/res/files/espresso_test.xlsx Скачать Excel-файл с численными данными]
+
[[Изображение:all.JPG]]
 +
* [http://vscripts.ru/res/files/Mul_espresso_results.xlsx Скачать Excel-файл с численными данными]

Текущая версия на 09:15, 27 мая 2013

Было проведено сравнение модулярных умножителей. Рассматриваемые методы:

Метод Espresso заключается в построении таблицы истинности для операции модулярного умножения, и дальнейшей минимизации получившейся булевой функции методом Espresso. Сравнение проводилось для расширенного набора оснований в диапазоне 3-149. Индексный метод работает только для простых чисел, метод, основанный на разности квадратов допускает любые нечетные числа, а метод Espresso работает для любых целых чисел. Маршрут проектирования для схем Espresso включал минимизацию булевых функций с помощью программного средства Logic Friday. Для автоматизации запуска Logic Friday использовался язык автоматизации AutoIt. Для остальных двух схем использовался стандартный подход с реализацией автоматизироанных генераторов.

Типовые Verilog-модули

1. Индексный модулярный умножитель (на примере модуля 7)

module multiplication_mod_7(inp1, inp2, out);
	input [2:0] inp1;
	input [2:0] inp2;
	output reg [2:0] out;
	wire [2:0] out_pre;
	wire [1:0] w_1_0;
	wire [1:0] w_2_0;
	wire [1:0] wout_0;
	wire [1:0] w_1_1;
	wire [1:0] w_2_1;
	wire [1:0] wout_1;
	lut_input_7 lut1(inp1, w_1_0, w_1_1);
	lut_input_7 lut2(inp2, w_2_0, w_2_1);
	sum_modulo_2 sm0(w_1_0, w_2_0, wout_0);
	sum_modulo_3 sm1(w_1_1, w_2_1, wout_1);
	lut_output_7 lut3(wout_0, wout_1, out_pre);
	always @ (*)
	begin
		if (inp1 == 0 || inp2 == 0)
		begin
			out = 0;
		end
		else
		begin
			out = out_pre;
		end
	end
endmodule

module sum_modulo_2(inp1, inp2, out);
	input [1:0] inp1;
	input [1:0] inp2;
	output reg [1:0] out;
	wire [2:0] int;
	assign int = inp1 + inp2;
	always @ (*)
	begin
		if (int < 2)
		begin
			out = int;
		end
		else
		begin
			out = int - 2;
		end
	end
endmodule

module sum_modulo_3(inp1, inp2, out);
	input [1:0] inp1;
	input [1:0] inp2;
	output reg [1:0] out;
	wire [2:0] int;
	assign int = inp1 + inp2;
	always @ (*)
	begin
		if (int < 3)
		begin
			out = int;
		end
		else
		begin
			out = int - 3;
		end
	end
endmodule

module lut_output_7(inp0, inp1, out);
	output reg [2:0] out;
	input [1:0] inp0;
	input [1:0] inp1;
	always @ (*)
	begin
		if (inp0 == 0 && inp1 == 0)
		begin
			out <= 1;
		end
		else if (inp0 == 0 && inp1 == 2)
		begin
			out <= 2;
		end
		else if (inp0 == 1 && inp1 == 1)
		begin
			out <= 3;
		end
		else if (inp0 == 0 && inp1 == 1)
		begin
			out <= 4;
		end
		else if (inp0 == 1 && inp1 == 2)
		begin
			out <= 5;
		end
		else if (inp0 == 1 && inp1 == 0)
		begin
			out <= 6;
		end
		else 
		begin
			out <= 0;
		end
	end
endmodule

module lut_input_7(inp, out0, out1);
	input [2:0] inp;
	output reg [1:0] out0;
	output reg [1:0] out1;
	always @ (inp)
	begin
		case(inp)
		1:
		begin
			out0 <= 0;
			out1 <= 0;
		end
		2:
		begin
			out0 <= 0;
			out1 <= 2;
		end
		3:
		begin
			out0 <= 1;
			out1 <= 1;
		end
		4:
		begin
			out0 <= 0;
			out1 <= 1;
		end
		5:
		begin
			out0 <= 1;
			out1 <= 2;
		end
		6:
		begin
			out0 <= 1;
			out1 <= 0;
		end
		default:
		begin
			out0 <= 0;
			out1 <= 0;
		end
		endcase
	end
endmodule

module atop_testbench();
	reg [2:0] inp1;
	reg [2:0] inp2;
	wire [2:0] out;

	integer i, j, l, m, k, t;
	reg dummy;
	integer fori, forj;
	multiplication_mod_7 mul1(inp1, inp2, out);
	initial
	begin
	k = 1;
	for (fori = 0; fori < 7; fori = fori + 1)
	begin
	for (forj = 0; forj < 7; forj = forj + 1)
	begin
		inp1 = fori;
		inp2 = forj;
		#1 dummy = 1;
		i = (fori*forj)%7;
		$display ("!!! OP1 = (%d) OP2 = (%d) RES = (%d) EXPECT = (%d)", fori, forj, out, i);
		l = out;
		if (l != i)
		begin
			$display ("!!! Error (%d, %d)!!!", i, l);
		end
		#1 dummy = 1;
	end
	end
	end
endmodule


2. Модулярный умножитель на базе формулы разности квадратов (на примере модуля 7)

module multiplication_mod_7(inp1, inp2, out);
	input [2:0] inp1;
	input [2:0] inp2;
	output [2:0] out;
	wire [3:0] plus;
	wire [3:0] minus;
	wire [2:0] plout;
	wire [2:0] miout;
	assign plus = inp1 + inp2; // [0; 12]
	assign minus = 6 + inp1 - inp2; // [0; 12]
	lut_sqr_sum ls1(plus, plout);
	lut_sqr_sub ls2(minus, miout);
	sub_mod_7 sub1(plout, miout, out);
endmodule

module lut_sqr_sum (in, out);
	input [3:0] in;
	output reg [2:0] out;
	always @ (in)
	begin
	case (in)
	0: out = 0;
	1: out = 2;
	2: out = 1;
	3: out = 4;
	4: out = 4;
	5: out = 1;
	6: out = 2;
	7: out = 0;
	8: out = 2;
	9: out = 1;
	10: out = 4;
	11: out = 4;
	12: out = 1;
	default: out = 0;
	endcase
	end
endmodule

module lut_sqr_sub (in, out);
	input [3:0] in;
	output reg [2:0] out;
	always @ (in)
	begin
	case (in)
	0: out = 2;
	1: out = 1;
	2: out = 4;
	3: out = 4;
	4: out = 1;
	5: out = 2;
	6: out = 0;
	7: out = 2;
	8: out = 1;
	9: out = 4;
	10: out = 4;
	11: out = 1;
	12: out = 2;
	default: out = 0;
	endcase
	end
endmodule

module sub_mod_7 (in1, in2, out);
	input [2:0] in1, in2;
	output [2:0] out;
	wire [3:0] data;

	assign data = 7 + in1 - in2;
	mod_7_13 mdval(data, out);
endmodule

module mod_7_13 (in, out);
	input [3:0] in;
	output reg [2:0] out;
	always @ (in)
	begin
	// we have small max value so we can use table here
	case (in)
		0: out = 0;
		1: out = 1;
		2: out = 2;
		3: out = 3;
		4: out = 4;
		5: out = 5;
		6: out = 6;
		7: out = 0;
		8: out = 1;
		9: out = 2;
		10: out = 3;
		11: out = 4;
		12: out = 5;
		13: out = 6;
		default: out = 0;
	endcase
	end
endmodule

module atop_testbench();
	reg [2:0] inp1;
	reg [2:0] inp2;
	wire [2:0] out;

	integer i, j, l, m, k, t;
	reg dummy;
	integer fori, forj;
	multiplication_mod_7 mul1(inp1, inp2, out);
	initial
	begin
	k = 1;
	for (fori = 0; fori < 7; fori = fori + 1)
	begin
	for (forj = 0; forj < 7; forj = forj + 1)
	begin
		inp1 = fori;
		inp2 = forj;
		#1 dummy = 1;
		i = (fori*forj)%7;
		$display ("!!! OP1 = (%d) OP2 = (%d) RES = (%d) EXPECT = (%d)", fori, forj, out, i);
		l = out;
		if (l != i)
		begin
			$display ("!!! Error (%d, %d)!!!", i, l);
		end
		#1 dummy = 1;
	end
	end
	end
endmodule

2. Модулярный сумматор по методу Espresso (на примере модуля 10)

module mul_mod10 (out, a, b); 
 
input  [3:0]  a, b; 
output  [3:0]  out; 
 
 
assign out[3] = (~a[3]&~a[2]&~a[1]&a[0]&b[3]) | (~a[2]&a[1]&~a[0]&b[3]&b[0]) | (a[3]&~b[3]&~b[2]&~b[1]&b[0]) | 
(a[2]&a[1]&~a[0]&b[3]&~b[0]) | (a[3]&~a[0]&b[2]&b[1]&~b[0]) | (a[3]&a[0]&~b[2]&b[1]&~b[0]) | (a[2]&a[1]&a[0]&b[2]&b[1]&b[0]) | 
(a[2]&~a[1]&~a[0]&b[2]&b[1]&b[0]) | (~a[2]&a[1]&a[0]&~b[2]&b[1]&b[0]) | (a[2]&a[1]&~a[0]&~b[2]&b[1]&b[0]) | 
(~a[2]&a[1]&a[0]&b[2]&b[1]&~b[0]) | (a[2]&~a[1]&~a[0]&~b[2]&b[1]&~b[0]) | (a[2]&a[1]&a[0]&b[2]&~b[1]&~b[0]) | 
(~a[2]&a[1]&~a[0]&b[2]&~b[1]&~b[0]); 

assign out[2] = (~a[2]&a[1]&a[0]&b[3]) | (a[3]&~a[0]&~b[2]&b[1]) | (a[2]&~a[1]&a[0]&b[0]) | (a[3]&~a[0]&b[1]&b[0]) | 
(a[3]&~b[2]&b[1]&b[0]) | (a[0]&b[2]&~b[1]&b[0]) | (~a[2]&a[1]&b[3]&~b[0]) | (a[1]&a[0]&b[3]&~b[0]) | (a[3]&~a[0]&b[3]&~b[0]) | 
(a[2]&~a[0]&b[2]&~b[0]) | (~a[2]&a[1]&~a[0]&b[1]&b[0]) | (a[1]&a[0]&~b[2]&b[1]&~b[0]) | (~a[3]&~a[2]&~a[1]&a[0]&b[2]) | 
(a[2]&~a[0]&~b[2]&~b[1]&b[0]) | (a[2]&~b[3]&~b[2]&~b[1]&b[0]) | (~a[2]&~a[1]&a[0]&b[2]&~b[0]) | (~a[2]&a[1]&~b[2]&b[1]&~b[0]); 

assign out[1] = (a[2]&a[1]&a[0]&b[3]) | (a[2]&~a[1]&~a[0]&b[3]) | (a[3]&~a[0]&b[3]&b[0]) | (a[3]&b[2]&b[1]&b[0]) | 
(a[3]&a[0]&b[3]&~b[0]) | (a[3]&b[2]&~b[1]&~b[0]) | (~a[3]&~a[2]&~a[1]&a[0]&b[1]) | (a[2]&a[1]&~a[0]&b[2]&b[1]) | 
(a[1]&~b[3]&~b[2]&~b[1]&b[0]) | (~a[2]&a[1]&~a[0]&b[3]&~b[0]) | (a[2]&a[1]&~a[0]&b[1]&~b[0]) | (a[2]&a[1]&b[2]&b[1]&~b[0]) | 
(a[1]&~a[0]&b[2]&b[1]&~b[0]) | (a[3]&~a[0]&~b[2]&b[1]&~b[0]) | (a[2]&~a[1]&~a[0]&~b[2]&b[1]&b[0]) | 
(~a[2]&a[1]&a[0]&b[2]&~b[1]&~b[0]) | (a[2]&~a[1]&~a[0]&b[2]&~b[1]&~b[0]) | (~a[2]&~a[1]&a[0]&b[1]&b[0]) | 
(a[1]&a[0]&~b[2]&~b[1]&b[0]) | (~a[2]&a[1]&~a[0]&~b[2]&b[1]&b[0]) | (~a[2]&a[1]&a[0]&~b[2]&b[1]&~b[0]); 

assign out[0] = (a[0]&b[0]); 
 
	 
endmodule 


Библиотека стандартных ячеек

NangateOpenCellLibrary.lib

Скрипт для запуска

lappend search_path "../libs" "../src" 
set target_library "NangateOpenCellLibrary.db"
set link_library [list "*" $target_library]

analyze -f <имя модуля>.v
elaborate <имя модуля>
uniquify
current_design <имя модуля>
check_design
set_load [load_of [get_lib_pins NangateOpenCellLibrary/INV_X4/A]] [all_outputs]
set_driving_cell -lib_cell DFFRS_X2 -library NangateOpenCellLibrary -pin Q  [all_inputs]
set_max_delay -to [all_outputs] 0
set_max_area 0
compile
report_timing > result/timing_<имя модуля>.rpt
report_area > result/area_<имя модуля>.rpt
remove_design -all 

Файлы для эксперимента

Результаты эксперимента

Boolean.JPG Sqr.JPG Index.JPG All.JPG