Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Problem with VHDL Code Modification

Status
Not open for further replies.
ok, so you attempted to make something similar to a spinlock. However, that isn't needed or possible in VHDL.

The nested if-else statements will perform the function you want. It forces the add/complement/load operations to only occur when the error flag is 0.

Specifically:
Code:
process (clk) is
begin
  if rising_edge(clk) then
    if clear = '1' then
      -- dReg should be cleared
      -- any error flag should be cleared.
    elsif error_flag = '0' then
      if load = '1' then
        -- code for load
      elsif add = '1' then
        --code for the addition and to set the error_flag.  
      elsif complement = '1' then
        -- code for complement
      end if;
    end if;
  end if;
end process;
This is the nested if-else statement. As you can see, if clear is set clear works. clear always works. However add/complement/load are inside of an elsif, and can only be used if the error flag is not set.


It may help you if you realize that you are describing hardware vs describing logic that would run on an existing piece of hardware.
 
ok, so you attempted to make something similar to a spinlock. However, that isn't needed or possible in VHDL.

The nested if-else statements will perform the function you want. It forces the add/complement/load operations to only occur when the error flag is 0.

Specifically:
Code:
process (clk) is
begin
  if rising_edge(clk) then
    if clear = '1' then
      -- dReg should be cleared
      -- any error flag should be cleared.
    elsif error_flag = '0' then
      if load = '1' then
        -- code for load
      elsif add = '1' then
        --code for the addition and to set the error_flag.  
      elsif complement = '1' then
        -- code for complement
      end if;
    end if;
  end if;
end process;
This is the nested if-else statement. As you can see, if clear is set clear works. clear always works. However add/complement/load are inside of an elsif, and can only be used if the error flag is not set.


It may help you if you realize that you are describing hardware vs describing logic that would run on an existing piece of hardware.

OK, I think should understand that the error_flag will stop the rest of the operations as long as it is '1'?

but how can i declare this flag in my code?

Code:
Library IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.numeric_std.all;

Entity calculator is
Port ( clk : in std_logic; 				                      -- clock
	Clear, load, add, complement : in std_logic;		     -- operation signals
 	Din : in std_logic_vector (15 downto 0);	          -- input data
	Result : out std_logic_vector (15 downto 0));	     -- output data
End calculator;

Architecture a1 of calculator is
Signal dReg : std_logic_vector (15 downto 0);
Variable error_flag : std_logic := '0';
Begin
Process (clk)
Begin
	If (rising_edge (clk)) then
 		If (clear ='1') then
      dReg <= "0000000000000000";
    elsif error_flag = '0' then
	  	if (load ='1') then
 			dReg <= Din;
 		elsif (add ='1') then
 			dReg <= std_logic_vector(error_flag & unsigned(dReg)+ unsigned(Din)); -- Using flag & to be able to assign additional bit
 		elsif (complement='1') then
 			dReg <= not Din;

			--values of dreg and din are converted to unsigned type with unsigned() function.
			--the unsigned values are added
			--the result is converted to standard logic vector with std_logic_vector() function.
      end if;
		end if;
 	end if;
end Process;
Result <= dReg;
end a1;

and this is the problem i got :Variable declaration 'error_flag' not allowed in this region.
4.png
 

One nice feature of VHDL is that variables are local to a process -- they must be declared between the "Process (clk)" and the "Begin". As a result the variable can only be accessed from within the process.

In this case, you want to use the variable for the addition operation. (assuming you want to use variables at all). Within the addition operation, the msb of the addition (the carry out) can be used as the error flag. the error flag will be a signal, and declared as std_logic near where dReg is declared. The codce to clear the flag will be in the clear operation.
 
Hi

I was trying to make a testbench for this code
Code:
Library IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.numeric_std.all;

Entity calculator is
Port ( clk : in std_logic; 				                      -- clock
	Clear, load, add, complement : in std_logic;		     -- operation signals
 	Din : in std_logic_vector (15 downto 0);	          -- input data
	Result : out std_logic_vector (15 downto 0));	     -- output data
End calculator;

Architecture a1 of calculator is
Signal dReg : std_logic_vector (15 downto 0);
Begin
Process (clk)
Variable error_flag : std_logic := '0';
Begin
	If (rising_edge (clk)) then
 		If (clear ='1') then
      dReg <= "0000000000000000";
    elsif error_flag = '0' then
	  	if (load ='1') then
 			dReg <= Din;
 		elsif (add ='1') then
 			dReg <= std_logic_vector(unsigned(dReg)+ unsigned(Din) & error_flag ); -- Using flag & to be able to assign additional bit
 		elsif (complement='1') then
 			dReg <= not Din;

			--values of dreg and din are converted to unsigned type with unsigned() function.
			--the unsigned values are added
			--the result is converted to standard logic vector with std_logic_vector() function.
      end if;
		end if;
 	end if;
end Process;
Result <= dReg;
end a1;

Library IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.numeric_std.all;

Entity calculator_test is
end calculator_test;

Architecture test of calculator_test is 
component
Port ( clk : in std_logic; 				                      -- clock
	Clear, load, add, complement : in std_logic;		     -- operation signals
 	Din : in std_logic_vector (15 downto 0);	          -- input data
	Result : out std_logic_vector (15 downto 0));	     -- output data
End component;

signal clk_test : std_logic := '0';
signal Clear_test, load_test, add_test, complement_test : in std_logic;
signal Din_test, Result_test : std_logic_victor (15 downto 0); 

begin 
  UUT : calculator
  Port map ( clk => clk_test,
    Clear => Clear_test,
    load => load_test,
    add => add_test,
    complement => complement_test,
    Din => Din_test,
    Result => Result_test);
    
  Testbench_process : process
  begin
    wait for 0 ns; Clear_test <='1';
    assert (Result_test = others => '0') report "Fail Clear" severity error;
    wait for 10 ns; load_test <='1';
    assert (Result_test = Din_test) report "Fail Laod" severity error;
    wait for 10 ns; add_test <='1';
    assert (Result_test = "1XXXXXXXXXXXXXXXX") report "Fail Add" severity failure;
    wait for 10 ns; complement_test <='1';
    assert (Result_test = not Din_test) report "Fail Complement" severity error;
    wait for 10 ns;
  end process;
end test;

I must verify when detecting an error and the error bit is cleared when a clear operation is performed and that other operations are blocked when the error bit is set.

so does my code is ok?

And I have a problem with compiling, in line 48 ,near "Port": expecting IDENTIFIER.

5.png
 

This is the last part of this code I added 5 seven segments to my code :

Code:
Library IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.numeric_std.all;

Entity calculator is
Port ( 
  clk : in std_logic; 				                            -- clock
	Clear, load, add, complement : in std_logic;		      -- operation signals
 	Din : in std_logic_vector (15 downto 0);	           -- input data
	Result : out std_logic_vector (15 downto 0);	       -- output data
	segment1 : out std_logic_vector(6 downto 0);        -- 7 bit decoded output.
	segment2 : out std_logic_vector(6 downto 0);        -- 7 bit decoded output.
	segment3 : out std_logic_vector(6 downto 0);        -- 7 bit decoded output.
	segment4 : out std_logic_vector(6 downto 0);        -- 7 bit decoded output.
	segment5 : out std_logic_vector(6 downto 0));       -- 7 bit decoded output.
	
End calculator;

Architecture a1 of calculator is

component seg1
port (BCD1 : in std_logic_vector(3 downto 0));      -- BCD input
end component;

component seg2
port (BCD2 : in std_logic_vector(7 downto 4));      -- BCD input
end component;


component seg3
port (BCD3 : in std_logic_vector(11 downto 8));     -- BCD input 
end component;


component seg4
port (BCD4 : in std_logic_vector(15 downto 12));    -- BCD input
end component;

component seg5
port (BCD5 : in std_logic_vector(3 downto 0));      -- BCD input
end component;   


signal dReg : std_logic_vector (15 downto 0);         -- Difining signals to be used inside process
signal error_flag : std_logic := '0';                 -- dReg as a result, error_flag as a carry 
Signal final : std_logic_vector (15 downto 0);        -- final as a final result
signal BCD1 : std_logic_vector (3 downto 0);          -- Defining signal
signal BCD2 : std_logic_vector (3 downto 0);          -- Defining signal
signal BCD3 : std_logic_vector (3 downto 0);          -- Defining signal
signal BCD4 : std_logic_vector (3 downto 0);          -- Defining signal
signal BCD5 : std_logic_vector (3 downto 0);          -- Defining signal


Begin 
  
  Map1 : seg1 
  port map (BCD1 => Result(3 downto 0));              -- Interconnecting ports with signal 
  
  Map2 : seg2 
  port map (BCD2 => Result(7 downto 4));              -- Interconnecting ports with signal
    
  Map3 : seg3 
  port map (BCD3 => Result(11 downto 8));             -- Interconnecting ports with signal
   
  Map4 : seg4 
  port map (BCD4 => Result(15 downto 12));            -- Interconnecting ports with signal
  
  Map5 : seg5 
  port map (BCD5 => Result(16));                      -- Interconnecting ports with signal
  
  
  
Process (clk)                                         -- The first process to do the operations
Begin
	If (rising_edge (clk)) then
 		If (clear ='1') then                              -- if we perform a clean the result(dReg) 
      dReg <= "0000000000000000";error_flag <= '0';   -- and the carry(error_flag), whold be zeros
    elsif error_flag = '0' then
	  	if (load ='1') then
 			dReg <= Din;
 		elsif (add ='1') then
 			dReg <= std_logic_vector(unsigned(dReg)+ unsigned(Din) & error_flag ); -- Using flag & to be able to assign additional bit
 		elsif (complement='1') then
 			dReg <= not Din;

			--values of dreg and din are converted to unsigned type with unsigned() function.
			--the unsigned values are added
			--the result is converted to standard logic vector with std_logic_vector() function.
			
	case  error_flag  is                                -- This additional case is used to
    when '0' => final <= dReg;                        -- detect when the error_flag is zero
    when others => null;                              -- so there will be a result and in
  end case;                                           -- other case NULL
  
       end if;
 			end if;
		end if;
end Process; 

Result <= final;                                      -- The Final Result 

proc1 : process (clk,BCD1)
begin
if (clk'event and clk='1') then
  case  BCD1 is
when "0000"=> segment1 <="0000001";                   -- '0'
when "0001"=> segment1 <="1001111";                   -- '1'
when "0010"=> segment1 <="0010010";                   -- '2'
when "0011"=> segment1 <="0000110";                   -- '3'
when "0100"=> segment1 <="1001100";                   -- '4' 
when "0101"=> segment1 <="0100100";                   -- '5'
when "0110"=> segment1 <="0100000";                   -- '6'
when "0111"=> segment1 <="0001111";                   -- '7'
when "1000"=> segment1 <="0000000";                   -- '8'
when "1001"=> segment1 <="0000100";                   -- '9' 
when others=> segment1 <="1111010";                   -- Display 'r' in other cases.
  end case;
end if;
end process proc1;


proc2 : process (clk,BCD2)
begin
if (clk'event and clk='1') then
  case  BCD2 is
when "0000"=> segment2 <="0000001";                   -- '0'
when "0001"=> segment2 <="1001111";                   -- '1'
when "0010"=> segment2 <="0010010";                   -- '2'
when "0011"=> segment2 <="0000110";                   -- '3'
when "0100"=> segment2 <="1001100";                   -- '4' 
when "0101"=> segment2 <="0100100";                   -- '5'
when "0110"=> segment2 <="0100000";                   -- '6'
when "0111"=> segment2 <="0001111";                   -- '7'
when "1000"=> segment2 <="0000000";                   -- '8'
when "1001"=> segment2 <="0000100";                   -- '9'
when others=> segment2 <="1100010";                   -- Display 'o' in other cases.
  end case;
end if;
end process proc2;


proc3 : process (clk,BCD3)
begin
if (clk'event and clk='1') then
  case  BCD3 is
when "0000"=> segment3 <="0000001";                   -- '0'
when "0001"=> segment3 <="1001111";                   -- '1'
when "0010"=> segment3 <="0010010";                   -- '2'
when "0011"=> segment3 <="0000110";                   -- '3'
when "0100"=> segment3 <="1001100";                   -- '4' 
when "0101"=> segment3 <="0100100";                   -- '5'
when "0110"=> segment3 <="0100000";                   -- '6'
when "0111"=> segment3 <="0001111";                   -- '7'
when "1000"=> segment3 <="0000000";                   -- '8'
when "1001"=> segment3 <="0000100";                   -- '9' 
when others=> segment3 <="1111010";                   -- Display 'r' in other cases.
  end case;
end if;
end process proc3;


proc4 :process (clk,BCD4)
begin
if (clk'event and clk='1') then
  case  BCD4 is
when "0000"=> segment4 <="0000001";                   -- '0'
when "0001"=> segment4 <="1001111";                   -- '1'
when "0010"=> segment4 <="0010010";                   -- '2'
when "0011"=> segment4 <="0000110";                   -- '3'
when "0100"=> segment4 <="1001100";                   -- '4' 
when "0101"=> segment4 <="0100100";                   -- '5'
when "0110"=> segment4 <="0100000";                   -- '6'
when "0111"=> segment4 <="0001111";                   -- '7'
when "1000"=> segment4 <="0000000";                   -- '8'
when "1001"=> segment4 <="0000100";                   -- '9'
when others=> segment4 <="1111010";                   -- Display 'r' in other cases.
  end case;
end if;
end process proc4;


                                                 
proc5 : process (clk,BCD5)
begin                                                 -- This Segment will not Display
if (clk'event and clk='1') then                       -- any thing but 'E'
  case  BCD5 is
when "0000"=> segment5 <="0000001";                   -- '0'
when "0001"=> segment5 <="1001111";                   -- '1'
when "0010"=> segment5 <="0010010";                   -- '2'
when "0011"=> segment5 <="0000110";                   -- '3'
when "0100"=> segment5 <="1001100";                   -- '4' 
when "0101"=> segment5 <="0100100";                   -- '5'
when "0110"=> segment5 <="0100000";                   -- '6'
when "0111"=> segment5 <="0001111";                   -- '7'
when "1000"=> segment5 <="0000000";                   -- '8'
when "1001"=> segment5 <="0000100";                   -- '9' 
when others=> segment5 <="0110000";                   -- Display 'E' in other cases.
  end case;
end if;
end process proc5;

end a1;

And I have problem with compiling :
Cannot resolve indexed name (type ieee.std_logic_1164.STD_ULOGIC) as type ieee.std_logic_1164.STD_LOGIC_VECTOR.
Cannot read output "Result"

8.png
 

The first error is because seg5 expects 4 bits - you only connected a single bit.

Result is an output, so it cannot be read with '93 VHDL.
To fix this you either need to :
1. Switch to 2008 mode
2. Use an internal signal for result - you already have an internal signal called final, connect to this instead.
 
You defined Result as an OUT port, in VHDL 2008 OUT ports can be read, but in earlier versions of VHDL OUT ports can not be read.

Instead of using Result as the input to the instantiated components use the signal final instead, which is local to the architecture.
 
--edit: apparently I missed that this was 2 pages.
 

In the previous code and exactly at this part:

Code:
dReg <= std_logic_vector(unsigned(dReg)+ unsigned(Din) & error_flag ); -- Using flag & to be able to assign additional bit
 		elsif (complement='1') then
 			dReg <= not Din;

			--values of dreg and din are converted to unsigned type with unsigned() function.
			--the unsigned values are added
			--the result is converted to standard logic vector with std_logic_vector() function.
			
	case  error_flag  is                                -- This additional case is used to
    when '0' => final <= dReg;                        -- detect when the error_flag is zero
    when others => null;                              -- so there will be a result and in
  end case;                                           -- other case NULL

I am trying to add std_logic_vector with std_logic_vector and both have the same size, but in case I have "1111111111111111" + "1111111111111111" then i will got a carry

Do you have any idea how to declare this carry? I tried to declared it as (error_flag) as you can see in the code but i got a warning and this warning is preventing me from Synthesizing.
 

dReg has to be defined as 1-bit wider than the inputs to the + operation. The error_flag (overflow) is then just dReg[MSB].
e.g. for two 16-bit values added:
dReg(16 downto 0) <= a(15 downto 0) + b(15 downto 0);
error_flag <= dReg[16];

Also if you plan on adding stuff, then you probably should NOT be using std_logic_vector, but should be using the numeric_std (IEEE standard) with unsigned types instead.
 

dReg has to be defined as 1-bit wider than the inputs to the + operation. The error_flag (overflow) is then just dReg[MSB].
e.g. for two 16-bit values added:
dReg(16 downto 0) <= a(15 downto 0) + b(15 downto 0);
error_flag <= dReg[16];

Also if you plan on adding stuff, then you probably should NOT be using std_logic_vector, but should be using the numeric_std (IEEE standard) with unsigned types instead.

sorry, but It did not work I tried

Code:
signal dReg : std_logic_vector (16 downto 0);

			dReg <=  final +Din;           -- Using flag & to be able to assign additional bit
 		
     	case  dReg (16)  is                                -- This additional case is used to
        when '0' => final <= dReg (15 downto 0);          -- detect when the error_flag is zero
        when others => null;                              -- so there will be a result and in
      end case;                                           -- other case NULL

9.1.png

I got this erorrs:

No feasible entries for infix operator "+".
Type error resolving infix expression "+" as type ieee.std_logic_1164.STD_LOGIC_VECTOR.

and i tried this too

Code:
signal dReg : std_logic_vector (16 downto 0);

			dReg <= ('0' & final) + ('0' & Din) + error_flag;           -- Using flag & to be able to assign additional bit
 		
     	case  dReg (16)  is                                -- This additional case is used to
        when '0' => final <= dReg (15 downto 0);          -- detect when the error_flag is zero
        when others => null;                              -- so there will be a result and in
      end case;                                           -- other case NULL

And I got errors about the sum operation :

No feasible entries for infix operator "+".
Bad expression in left operand of infix expression "+".
Type error resolving infix expression "+" as type ieee.std_logic_1164.STD_LOGIC_VECTOR.

9.png
 

You left out all the type conversions you previously had. You are aware that VHDL is STRONGLY typed?

Note I'm lazy and am not going to add all the type garbage in my pseudo code. Either make all of your signals unsigned which numeric_std has + defined for, or continue to use std_logic_vector (which is not a number, it is a collection of bits) and suffer all the type conversions.
 
I tried
Code:
	dReg <= std_logic_vector(unsigned ( final) + unsigned (Din));

I cause a fatal erorr in simulation

then i tried

Code:
	dReg <= std_logic_vector(unsigned ('0' & final) + unsigned ('0' & Din));

It compiled perfectly without any warnings but the result in simulation is not ok
 

I tried
Code:
	dReg <= std_logic_vector(unsigned ( final) + unsigned (Din));

I cause a fatal erorr in simulation

then i tried

Code:
	dReg <= std_logic_vector(unsigned ('0' & final) + unsigned ('0' & Din));

It compiled perfectly without any warnings but the result in simulation is not ok

Sorry about that I forgot about the width expansion of the data being added to match the output width (I seldom have to code in VHDL, so I forget stuff like this).

What results are you getting? Unless there is something else I'm forgetting about, that code should add final and Din correctly and put the result in dReg. Can you post the result, simulation waveform, of the incorrect calculation being done?

- - - Updated - - -

Wait it just dawned on me you have TWO threads on the same design. Besides confusing things this is against forum policies.

Your error in the add result is probably due to the bad testbench design, that I've been telling you to fix.

- - - Updated - - -

Just took another look at the waveform in your other thread the update to U at 30 ns is because the operation for add is immediately applied, but the assignment to final hasn't occurred as you haven't reached the end of the process, where the scheduling of assignments occurs. Basically more failures due to the bad assignments being done in the testbench.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top