VHDL, process not updating variable's value, implementing a Merge Sort - process

I am trying to implement an example of Merge Sort algorithm on VHDL in order to sort 4 128bit numbers.
I am using sequential code. I have a process on which I make comparisons. The process consists of 3 phases which implement the logic behind Merge Sort.
The problem is that I am using a variable count : integer which counts clock cycles. I want the phases to follow clock cycles.
It seems like the simulation enters the first IF statement (of Phase 1) but does not enter the others so I guess count variable does not update its value.
I have tried several changes but seems like I am missing something here.
I know the post is a little big, I would appreciate any help! Thanks!
entity Merge_Sort is
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
en : in STD_LOGIC;
In_a : in STD_LOGIC_VECTOR(15 downto 0 ) ;
In_b : in STD_LOGIC_VECTOR(15 downto 0 ) ;
In_c : in STD_LOGIC_VECTOR(15 downto 0 ) ;
In_d : in STD_LOGIC_VECTOR(15 downto 0 ) ;
Sorted_a : out STD_LOGIC_VECTOR(15 downto 0 ) ;
Sorted_b : out STD_LOGIC_VECTOR(15 downto 0 ) ;
Sorted_c : out STD_LOGIC_VECTOR(15 downto 0 ) ;
Sorted_d : out STD_LOGIC_VECTOR(15 downto 0 ) );
end Merge_Sort;
architecture Behavioral of Merge_Sort is
signal temp1a,temp1b,temp1c,temp1d : STD_LOGIC_VECTOR(15 downto 0 ) ;
TYPE arr2 IS ARRAY (0 to 1 ) of STD_LOGIC_VECTOR(15 downto 0) ;
TYPE arr4 IS ARRAY (0 to 3 ) of STD_LOGIC_VECTOR(15 downto 0) ;
signal Array1 , Array2 : arr2 ;
signal mergedArr : arr4 ;
signal temp : std_logic_vector(15 downto 0 ) ;
begin
temp1a <= (others =>'0' ) WHEN reset ='1' else -- Asychronous Resetting
In_a ;
temp1b <= (others =>'0' ) WHEN reset ='1' else
In_b ;
temp1c <= (others =>'0' ) WHEN reset ='1' else -- Asychronous Resetting
In_c ;
temp1d <= (others =>'0' ) WHEN reset ='1' else
In_d ;
Sorted_a <= MergedArr(0) ;
Sorted_b <= MergedArr(1) ;
Sorted_c <= MergedArr(2) ;
Sorted_d <= MergedArr(3) ;
Sort: PROCESS(clk)
variable count : integer range 0 to 3 ;
BEGIN
if(reset ='1' ) then count := 0 ;
end if ;
IF ( clk'EVENT AND clk='1' ) then -- Conditions for process to run
IF (en ='1') then
IF(count =0) THEN -- Phase 1 of sort
if (temp1a<temp1b ) then Array1(0)<=temp1a ; Array1(1) <= temp1b ;
else Array1(1)<=temp1a ; Array1(0) <= temp1b ;
end if ;
if (temp1c<temp1d ) then Array2(0)<=temp1c ;Array2(1) <= temp1d ;
else Array2(1)<=temp1c ; Array2(0) <= temp1d ;
end if ;
count := count +1 ;
END IF ;
IF( count = 1) THEN -- Phase 2 of sort , computing min and max of array
if ( Array1(1) < Array2(1) ) then MergedArr(1) <= Array1(1) ; MergedArr(3) <= Array2(1) ;
else MergedArr(3) <= Array1(1) ; MergedArr(1) <= Array2(1) ;
end if ;
if ( Array1(0) < Array2(0) ) then MergedArr(0) <= Array1(0) ; MergedArr(2) <= Array2(0) ;
else MergedArr(2) <= Array1(0) ; MergedArr(0) <= Array2(0) ;
end if ;
count:= count +1 ;
END IF ;
IF(count =2 ) THEN -- Phase 3 of sort , FINAL
if ( MergedArr(1) > MergedArr(2) ) then
temp<= MergedArr(2 ) ;
MergedArr(2) <= MergedArr(1) ;
MergedArr(1) <= temp ;
end if ;
END IF ;
END IF;
END IF ;
END PROCESS ;
end Behavioral;

The variable count is updated immediately inside each IF condition. So, for example, inside the IF(count=0), it is incremented to 1. Then it reaches the IF(count=1) statement, which will of course already be true.
I think really all you need to do is change it to IF ... ELSIF statements:
IF(count =0) THEN -- Phase 1 of sort
...
ELSIF( count = 1) THEN -- Phase 2 of sort , computing min and max of array
...
ELSIF(count =2 ) THEN -- Phase 3 of sort , FINAL
and I think it will work exactly as you expect.

Related

VHDL output module to input in another module

I am new to VHDL and i am trying to implement CMOS CD4543 into FPGA basys 3 ,
and i am stuck because i wrote 2 modules and the output remains U and this output is supposed to be input in the second module. I've made testbenches for both of them and separatly they are working corect. I will put the code here to see what is wrong. Thanks!
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity latch is
Port ( datain : in STD_LOGIC_VECTOR (3 downto 0);
load : in STD_LOGIC;
data_out : out STD_LOGIC_VECTOR(3 downto 0));
end latch;
architecture Behavioral of latch is
signal data : std_logic_vector (3 downto 0);
Begin
data <= datain when (load = '1') else data;
data_out <= data;
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity to7segments is
Port ( datain : in STD_LOGIC_VECTOR (3 downto 0);
bl :in std_logic;
ph :in std_logic;
seg : out STD_LOGIC_VECTOR (6 downto 0);
an : out STD_LOGIC_VECTOR (3 downto 0));
end to7segments;
architecture behavioral of to7segments is
signal data: std_logic_vector(3 downto 0);
Begin
an<="1110";
decoder: process(bl,ph)
begin
if bl= '0' then
if ph ='1' then
data <= not(datain);
end if;
data<=datain;
case data is
when "0000" => seg <="0000001" ;
when "0001" => seg <= "1001111" ;
when "0010" => seg <= "0010010" ;
when "0011" => seg <= "0000110" ;
when "0100" => seg <= "1001100" ;
when "0101" => seg <= "0100100" ;
when "0110" => seg <= "0100000" ;
when "0111" => seg <= "0001111" ;
when "1000" => seg <= "0000000" ;
when "1001" => seg <= "0000100" ;
when "1010" => seg <= "0001000" ;
when "1011" => seg <= "1100000" ;
when "1100" => seg <= "0110001" ;
when "1101" => seg <= "1000010" ;
when "1110" => seg <= "0110000" ;
when "1111" => seg <= "0111000" ;
when others => seg <= "1111111" ;
end case;
elsif bl='1' then
seg<="1111111";
end if;
end process decoder;
end behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity top is
Port ( load : in STD_LOGIC;
ph : in STD_LOGIC;
bl : in STD_LOGIC;
datain :in std_logic_vector( 3 downto 0);
seg : out STD_LOGIC_VECTOR (6 downto 0);
an : out STD_LOGIC_VECTOR (3 downto 0));
end top;
architecture behavioral of top is
component latch PORT ( datain : in STD_LOGIC_VECTOR (3 downto 0);
load : in STD_LOGIC;
data_out : out STD_LOGIC_VECTOR(3 downto 0));
end component;
component to7segments PORT ( datain : inout STD_LOGIC_VECTOR (3 downto 0);
bl :in std_logic;
ph :in std_logic;
seg : out STD_LOGIC_VECTOR (6 downto 0);
an : out STD_LOGIC_VECTOR (3 downto 0));
end component;
signal datain2 : std_logic_vector(3 downto 0);
begin
latch1: latch PORT MAP(datain=>datain,
load =>load,
data_out=>datain2);
decoder: to7segments PORT MAP(datain=>datain2,
bl=>bl,
ph=>ph,
seg=>seg,
an=>an);
end behavioral;

VHDL - Three layers of processes but no output from a logic unit in simulation

My lab partner and I can't figure out why we're not getting any output in our waveform simulation of this component. We simulated the component by itself and obtained the expected behavior, but nested inside the entity, the output signal was not being initialized and only had uninitialized 'X' response.
This is the component declaration in the top level entity:
99 component CH is
100 Port ( clk : in std_logic;
101 X : in std_logic_vector(31 downto 0);
102 Y : in std_logic_vector(31 downto 0);
103 Z : in std_logic_vector(31 downto 0);
104 CH_OUT : out std_logic_vector(31 downto 0)
105 );
106 end component;
This is the process we use to assign input/output:
289 round_compute2 : process (clk, CH_OUT_sig, e_sig, f_sig, g_sig, T1_sig)
290 begin
291 CH_X_in <= e_sig;
292 CH_Y_in <= f_sig;
293 CH_Z_in <= g_sig;
294 T1_sig <= std_logic_vector(unsigned(CH_OUT_sig));
295 end process;
This is the code for the CH component
1 library IEEE;
2 use IEEE.STD_LOGIC_1164.ALL;
3 use IEEE.STD_LOGIC_ARITH.ALL;
4 use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
6 -- CH is defined as (X AND Y) XOR (X' AND Z)
7 -- Verified working
8
9 entity CH is
10 Port ( clk : in std_logic;
11 X : in std_logic_vector(31 downto 0);
12 Y : in std_logic_vector(31 downto 0);
13 Z : in std_logic_vector(31 downto 0);
14 CH_OUT : out std_logic_vector(31 downto 0)
15 );
16 end CH;
17
18 architecture Behavioral of CH is
19
20 begin
21
22 Compute : process (clk, X, Y, Z)
23 begin
24
25 CH_OUT <= (X and Y) xor ((not X) and Z);
26
27 end process;
28
29 end Behavioral;
These questions are similar, but do not address the issue in this post because-
VHDL component and outputs based on generic
- Does not involve processes
Simple VHDL Problem with synchronous/asynchronous logic
- Does not involve components and signals that are assigned from the system to the component
Why doesn't my code produce output?
- Our code has the correct sensitivity list, I think
You should look through your tool's output for warnings. It sounds like you have an unbound component CH.
With:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- 3 use IEEE.STD_LOGIC_ARITH.ALL;
-- 4 use IEEE.STD_LOGIC_UNSIGNED.ALL;
-- CH is defined as (X AND Y) XOR (X' AND Z)
-- Verified working
entity CH is
Port ( clk : in std_logic;
X : in std_logic_vector(31 downto 0);
Y : in std_logic_vector(31 downto 0);
Z : in std_logic_vector(31 downto 0);
CH_OUT : out std_logic_vector(31 downto 0)
);
end CH;
architecture Behavioral of CH is
begin
Compute : process (clk, X, Y, Z)
begin
CH_OUT <= (X and Y) xor ((not X) and Z);
end process;
end Behavioral;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ch_comp is
end entity;
architecture foo of ch_comp is
component CH is
Port ( clk : in std_logic;
X : in std_logic_vector(31 downto 0);
Y : in std_logic_vector(31 downto 0);
Z : in std_logic_vector(31 downto 0);
CH_OUT : out std_logic_vector(31 downto 0)
);
end component;
signal CH_X_in: std_logic_vector(31 downto 0);
signal CH_Y_in: std_logic_vector(31 downto 0);
signal CH_Z_in: std_logic_vector(31 downto 0);
signal CH_OUT_sig: std_logic_vector(31 downto 0);
signal e_sig: std_logic_vector(31 downto 0) := X"feedface";
signal f_sig: std_logic_vector(31 downto 0) := X"deadbeef";
signal g_sig: std_logic_vector(31 downto 0) := X"ffffffff";
signal T1_sig: std_logic_vector(31 downto 0);
signal clk: std_logic := '0';
begin
round_compute2 : process (clk, CH_OUT_sig, e_sig, f_sig, g_sig) --, T1_sig)
begin
CH_X_in <= e_sig;
CH_Y_in <= f_sig;
CH_Z_in <= g_sig;
T1_sig <= std_logic_vector(unsigned(CH_OUT_sig));
end process;
UUT:
CH
port map (
clk => clk,
X => CH_X_in,
Y => CH_Y_in,
Z => CH_Z_in,
CH_OUT => CH_OUT_sig
);
TEST:
process
begin
wait for 10 ns;
e_sig <= X"deadface";
f_sig <= X"facebeef";
g_sig <= X"EEEEFFFF";
wait for 10 ns;
wait;
end process;
end architecture;
I got:
Which is to say, it appears not to exhibit only uninitialized 'X's on CH_out_sig or T1_sig.
And it would appear you haven't revealed either enough or your VHDL design description or enough of the tool build and simulation process for a third party to see where you went wrong.

I'm having problems implementing Verilog Test Fixture to simulate my design

I'm a beginner at vhdl and I'm trying to make a 8 bit divider using shift and subtract method. The code for the divider is okay, I guess, but I'm having problems in simulating the inputs. When I use the Verilog test fixture, my inputs which should be (dividend=51 [00110011b], divisor=19 [00010011b]) always end up becoming (dividend=49 [00110001b], divisor=49 [00110001b])) in iSim, and then the outputs (Quotient and remainder = xxxxxxx (unknown)) instead of (quotient=2[00000010b] and remainder=13 [00001101b])...
As I mentioned before, I'm a beginner at vhdl and I've been at this for five hours, I've tried my best to search for a solution online, but failed.... so any help or alternative solution would be greatly appreciated.
I'm using Xilinx ISE 14.3 and iSim.
Here is the code for the 8 bit binary divider.
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
use IEEE.STD_LOGIC_ARITH.all;
entity division is
generic(SIZE: INTEGER := 8);
port(reset: in STD_LOGIC; --reset
en: in STD_LOGIC; --enable
clk: in STD_LOGIC; --clock
num: in STD_LOGIC_VECTOR((SIZE - 1) downto 0); --dividend
den: in STD_LOGIC_VECTOR((SIZE - 1) downto 0); --divisor
res: out STD_LOGIC_VECTOR((SIZE - 1) downto 0); --result/quotient
rm: out STD_LOGIC_VECTOR((SIZE - 1) downto 0) --remainder
);
end division;
architecture behav of division is
signal bufreg: STD_LOGIC_VECTOR((2 * SIZE - 1) downto 0); --signal array to hold both accumulator and dividend registers as one i.e bufreg(18 bits)
signal dbuf: STD_LOGIC_VECTOR((SIZE - 1) downto 0); --signal array to hold the divisor
signal count: INTEGER range 0 to SIZE; --count to determine when to stop
alias ADreg is bufreg((2 * SIZE - 1) downto SIZE); --ADreg is is alias for top half of bufreg register(17th to 9th bit)
alias DVNDreg is bufreg((SIZE - 1) downto 0); --DVNDreg is is alias for bottom half of bufreg register(8th to 0th bit)
begin
--our process begins here
p_001: process(reset, en, clk)
begin
if reset = '1' then
res <= (others => '0');
rm <= (others => '0');
count <= 0;
elsif rising_edge(clk) then
if en = '1' then
case count is
when 0 =>
ADreg <= (others => '0');
DVNDreg <= num;
dbuf <= den;
res <= DVNDreg;
rm <= ADreg;
count <= count + 1;
when others =>
if bufreg((2 * SIZE - 2) downto (SIZE - 1)) >= dbuf then
ADreg <= '0' & (bufreg((2 * SIZE - 3) downto (SIZE - 1)) - dbuf((SIZE - 2) downto 0));
DVNDreg <= DVNDreg ((SIZE - 2) downto 0) & '1';
else
bufreg <= bufreg((2 * SIZE - 2) downto 0) & '0';
end if;
if count /= SIZE then
count <= count + 1;
else
count <= 0;
end if;
end case;
end if;
end if;
end process;
end behav;
And here is the code for the Verilog test fixture (.v file):
module BINdivisionTEST;
// Inputs
reg reset;
reg en;
reg clk;
reg [7:0] num ;
reg [7:0] den ;
// Outputs
wire [7:0] res;
wire [7:0] rm;
// Instantiate the Unit Under Test (UUT)
division uut (
.reset(reset),
.en(en),
.clk(clk),
.num(num),
.den(den),
.res(res),
.rm(rm)
);
initial begin
// Initialize Inputs
reset = 0;
en = 0;
clk = 0;
//num = 0;
//den = 0;
// Wait 100 ns for global reset to finish
#100;
en = 1;
#100;
clk=1;
num <= "00110011" ;
den <= "00010011" ;
// Add stimulus here
end
endmodule
My biggest problems seem to be initialization of the inputs and probably some mistaken assignments, misuse of the test fixture file and some bad coding.
I should also add that the divider code was compiled in vhdl, ISE 14.3.
I'm extremely sorry if this has been answered before and I don't mean to piss anyone off by uploading bad and amateur code. If this kind of problem has been addressed before could you please provide me with a link.
Again, any help is greatly appreciated.
The simulator may be treating those as strings instead of numbers. Try changing:
num <= "00110011" ;
den <= "00010011" ;
to:
num <= 8'b00110011;
den <= 8'b00010011;
I'm no expert on Verilog but it looks as if you might not be asserting Reset to your VHDL component before testing it.
That would lead "Count" in an uninitialised state so that when you use it, anything could happen and the "XXXX" outputs are a reflection of that.
The reset sequence should look like
En <= '0';
Clk <= '0';
Reset <= '1';
wait for 100 ns;
Reset <= '0';
wait for 100 ns;
-- start testing here
(in VHDL of course ... but it'll translate to Verilog easily)

VHDL state machine outputs not in sync

This a general FPGA design question, I'm kind of new to FPGA design and have just embarked on my first large scale project, building some nice linear algebra solvers. The systems are pretty large so getting it right first time is important.
After successful simulations I am now sythensizing, but am having a nightmare, I am having to build and test it component by component as nothing behaves as it does in simulation! I'm mainly having issues with state machines where outputs are not being synchronized for example this is a data loader i'm using:
entity TriDiag_Data_Scheduler is
generic( W : integer :=16;
AW : integer := 10 -- address width
);
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC; --attatched to data finished
d_ready : in STD_LOGIC;
din : in STD_LOGIC_VECTOR (W-1 downto 0);
wr_en : out STD_LOGIC_VECTOR (3 downto 0);
dout_a, dout_b, dout_c, dout_y : out STD_LOGIC_VECTOR (W-1 downto 0);
addr_out : out STD_LOGIC_VECTOR (AW-1 downto 0));
end TriDiag_Data_Scheduler;
architecture Behavioral of TriDiag_Data_Scheduler is
type state is (a,b,c,y);
signal state_pr, state_next : state := y;
signal addr_reg, addr_next : std_logic_vector(AW-1 downto 0) :=(others =>'1');
signal wr_en_next : std_logic_vector(3 downto 0);
--data buffer
signal d_buff, d_buff_a, d_buff_b, d_buff_c, d_buff_y : std_logic_vector (W-1 downto 0) :=(others =>'0');
signal d_buff_a_reg, d_buff_b_reg, d_buff_c_reg, d_buff_y_reg : std_logic_vector (W-1 downto 0) :=(others =>'0');
begin
process(clk,rst)
begin
if(clk'event and clk ='1') then
state_pr <= state_next;
d_buff_a <= d_buff_a_reg;
d_buff_b <= d_buff_b_reg;
d_buff_c <= d_buff_c_reg;
d_buff_y <= d_buff_y_reg;
addr_reg <= addr_next;
wr_en <= wr_en_next;
end if;
end process;
addr_out <= addr_reg;
dout_a <= d_buff_a;
dout_b <= d_buff_b;
dout_c <= d_buff_c;
dout_y <= d_buff_y;
--Data out logic
process(state_pr, d_buff_a, d_buff_b, d_buff_c, d_buff_y, d_buff)
begin
d_buff_a_reg <= d_buff_a;
d_buff_b_reg <= d_buff_b;
d_buff_c_reg <= d_buff_c;
d_buff_y_reg <= d_buff_y;
case state_pr is
when a => --move data to a reg
d_buff_a_reg <= d_buff;
when b => --move data to b reg
d_buff_b_reg <= d_buff;
when c => --move data to c reg
d_buff_c_reg <= d_buff;
when y =>
d_buff_y_reg <= d_buff;
end case;
end process;
--next state and addr logic
process(state_pr, d_ready, rst, din)
begin
state_next <= state_pr;
addr_next <= addr_reg;
wr_en_next <= (others => '0');
if(rst = '1') then
state_next <= a;
addr_next <= (others =>'1');
wr_en_next <= (others => '0');
elsif(d_ready = '1') then
--Read in the data to the buffer
d_buff <= din;
--next state logic
case state_pr is
when a => --move data to a reg
addr_next <= addr_reg + 1;
-- d_buff_a_reg <= din;
wr_en_next <= "0001";
state_next <= b;
when b => --move data to b reg
wr_en_next <= "0010";
-- d_buff_b_reg <= din;
state_next <= c;
when c => --move data to c reg
wr_en_next <= "0100";
-- d_buff_c_reg <= din;
state_next <= y;
when y =>
-- d_buff_y_reg <= din;
wr_en_next <= "1000";
state_next <= a;
end case;
end if;
end process;
end Behavioral;
Basically when data is received via a UART module its job is to then load into the correct memory (controlled by write_en signal). The issue is that in all my designs (this is revision 7) all addr_out, wr_en and the correct data are in syn, but in synthesis I keep finding that the addr and wr_en are not in syn with the data and reads half from the preceding and half from the previous state.
What design practices should I use so that my VHDL is more syntheziable friendly because at this rate I will have to re-write all my previous hard-work for each component!
Many thanks
Sam
Working design, the old design was suffering from skew between the d_ready signal asserted from another module and this modules clk. As such the changes where not being synced as first hoped. To fixed this I but in the d_tick_next signal which asserts a locally sync signal d_tick which allowed all the correct behavior. One lesson learnt (correct me if i'm wrong) is that you can't rely on supposed externally clocked signals (such as d_ready) to be in sync with the receiving modules clk.
library IEEE;
use IEEE.STD_LOGIC_1164.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;
-- ////////////////////////////////////////////////////////////////////
--Takes in the linear stream of data and builds up the memory structure
--INPUT DATA MUST FOLLOW SEQUENCE [a b c] x = [y] (0 if a or c do not exist) rows 0 and N respectivly
--//////////////////////////////////////////////////////////////////////
entity TriDiag_Data_Scheduler is
generic( W : integer :=16;
AW : integer := 10 -- address width
);
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC; --attatched to data finished
d_ready : in STD_LOGIC;
din : in STD_LOGIC_VECTOR (W-1 downto 0);
wr_en : out STD_LOGIC_VECTOR (3 downto 0);
dout_a, dout_b, dout_c, dout_y : out STD_LOGIC_VECTOR (W-1 downto 0);
addr_out : out STD_LOGIC_VECTOR (AW-1 downto 0));
end TriDiag_Data_Scheduler;
architecture Behavioral of TriDiag_Data_Scheduler is
type state is (a,b,c,y);
signal state_pr, state_next : state := y;
signal addr_reg, addr_next : std_logic_vector(AW-1 downto 0) :=(others =>'1');
signal wr_en_next : std_logic_vector(3 downto 0);
signal d_tick, d_tick_next : std_logic;
--data buffer
signal d_buff, d_buff_a, d_buff_b, d_buff_c, d_buff_y : std_logic_vector (W-1 downto 0) :=(others =>'0');
signal d_buff_a_reg, d_buff_b_reg, d_buff_c_reg, d_buff_y_reg : std_logic_vector (W-1 downto 0) :=(others =>'0');
begin
process(clk,rst)
begin
if(clk'event and clk ='1') then
state_pr <= state_next;
d_buff_a <= d_buff_a_reg;
d_buff_b <= d_buff_b_reg;
d_buff_c <= d_buff_c_reg;
d_buff_y <= d_buff_y_reg;
d_tick <= d_tick_next;
addr_reg <= addr_next;
wr_en <= wr_en_next;
end if;
end process;
addr_out <= addr_reg;
dout_a <= d_buff_a;
dout_b <= d_buff_b;
dout_c <= d_buff_c;
dout_y <= d_buff_y;
--Data out logic
process(state_pr,d_tick,rst)
begin
d_buff_a_reg <= d_buff_a;
d_buff_b_reg <= d_buff_b;
d_buff_c_reg <= d_buff_c;
d_buff_y_reg <= d_buff_y;
wr_en_next <= (others => '0');
if(rst = '1') then
addr_next <= (others =>'1');
else
addr_next <= addr_reg;
end if;
if(d_tick = '1') then
case state_pr is
when a => --move data to a reg
d_buff_a_reg <= d_buff;
addr_next <= addr_reg + 1;
wr_en_next <= "0001";
when b => --move data to b reg
d_buff_b_reg <= d_buff;
wr_en_next <= "0010";
when c => --move data to c reg
d_buff_c_reg <= d_buff;
wr_en_next <= "0100";
when y =>
d_buff_y_reg <= d_buff;
wr_en_next <= "1000";
end case;
end if;
end process;
--next state and d_tick
process(state_pr, d_ready, rst, din)
begin
state_next <= state_pr;
d_tick_next <='0';
if(rst = '1') then
state_next <= y;
elsif(d_ready = '1') then
--Read in the data to the buffer
d_buff <= din;
-- set sync tick
d_tick_next <= '1';
--next state logic
case state_pr is
when a =>
state_next <= b;
when b =>
state_next <= c;
when c =>
state_next <= y;
when y =>
state_next <= a;
end case;
end if;
end process;
end Behavioral;

Subprocedure call in VHDL

I have two nested procedures, where the "main" procedure
makes use of "subproc" to accumulates a result in variables
t0 and t1, which is then returned at the end. This should all
be computed in one clock cycle, and the circuit more or less
just consists of simple logic gates (xor, or, and). When I try
to describe the circuit as below I get the following error:
Acutal (variable t0) for formal "a" is not a signal
That makes sense as the subprocure requires signals as input,
but I wanna pass it a variable during the main procedure. Is
there a simple way to circumvent this problem with casting for
example?
Thanks
procedure subproc
(
signal a : in std_logic_vector(31 downto 0);
signal b : in std_logic_vector(31 downto 0);
signal c : in std_logic_vector(31 downto 0);
signal d : in std_logic_vector(31 downto 0);
signal e : out std_logic_vector(31 downto 0);
signal f : out std_logic_vector(31 downto 0)
)
is
variable x : std_logic_vector(31 downto 0);
variable y : std_logic_vector(31 downto 0);
begin
x := (others => '0');
y := (others => '0');
for i in 0 to 31 loop
x(i) := (a(i) xor b(i)) and (c(i) xor d(i));
y(i) := (a(i) xor b(i)) or ((d(i) xor c(i)) xor b(i));
end loop;
e <= x(31 downto 0);
f <= y(31 downto 0);
end;
procedure main
(
signal a : in std_logic_vector(31 downto 0);
signal b : in std_logic_vector(31 downto 0);
signal r : out std_logic_vector(31 downto 0)
)
is
variable res : std_logic_vector(31 downto 0);
variable t0, t1 : std_logic_vector(31 downto 0);
constant c : std_logic_vector(31 downto 0) := X"fedcba90";
constant d : std_logic_vector(31 downto 0) := X"7654321f";
begin
t0 := (others => '0');
t1 := (others => '0');
for i in 0 to 31 loop
if ( (c(i) = '0') && (d(i) = '1') ) then
subproc( t0, t1,
a, b, t0, t1 );
end if;
end loop;
r <= t0;
end;
First off, your "if" clause is written in C-style. You want to say:
if (c(i) = '0') and (d(i) = '1') then
But the problem really is that you describe the procedure as taking SIGNALs as arguments. If you want the results to be assigned to variables, you need to declare a different procedure signature:
procedure subproc (
signal a : in std_logic_vector(31 downto 0);
signal b : in std_logic_vector(31 downto 0);
signal c : in std_logic_vector(31 downto 0);
signal d : in std_logic_vector(31 downto 0);
variable e : out std_logic_vector(31 downto 0);
variable f : out std_logic_vector(31 downto 0))
But then, you also need to change all assignments to e and f, so that they are variable assignments:
e := x(31 downto 0);
Why don't you just define the subproc parameters as variables instead of signals?