Error (10327): can't determine definition of operator ""="" -- found 0 possible definitions - vhdl

In VHDL '93 the compiler told me it found 0 possible definitions for operator "=".
It causes an error with the following error message:
Error (10327): VHDL error at mst_fifo_fsm.vhd(171): can't determine definition of operator ""="" -- found 0 possible definitions
Line 171 is at the first assignment of ifsm_cond(0):
process(clk, rst_n)
begin
if (rst_n = '0') then
ifsm_cond <= "0000";
elsif (rising_edge(clk)) then
if (mltcn = '0') then
ifsm_cond(0) <= (cur_stap1 = IDLE) AND (not imst_rd_n(0)) AND (not rxf_n) AND (not ibuf_ful(0));
ifsm_cond(1) <= (cur_state = MTRD) AND ( imst_rd_n(0) OR (rxf_n AND (not rxf_n_p1)) OR ibuf_ful(0)) ;
ifsm_cond(2) <= (cur_state = MDLE) AND (not imst_wr_n(0)) AND (not txe_n)& (ibuf_nep(0) OR stren OR w_1byte) AND (not w_1flag);
ifsm_cond(3) <= (cur_stap3 = MTWR) AND ( imst_wr_n(0) OR (txe_n AND (not txe_n_p1)) OR r_oobe OR ((not ififonempt(0)) AND (not stren) AND (not prefnempt(0))));
else
ifsm_cond(0) <= (not imst_rd_n(conv_integer(ichannel))) AND (not irxf_n(conv_integer(ichannel))) AND (not ibuf_ful(conv_integer(ichannel))) AND (cur_stap3 = IDLE);
ifsm_cond(1) <= ( imst_rd_n(conv_integer(ichannel)) OR (rxf_n & (not rxf_n_p1)) OR ibuf_ful(conv_integer(ichannel))) AND (cur_state = MTRD);
ifsm_cond(2) <= (not imst_wr_n(conv_integer(ichannel))) AND (not itxe_n(conv_integer(ichannel))) AND (ibuf_nep(conv_integer(ichannel)) OR stren) AND (cur_stap3 = MDLE);
ifsm_cond(2) <= (not imst_wr_n(conv_integer(ichannel))) AND (not itxe_n(conv_integer(ichannel))) AND (ibuf_nep(conv_integer(ichannel)) OR stren) AND (cur_stap3 = MDLE);
ifsm_cond(3) <= ( imst_wr_n(conv_integer(ichannel)) OR (rxf_n AND
(not rxf_n_p1)) OR ((not ififonempt(conv_integer(ichannel)) AND (not stren)
AND (not prefnempt(conv_integer(ichannel)))))) AND (cur_stap3 = MTWR);
end if;
end if;
end process;
I guess it is at the statement (cur_stap1 = IDLE).
cur_stap1 is a user defined signal with the following declaration:
type states is (IDLE, MTRD, MDLE, MTWR);
signal cur_state, next_statem, cur_stap1, cur_stap2, cur_stap3, cur_stap4 :
states;
I thougt of one possible solution to clarify first in a conditional concurrent signal assignment if cur_stap1 is IDLE and assign this to a signal which replaces (cur_stap1 = IDLE). But I have some more lines with other statements like this.
Is there a better solution to solve this issue? This concurrent signal assignment is done in a process. Should I rather try an IF ELSIF END IF statement for the whole line?
Thank you in advance.

The problem is that not imst_rd_n(0) returns a std_logic type, while cur_stap1 = IDLE returns a boolean type. There is no and operator that accepts both types, thus the compiler tries to solve it another way: by looking for an = operator defined for your custom type (state) that returns a std_logic, which there isn't. Hence the error.
Instead of not imst_rd_n(0), you should write imst_rd_n(0)='0' and so on. This returns a boolean and a boolean and operator is defined. Imho it's also better for readability.
You should then write your assignment in an if statement.
If [boolean expression] then
[Signal] <= '1';
Else
[Signal] <= '0';
End if;
Also try to design a state machine with a simple output:
Case [current_state] is
When [state 1] =>
If ....
When ....
End case;
You can work with default assignment.
Example:
if rising_edge(clk) then
ifsm_cond <= (others => '0'); -- default assignment
case cur_state is
when IDLE =>
if imst_rd_n(0)='0' AND rxf_n='0' AND ibuf_ful='0' then
ifsm_cond(0) <= '1';
end if;
when MTRD =>
if imst_rd_n(0)='1' OR (rxf_n='1' AND rxf_n_p1='0') OR ibuf_ful(0)='1' then
ifsm_cond(1) <= '1';
end if;
etc.
I would not write a function for operator = for two input's type states that returns a std_logic, as that could lead to other unwanted conflicts. I would instead propose to make a casting function from boolean to std_logic. E.g.:
function to_std_logic(input : boolean) return std_ulogic is
begin
if input then
return '1';
end if;
return '0';
end function;
Usage example: ifsm_cond(0) <= to_std_logic(cur_stap1 = IDLE) AND (not imst_rd_n(0)) AND (not rxf_n) AND (not ibuf_ful(0));

Related

VHDL record assignment through for loop

I have a for loop in process, which works fine with std_logic arrays, but not with record arrays. I use Xilinx ISE along with ISIM and the code is vhdl-93. The target will be a Spartan 3.
Here is the record definition:
TYPE spi_rx_t IS RECORD
CS : std_logic;
MOSI : std_logic;
CLK : std_logic;
END RECORD;
constant SYNC_LATCHES : integer := 2;
Here is the array definition and declaration:
type spi_rx_array_t is array (0 to SYNC_LATCHES) of spi_rx_t;
signal spi_in_array : spi_rx_array_t;
Below is the process:
spi_in_array(0).MOSI <= SPI_MOSI;
spi_in_array(0).CLK <= SPI_CLK;
spi_in_array(0).CS <= SPI_CS;
sync_p: process (clk_100)
begin
if rising_edge(clk_100) then
-- for I in 1 to SYNC_LATCHES loop
-- spi_in_array(I) <= spi_in_array(I - 1);
-- end loop;
spi_in_array(1) <= spi_in_array(0);
spi_in_array(2) <= spi_in_array(1);
end if;
end process;
The 2 lines below the commented code works exactly as expected (allowing me to synchronize external signals to clk_100), but I'd rather implement them as a for loop (such the commented one).
However, these commented lines does not produce the same result in my ISIM test bench (spi_in_array stays in unknown state when using the for loop). Why?
Please kindly help me with this.
As commented by Morten Zilmer, this is due to the VHDL concept "longest static prefix". This SO answer is similar to my issue.
In my case, the simplest way to resolve the issue was to move the assignment of the first element of the array into the same process as the for loop. I also had to decrease SYNC_LATCHES constant from 2 to 1, because spi_in_array(0) is now latched with clk_100.
sync_p: process (clk_100)
begin
if rising_edge(clk_100) then
spi_in_array(0).MOSI <= SPI_MOSI;
spi_in_array(0).CLK <= SPI_CLK;
spi_in_array(0).CS <= SPI_CS;
for I in 1 to SYNC_LATCHES-1 loop
spi_in_array(I) <= spi_in_array(I - 1);
end loop;
end if;
end process;

VHDL syntax issue

I'm getting an error during CheckSyntax for the following code I've tried. The error says:
"Line 48. parse error, unexpected VARIABLE Line 53. Undefined symbol 'InOutDetector'.
Line 57. InOutDetector: Undefined symbol (last report in this block)".
Can you let me know how should I fix this?
Here is an image of my code, as I could not paste it.
https://www.dropbox.com/s/ay8pjq4ojoep6ry/RoomLightController.png?dl=0
entity Room_Light_Controller is
port (
clk, sA, sB: IN STD_LOGIC;
sL: OUT STD_LOGIC
);
end Room_Light_Controller;
architecture Behavioral of Room_Light_Controller is
-- assuming sensors are variables sA and sB, and lights switch is sL
SIGNAL People : INTEGER:=0;
SIGNAL AllowNextCount : BIT:='0';
--unsigned int People=0; -- counter for people inside the room
--char AllowNextCount=0; -- boolean indicating if allowing next count or not
--short int InOutDetector; -- 1 = entering; -1 = exiting
begin
variable InOutDetectorDetector: integer;
process (clk)
begin
if ((sA = '0') and (sB = '1')) then
-- entering
InOutDetector := 1;
end if;
if ((sA = '1') and (sb = '0')) then
-- exiting
InOutDetector := -1;
end if;
if ((sA ='1') and (sB = '1') and (AllowNextCount = '1')) then
-- only when both sensors are touched validate the people counter
People := People+InOutDetector;
-- count once then block counting until the same person has finished entering/exiting
AllowNextCount <= '0';
end if;
if ((sA = '0') and (sB = '0')) then
-- it gets 0;0 only when someone has finished entering/exiting
-- pr at turn on; so now allow to counting again
AllowNextCount <= '1';
end if;
if (People > 0) then
sL <= '1'; -- Turn/keep lights on as long as People greater than 0
else
sL <= '0'; -- otherwise, turn them off
end if;
end process;
end Behavioral;
In addition to the error Amir notes that there is a name mismatch and the variable is declared in the wrong place, there is an additional error with the assignment to People:
library ieee;
use ieee.std_logic_1164.all;
entity Room_Light_Controller is
port (
clk, sA, sB: in std_logic;
sL: out std_logic
);
end entity Room_Light_Controller;
architecture Behavioral of Room_Light_Controller is
-- assuming sensors are variables sA and sB, and lights switch is sL
signal people: integer := 0;
signal allownextcount: bit := '0';
--unsigned int People=0; -- counter for people inside the room
--char AllowNextCount=0; -- boolean indicating if allowing next count or not
--short int InOutDetector; -- 1 = entering; -1 = exiting
begin
-- variable InOutDetectorDetector: integer;
process (clk)
variable InOutDetector: integer; -- as per Amir
begin
if sA = '0' and sB = '1' then
-- entering
InOutDetector := 1;
end if;
if sA = '1' and sb = '0' then
-- exiting
InOutDetector := -1;
end if;
if sA ='1' and sB = '1' and AllowNextCount = '1' then
-- only when both sensors are touched validate the people counter
People <= People + InOutDetector; -- was :=, signal assignment
-- count once then block counting until the same person has finished entering/exiting
AllowNextCount <= '0';
end if;
if sA = '0' and sB = '0' then
-- it gets 0;0 only when someone has finished entering/exiting
-- pr at turn on; so now allow to counting again
AllowNextCount <= '1';
end if;
if People > 0 then
sL <= '1'; -- Turn/keep lights on as long as People greater than 0
else
sL <= '0'; -- otherwise, turn them off
end if;
end process;
end architecture Behavioral;
People is a signal and requires the signal assignment symbol (<=) not the variable assignment symbol (:=).
After the two changes the VHDL design specification analyzes and elaborates.
Notice a context clause has been added to make your code a Minimal, Verifiable and Complete example.
Also note in the Help Center web page on Minimal, Complete, and Verifiable example the section Minimal and readable,
..Use consistent naming and indentation, and include comments if needed to explain portions of the code.
If this code were intended to be synthesize you might likely need to constrain the integers.
For execution efficiency all the independent if statements could be consolidated using elsif. That's hardly an issue in a small design, but the binary patterns described for sA and sB are mutually exclusive (while not exhaustive for type std_logic).
You neglected to provide the complete error messages, which appear to be output from XST. Historically the recommended design flow includes simulation, which if for no other purpose provides better syntax error messages from VHDL analysis.
XST historically assumes you are handing it a design description that is syntax error free, and is other wise quite sparse in providing adequate error messages.
The error message prefix (e.g. ERROR:HDLParsers:1209) can tell you how to find the problem via Xilinx's support site and/or documentation.
Declare the variable inside the process and rename it to (InOutDetector). You used (InOutDetector) inside the process.
Then if you want to run the process on clk rising edge, complete your process such as the following code :
process(clk)
variable InOutDetector : integer;
begin
if clk = '1' and clk'event then
-- your code
end if;
end process;
However if you don't want to use the clk rising edge, just complete the sensitivity list with parameters that you read or check it inside the process (sA,sB,AllowNextCount,People) and remove clk from the process sensitivity list.
Also be careful about incomplete if statements. Latches may be generated from incomplete case or if statements.

How to fix Xilinx ISE warning about sensitivity list?

I synthesized my design with Xilinx ISE 13.1. Target device is Virtex 5. Then I encountered this warning:
WARNING:Xst:819 - "F:/FRONT-END/h264/inter/src/eei/eei_mvd.vhd"
line 539: One or more signals are missing in the process sensitivity list.
To enable synthesis of FPGA/CPLD hardware, XST will assume that all necessary signals are present in the sensitivity list.
Please note that the result of the synthesis may differ from the initial design specification. The missing signals are:
<mvd_l0<3><3>>, <mvd_l0<3><2>>, <mvd_l0<3><1>>, <mvd_l0<3><0>>, <mvd_l0<2><3>>, <mvd_l0<2><2>>,
<mvd_l0<2><1>>, <mvd_l0<2><0>>, <mvd_l0<1><3>>, <mvd_l0<1><2>>, <mvd_l0<1><1>>, <mvd_l0<1><0>>,
<mvd_l0<0><3>>, <mvd_l0<0><2>>, <mvd_l0<0><1>>, <mvd_l0<0><0>>, <mvd_l1<3><3>>, <mvd_l1<3><2>>,
<mvd_l1<3><1>>, <mvd_l1<3><0>>, <mvd_l1<2><3>>, <mvd_l1<2><2>>, <mvd_l1<2><1>>, <mvd_l1<2><0>>,
<mvd_l1<1><3>>, <mvd_l1<1><2>>, <mvd_l1<1><1>>, <mvd_l1<1><0>>, <mvd_l1<0><3>>, <mvd_l1<0><2>>,
<mvd_l1<0><1>>, <mvd_l1<0><0>>, <mvd<0>>, <mvd<1>>
Here is my source code:
proc_update_next: process(mvd_l0, mvd_l1, mvd, subMBPart_Idx, MBPart_Idx, eei_info )
begin
--// Init
next_mvd_l0 <= mvd_l0;
next_mvd_l1 <= mvd_l1;
--// Change
if eei_info.mb_type = BLK_8x8 then
for i in 3 downto 0 loop
for j in 3 downto 0 loop
if i = to_integer(unsigned(MBPart_Idx)) and j = to_integer(unsigned(subMBPart_Idx)) then
next_mvd_l0(i)(j) <= mvd(0);
next_mvd_l1(i)(j) <= mvd(1);
end if;
end loop;
end loop;
else
for i in 3 downto 0 loop
if i = to_integer(unsigned(MBPart_Idx)) then
next_mvd_l0(i)(0) <= mvd(0);
next_mvd_l1(i)(0) <= mvd(1);
end if;
end loop;
end if;
end process;
Update: I change a little bit in my code and still this warning.
The mvd_l0 and mvd_l1 is two-dimension array and it appeared on sensitivity list. I know my source code is too abstract and ISE may can not understand.
I tried with Virtex 7 (not avaiable in laboratory) then there are no error. So, my question is how to fix this warning ? I can't ignore this warning because it can lead to latch.
Use the VHDL-2008 construct process(all) to tell the tools you want the sensitivity list to include all signals which are read.
Alternatively, make it a clocked process, only sensitive to the clock, and then you don't have to worry either.
You should only set signals like next_mvd_l0 and next_mvd_l1 once for a set of conditions. The "init" section is still an issue. It may be better to use local variables if you are avoiding reseting the process.
Best option: add a reset to the sensitivity list and if its enabled, set next_mvd_* to your init values
--// Init
if (reset = '1') then
next_mvd_l0 <= mvd_l0;
next_mvd_l1 <= mvd_l1;
end if;
Second option: use a local variable
proc_update_next: process(mvd_l0, mvd_l1, mvd, subMBPart_Idx, MBPart_Idx, eei_info )
variable mvd_10_local : 2dArrayType;
variable mvd_11_local : 2dArrayType;
begin
--// Init
mvd_10_local := mvd_l0;
mvd_11_local := mvd_l1;
--// Change
if eei_info.mb_type = BLK_8x8 then
for i in 3 downto 0 loop
for j in 3 downto 0 loop
if i = to_integer(unsigned(MBPart_Idx)) and j = to_integer(unsigned(subMBPart_Idx)) then
mvd_10_local(i)(j) := mvd(0);
mvd_11_local(i)(j) := mvd(1);
end if;
end loop;
end loop;
else
for i in 3 downto 0 loop
if i = to_integer(unsigned(MBPart_Idx)) then
mvd_10_local(i)(j) := mvd(0);
mvd_11_local(i)(j) := mvd(1);
end if;
end loop;
end if;
next_mvd_l0 <= mvd_10_local;
next_mvd_l1 <= mvd_l1_local;
end process;
You use the VHDL record construct (eei_info.mb_type). You can add every record element to the sens-list to make xst happy. I just ignore this warning.

VHDL 'generate' FSM states

I have a variable number of modules linked to another module via a signal bus : std_logic_vector(NUM-1 downto 0), with each component using 8 bits, so that:
bus(7 downto 0) = first module
bus(15 downto 8) = second module
As for creating the instances and doing the port mapping, that is easily done with a
INST: for i in 0 to NUM-1 generate
Inst_module port map ( bus => bus(i*8+7 downto i*8) );
end generate INST;
My question:
I would like to be able to interface with each module via a FSM (since it needs to do some other things too), so would like to be able to 'generate' the following code, rather than having to write out each state manually (Where signal empty : std_logic_vector(NUM-1 downto 0) is a status flag for each module)
type state_type is (st0_idle, st1_work0, st1_work1 --,etc.)
signal state : state_type;
begin
process(empty)
begin
if RESET = '1' then
--reset FSM
state <= st0_idle;
else
if CLK'event and CLK='1' then
case state is
when st0_idle =>
if empty(0) = '0' then
state <= st1_work0;
elsif empty(1) = '1' then
state <= st1_work1;
--etc.
end if;
when st1_work0 =>
bus(7 downto 0) <= SOMETHING;
state <= st0_idle;
when st1_work1 =>
bus(15 downto 8) <= SOMETHINGELSE;
state <= st0_idle;
--etc..
end if;
end if;
end process;
As you can see, there is a lot of repetition. But I can't simply put a for-generate inside the case, so what should I do?
One good way to make processes with state machines more readable is to merge common code into procedures defined within the process. For example:
process (empty) is
procedure assign_something (
index : natural;
something : std_logic_vector(7 downto 0)
next_state : state_type
) is
begin
bus(index*8+7 downto index*8) <= something;
state <= next_state;
end procedure;
begin
wait until rising_edge(clk);
case state is
when st0_idle => ...
when st1_work0 => assign_something(0, something, st0_idle);
when st1_work1 => assign_something(1, something_else, st0_idle);
-- ... etc ...
end case;
if reset = '1' then
state <= st0_idle;
end if;
end procedure;
Hopefully you get the idea. Depending on how regular the state machine structure is, you may also want to replace the enumerated state variables that correspond to each index with a simple count or index variable that you keep track of along with the named state.
That's all up to you, but however you do it, using procedures to factor out common code whenever you can will probably make your VHDL much easier to work with.
Applying this change would make the code look something like this:
architecture ...
type state_type is (st_idle, st_work);
signal state : state_type;
signal index : integer range 0 to NUM-1;
...
begin
...
process (empty) is
procedure assign_something (
index : natural;
something : std_logic_vector(7 downto 0)
next_state : state_type
) is
begin
bus(index*8+7 downto index*8) <= something;
state <= next_state;
end procedure;
begin
wait until rising_edge(clk);
case state is
when st_idle =>
for i in 0 to NUM-1 loop
if empty(i) = '1' then
index := i;
exit;
end if;
end loop;
when st_work => assign_something(index, something, st_idle);
end case;
if reset = '1' then
state <= st_idle;
end if;
end procedure;
Obviously this has to be changed to match exactly what you want to do ... =)

Conditional Assignments in a 'With Select' block

Is it possible to add conditional asignments to a signal from within a 'with select' block. eg.
with state select
Data <= x"00" when IDLE,
(x"01" when Count = 0 else x"10") when DATA,
x"FF" when others;
This doesn't compile, but is it possible to include a second variable within this block?
Short answer is no.
You could do something like this instead.
process (Count, state)
variable countData : std_logic_vector (7 downto 0);
begin
if Count = 0 then
countData := x"01";
else
countData := x"10";
end if;
case state is
when IDLE => Data <= x"00";
when DATA => Data <= countData;
when others => Data <= x"FF";
end case;
end process;

Resources