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

Материал из Модулярная арифметики
Перейти к: навигация, поиск

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

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

Содержание

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

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

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


Персональные инструменты
Пространства имён

Варианты
Действия
Навигация