Continue to Site

# is this multiplier correct? VHDL FSM

Status
Not open for further replies.

#### gentleoyink

##### Newbie level 4
Hello everyone,

I just tried to design a multiplier with 8 bits input and 17 bits output using vhdl. I intend to use the add shift method.
These are the step taken
1. 4 bit carry look ahead adder (cla)
2. with 4 bit cla made eight bits cla
3. 4 bits counter that resets at 8 ie 1000
4 17 bits shift register (to be used for the accumulator)
5 the control which uses states.

Below are the codes

1. 4 bit cla

library ieee;
use ieee.std_logic_1164.all;

entity cla_4 is
generic(n : integer := 4);
port
(
x, y : in STD_LOGIC_VECTOR(n-1 downto 0);
cin, add_cmd : in STD_LOGIC;
sum : out STD_LOGIC_VECTOR(n-1 downto 0);
cout, pg, gg : out STD_LOGIC);
end cla_4;

architecture behavioural of cla_4 is

signal c: STD_LOGIC_VECTOR(n downto 0);

signal p, g: STD_LOGIC_VECTOR(n-1 downto 0);
begin

sum_prc: process(p, g, x, y, c, cin)

begin

if add_cmd = '1' then

for i in 3 downto 0 loop
sum(i) <= x(i) xor y(i) xor c(i);
p(i) <= x(i) or y(i);
g(i) <= x(i) and y(i);
end loop;

c(0) <= cin;

for i in 4 downto 1 loop
c(i) <= g(i-1) or (p(i-1) and c(i-1));
end loop;
end if;
end process;

cout <= c(4);

pg <= p(0) and p(1) and p(2) and p(3);
gg <= g(3) or (g(2) AND p(3)) or (g(1) and g(3) and g(2)) or (g(0) and p(3) and p(2) and p(1));

end behavioural;

2. 8 bit cla

LIBRARY ieee;
USE ieee.std_logic_1164.all;

entity cla_16_4 is
generic(n : integer := 8);
PORT
(x, y : in STD_LOGIC_VECTOR(n-1 downto 0);
cin, add_cmd : in STD_LOGIC;
sum : out STD_LOGIC_VECTOR(n-1 downto 0);
cout : out STD_LOGIC);
end cla_16_4;

architecture behavioural of cla_16_4 is

signal c, co: STD_LOGIC_VECTOR(2 downto 0);
signal p, g: STD_LOGIC_VECTOR(1 downto 0);

component cla_4 is
PORT ( x, y : in STD_LOGIC_VECTOR(3 downto 0);
cin, add_cmd : in STD_LOGIC;
sum : out STD_LOGIC_VECTOR(3 downto 0);
cout, pg, gg : out STD_LOGIC );

end component;

begin
c(0) <= cin;

ikes: for i in 1 to 2 generate
new4_1 : cla_4
port map( x((i*4)-1 downto (i*4)-4), y((i*4)-1 downto (i*4)-4), c(i-1), add_cmd, sum((i*4)-1 downto (i*4)-4), co(i-1), p(i-1), g(i-1) );

c(i) <= g(i-1) or (p(i-1) and co(i-1));
end generate;

cout <= c(2);

end behavioural;

3. Counter

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;

entity counter is
generic(n : integer := 4);
port
(clock, reset : in STD_LOGIC;
counter_o : out STD_LOGIC_VECTOR(n-1 downto 0));

end counter;

architecture behavioural of counter is
signal temp : STD_LOGIC_VECTOR(n-1 downto 0);

begin
sum_prc:

process (reset, clock)
begin
if (reset = '1') then
temp <= (others => '0');
else

if (clock'event) and (clock = '1') then
if (temp = "1000") then
temp <= (others => '0');
else
temp <= temp + 1;
end if;

end if;
end if;
end process;
counter_o <= temp;
end behavioural;

4. Shift Register

library ieee;
use ieee.std_logic_1164.all;

entity shift_reg is
generic(n : integer := 16);
port
(
x : in STD_LOGIC_VECTOR(n downto 0);
clock, reset, en :in STD_LOGIC;
y : out STD_LOGIC_VECTOR(n downto 0));
end shift_reg;

architecture behavioural of shift_reg is
signal c: STD_LOGIC_VECTOR(n downto 0);

begin

process (reset, clock)
begin
if reset = '1' then
y <= (others => '0');
else
if (clock'event) and (clock = '1') then
if (en = '0') then
y(n-1 downto 0) <= x(n downto 1);
y <= '0';
end if;
end if;
end if;

end process;

end behavioural;

5. Control

library ieee;
use ieee.std_logic_1164.all;

entity controlled is
generic(n : integer := 8);
port
(clock, reset :in STD_LOGIC;
m1, m2: in STD_LOGIC_VECTOR(n-1 downto 0);
s: out std_logic;
product: out STD_LOGIC_VECTOR(2*n downto 0));
end controlled;

architecture behavioural of controlled is

component cla_16_4
port(x, y : in STD_LOGIC_VECTOR(n-1 downto 0);
cin, add_cmd : in STD_LOGIC;
sum : out STD_LOGIC_VECTOR(n-1 downto 0);
cout : out STD_LOGIC);
end component;

component counter
port(clock, reset : in STD_LOGIC;
counter_o : out STD_LOGIC_VECTOR(n-1 downto 0));
end component;

component shift_reg
port( x : in STD_LOGIC_VECTOR(n downto 0);
clock, en, reset :in STD_LOGIC;
y : out STD_LOGIC_VECTOR(n downto 0));
end component;

type states is (none, a, b, c, d, e); --Defines the type of states in the state machine
signal state, next_state : states;
signal new_m1 : STD_LOGIC_VECTOR(n-1 downto 0);
signal counter_out: STD_LOGIC_VECTOR(3 downto 0);
signal add_en, shift_clock, count, clear : STD_LOGIC;
signal accum : STD_LOGIC_VECTOR(2*n downto 0);

begin

fsm: process (state)
begin
case state is

when none =>

next_state <= a;

when a =>
next_state <= b;

when b =>
next_state <= c;
when c =>
next_state <= d;

when d =>
next_state <= e;

when e =>
if (counter_out = "1000") then
next_state <= none;
else
next_state <= b;
end if;

end case;
end process fsm;

fsm1: process (clock)

begin

if (reset = '1') then
clear <= '1';
else
clear <= '0';
end if;

if (clock'event) and (clock = '1') then
case state is
when none =>
clear <= '1';

when a =>
clear <= '0';
accum(7 downto 0) <= m2;

when b =>
if (accum(0) = '1') then
new_m1 <= m1;
else
new_m1 <= (others => '0');

count <= '0';
end if;
when c =>

when d =>

shift_clock <= '1';
when e =>
count <= '1';

end case;
end if;
end process fsm1;

fsm2: process (clock)
begin
if (clock'event) and (clock = '1') then
state <= next_state;
end if;

product <= accum;
end process fsm2;
p1 : cla_16_4 port map (accum(15 downto 8), new_m1, add_en, add_en, accum(15 downto 8), accum(16));
p2 : shift_reg port map (accum, shift_clock, add_en, clear, accum);
p3 : counter port map (count, clear, counter_out);

end behavioural;

-------------------------------------------------------------------------------------------------------------
They all compiled successfully. However, I was unable to write a proper testbench for the design hence I am not sure if it is a working/proper design.
I created a thread earlier to see a good example of test bench for a fsm, but did not get any reply.

I have tried to implement test bench, but modelsim gave me no output.

Please take a look at the codes above and tell me if I am correct or wrong.

Below is the test bench I tried to i mplement

library ieee;
use ieee.std_logic_1164.all;

entity controlled_tb is
generic(n : integer := 8);
end controlled_tb;

architecture behavioural of controlled_tb is

component controlled
port (clock, reset :in STD_LOGIC;
m1, m2: in STD_LOGIC_VECTOR(n-1 downto 0);

product: out STD_LOGIC_VECTOR(2*n downto 0));
end component;

signal m1_tb, m2_tb : std_logic_vector(n-1 downto 0 );
signal clock_tb, reset_tb : std_logic;
signal product_tb: std_logic_vector(2*n downto 0);
begin
-- instantiate the Device Under Test
inst_DUT : controlled
port map (
m1 => m1_tb,
m2 => m2_tb,
clock => clock_tb,
reset => reset_tb,
product => product_tb);

-- Generate clock stimulus
clock_stim : process
begin
clock_tb <= '0';
wait for 10 ns;
clock_tb <= '1';

wait for 10 ns;
end process clock_stim;
-- Generate reset stimulus
reset_stim : process
begin
reset_tb <= '0';
wait for 10 ns;
end process reset_stim;
-- Generate multiplication requests

m1_tb <= "10011101";
m2_tb <= "11100111";

end behavioural;

Thanks very much as I await your good responses.

Okay so it compiles...
when it runs it produces mostly U. (undefined)

I would strongly suggest you use code /code tags or syntax=vhdl /syntax tags in the future. It should also preserve formatting. The 362 lines of code is pretty much unreadable without reformatting. I would also advise using signal names that mean something... a, b, c are poor names for states, temp is not a good choice to name a counter...etc.

I suspect the usage of multiple entities is because that is part of your project assignment. There is something to be said for modular code but this appears to be overkill.

Your TB is generating the correct signals except for the reset which never gets asserted. I made a code change to have it assert for 100 ns.

Code VHDL - [expand]1
2
3
4
5
6
7
8
-- Generate reset stimulus
reset_stim : process
begin
reset_tb <= '1';
wait for 100 ns;
reset_tb <= '0';
wait;
end process reset_stim;

So your problem is in the multiplier design, but I'm not even going to try debugging it. I suggest you find out why you have so many U's first.

I see one glaring problem...
p2 : shift_reg port map (accum, shift_clock, add_en, clear, accum);

the accum is connected to an input and an output port, and is loaded with m2 in the top level controlled file in the FSM. This won't work you have multiple drivers on the signal. You need to rewrite this code and make it readable plus add comments.

Last edited:

Thank you.
Corrections have been noted.

Status
Not open for further replies.