If he is doing a calculation on a polynomial, I understand why he wants
a multiply with no carries. Each term of the polynomial has a
coefficient which is all the terms of the same value summed together mod
2 (XOR). But I don't understand his other statements. As you showed
earlier his general form above for the product is not accurate. Or he
is saying something we don't understand.
From what I understand (or think I understand) this should be code he
could use.
subtype binary_num_5 is std_logic_vector (4 downto 0);
signal A : binary_num_5;
signal B : binary_num_5;
function square (arg : std_logic_vector) return std_logic_vector is
constant arg_Hi : integer := arg'HIGH;
constant arg_Lo : integer := arg'LOW;
constant arg_Len : integer := arg'LENGTH;
variable prod : std_logic_vector ((arg_Hi + arg_Len) downto arg_L)
:= (others => '0');
begin
for i in arg'range loop
prod := prod XOR std_logic_vector (
SHIFT_LEFT (RESIZE (unsigned(arg), 2*arg_Len), i));
end loop;
return prod;
end square;
...
B<= square (A);
I think this will do the job but I haven't tested it, so many errors can
be present! If nothing else, it should give a good idea on how to
proceed. I will say the whole thing is a little bit simpler if it is
done with unsigned type signals rather than std_logic_vector. This
would eliminate the type casts in the loop assignment statement.
prod := prod XOR SHIFT_LEFT (RESIZE (arg, 2*arg_Len), i));
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
--use work.my_package.all;
entity square_163_7_6_3 is
port (
a: in std_logic_vector(162 downto 0);
z: out std_logic_vector(162 downto 0)
);
end square_163_7_6_3;
architecture circuit of square_163_7_6_3 is
signal s, t, u, s_plus_t: std_logic_vector(162 downto 0);
signal xor1, xor2: std_logic;
begin
vector_s: for i in 0 to 80 generate
s(2*i)<= a(i);
s(2*i + 1)<= a(i+82);
end generate;
s(162)<= a(81);
vector_t1: for j in 0 to 6 generate
t(j) <= '0';
end generate;
t(7) <= a(82);
vector_t2: for i in 4 to 80 generate
t(2*i) <= a(i+78);
t(2*i + 1) <= a(i+79);
end generate;
t(162) <= a(159);
xor1 <= a(160) xor a(161);
xor2 <= a(161) xor a(162);
u(0) <= a(160);
u(1) <= a(160) xor a(162);
u(2) <= a(161);
u(3) <= xor1;
u(4) <= a(82) xor a(160);
u(5) <= xor2;
u(6) <= a(83) xor xor1;
u(7) <= '0';
u(8) <= a(84) xor xor1;
u(9) <= '0';
u(10) <= a(85) xor xor2;
u(11) <= '0';
u(12) <= a(86) xor a(162);
u(13) <= '0';
vector_u: for i in 7 to 80 generate
u(2*i) <= a(i+80);
u(2*i + 1) <= '0';
end generate;
u(162)<= a(161);
xor_gates1: for j in 0 to 162 generate
s_plus_t(j) <= s(j) xor t(j);
end generate;
xor_gates2: for j in 0 to 162 generate
z(j)<= s_plus_t(j) xor u(j);
end generate;
end circuit;
This the the exact code I found online, I think. But it is for 163-bit. So it is difficult to test and verify. Can you please help me to convert it for a 5-bit to make me understand it?
Many Thanks!
Hmmm... I don't think I can help you understand the code above. The
purpose of the code you posted, or at least how it was derived, is not
clear to me. If it helps you any, I have replaced it with a version
containing more white space for clarity.
Polynomial arithmetic is not my strong suit, but it seems familiar, so I
must have done it somewhere, sometime. Maybe it was that class in
multivalued logic which was actually a thinly disguised course in
abstract algebra taught in the EE department. Or more likely it is just
familiar from working with CRC calculations.
Here is my take on why you came up with the description of the formula
that you did. I am assuming that multiplication is the AND operation
and addition is the XOR operation. So '*' really means AND while '+'
really means XOR.
With that in mind here are some identities...
a(n) * a(n) = a(n)
a(n) * a(m) + a(m) * a(n) = a(n) * a(m) + a(n) * a(m) = 0
a(4 downto 0) is your input and z(8 downto 0) is your output.
a4, a3, a2, a1, a0 * a0
a4, a3, a2, a1, a0 * a1
a4, a3, a2, a1, a0 * a2
a4, a3, a2, a1, a0 * a3
a4, a3, a2, a1, a0 * a4
+ ----------------------------------
z8, z7, z6, z5, z4, z3, z2, z1, z0
z0 = a0 * a0 = a0
z1 = a0 * a1 + a1 * a0 = 0
z2 = a0 * a2 + a1 * a1 + a2 * a0 = a1
z3 = a0 * a3 + a1 * a2 + a2 * a1 + a3 * a0 = 0
z4 = a0 * a4 + a1 * a3 + a2 * a2 + a3 * a1 + a4 * a0 = a2
z5 = a1 * a4 + a2 * a3 + a3 * a2 + a4 * a1 = 0
z6 = a2 * a4 + a3 * a3 + a4 * a2 = a3
z7 = a3 * a4 + a4 * a3 = 0
z8 = a4 * a4 = a4
So this shows (at least for this case) the square of a polynomial *is*
represented by the formula you gave at the beginning (which includes one
more bit than needed).
'If we do AxA then the output result will be "0 a4 0 a3 0 a2 0 a1 0 a0"'
So here is the code for your square...
output_even: for i in 0 to 4 generate
z(2*i-1) <= a(i);
end generate;
output_odd: for i in 0 to 3 generate
z(2*i) <= '0';
end generate;
Replace the constants with the appropriate parameters and I expect you
can make a general function.
function poly_square (arg : std_logic_vector) return std_logic_vector is
constant arg_Hi : integer := arg'HIGH;
constant arg_Lo : integer := arg'LOW;
constant arg_Len : integer := arg'LENGTH;
variable prod : std_logic_vector ((2 * (arg_Len - 1)) downto 0)
:= (others => '0');
begin
for i in arg'range loop
prod(2*(i-arg_Lo)-1) := arg(i);
end loop;
return prod;
end poly_square;
....
signal A : std_logic_vector (4 downto 0);
signal B : std_logic_vector (8 downto 0);
....
B <= poly_square (A);
Again, not tested so there are likely errors.