Swap elements in an array - VHDL - arrays

I have a piece of code in VHDL:
I want to swap the signalIn(0) and signalIn(1) values.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity SwapFP is
port(clockIn:in std_logic);
end SwapFP;
architecture Behavioral of SwapFP is
signal tempOne,tempTwo,a1,a2 : STD_LOGIC_VECTOR(31 DOWNTO 0);
signal state : integer range 0 to 7 := 0;
begin
process(clockIn) is
type floatingPointArray is array(1 downto 0) of std_logic_vector(31 downto 0);
variable signalIn : floatingPointArray;
begin
signalIn(0) := X"3D52CEF8";
signalIn(1) := X"3FBC9F1A";
if rising_edge(clockIn) then
case state is
when 0 =>
tempOne <= signalIn(0);
tempTwo <= signalIn(1);
state <= 1;
when 1 =>
signalIn(1) := tempOne;
signalIn(0) := tempTwo;
state <= 2;
when 2 =>
a1 <= signalIn(0);
a2 <= signalIn(1);
state <= 3;
when others =>
end case;
end if;
end process;
end Behavioral;
In a1 and a2 signals, I am getting the original values X"3D52CEF8" and X"3FBC9F1A" respectively. Means that swapping is not happening. Why is it so?

Your variable assignments to signalIn at the top of the process happen every time the process runs. When state is 2, the values you assigned to signalIn when state equaled 1 are overwritten by this initial assignment.
You can much more easily swap two items like this:
process (clk)
begin
if (rising_edge(clk)) then
signalIn(0) <= signalIn(1);
signalIn(1) <= signalIn(0);
end if;
end process;
This works because the signal assignments using <= do not take place immediately, rather they are scheduled to take place after the process has run.

Related

Assigning to record type arrays in generate statements

How do you use record arrays in generate statements in VHDL? Below is what I have done, which passes synthesis and implementation in Vivado (2021.1). However, when I simulate it, it shows none of the record signals getting assigned and are always "U". I can also not find any examples of record fields used in port maps in generate statements.
type record_a_t is record
a : std_logic;
b : std_logic_vector(7 downto 0);
c : std_logic_vector(3 downto 0);
d : std_logic;
e : std_logic;
end record record_a_t;
type record_a_array_t is array (0 to 3) of record_a_t;
signal record_a_array : record_a_array_t;
Then, I generate the modules with signal mapping like:
GEN_MODULES : for i in 0 to 3 generate
modules : entity work.module
port map(
clk => clk,
rst_n => rst_n,
a => record_a_array(i).a,
b => record_a_array(i).b,
c => record_a_array(i).c,
d => record_a_array(i).d,
e => record_a_array(i).e
);
end generate GEN_MODULES;
Again, the above seems to pass all the tools syntax checking and builds in Vivado, but simulation (RivPro 2018) and implementation show signals not getting assigned or changing. They are always "U", even if driven from the module. For example, if port a is an output that is initialized in the module, record_a_array(i).c is always "U". Even the module output port is "U", as if the internal initialization is ignored, which makes no sense to me.
Below is an example.
Test Module:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity module is
port(
clk : in std_logic;
rst_n : in std_logic;
a : in std_logic;
b : out std_logic_vector(7 downto 0);
c : out std_logic_vector(3 downto 0);
d : out std_logic;
e : out std_logic
);
end module;
architecture rtl of module is
begin
process(clk, rst_n)
begin
if(rst_n = '0') then
b <= (others=> '0');
c <= (others=> '0');
d <= '0';
e <= '0';
elsif(rising_edge(clk)) then
if(a = '1') then
b <= b + '1';
c <= c + '1';
d <= not d;
e <= not e;
end if;
end if;
end process;
end rtl;
Test Bench:
library ieee;
use ieee.std_logic_1164.all;
entity testbench is
end entity testbench;
---------------------------------------------------
architecture arch of testbench is
---------------------------------------------------
type record_a_t is record
a : std_logic;
b : std_logic_vector(7 downto 0);
c : std_logic_vector(3 downto 0);
d : std_logic;
e : std_logic;
end record record_a_t;
type record_a_array_t is array (0 to 3) of record_a_t;
signal record_a_array : record_a_array_t;
signal clk : std_logic := '1';
signal rst_n : std_logic := '0';
---------------------------------------------------
begin
clk <= not clk after 5 ns;
rst_n <= '1' after 20 ns;
GEN_MODULES : for i in 0 to 3 generate
modules : entity work.module
port map(
clk => clk,
rst_n => rst_n,
a => record_a_array(i).a,
b => record_a_array(i).b,
c => record_a_array(i).c,
d => record_a_array(i).d,
e => record_a_array(i).e
);
end generate GEN_MODULES;
process(clk, rst_n)
begin
if(rst_n = '0') then
for i in 0 to 3 loop
record_a_array(i).a <= '0';
end loop;
elsif(rising_edge(clk)) then
for i in 0 to 3 loop
record_a_array(i).a <= not record_a_array(i).a;
end loop;
end if;
end process;
end arch;
Simulation:
Simulation of module example
Notice how the record signals wired to the module outputs in at the TestBench level are never defined and how the outputs of the generated module instances themselves are not driven, even though they all get asserted in the reset condition. The only signal that gets driven is the 'a' signal from the test bench level.
Since the record is not crossing into the RTL space, unwanted drivers can be turned off using std_logic using 'Z':
constant REC_INIT : record_a_t := (
a => 'Z',
b => "ZZZZZZZZ",
c => "ZZZZ",
d => 'Z',
e => 'Z'
) ;
. . .
signal record_a_array : record_a_array_t := (0 to 3 => REC_INIT) ;
As you start to look at the issue in the LRM, you might also note you can find the issues the IEEE VHDL working group has recorded at: : https://gitlab.com/IEEE-P1076/VHDL-Issues/-/issues. There is a remotely related issue in https://gitlab.com/IEEE-P1076/VHDL-Issues/-/issues/275 that may be able to address both its issue and this one - though time will tell on that.
For verification, I use Open Source VHDL Verification Methodology (OSVVM). We use records on ports and as a result, use special resolution functions with them so they do not require initialization.

Modelsim. Length of arrays do not match

I have written a program in modelsim that add to numbers and put the result in Ra/Sum. I have used a tristate buffer, but I get this: Fatal: (vsim-3420) Array lengths do not match. Left is 16 (15 downto 0). Right is 8 (7 downto 0). I understand that this is because they have different lengths. But they cant have the same length either, because then I get an error when adding add1 and add2 and putting them in Sum. So what can I do to make this work?
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.numeric_std.all;
entity MAC is
generic (width: integer := 8);
port(
clk, reset : in STD_LOGIC;
MLS_select : in STD_LOGIC;
Rn, Rm, Ra : in STD_LOGIC_VECTOR(width-1 downto 0);
Rd : out STD_LOGIC_VECTOR(width-1 downto 0)
);
end;
architecture behavioral of MAC is
signal mul1, mul2, add1 : UNSIGNED(width-1 downto 0);
signal add2, sum : UNSIGNED(width*2-1 downto 0);
begin
process(clk, reset)
begin
if reset = '1' then Rd <= (others => '0');
elsif rising_edge(clk) then
Rd <= STD_LOGIC_VECTOR(sum(width-1 downto 0));
end if;
end process;
mul1 <= UNSIGNED(Rn);
mul2 <= UNSIGNED(Rm);
add1 <= UNSIGNED(Ra);
add2 <= mul1*mul2;
sum <= add2 when clk = '1' else add2;
sum <= add1+add2;
end architecture;
At first, ... when clk = '1' else ... will create a latch, but no flip-flop.
You need to use ... when rising_edge(clk);.
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity MAC is
generic (width: integer := 8);
port(
clk, reset : in STD_LOGIC;
MLS_select : in std_logic;
Rn, Rm, Ra : in std_logic_vector(width - 1 downto 0);
Rd : out std_logic_vector(width - 1 downto 0) := (others => '0')
);
end entity;
architecture rtl of MAC is
signal mul1, mul2, add1 : unsigned(width - 1 downto 0);
signal add2, sum : unsigned(width * 2 - 1 downto 0);
begin
process(clk, reset)
begin
if (reset = '1') then
Rd <= (others => '0');
elsif rising_edge(clk) then
Rd <= std_logic_vector(sum(Rd'range));
end if;
end process;
mul1 <= unsigned(Rn);
mul2 <= unsigned(Rm);
add1 <= unsigned(Ra);
add2 <= (mul1 * mul2) when rising_edge(clk);
sum <= resize(add1, add'length) + add2;
end architecture;
Signal MLS_select is unused. There is no need to calculate the sum with so many bits. I suggest to truncate add2 before the addition, to reduce the number of unused bits (and warnings generated by them).

BCD Timer in VHDL

Just started out in VHDL not long ago,out of curiosity.
So I was trying to write BCD timer on spartan 3 board and
Somehow I couldn't find out why it keeps showing 'unexpected with' error.
So if I want to have such function as shown in the link of picture,
how can I modify the code?any help would be grateful.
(clickable)
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity w3 is
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC;
stp : in STD_LOGIC;
an : out STD_LOGIC_VECTOR (3 downto 0);
c : out STD_LOGIC_VECTOR (6 downto 0));
end w3;
architecture timer of w3 is
signal div1 : integer range 0 to 499999 :=0; -- 100Hz
signal ck100hz : std_logic; -- 100Hz output
signal div2 : integer range 0 to 249999 :=0; -- 200Hz
signal ck200hz : std_logic; -- 200Hz output
signal div3 : integer range 0 to 124999 :=0; -- 400Hz
signal ck400hz : std_logic; -- 400Hz output
signal index : integer range 0 to 9 :=0;
signal scan : std_logic_vector (3 downto 0);
signal S : std_logic;
signal disp : std_logic_vector (3 downto 0);
begin
process begin
wait until rising_edge(clk);
if div1 < 499999 then
ck100hz <= '0';
div1 <= div1+1;
else
ck100hz <= '1';
div1 <= 0;
end if;
if div2 < 249999 then
ck200hz <= '0';
div2 <= div2+1;
else
ck200hz <= '1';
div2 <= 0;
end if;
if div3 < 124999 then
ck400hz <= '0';
div3 <= div3+1;
else
ck400hz <= '1';
div3 <= 0;
end if;
end process;
process begin
wait until rising_edge(clk);
if rst = '1' then
index <= 0;
end if;
if stp = '1' then
index <= index;
end if;
if ck100hz = '1' then
if index < 3 then index <= index+1;
else index <= 0;
if index < 4 and index > 7 then index <= index+1;
else index <= 0;
if index < 8 and index > 11 then index <= index+1;
else index <= 0;
if index < 12 and index > 15 then index <= index+1;
else index <= 0;
end if;
end if;
end if;
end if;
end if;
end process;
process begin
wait until rising_edge(clk);
if ck400hz = '1' then
With scan select -- error unexpected With
an <= an(0) when "00",
an(1) when "01",
an(2) when "10",
an(3) when others;
end if;
end process;
process begin
wait until rising_edge(clk);
if ck200hz = '1' then
With S select -- error unexpected With
disp <= index integer range 0 to 3 when "00",
index integer range 4 to 7 when "01",
index integer range 8 to 11 when "10",
index integer range 12 to 15 when others;
end if;
end process;
with index select
C <= "1000000" when 0,
"1111001" when 1,
"0100100" when 2,
"0110000" when 3,
"0011001" when 4,
"0010010" when 5,
"0000010" when 6,
"1111000" when 7,
"0000000" when 8,
"0011000" when 9;
end timer;
For low-active:
You should assign 0111111 to C in case of index = 0. You have to enable almost all segments. Now your internal calculation would be high-active. The display itself is low-active, because of the PCB layout, thus you should invert the whole C vector before assigning it to a Cathode_n port: Cathode_n <= not C; Note, I used _n to designate the low-active behavior of this port.
Old code:
with index select
C <= "1000000" when 0,
"1111001" when 1,
-- ...
"0011000" when 9;
This should be the goal when writing purely high-active code:
with index select
C <= "0111111" when 0,
"0000110" when 1,
-- ...
"1100111" when 9;
Cathode_n <= not C;
High-active means: If a bit is high (1) then a thing is active. In your case an LED of a 7-segment display is activated. Based on the PCB design, you have to drive low (0) to activate a light. This is low-active, because a low value activates something.
The select statement needs to assign the position to 1 that should be enlightened, not the positions to turn off. More over low-active signals should be marked in to code to denote there different behavior. Only a top-level component should translate high-active signals to low-active signals and vice versa. This ensures, the inner parts of your design are purely high-active.
For no driver:
There is no assignment to S and scan. Both signals are 'U' or "UUUU", respectively.
Edit:
Each signal assignment creates a driver on a signal. Currently, your code never assigns any value to S nor scan. Thus the initial values of S and scan become the driving value of the signals. You should run a simulation und see a lot of Us in your waveform.
Synthesis tools might report: Signal S is read, but never assigned.
For using elsif:
I reformatted you horrible if-then-else construct:
if ck100hz = '1' then
if index < 3 then
index <= index+1;
else
index <= 0;
if index < 4 and index > 7 then
index <= index+1;
else
index <= 0;
if index < 8 and index > 11 then
index <= index+1;
else
index <= 0;
if index < 12 and index > 15 then
index <= index+1;
else
index <= 0;
end if;
end if;
end if;
end if;
end if;
Now we see, you code can not use elsif, because you have assignments in the else branch before the next if statement. On the otherhand, the index <= 0; assignment is redundant and can be removed:
if ck100hz = '1' then
if index < 3 then
index <= index+1;
else
if index < 4 and index > 7 then
index <= index+1;
else
if index < 8 and index > 11 then
index <= index+1;
else
if index < 12 and index > 15 then
index <= index+1;
else
index <= 0;
end if;
end if;
end if;
end if;
end if;
Now we can transform it to use elsif branches:
if ck100hz = '1' then
if index < 3 then
index <= index + 1;
elsif index < 4 and index > 7 then
index <= index + 1;
elsif index < 8 and index > 11 then
index <= index + 1;
elsif index < 12 and index > 15 then
index <= index+1;
else
index <= 0;
end if;
end if;
Much more readable, right?
Next, lets check your expressions in that statement:
elsif index < 4 and index > 7 then
index cannot be less than 4 and greater than 7 at the same time. So lets play synthesis and optimized away unreachable branches:
if ck100hz = '1' then
if index < 3 then
index <= index + 1;
else
index <= 0;
end if;
end if;
Ok, other problems in the code:
if rst = '1' then
index <= 0;
end if;
if stp = '1' then
index <= index;
end if;
if ck100hz = '1' then
-- ...
end if;
Reset should always have highest priority. In your case, e.g. stp has higher priority. In a good case you're only wasting FPGA resources, in a bad case synthesis can not translate your code to primitives in the FPGA. E.g. flip-flops with matching reset behavior.
Correct implementation:
if rst = '1' then
index <= 0;
elsif stp = '1' then
index <= index;
elsif ck100hz = '1' then
-- ...
end if;
I think for now, you have enough input to fix your code.

VHDL: Multiple for loop serial execution

I might be new to synthesizing loops. I am trying to create a counting sort in VHDL which takes arbitary length(say N) of integer array as input for sorting.
The code for design heavily relies on for loop. The looping logic seems to be parallel within a process or may be across processes. So I put all of the for loop in one process. But with that, the loops seem to execute in parallel independently. Which defeats the purpose as one loop should follow the other.
I have used counting sort algorithm from https://www.geeksforgeeks.org/counting-sort/
I am unable to get the logic working as mentioned in the algorithm.
Q1: How does the for loop execute within a process. Does all the for loop execute in parallel.
Q2:Is there an alternate way of implementing this for loop logic in VHDL, so that it executes serially?
Q3:Are there limitations for synthesizing for loops?
Design code:
library ieee;
use ieee.std_logic_1164.all;
package sorting_pkg is
type intarray is array(natural range <>) of std_logic_vector(7 downto 0);
end package;
library ieee;
use ieee.std_logic_1164.all;
use work.sorting_pkg.all;
use IEEE.NUMERIC_STD.all;
use ieee.std_logic_unsigned.all;
entity Sorting is
generic (
N : integer );
port(
--clk : in STD_LOGIC;
rst : in STD_LOGIC;
inStream : in intarray(0 to N-1);
outStream : out intarray(0 to N-1);
BoutArray: out intarray(0 to 16);
CoutArray: out intarray(0 to 16)
);
end entity;
architecture behavior of Sorting is
signal BArray: intarray(0 to 16) := (others => "00000000");
signal CArray: intarray(0 to 16) := (others => "00000000");
signal DArray: intarray(0 to 16) := (others => "00000000");
--signal Aindex1,Aindex2,Cindex,k: std_logic_vector(7 downto 0);
--signal Aindex1,Aindex2,Cindex,k : natural range 0 to 16;
begin
process
begin
if(rst = '1') then
outStream <=(others => "00000000");
else
Bloop: for i in 0 to N-1 loop
BArray(to_integer(unsigned(inStream(i)))) <=BArray(to_integer(unsigned(inStream(i)))) + 1;
end loop;
CArray(0) <= BArray(0);
Cloop: for j in 1 to 16 loop
CArray(j) <= BArray(j) + CArray(j - 1);
end loop;
Coutloop:for l in 0 to N-1 loop
DArray(to_integer(unsigned(inStream(l)))) <= CArray(to_integer(unsigned(inStream(l)))) - 1;
end loop;
outloop:for m in 0 to N-1 loop
outStream(to_integer(unsigned(DArray(to_integer(unsigned(inStream(m))))))) <= inStream(m);
end loop;
BoutArray <= BArray;
CoutArray <= DArray;
end if;
wait;
end process;--end proc
end architecture;
Testbench code:
library ieee;
use ieee.std_logic_1164.all;
library work;
use work.sorting_pkg.all;
use IEEE.NUMERIC_STD.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 leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity tb_camera is
-- Port ( );
end tb_camera;
architecture Behavioral of tb_camera is
component Sorting
generic (
N : integer := 10);
PORT
(--clk: in std_logic;
rst : in std_logic;
inStream : in intarray(0 to 9);
outStream : out intarray(0 to 9);
BoutArray: out intarray(0 to 16);
CoutArray: out intarray(0 to 16)
);
end component;
signal A : intarray(0 to 9);
signal D : intarray(0 to 9);
signal rst_tb : std_logic;
-- signal clk_tb : std_logic;
signal BoutArray : intarray(0 to 16);
signal CoutArray : intarray(0 to 16);
--constant clk_period : time :=500ns;
begin
uut:Sorting port map (inStream => A, outStream => D, rst => rst_tb,
BoutArray => BoutArray, CoutArray=> CoutArray );
sim_tb:process
begin
wait for 100ns;
rst_tb<='1';
wait for 100ns;
rst_tb<='0';
--wait for 50ns;
A(0 to 9) <= (0 => x"07",
1 => x"09",
2 => x"06",
3 => x"02",
4 => x"05",
5 => x"00",
6 => x"08",
7 => x"01",
8 => x"03",
9 => x"04");
wait;
end process;
end Behavioral;

Sum of Array elements VHDL

I am new to VHDL and I searched all of the internet and i didnt find anything that would help me !
I am trying to add the elements of an array (32 Elements !), so i cant just write
for example s <= s(0) + s(1) + s(3) ... s(5) + ....s(32)
how can i generalise such a calculation ??
or what am i doing wrong ?
My Code (that didnt work in the simulation) is ..
(just for 5 elemets ....)
library IEEE;
library work;
library std;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
use ieee.std_logic_arith.all;
entity main is Port (
EIN : in std_logic;
AUS_1 : out std_logic_vector(3 downto 0));
end main;
architecture Behaviour of main is
type Cosinus is array (0 to 4) of std_logic_vector(3 downto 0);
type Sinus is array (0 to 4) of std_logic_vector(3 downto 0);
Signal SumSin :std_logic_vector(3 downto 0);
begin
main : process(Ein)
variable Cos : Cosinus;
variable Sin : Sinus;
begin
if( Ein='1' ) then
sin(0) := "0011";
sin(1) := "0001";
sin(2) := "1010";
sin(3) := "1111";
sin(4) := "1110";
for n in 0 to 4 loop
SumSin <= SumSin + Sin(n);
end loop;
else
sin(0) := "1011";
sin(1) := "0101";
sin(2) := "1000";
sin(3) := "1001";
sin(4) := "1100";
for n in 0 to 4 loop
SumSin <= SumSin + Sin(n);
end loop;
end if;
end process;
Aus_1 <= SumSin;
end Behaviour;
I would be thanksfull
First... Don't use std_logic_arith.
Then, Use a variable for the running sum and assign is to a signal afterwards:
...
main : process(Ein)
variable Cos : Cosinus;
variable Sin : Sinus;
variable SumSin : signed(3 downto 0);
begin
sumsin := (others => '0');
....
for n in Sin'range loop
SumSin := SumSin + Sin(n);
end loop;
end if;
Aus_1 <= SumSin;
end process;

Resources