I have multiple VHDL code coming from separate sources, and I want to combine them to make a single system.
My understanding is that I have to extract entities and architectures that I'm interested in from each code then I make a new entity that combines them and same for architecture.
I'm missing the next steps in how to use these in the process.
It would be nice to get some tips and tricks from you guys on how to do it correctly and avoid the mistakes that a newbie in VHDL like me will probably do.
The figure summarizes what I have and what I need.
Multiple VHDL to one
Regards
The example can be if you have two modules, the mdl_sub sub-module:
library ieee;
use ieee.std_logic_1164.all;
entity mdl_sub is
generic(
A_L : natural;
Z_L : natural);
port(
clk_i : in std_logic;
rst_i : in std_logic;
a_i : in std_logic_vector(A_L - 1 downto 0);
z_o : out std_logic_vector(Z_L - 1 downto 0));
end entity;
library ieee;
use ieee.numeric_std.all;
architecture syn of mdl_sub is
signal z : std_logic_vector(z_o'range);
begin
process (clk_i, rst_i) is
begin
-- Clock
if rising_edge(clk_i) then
z <= std_logic_vector(unsigned(z) + unsigned(a_i));
end if;
-- Reset
if rst_i = '1' then
z <= (others => '0');
end if;
end process;
-- Drive output
z_o <= z;
end architecture;
and the mdl_top top-module:
library ieee;
use ieee.std_logic_1164.all;
entity mdl_top is
generic(
M0_A_L : natural := 8;
M0_Z_L : natural := 8;
M1_A_L : natural := 4;
M1_Z_L : natural := 4);
port(
clk_i : in std_logic;
rst_i : in std_logic;
m0_a_i : in std_logic_vector(M0_A_L - 1 downto 0);
m0_z_o : out std_logic_vector(M0_Z_L - 1 downto 0);
m1_a_i : in std_logic_vector(M1_A_L - 1 downto 0);
m1_z_o : out std_logic_vector(M1_Z_L - 1 downto 0));
end entity;
library ieee;
use ieee.numeric_std.all;
architecture syn of mdl_top is
begin
-- Sub-module 0
mdl_sub_0 : entity work.mdl_sub
generic map(
A_L => M0_A_L,
Z_L => M0_Z_L)
port map(
clk_i => clk_i,
rst_i => rst_i,
a_i => m0_a_i,
z_o => m0_z_o);
-- Sub-module 1
mdl_sub_1 : entity work.mdl_sub
generic map(
A_L => M1_A_L,
Z_L => M1_Z_L)
port map(
clk_i => clk_i,
rst_i => rst_i,
a_i => m1_a_i,
z_o => m1_z_o);
end architecture;
then the two files with the modules can be compiled separately, and the mdl_sub is then integrated into mdl_top, as Brian Drummond describes.
Sorry for the longer modules, but I had those readily available as examples ;-)
Related
I'm trying to implement a MOD-5 counter in VHDL and I've tried using the following steps:
I created a GENERIC N bit counter
Then I instantiated a 3 bit counter
Using the 3 bit counter as a COMPONENT I reset the Count to 0 when it reaches 4
I've tested it and it's not working, the Count signal stays Undefined for the whole simulation. Can anyone solve this problem?
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
ENTITY counter_n_bit IS
GENERIC(
N : INTEGER);
PORT(
Clock : IN STD_LOGIC;
Enable : IN STD_LOGIC;
-- Clear is a synchronous reset
Clear : IN STD_LOGIC;
Count : BUFFER UNSIGNED(N - 1 DOWNTO 0)
);
END counter_n_bit;
ARCHITECTURE behaviour OF counter_n_bit IS
BEGIN
PROCESS(Clock)
BEGIN
-- since this is a synchronous circuit, signal should
-- only change on clock's edges. I chose rising edges.
IF Clock'EVENT AND Clock = '1' THEN
-- if clear is set to 1, no matter the other signals, the counter resets
-- same if it got to the max integer that can be represented on N bits (2^N - 1)
IF Clear = '1' OR Count = 2**N - 1 THEN
Count <= (OTHERS => '0');
ELSE
-- if none of this condtions are satisfied we're in the regular case
-- and I update the Count value incrementing it by one
IF Enable = '1' THEN
Count <= Count + 1;
END IF;
END IF;
END IF;
END PROCESS;
END behaviour;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
ENTITY counter_3_bit IS
PORT(
Clock : IN STD_LOGIC;
Enable : IN STD_LOGIC;
Clear : IN STD_LOGIC;
Count : OUT UNSIGNED(2 DOWNTO 0)
);
END counter_3_bit;
ARCHITECTURE behaviour OF counter_3_bit IS
COMPONENT counter_n_bit
GENERIC(
N : INTEGER);
PORT(
Clock : IN STD_LOGIC;
Enable : IN STD_LOGIC;
Clear : IN STD_LOGIC;
Count : OUT UNSIGNED(N - 1 DOWNTO 0)
);
END COMPONENT;
BEGIN
-- instantiation of a 3 bit counter
counter_3: counter_n_bit GENERIC MAP (N => 3) PORT MAP (Clock => Clock, Enable => Enable, Clear => Clear, Count => Count);
END behaviour;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
ENTITY counter_3_bit_5 IS
PORT(
Clock : IN STD_LOGIC;
Enable : IN STD_LOGIC;
Clear : IN STD_LOGIC;
Count : BUFFER UNSIGNED(2 DOWNTO 0)
);
END counter_3_bit_5;
ARCHITECTURE behaviour OF counter_3_bit_5 IS
COMPONENT counter_3_bit
PORT(
Clock : IN STD_LOGIC;
Enable : IN STD_LOGIC;
Clear : IN STD_LOGIC;
Count : OUT UNSIGNED(2 DOWNTO 0)
);
END COMPONENT;
BEGIN
-- instantiation of a 3 bit counter
counter_3: counter_3_bit PORT MAP (Clock => Clock, Enable => Enable, Clear => Clear, Count => Count);
PROCESS (Count)
BEGIN
IF Count = "100" THEN
Count <= "000";
END IF;
END PROCESS;
END behaviour;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
ENTITY tb_counter_3_bit_5 IS
END tb_counter_3_bit_5;
ARCHITECTURE behaviour OF tb_counter_3_bit_5 IS
COMPONENT counter_3_bit_5
PORT(
Clock : IN STD_LOGIC;
Enable : IN STD_LOGIC;
Clear : IN STD_LOGIC;
Count : BUFFER UNSIGNED(2 DOWNTO 0)
);
END COMPONENT;
SIGNAL Clock_tb, Clear_tb, Enable_tb : STD_LOGIC;
SIGNAL Count_tb : UNSIGNED(2 DOWNTO 0);
BEGIN
Clear_tb <= '1', '0' AFTER 6 ns;
Enable_tb <= '1';
clk_process: PROCESS
BEGIN
Clock_tb <= '0';
WAIT FOR 5 ns;
Clock_tb <= NOT Clock_tb;
WAIT FOR 5 ns;
END PROCESS;
-- instantiation of a 3 bit counter
dut: counter_3_bit_5 PORT MAP (Clock => Clock_tb, Enable => Enable_tb, Clear => Clear_tb, Count => Count_tb);
END behaviour;
this is my first time working in VHDL, and I was wondering why I am getting an error of "gt1 is not compiled in library 'xil_defaultlib', and 'gt is not declared' in struc_arch. The purpose of the code is to basically have a 2 bit comparator that will output 1 if a is greater than b.
architecture struc_arch of gt2 is
signal g1 : std_logic;
begin
gt_bit0_unit : entity work.gt0(sop_arch)
port map(
i0 => a(1),
i1 => b(0),
gt => g0
);
agtb <= gt;
end struc_arch;
And the code of the sop_arch that is referenced:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity gt2 is
port (a,b : in std_logic_vector(1 downto 0);
agtb : out std_logic);
end gt2;
architecture sop_arch of gt2 is
begin
agtb <= '1' when (a>b) else
'0';
end sop_arch;
I'm reasonably new to vhdl and wondering what the best way is to manage the following situation / pattern:
Say I have an entity A whose architecture instantiates a component B. I would then like to reuse A but this time instantiate a component C in the place of B. C has a completely different functionality to B. B and C may have different sized ports, however the functionality of A is such that it can handle the different port sizes, using, say, generics and generate statements. Essentially A is like a container for either component B, C or maybe D, E, F etc. It maybe performs some logic/buffering on the inputs and outputs of B, C etc. in a way that is common for all these components.
I have read about configurations and my understanding is that I can instantiate a component in A (call it Z), and then link it's entity to different architectures using configurations. It seems not many people use this feature of vhdl.
Are configurations the right way to go for this situation?
Ideally, I would like all of the parameters in the design to depend ultimately on the architecture chosen for Z so that the architecture dictates the port sizes of the entity its linked to (Z), and in turn the port sizes of Z dictate the parameters of A and finally these parameters dictate the port sizes of A. Is this possible?
(I am using 'parameterisation' in the general sense to mean a way of configuring a design. Generics, packages, 'range attributes etc would all be examples of parameterisation)
A pseudocode example of what I mean is below. The values in capitals should depend on the architecture chosen for Z.
entity A is
port
(
clk : in std_logic;
reset : in std_logic;
inputs : in std_logic_vector(SOME_WIDTH_A_IN - 1 downto 0);
outputs : out std_logic_vector(SOME_WIDTH_A_OUT - 1 downto 0);
);
end A;
architecture A_arch of A is
component Z
port
(
clock : in std_logic;
inputs : std_logic_vector(SOME_WIDTH_Z_IN - 1 downto 0);
ouputs : std_logic_vector(SOME_WIDTH_Z_OUT - 1 downto 0)
);
end component;
begin
for i in 1 to SOME_VALUE generate
-- whatever logic/buffering we want to perform on the inputs
end generate;
for i in 1 to SOME_VALUE generate
-- whatever logic/buffering we want to perform on the outputs
end generate;
instance: Z
port map(
clock => clk,
inputs => --output of logic/buffering above
outputs => -- input of logic/buffering above
);
end A_arch;
I may be thinking about this the wrong way - Essentially I would like to avoid having to copy/paste the 'container' entity A to work with different components B, C etc. What is the best way to do this?
It seems that you want your components B,C,D, etc... to do exactly the same except for different port sizes. The best approach to do this is with GENERIC. Let's say your other entity (let's call it INNER_ENTITY) is configurable n-bit wide double flip flop (can be used to resolve metastability).
Here is the example code for OUTER_ENTITY and INNER_ENTITY:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity OUTER_ENTITY is
port (
CLK : in std_logic;
RST : in std_logic;
PORT_A : in std_logic_vector(6 downto 0);
PORT_B : in std_logic_vector(13 downto 0);
SUM_A_B : out std_logic_vector(13 downto 0)
);
end entity;
architecture RTL_OUTER_ENTITY of OUTER_ENTITY is
signal PORT_A_INNER : std_logic_vector(6 downto 0);
signal PORT_B_INNER : std_logic_vector(13 downto 0);
component INNER_ENTITY
generic (PORT_SIZE : integer);
port (
CLK : in std_logic;
RST : in std_logic;
PORT_IN : in std_logic_vector(PORT_SIZE - 1 downto 0);
PORT_OUT : out std_logic_vector(PORT_SIZE - 1 downto 0);
);
end component INNER_ENTITY;
begin
SUM_A_B <= PORT_A_INNER + PORT_B_INNER;
INNER_7_BIT : INNER_ENTITY
generic map (PORT_SIZE => 7)
port map (
CLK => CLK,
RST => RST,
PORT_IN => PORT_A,
PORT_OUT => PORT_A_INNER
);
INNER_14_BIT : INNER_ENTITY
generic map (PORT_SIZE => 14)
port map (
CLK => CLK,
RST => RST,
PORT_IN => PORT_B,
PORT_OUT => PORT_B_INNER
);
end RTL_OUTER_ENTITY;
entity INNER_ENTITY
generic (PORT_SIZE : integer);
port (
CLK : in std_logic;
RST : in std_logic;
PORT_IN : in std_logic_vector(PORT_SIZE - 1 downto 0);
PORT_OUT : out std_logic_vector(PORT_SIZE - 1 downto 0);
);
end entity;
architecture RTL_INNER_ENTITY of INNER_ENTITY is
signal PORT_X : std_logic_vector(PORT_SIZE - 1 downto 0);
begin
process(CLK, RST)
begin
if RST = '1' then
PORT_OUT <= (OTHERS => '0');
PORT_X <= (OTHERS => '0');
elsif rising_edge(CLK) then
PORT_OUT <= PORT_X;
PORT_X <= PORT_IN;
end if;
end process;
end RTL_INNER_ENTITY;
Please note that I did not compile this code so it might have some minor syntax errors but it should give you an overview to how GENERICs might be used to do what you want.
my vhdl code is as follows:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
ENTITY pc IS PORT(
d : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
clk : IN STD_LOGIC; -- clock.
q : OUT STD_LOGIC_VECTOR(31 DOWNTO 0) -- output
);
END pc;
ARCHITECTURE description OF pc IS
BEGIN
process(clk)
begin
if rising_edge(clk) then
q <= d;
else
q <= x"00000000";
end if;
end process;
END description;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity ins_memory is
port( inp1 : in std_logic_vector(31 downto 0);
oup1 : out std_logic_vector (4 downto 0);
clk : in std_logic);
end ins_memory;
architecture behv1 of ins_memory is
type ROM_Array is array (0 to 14)
of std_logic_vector(4 downto 0);
constant Content: ROM_Array := (
0 => "00001",
-- Suppose ROM has
1 => "00010",
-- prestored value
2 => "00011",
-- like this table
3 => "00100",
--
4 => "00101",
--
5 => "00110",
--
6 => "00111",
--
7 => "01000",
--
8 => "01001",
--
9 => "01010",
--
10 => "01011",
--
11 => "01100",
--
12 => "01101",
--
13 => "01110",
--
14 => "01111",
--
OTHERS => "11111"
--
);
component pc IS PORT(
d : IN STD_LOGIC_VECTOR(31 DOWNTO 0) :=x"00000000";
clk : IN STD_LOGIC; -- clock.
q : OUT STD_LOGIC_VECTOR(31 DOWNTO 0)
);
END component;
begin
D1: pc port map(q=> inp1,clk=>clk,d=>open);
process(inp1,clk)
begin
oup1<= Content (conv_integer(inp1));
end process;
end behv1;
basically, I trying to connect 'signal q' which is output of entity pc with 'signal inp1' which is input of entity ins_memory, but I am getting following error when I tried it in simple way
D1: pc port map(q=> inp1,clk=>clk,d=>open);
Updating port BEHV1:INP1 of mode IN is not allowed.
Please verify the port mapping for correctness.
The inp1 port is the input of the top level entity (memory), and you are trying to connect it to the output of the internal component (pc). So it is going to be driven from two directions - from outside of the top-level module, and by this internal component. Which is obviously illegal.
I am just trying to make a simple two's complement device in VHDL but it is throwing back this really annoying error and I'm unsure what I have done wrong. Probably something very silly...The error is
"Error (10327): VHDL error at twocompliment.vhd(21): can't determine definition of operator ""nand"" -- found 0 possible definitions"
The code is
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity twoscompliment is
generic
(
Nbits : positive := 8
);
port
(
--Inputs
A : in std_logic_vector (Nbits-1 downto 0);
--Outputs
Y : out std_logic_vector (Nbits downto 0)
);
end twoscompliment;
architecture twoscompliment_v1 of twoscompliment is
begin
Y <= std_logic_vector(unsigned(A NAND '1') + '1');
end twoscompliment_v1;
Any help would be awesome!
It seems to me you are trying to negate the input number... Maybe I'm missing something vital, but the other answers give a solution which, whilst achieving the goal, appear to be one step more obfuscated than they need to be.
Barring the ugly conversions, what's wrong with
y <= std_logic_vector(-signed(resize(unsigned(A)), y'length));
Of course, I would argue that if A and Y are supposed to be representing signed numbers (or unsigned numbers), they should be expressed as such:
library ieee;
use ieee.numeric_std.all;
entity twoscomplement is
generic
(
Nbits : positive := 8
);
port
(
A : in unsigned (Nbits-1 downto 0);
Y : out signed (Nbits downto 0)
);
end entity twoscomplement;
architecture a1 of twoscomplement is
begin
Y <= -signed(resize(A, Y'length));
end architecture;
Let's check the results:
entity test_twoscomplement is
end entity;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
architecture test of test_twoscomplement is
signal A : unsigned (7 downto 0);
signal Y : signed(8 downto 0);
begin
dut : entity work.twoscomplement port map (A => A, Y=>Y);
process
begin
for i in 0 to 255 loop
A <= to_unsigned(i, A'length);
wait for 1 ns;
assert to_integer(Y) = -i severity error;
end loop;
report "tests done";
wait;
end process;
end architecture;
Running with GHDL:
$ ghdl -a twoscomp.vhd
$ ghdl --elab-run test_twoscomplement
twoscomp.vhd:40:8:#256ns:(report note): tests done
Success!
Try this:
architecture twoscompliment_v1 of twoscompliment is
signal temp : std_logic_vector(Nbits-1 downto 0);
begin
temp <= not A;
Y <= std_logic_vector(unsigned(temp + 1));
end twoscompliment_v1;
architecture twoscompliment_v1 of twoscompliment is
constant ONE: UNSIGNED(Y'RANGE) := (0 => '1', others => '0');
begin
Y <= std_logic_vector(unsigned (not A) + ONE);
end twoscompliment_v1;
Hi gentleman basically 2's complement is done by inverting the binary bits of a
given no. i.e changing ones to zeroes and zeroes to ones, after that add the
binary bit '1' to the Least significant bit of the given binary number. Now I
have a program
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity twoscomplementconversion is Port (
bin : in STD_LOGIC_VECTOR (3 downto 0);
twos : out STD_LOGIC_VECTOR (3 downto 0)
);
end twoscomplementconversion;
architecture Behavioral of twoscomplementconversion is
component fourbitadder45 Port (
a : in std_logic_vector (3 downto 0);
b : in std_logic_vector(3 downto 0);
cin : in std_logic;
cout : out std_logic;
sum : out std_logic_vector (3 downto 0)
);
end component;
signal onebit : std_logic_vector(3 downto 0):="0001";
signal cin1 : std_logic:='0';
signal notbin : std_logic_vector(3 downto 0);
signal cout1 : std_logic;
begin
notbin <= not(bin);
twos1: fourbitadder45 port map (
a => notbin,
b => onebit,
cin => cin1,
cout => cout1,
sum => twos
);
end Behavioral;
The four bit adder program is given below:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity fourbitadder45 is Port (
a : in std_logic_vector (3 downto 0);
b : in std_logic_vector(3 downto 0);
cin : in std_logic;
cout : out std_logic;
sum : out std_logic_vector (3 downto 0)
);
end fourbitadder45;
architecture Behavioral of fourbitadder45 is
component fulladder2 Port (
a : in std_logic;
b : in std_logic;
cin : in std_logic;
cout : out std_logic;
sum : out std_logic
);
end component;
signal c:std_logic_vector (3 downto 1);
begin
fa1 :fulladder2 port map (a => a(0), b => b(0), cin => cin, cout => c(1), sum => sum(0));
fa2 :fulladder2 port map (a => a(1), b => b(1), cin => c(1), cout => c(2), sum => sum(1));
fa3 :fulladder2 port map (a => a(2), b => b(2), cin => c(2), cout => c(3), sum => sum(2));
fa4 :fulladder2 port map (a => a(3), b => b(3), cin => c(3), cout => cout, sum => sum(3));
end Behavioral;
four bit adder contains 4 full adders so the full adder program is given below:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity fulladder2 is Port (
a : in std_logic;
b : in std_logic;
cin : in std_logic;
cout : out std_logic;
sum : out std_logic
);
end fulladder2;
architecture Behavioral of fulladder2 is
begin
sum <= a xor b xor cin;
cout <= ((a and b) or (b and cin) or (cin and a));
end Behavioral;
I hope that answers the question. This is a method there are many different methods