I'm attempting to create synthesizable VHDL (function or procedure) for an ASIC (it must be part of the ASIC) that will look for the first '1' in a standard_logic_vector and output which vector position that '1' was in. For example, I have an 8-bit slv of "10001000" (a '1' in position 3 and 7). If I use this slv, the output should be 4 (the output is 1 based).
The actual VHDL will be searching a large slv, up to 512 bits in length. I tried implementing a binary search function but I get synthesis errors that states "Could not synthesize non-constant range values. [CDFG-231] [elaborate]
The non-constant range values are in file '...' on line 61" I indicated in the code below where it complains. I'm not sure how to implement a binary search algorithm without having non-constant range values. How would I modify this code so it's synthesizable?
I have attempted to search for binary search algorithms for HDL for potential code to look at and for my error, but I didn't find anything.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
entity bin_search is
generic (
constant NREGS : positive := 16 -- number of registers
);
port (
clk_i : in std_logic; -- clock
bin_i : in unsigned( NREGS-1 downto 0 ); -- input
en_i : in std_logic; -- input enable
addr_o : out natural range 0 to NREGS -- first binary location
);
end bin_search;
architecture rtl of bin_search is
function f_bin_search( input: unsigned; nob: positive ) return natural is
constant nbits : positive := 2**nob;
variable lower : natural range 0 to 1 := 0;
variable upper : natural range 0 to 1 := 0;
variable idx : natural range 0 to nob := 4;
variable cnt : natural range 0 to nbits := 0;
variable mid : positive range 1 to nbits := nbits/2; --
variable ll : natural range 0 to nbits := 0;
variable ul : positive range 1 to nbits := nbits; --
begin
if input = 0 then
cnt := 0;
return cnt;
else
loop1: while ( idx > 0 ) loop
if ( input( mid-1 downto ll ) > 0 ) then -- <===WHERE SYNTH COMPLAINS
lower := 1;
else
lower := 0;
end if;
if ( input( ul-1 downto mid ) > 0 ) then
upper := 1;
else
upper := 0;
end if;
if ( idx = 1 ) then
if ( lower = 1 ) then
cnt := mid;
else
cnt := ul;
end if;
elsif ( lower = 1 ) then
ul := mid;
mid := ( ( ll+ul )/2 );
elsif ( upper = 1 ) then
ll := mid;
mid := ( ll+ul )/2;
else
cnt := 0;
exit loop1;
end if;
idx := idx-1;
end loop loop1;
return cnt;
end if;
end f_bin_search;
begin
test_proc: process ( clk_i )
begin
if rising_edge( clk_i ) then
if en_i = '1' then
addr_o <= f_bin_search( bin_i, 4 );
end if;
end if;
end process test_proc;
end rtl;
Here's a simple test bench where the input is inc'd by '1'. The addr_o should be the location (1 based) of the input lsb with a '1'.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_misc.all;
use ieee.numeric_std.all;
entity bin_search_tb is
end bin_search_tb;
architecture behavior of bin_search_tb is
constant NREGS : positive := 16;
signal clk : std_logic;
signal input : unsigned( NREGS-1 downto 0 );
signal start : std_logic;
signal addr : natural range 0 to NREGS;
constant clk_per : time := 1 ns;
signal row : natural range 0 to 2**NREGS-1;
begin
bin_search_inst: entity work.bin_search( rtl )
generic map (
NREGS => NREGS
)
port map (
clk_i => clk, -- master clock
bin_i => input, -- captured events
en_i => start, -- start binary search
addr_o => addr -- addr where the first '1' appears
);
-- master clock process
clk_proc: process
begin
clk <= '0';
wait for clk_per / 2;
clk <= '1';
wait for clk_per / 2;
end process clk_proc;
--
stim1_proc: process
begin
input <= ( others => '0' );
start <= '0';
row <= 1;
wait until clk'event and clk = '1';
loop
wait until clk'event and clk = '1';
input <= to_unsigned( row, input'length );
start <= '1';
wait until clk'event and clk = '1';
start <= '0';
wait for 4*clk_per;
row <= row+1;
end loop;
end process stim1_proc;
end architecture behavior;
Thanks for your assistance!
-Jason
Edited code and added a testbench
Your design will most certainly depend on latency and other performance requirements, but, you could use some combination of or-reduction, sequencers (for mux selection of sliced vectors), shift register, and counters. I drew up a simple circuit that should find your lsb instance of "1" in ~30 clock cycles
The RTL translation that implements this design should be straight forward.
You say that you are thinking in hardware, but in fact you're not. Or you are misleading yourself.
input( mid-1 downto ll ) > 0
is not an OR-reduction, but a comparison operation. You must know > is the larger than comparison operator. The synthesis will therefor infer a comparator. But how many inputs must that comparator have, I ask? Well, there's your problem: it depends on the value of mid, which:
initially depends on the value of nbits, which depends on the value of nob which is a variable input for the function.
is changed within the loop. Thus it's value is not constant.
A hardware component cannot have a variable amount of wires.
But why do you want binary search? Why not keep-it-simple?
library ieee;
use ieee.std_logic_1164.all;
entity detect_one is
generic(
input_size : positive := 512);
port(
input : in std_logic_vector (input_size-1 downto 0);
output : out natural range 0 to input_size);
end entity;
architecture rtl of detect_one is
begin
main: process(input)
begin
output <= 0;
for i in input_size-1 downto 0 loop
if input(i)='1' then
output <= i+1;
end if;
end loop;
end process;
end architecture;
entity detect_one_tb is end entity;
library ieee;
architecture behavior of detect_one_tb is
constant input_size : positive := 512;
use ieee.std_logic_1164.all;
signal input : std_logic_vector (input_size-1 downto 0) := (others => '0');
signal output : integer;
begin
DUT : entity work.detect_one
generic map ( input_size => input_size )
port map(
input => input,
output => output);
test: process begin
wait for 1 ns;
assert (output = 0) report "initial test failure" severity warning;
for i in 0 to input_size-1 loop
input <= (others => '0');
input(i) <= '1';
wait for 1 ns;
assert (output = i+1) report "single ones test failure" severity warning;
end loop;
input <= (others => '1');
wait for 1 ns;
assert (output = 1) report "initial multiple ones test failure" severity warning;
for i in 0 to input_size-2 loop
input(i) <= '0';
wait for 1 ns;
assert (output = i+2) report "multiple ones test failure" severity warning;
end loop;
wait;
end process;
end architecture;
Related
I was wondering if someone could help me to find the error I am making when reading the analog input introduced to the AD7822 converter by a potentiometer capable of varying its voltage in a range of 0 to 5V.
As far as I understand what I have to do is to generate a 20ns wide pulse for the CONVST bit every 10MHz at most (starting from a clock operating at a maximum frequency of 50 MHz), then wait for the DR to be set to 0 and the value of the digital inputs could be taken.
Timeline for working with AD7822 in automatic mode
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity db_read is
generic
(
div : natural := 5
);
port
(
-- Input ports
clk_in : in std_logic;
rd : in std_logic;
db_input : in std_logic_vector (7 downto 0) := (others => '0');
-- Output ports
convst : out std_logic := '1';
db_output : out std_logic_vector (7 downto 0) := (others => '0')
);
end db_read;
-- Library Clause(s) (optional)
-- Use Clause(s) (optional)
architecture arch1 of db_read is
begin
----------------------------------------------------------------------
-- Send CONVST each div/50MHz ms.
----------------------------------------------------------------------
process(clk_in)
variable cont_convst : integer range 0 to div := 0;
begin
if (rising_edge(clk_in)) then
cont_convst := cont_convst + 1;
if (cont_convst = 1) then
convst <= '0';
else
convst <= '1';
end if;
if (cont_convst = div) then
cont_convst := 0;
end if;
end if;
end process;
----------------------------------------------------------------------
-- Read digital inputs when ready
----------------------------------------------------------------------
process(clk_in)
variable cont_rd : integer := 0;
begin
if (rising_edge(clk_in)) then
-- Detect if RD takes '0' value
if (rd = '0') then
cont_rd := cont_rd + 1;
end if;
if (cont_rd = 1) then
db_output <= db_input;
end if;
if (rd = '1') then
cont_rd := 0;
end if;
end if;
end process;
end arch1;
When I simulate it on a board what I see is that I always have all the outputs at high state regardless of the voltage that I introduce to the input of the converter.
I'm learning VHDL language right now and I have some problems of understanding a part of the code in my course. I don't understand in process freq_counter this statement -> if(pwm_count < max_pwm_count), because we don't know the value of max_pwm_count and also I don't see any incrementation of variable pwm_count.
Thank you, guys!
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
entity PWM is
generic (
freq : integer := 50; --50Hz
INPUT_CLK : integer := 50000000; --50MHz
BITH_DEPTH : integer := 8
);
Port (
ENABLE : in std_logic;
CLK : in std_logic;
PWM_OUT : out std_logic;
DUTY_CYCLE : in std_logic_vector(BITH_DEPTH-1 downto 0)
);
end PWM;
architecture behavioral of PWM is
constant max_freq_count : integer:= INPUT_CLK/freq;
constant pwm_step : integer := max_freq_count/2**BITH_DEPTH;
signal PWM_value : std_logic := '0';
signal freq_count : integer range from 0 to max_freq_count := 0;
signal pwm_count : integer range from 0 to 2**BITH_DEPTH := 0;
signal max_pwm_count : integer range from 0 to 2**BITH_DEPTH := 0;
signal pwm_step_count : integer range from 0 to max_freq_count := 0;
begin
max_pwm_count <= TO_INTEGER(unsigned(DUTY_CYCLE));
PWM_OUT <= PWM_value;
freq_counter: process(CLK)
begin
if rising_edge(CLK) then
if(ENABLE='0') then
if(freq_count < max_freq_count) then
freq_count <= freq_count + 1;
if(pwm_count < max_pwm_count) then
PWM_value<='1';
if(pwm_step_count<pwm_step) then
pwm_step_count<=pwm_step_count+1;
else
pwm_step_count<=0;
pwm_count<=0;
end if;
else
pwm_value<='0';
end if;
else
freq_count <= 0;
pwm_count <= 0;
end if;
else
PWM_value <= '0';
end if;
end if;
end process freq_counter;
end PWM;
We DO know the value of max_pwm_count : it is initialised to 0 and never re-assigned. Therefore the IF can never be true and ... so on.
As far as incrementing PWM_Count is concerned, your understanding seems to be better than the author's, which puts you in a reasonable position for the necessary re-write.
I recommend first writing a testbench so you can observe its behaviour, and get it correct in simulation.
I am learning VHDL right now and I tried to implement UART (1 start bit, 8 data bits, 1 stop bit) to periodically send a hardcoded string.
Everything works as expected - I receive string every 1 second. However, there is no second character.
No matter how long the string is, which character it is. I checked this fact on a oscilloscope and there is no waveform for this particular character. 1 start bit, 8 bits for first character, stop bit, start bit and 8 bits for third character, not the second one.
Following code is for 10 MHz clock divided to send with ~38 400 bits per second, I also tried with 9600 bits per second, both the same problem.
I'm using Altera MAX10 dev board: http://maximator-fpga.org/
Short video how it works:
https://gfycat.com/JoyousIlliterateGuillemot
UART.vhd:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.ALL;
use ieee.std_logic_arith.all;
entity UART is
port (
clk_10mhz: in STD_LOGIC;
txPin: out STD_LOGIC
);
end entity;
architecture Test of UART is
signal txStart: STD_LOGIC;
signal txIdle: STD_LOGIC;
signal txData: STD_LOGIC_VECTOR(7 downto 0);
component TX is
port (
clk_in: in STD_LOGIC;
start: in STD_LOGIC;
data: in STD_LOGIC_VECTOR(7 downto 0);
tx: out STD_LOGIC;
txIdle: out STD_LOGIC
);
end component TX;
begin
process (clk_10mhz, txIdle)
variable clkDividerCounter : integer range 0 to 10000000;
variable textToSend : string(1 to 31) := "Hello darkness my old friend!" & CR & LF;
variable currentCharacterIndex : integer range 0 to 31;
begin
if (rising_edge(clk_10mhz)) then
if (clkDividerCounter < 10000000) then
clkDividerCounter := clkDividerCounter + 1;
else
clkDividerCounter := 0;
currentCharacterIndex := 1;
end if;
if (txIdle = '1' and currentCharacterIndex > 0) then
txData <= CONV_STD_LOGIC_VECTOR(character'pos(textToSend(currentCharacterIndex)),8);
txStart <= '1';
if (currentCharacterIndex < 31) then
currentCharacterIndex := currentCharacterIndex + 1;
else
currentCharacterIndex := 0;
txStart <= '0';
end if;
end if;
end if;
end process;
u1: TX port map (clk_10mhz, txStart, txData, txPin, txIdle);
end Test;
TX.vhd:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.ALL;
entity TX is
port (
clk_in: in STD_LOGIC;
start: in STD_LOGIC;
data: in STD_LOGIC_VECTOR(7 downto 0);
tx: out STD_LOGIC;
txIdle: out STD_LOGIC
);
end entity;
architecture Test of TX is
signal idle: STD_LOGIC;
begin
process (clk_in)
variable bitIndex : integer range 0 to 9;
variable clkDividerCounter : integer range 0 to 260;
variable dataFrame : STD_LOGIC_VECTOR(9 downto 0);
variable dataFrameCurrentIndex : integer range 0 to 9;
begin
if (rising_edge(clk_in)) then
if (start = '1' and idle = '1') then
dataFrame(0) := '0';
dataFrame(8 downto 1) := data;
dataFrame(9) := '1';
dataFrameCurrentIndex := 0;
idle <= '0';
end if;
if (idle = '0') then
if (clkDividerCounter < 260) then
clkDividerCounter := clkDividerCounter + 1;
else
if (dataFrameCurrentIndex <= 9) then
tx <= dataFrame(dataFrameCurrentIndex);
dataFrameCurrentIndex := dataFrameCurrentIndex + 1;
else
idle <= '1';
end if;
clkDividerCounter := 0;
end if;
end if;
txIdle <= idle;
end if;
end process;
end Test;
Move the line
txIdle <= idle;
from TX.vhd outside the process. Signals take their new value after the process ends.
For example:
idle <= '0';
txIdle <= idle;
Will set txIdle to '1' if idle was '1' when the two statements were executed inside a process. You should notice that this means that txIdle will be '1' for two consecutive cycles and causes currentCharacterIndex to increment twice at the start.
Note that contrary to signals, variable take their new value when the assigning statement is encountered, and not at the end of the process as signals do.
While your code is not that terrible for a beginner, I recommend to use only signal when you start learning VHDL. It is much easier to make mistake with variables, or describe sub-optimal or broken implementation.
Also, as Brian mentioned, don't use std_logic_arith, especially when using numeric_std. They are conflicting with each other (some tools deal with it though) and std_logic_arith is not a IEEE standard, while numeric_std is.
Finally, simulation is a crucial part of hardware design. To avoid uninitialized pin, add a reset to your circuit, which is generally a good idea.
I'm new to VHDL and am trying to code up Booth's Multiplication Algorithm. I'm using XILINX and when I synthesize my code, I end up with a lot of warnings:
Upper is assigned but never used,
Product is used but never assigned,
LowerPrevLSB is assigned but never used,
Lower is assigned but never used,
A_2sComp is assigned but never used,
Z has a constant value of 0,
Product has a constant value of 0.
I thought I assigned and wrote the code correctly, but evidently I am not. Any advice and help would be appreciated.
library IEEE;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_arith.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
-- X * Y = Z
entity BoothMultiplier is
generic
(
numBits_X : integer := 8;
numBits_Y : integer := 8
);
port
(
CLK : in std_logic;
X : in std_logic_vector((numBits_X - 1) downto 0);
Y : in std_logic_vector((numBits_Y - 1) downto 0);
Z : out std_logic_vector((numBits_X + numBits_Y - 1) downto 0)
);
end BoothMultiplier;
architecture Behavioral of BoothMultiplier is
-- Two's Complement Function
function TwosComplement(inputNum : std_logic_vector) return std_logic_vector;
function TwosComplement(inputNum : std_logic_vector) return std_logic_vector is
variable temp : std_logic_vector(inputNum'range);
begin
temp := (not inputNum) + 1;
return temp;
end TwosComplement;
-- End Two's Complement Function
-- MIN Function
function MIN(Left, Right : integer) return integer;
function MIN(Left, Right : integer) return integer is
begin
if Left < Right then return Left;
else return Right;
end if;
end Min;
-- End MIN Function
-- MAX Function
function MAX(Left, Right : integer) return integer;
function MAX(Left, Right : integer) return integer is
begin
if Left > Right then return Left;
else return Right;
end if;
end MAX;
-- End MAX Function
-- Signals
signal Upper : std_logic_vector(MAX(numBits_X, numBits_Y) - 1 downto 0)
:= (others => '0');
signal Lower : std_logic_vector(MIN(numBits_X, numBits_Y) - 1 downto 0)
:= (others => '0');
signal LowerPrevLSB : std_logic := '0';
signal Product : std_logic_vector(numBits_X + numBits_Y - 1 downto 0)
:= (others => '0');
signal A, A_2sComp : std_logic_vector(MAX(numBits_X, numBits_y) - 1 downto 0)
:= (others => '0');
signal counter : integer := 0;
-- End Signals
begin
assert Z'length = (X'length + Y'length) report "Bad Product Length" severity failure;
Lower <= X when (numBits_X <= numBits_Y) else Y;
A <= X when (numBits_X > numBits_Y) else Y;
A_2sComp <= TwosComplement(A);
process(CLK)
begin
if rising_edge(CLK) then
if (Lower(0) = '0' and LowerPrevLSB = '1') then
Upper <= Upper + A;
elsif (Lower(0) = '1' and LowerPrevLSB = '0') then
Upper <= Upper + A_2sComp;
end if;
LowerPrevLSB <= Lower(0);
Product <= Upper & Lower;
for i in 0 to Product'length - 2 loop
Product(i) <= Product(i+1);
end loop;
Product(Product'length-1) <= Product(Product'length-1);
Upper <= Product(Product'length - 1 downto MIN(numBits_X, numBits_Y));
Lower <= Product(MIN(numBits_X, numBits_Y) - 1 downto 0);
counter <= counter + 1;
if (counter = MIN(numBits_X, numBits_Y)) then
Z <= Product;
end if;
end if;
end process;
end Behavioral;
In VHDL, successive assignments to the same signal in a process overrides previous assignments, thus:
if (Lower(0) = '0' and LowerPrevLSB = '1') then
Upper <= Upper + A;
elsif (Lower(0) = '1' and LowerPrevLSB = '0') then
Upper <= Upper + A_2sComp;
end if;
...
Upper <= Product(Product'length - 1 downto MIN(numBits_X, numBits_Y));
The first assignments, in the if block, is completely ignored. If you look at your code, assignments to Product, Upper and Lower are overridden.
I suggest you simulate your design before synthesizing your design with Xilinx. It will be much easier to test and debug. For instance, your counter signal is never reset, and will count up to 2^31-1, then wrap to -2^31. What will happen to your design in those cases? Simulation would point out these error easily, leave synthesis for later!
I have stuck on this problem since last week and tried to receive a correct answer from different ways but unfortunately since now it has not worked.
I hae a state machine that receives three patterns and make a matrix for each one of them and then sum all of them together and sends it to output. But the state machine sends the matrix of first pattern to output.
I think the problem is that adder should work with the clock (state one) and state machine goes to the next state with event edge of each clock, therefore it can't synchronize with the adder. But i don't know how i can fix this problem. I would appriciate any help kindly.
P.S The package must be included in the code.
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 14:11:16 0NUMBITS-1/11/2012
-- Design Name:
-- Module Name: state_machine - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
use work.my_data_types.all;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity state_machine2 is
port(
pattern : in std_logic_vector(0 to NUMBITS-1); --The incorrect pattern
clk : in std_logic;
result : out matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1)
);
end state_machine2;
architecture Behavioral of state_machine2 is
type state is (zero , one, two);
signal pr_state, nx_state : state ;
signal s_out_matrix : matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1);
signal s_flipflop_adder : matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1):= (others => (others => (others => '0')));
signal q : integer;
begin
process(clk)
begin
if(clk'event and clk = '1')then
pr_state <= nx_state;
end if;
end process;
process(pattern, pr_state)
variable cnt: integer := -1;
begin
case pr_state is
when zero =>
q <= 0; -- state number
if(cnt < NUM_TRAIN_PATTERN)then
cnt := cnt + 1;
nx_state <= one;
else
nx_state <= two;
end if;
when one =>
q <= 1;
For i in 0 to NUMBITS-1 loop --The multiplication in the pattern
For j in 0 to NUMBITS-1 loop
if(i = j) then
s_out_matrix(i,j) <= (others => '0');
elsif(pattern(i) = pattern(j)) then
s_out_matrix(i,j) <= (0 => '1', others => '0');
else
s_out_matrix(i,j) <= (others => '1');
end if;
end loop;
end loop;
if(clk'event and clk = '1')then -- Sum of the matrixes
For i in 0 to NUMBITS-1 loop
For j in 0 to NUMBITS-1 loop
s_flipflop_adder(i,j) <= s_flipflop_adder(i,j) + s_out_matrix(i,j);
end loop;
end loop;
end if;
nx_state <= zero;
when two =>
q <= 2;
result <= s_flipflop_adder;
end case;
test_q <= q;
end process;
end Behavioral;
the package:
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
package my_data_types is
type matrix2D is array (integer range <> , integer range <> ) of signed(2 downto 0); -- Matrix2D
constant NUMBITS : integer := 3;
constant NUM_TRAIN_PATTERN : natural := 3;
end my_data_types;
A few thing stand out...
First of all, whenever you create a state machine, there needs to be a way to reset it, ideally an input signal which forces the sequential elements to a known state. In your case, there is no way to reset pr_state, and thus no way to know from the code what the starting state should be. Also, avoid "resetting" sequential elements by assigning a default value as is done for s_flipflop_adder, because that is likely to lead to a mismatch between simulation and actual implementation.
Second, do not generate sequential and combinatorial signals inside the same process. For each signal, decide if it is sequential (i.e. a flip flop, updated on a clock edge), or combinatorial (i.e. updated almost instantly from the value of other signals, slowed down only by the propagation delays in the logic elements). For sequential signals, create a sequential process in which everything is inside an if rising_edge(clk) or if clk'event and clk = '1' statement (equivalent for most purposes), and with only the clock (and maybe your reset signal, if it is asynchronous) in the sensitivity list. For combinatorial signals, put them in a combinatorial process, which is a process with no clock and a complete sensitivity list.
In your design, the first process is a proper sequential process. The second process, however, starts as a combinatorial process (with an incomplete sensitivity list), but then there is a sequential assignment to s_flipflop_adder nested in a branch of the case statement. The signal s_flipflop_adder is unlikely to ever be assigned because clk is not in the sensitivity list, and even if it was, the synthesis tools will likely not interpret that mix as you intended it.
Finally, do not use a variable to keep state information as you do with the cnt variable, and make sure you update your state only on a clock edge (i.e. sequentially).
With these three points in mind, the state machine will look something more akin to this (I inlined the definitions from the my_data_types package only to make the answer easier to read):
library ieee;
use ieee.std_logic_vector_1164.all;
use ieee.std_logic_arith.all;
entity state_machine2 is
port(
clk : in std_logic;
rst : in std_logic;
pattern : in std_logic_vector(0 to NUMBITS-1);
result : out matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1) );
end state_machine2;
architecture Behavioral of state_machine2 istype state is (zero , one, two);
constant NUMBITS : integer := 3;
constant NUM_TRAIN_PATTERN : natural := 3;
subtype signed3 is signed(NUMBITS-1 downto 0);
type matrix2D is array (integer range <> , integer range <> ) of signed3;
signal pr_state : state;
signal s_flipflop_adder : matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1);
signal cnt : integer;
begin
process(clk) is
variable add_operand : signed3;
begin
if rising_edge(clk) then
if rst = '1' then
pr_state <= zero;
cnt <= -1;
s_flipflop_adder <= (others => (others => (others => '0')));
else
case pr_state is
when zero =>
cnt <= cnt + 1;
if cnt < NUM_TRAIN_PATTERN then
pr_state <= one;
else
pr_state <= two;
end if;
when one =>
for i in 0 to NUMBITS-1 loop
for j in 0 to NUMBITS-1 loop
if i = j then
add_operand := (others => '0');
elsif pattern(i) = pattern(j) then
add_operand := (0 => '1', others => '0');
else
add_operand := (others => '1');
end if;
s_flipflop_adder(i,j) <= s_flipflop_adder(i,j)
+ add_operand;
end loop;
end loop;
when two =>
result <= s_flipflop_adder;
end case;
end if;
end if;
end process;
end Behavioral;
Thank you for posting this question, as these are very common mistakes.