Read VHDL data from another architecture - vhdl

I need to read data from a defined VHDL (.vhd) file. The file is like this:
entity ROM is
port ( address : in std_logic_vector(3 downto 0);
data : out std_logic_vector(7 downto 0) );
end entity ROM;
architecture behavioral of ROM is
type ROM is array ( 0 to 2**4 - 1) of std_logic_vector(7 downto 0);
constant my_ROM : ROM := (
0 => "00000000",
1 => "00000001");
begin
data <= my_ROM(to_integer(unsigned(address)));
end architecture behavioral;
I know similar question has been posted, How to read data from rom_type in VHDL?, but I think I still need help on it. Let's say I have another .vhd file, how should I get the data stored inside this ROM entity?

You need to define an address and data signal to connect to the ROM entity in this architecture. For example;
signal rom_address : std_logic_vector(3 downto 0);
signal rom_data : std_logic_vector(7 downto 0);
Then you can add the following instantiation to your architecture.
somelabel : entity work.ROM
port map (
address => rom_address,
data => rom_data
);
You need to drive the rom_address signal to get the data from the corresponding addresses in your ROM.
What you could also do is declare this entity as a component in a package or in the architecture from which are going to instantiate it.
The component declaration looks like this;
component ROM is
port (
address : in std_logic_vector(3 downto 0);
data : out std_logic_vector(7 downto 0)
);
end component;
This allows you to instantiate this entity as a component in your architecture.
somelabel : ROM
port map (
address => rom_address,
data => rom_data
);

Related

VHDL: When can ports be used as signals?

Please help me understand when ports can be used as signals in VHDL.
I am asking this question because I am using ports to move data from one component to another in Xilinx ISim, but the data remains undefined at it's destination. My problems could be caused if I am inferring data transfer by wiring port to port as in my first and third examples below without an explicity assignment statement.
I believe this is valid use of a ports from the entity as a signals wired to the ports of an included component.
-- Example 1 - Use ports instead of signals
entity user is
port(
data_bus : inout std_logic_vector(15 downto 0);
address_bus: in std_logic_vector(12 downto 0)
);
end user;
architecture Behavioral of user is
-- Component Port Definitions
component memory
port(
mem_data_bus : inout std_logic_vector(15 downto 0);
mem_address_bus: in std_logic_vector(12 downto 0)
);
end component memory;
begin
-- some logic
-- Instantiate thing
a_memory : memory
port map(
mem_data_bus => data_bus,
mem_address_bus => address_bus
);
end architecture;
I am not sure this is valid. Are extra signals required to wire components together or can the entity ports be used? (I realise there could be a problem joining to inout ports together, but this question is about when ports can be used as signals).
-- Example 2 - connect ports to multiple components
entity user is
port(
data_bus : inout std_logic_vector(15 downto 0);
address_bus: in std_logic_vector(12 downto 0)
);
end entity user;
architecture Behavioral of user is
-- Component Port Definitions
component memory_a
port(
ma_data_bus : inout std_logic_vector(15 downto 0);
ma_address_bus: in std_logic_vector(12 downto 0)
);
end component memory_a;
component memory_b
port(
mb_data_bus : inout std_logic_vector(15 downto 0);
mb_address_bus: in std_logic_vector(12 downto 0)
);
end component memory_b;
begin
-- some logic
-- Instantiate memories
a_memory_a : memory_a
port map(
ma_data_bus => data_bus,
ma_address_bus => address_bus
);
a_memory_b : memory_b
port map(
mb_data_bus => data_bus,
mb_address_bus => address_bus
);
end architecture
If the entity port definition does not include the ports, signals are required and cannot be inferred from ports.
-- Example 3 - Use signals for inteconnection as no suitable ports available
entity user is
end user;
architecture Behavioral of user is
-- Component Port Definitions
component memory_a
port(
data_bus : inout std_logic_vector(15 downto 0);
address_bus: in std_logic_vector(12 downto 0)
);
end component memory_a;
component memory_b
port(
data_bus : inout std_logic_vector(15 downto 0);
address_bus: in std_logic_vector(12 downto 0)
);
end component memory_b;
signal data_bus_sig : std_logic_vector(15 downto 0);
signal address_bus_sig : std_logic_vector(12 downto 0);
begin
-- some logic
-- Instantiate memories
a_memory_a : memory_a
port map(
data_bus => data_bus_sig,
address_bus => address_bus_sig
);
a_memory_b : memory_b
port map(
data_bus => data_bus_sig,
address_bus => address_bus_sig
);
end architecture
This is wrong because neither signals nor entity ports are defined.
-- Example 4 - WRONG? - Try to infer ports
entity user is
end user;
architecture Behavioral of user is
-- Component Port Definitions
component memory_a
port(
data_bus : inout std_logic_vector(15 downto 0);
address_bus: in std_logic_vector(12 downto 0)
);
end component memory_a;
component memory_b
port(
data_bus : inout std_logic_vector(15 downto 0);
address_bus: out std_logic_vector(12 downto 0)
);
end component memory_b;
begin
-- some logic
-- Instantiate memories
a_memory_a : memory_a
port map(
data_bus => data_bus,
address_bus => address_bus
);
a_memory_b : memory_b
port map(
data_bus => data_bus,
address_bus => address_bus
);
end architecture
I will refer to your example codes as 1, 2 3 and 4.
1) Example 1 is correct. This is a viable way to connect port in a hierarchical way.
2) For sure you will have compilation/synthesis errors in particular for the output ports.
In fact you will have multiple drivers (each of the out ports of the instantiated components) impacting on the same signal/port of the top entity. It will be easy to see in a simulation too, since you will see 'X's appear at that port (indicating multiple driver to the same signal). Please note that multiple input ports can be connected to a single driver (e.g. same input port of top entity, same signal, etc...)
3) It is partially correct! You have the same issue as in example 2 with the multiple drivers acting on the same signal.
4) This is definitely wrong!. You have not defined neither ports nor signals to be bonded to
UPDATE after changes in entity:
1) It is still correct, entity port can be used as (implicit) signal in this way. You can imagine the top entity just as a container for the 2 sub-component where you have "soldered" the pin of the components to the pins of the top-entity/container (the soldering material provides the electrical continuity)
2) This might be OK when the inout ports are used as input, but when you try to use then as outputs, there might be issues. There is a heavy dependency on how they component are described. If the components use weak logic values ('L' & 'H') then if you drive strong values ('0' & '1') then it might behave OK. It would be better to use intermediate signal end probably some sort of mux/demux to select/steer the data to/from the proper internal component.
3) From the pure interconnect point of view, this is OK. However, from the functional point of view you have to be sure that there is always on component that is acting as a driver and the other as a receiver. Otherwise you will have either undefined value on the internal signal or 'X' due to multiple drivers. However, for the address signal, no one is driving it, so it will be always 'U' (undifined). You need something (a port in top entity, a process, etc...) this si driving some kind of value on it.
4) As before, this is incorrect. The port of the component are connected to nothing. Please note that VHDL (but the same is valid for verilog) is a description language; you try to describe an actual circuit (like one made of chips on a PCB). Like in a real circuit you need some sort of wire to connect one pin of a chip to another pin in another IC, then also in VHDL/verilog you need an equivalent "object" to enabel the interconnection.Thus, you need to define the object (in this case the signal) and then describe its behavior (in this case bind together 2 ports of 2 components).
I hope this time is a bit clearer

VHDL testbench for a device that uses two previously defined and tested entities

Warning: this is going to be long. Sorry if it's too verbose.
I'm just starting out on learning FPGAs and VHDL using Quartus Prime. Over the past few days I've taught myself:
How to write VHDL
How to make a component
How to write a testbench
How to use previously created and tested components - knitted together - to create a new component
What I can't work out though is how I would create a testbench that tests a new component that uses two existing components, when some of the signals that are in this new component are only internal signals.
So, here are two super-simple components that I have successfully written and tested with test benches. I realise this is not real world by the way, I'm just trying to take baby steps.
1. A four bit register
library ieee;
use ieee.std_logic_1164.all;
entity four_bit_reg is
port
(
bcd_in: in std_logic_vector(3 downto 0);
clk: in std_logic;
clr: in std_logic;
bcd_out: out std_logic_vector(3 downto 0)
);
end four_bit_reg;
architecture behaviour of four_bit_reg is
begin
process (clk,clr)
begin
if (clr = '1') then
bcd_out <= "0000";
elsif rising_edge(clk) then
bcd_out <= bcd_in;
end if;
end process;
end behaviour;
2. A BCD to seven segment converter
library ieee;
use ieee.std_logic_1164.all;
entity sev_seg is
port
(
bcd_value : in std_logic_vector(3 downto 0);
sev_seg_value : out std_logic_vector(6 downto 0)
);
end sev_seg;
architecture behaviour of sev_seg is
begin
sev_seg_process : process (bcd_value)
begin
case bcd_value is
when "0000" => sev_seg_value <="0111111"; -- 0
when "0001" => sev_seg_value <="0000110"; -- 1
when "0010" => sev_seg_value <="0111011"; -- 2
when "0011" => sev_seg_value <="1001111"; -- 3
when "0100" => sev_seg_value <="1100110"; -- 4
when "0101" => sev_seg_value <="1101101"; -- 5
when "0110" => sev_seg_value <="1111101"; -- 6
when "0111" => sev_seg_value <="0000111"; -- 7
when "1000" => sev_seg_value <="1111111"; -- 8
when "1001" => sev_seg_value <="1101111"; -- 9
when others => sev_seg_value <= "0000000"; -- A to F should show blank
end case;
end process sev_seg_process;
end behaviour;
First question: What do you call the two things above? Components? Modules? Entities? Something else?
I then use these two in another new component/entity/module (as applicable) as below:
library ieee;
use ieee.std_logic_1164.all;
entity two_modules is
port
(
bcd_pins : in std_logic_vector(3 downto 0);
sev_seg_pins : out std_logic_vector(6 downto 0)
);
end two_modules;
architecture behaviour of two_modules is
-- Internal signals
signal int_clk: std_logic;
signal int_bus: std_logic_vector(3 downto 0);
-- List any components used in the design
component four_bit_reg is
port
(
bcd_in: in std_logic_vector(3 downto 0);
clk: in std_logic;
clr: in std_logic;
bcd_out: out std_logic_vector(3 downto 0)
);
end component;
component sev_seg is
port
(
bcd_value : in std_logic_vector(3 downto 0);
sev_seg_value : out std_logic_vector(6 downto 0)
);
end component;
begin -- start the instances
fbr: four_bit_reg port map
(
clk => int_clk,
bcd_in => bcd_pins,
clr => '0',
bcd_out => int_bus
);
sseg: sev_seg port map
(
bcd_value => int_bus,
sev_seg_value => sev_seg_pins
);
end behaviour;
So, for this thing I have called two_modules, the framework for the test bench created by Quartus is as follows:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY two_modules_vhd_tst IS
END two_modules_vhd_tst;
ARCHITECTURE two_modules_arch OF two_modules_vhd_tst IS
-- constants
-- signals
SIGNAL bcd_pins : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL sev_seg_pins : STD_LOGIC_VECTOR(6 DOWNTO 0);
signal internal_clock : std_logic := '0';
COMPONENT two_modules
PORT (
bcd_pins : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
sev_seg_pins : OUT STD_LOGIC_VECTOR(6 DOWNTO 0)
);
END COMPONENT;
BEGIN
i1 : two_modules
PORT MAP (
-- list connections between master ports and signals
bcd_pins => bcd_pins,
sev_seg_pins => sev_seg_pins
);
internal_clock <= not internal_clock after 500 us;
init : PROCESS
-- variable declarations
BEGIN
-- code that executes only once
WAIT;
END PROCESS init;
always : PROCESS
-- optional sensitivity list
-- ( )
-- variable declarations
BEGIN
-- code executes for every event on sensitivity list
WAIT;
END PROCESS always;
END two_modules_arch;
As you can see I have created an internal clock and I would like to, purely for the purposes of learning how to do this type of thing, I stress I realise this is not a complete design, join the internal_clock (that I can see works and is a waveform in the waveform editor of Model Sim) to clk in the four_bit_reg.
I think and hope once I know how to do this I'll be able to plough on and get a real world, more complicated test bench knocked up. However, after much Googling I can find no reference on how to bind together signals from subcomponents. This may be because I am using completely the wrong terminology and there may be a perfect tutorial somewhere out there.
So:
How can I just for a start get my internal_clock connected to subcomponent, four_bit_reg's clk input?
What is the correct teminology for when you use and knit together things like four_bit_reg and sev_seg? Subcomponents? Something else?
Many thanks if you got this far!
With the comments, I understand that you are using an internal oscillator from Altera in your CPLD.
I suggest to add a third module named "internal_oscillator" which can be described as follow :
library ieee;
use ieee.std_logic_1164.all;
entity internal_oscillator is
port (
CLK : out std_logic
);
end entity;
architecture for_simulation_only of internal_oscillator is
constant C_HALF_PERIOD : time := 5 ns; -- 100MHz
signal clk_internal : std_logic := '0';
begin
clk_internal <= not clk_internal after C_HALF_PERIOD;
CLK <= clk_internal;
end architecture;
You can now add this module in your design and you'll get a clock without adding a new pin on your top level entity :
osc_inst : entity work.internal_oscillator
port map (CLK => int_clk);
In your two_models entity, add a new port for the clock signal:
entity two_modules is
port
(
clk : in std_logic;
bcd_pins : in std_logic_vector(3 downto 0);
sev_seg_pins : out std_logic_vector(6 downto 0)
);
end two_modules;
Remove the int_clk signal in the two_models architecture. Replace it with the previously defined input signal instead when you are connecting the submodules:
fbr: four_bit_reg port map
(
clk => clk_in,
bcd_in => bcd_pins,
clr => '0',
bcd_out => int_bus
);
In your testbench, connect the internal clock signal internal_clock into that port of the two_modules:
PORT MAP (
-- list connections between master ports and signals
clk_in => internal_clock,
bcd_pins => bcd_pins,
sev_seg_pins => sev_seg_pins
);
In most cases the clock is an input to the module. Often accompanied by a reset.
If you look around on the www for example VHDL code you will notice that every module, has a clock input.
There are general two exceptions:
Test-benches generate an artificial clock inside to drive the Device Under test.
Modules which simulate a real clock generating circuit e.g. a Crystal oscillator.

How to create a subsignal / subvariable from an entity variable in VHDL?

I am currently implementing a MIPS processor in VHDL. The system component (which glues together the ALU, register file, control unit, etc.) has the follow entity description:
entity system is
port (
reset : in std_logic;
sys_clk : in std_logic;
instruction : in std_logic_vector(15 downto 0);
sys_mem_dump : in std_logic := '0'
);
end system;
In the architecture section of this system, I am trying to create "subvariables" of the instruction variable, corresponding to the opcode and registers in use.
architecture Behavioral of system is
instruction_opcode : std_logic_vector(3 downto 0) := instruction(15 downto 12);
instruction_rd : std_logic_vector(3 downto 0) := instruction(11 downto 8); -- destination register
instruction_rs : std_logic_vector(3 downto 0) := instruction(7 downto 4); -- source register
instruction_rt : std_logic_vector(3 downto 0) := instruction(3 downto 0); -- target register
-- a bunch of signals
begin
-- a bunch of port maps
end Behavioral
I've tried signal, variable, shared_variable, and constant, but these result in the register file's addresses not being initialized when I port map one of these variables to it. I've also tried putting these variables in the system entity port, but that also doesn't work. I don't want to split the instruction variable in the system entity port into those four variables either.
agree with paebles: you seem to lack basic VHDL knowledge and should look for this in your book.
You should at least know this method:
architecture Behavioral of system is
signal instruction_opcode : std_logic_vector(3 downto 0);
begin
instruction_opcode <= instruction(15 downto 12);
end architecture;
But you can in fact use aliases:
architecture Behavioral of system is
alias instruction_opcode : std_logic_vector(3 downto 0) is instruction(15 downto 12);
begin
end architecture;
A common thread reflecting your comment
#Paebbels Is it simply not possible to do this in VHDL? I have looked at the synario manual and some other websites, and none of the data object types match this use case.
is that the references you have used are inadequate.
In addition to intermediary signals and object aliases described in JH Bonarius' answer there is a method using index ranges declared as subtypes:
library ieee;
use ieee.std_logic_1164.all;
entity field is
port (
fourbitfield: in std_logic_vector (3 downto 0)
);
end entity;
architecture foo of field is
begin
end architecture;
library ieee;
use ieee.std_logic_1164.all;
entity system is
port (
reset: in std_logic;
sys_clk: in std_logic;
instruction: in std_logic_vector(15 downto 0);
sys_mem_dump: in std_logic := '0'
);
end entity system;
architecture foo of system is
subtype opcode is integer range 15 downto 12;
subtype rd is integer range 11 downto 8;
subtype rs is integer range 7 downto 4;
subtype rt is integer range 3 downto 0;
begin
U1:
entity work.field port map (instruction(opcode));
U2:
entity work.field port map (instruction(rd));
U3:
entity work.field port map (instruction(rs));
U4:
entity work.field port map (instruction(rt));
end architecture;
This analyzes, elaborates and simulates (Not actually doing anything while proving a lack of bounds errors).
An entity is an independent design unit and naturally allows abstraction (port names are associated with actual signals in a port map during elaboration of a component instantiation). All other forms of names or using intermediary objects are forms of abstraction intended for readability and are dictated by style.
In the above instruction(opcode) and it's like are slice names (IEEE Std 1076-2008 8.5 Slice names) providing a discrete range in the form of a integer subtype. You could likewise use slice names with discrete ranges (e.g. 15 downto 12) as actuals in association lists directly without declaring subtypes:
U1:
entity work.field port map (fourbitfield => instruction(15 downto 12));
Using named association between formal port and actual signals shown here can preclude the need for further abstraction. Dictating abstraction impinges on style not required by the VHDL standard.
Your idea of sub signals or variables aligns with slice names in VHDL as easily as the use of intermediary signals. Aliases are simply other names for named entities (including object slices).
Which additional abstraction method if any you use might depend on the sophistication level of anticipated readers.
If someone were to search the vhdl tag on Stackoverflow thoroughly you'd find examples of all three of these methods. A wile reader could edit your question to align with VHDL syntax and submit it as a duplicate.

ALTFP_ADD_SUB megafunction in ALTERA

I have the following entity calling the add_sub megafunction created by megafunction wizard under Quartus II :
library ieee;
use ieee.std_logic_1164.all;
library altera_mf;
use altera_mf.altera_mf_components.all;
entity fp_adder is
port(clock : in std_logic;
dataa : in STD_LOGIC_VECTOR (31 DOWNTO 0);
datab : in STD_LOGIC_VECTOR (31 DOWNTO 0);
result : out STD_LOGIC_VECTOR (31 DOWNTO 0));
end fp_adder;
architecture fp_adder_impl of fp_adder is
begin
add: altfp_add_sub
generic map(width_exp => 8, width_man => 23)
port map(clock => clock, dataa => dataa, datab => datab,
result => result);
end fp_adder_impl;
The code synthesises fine but when I launch a waveform to simulate it I always end up with an empty result output. Is there anything I'm missing ?
The ModelSim-Altera pre-build libraries do not contain a model for altfp_add_sub, which is probably the reason why it cannot simulate right away.
Take a look at Floating-Point Megafunctions User Guide page 27 / 4-4, where the reference to "altfp_add_sub_ex_msim.zip (ModelSim-Altera files)" probably points to the megafunction files that you must compile to get a simulation model for altfp_add_sub.

Passing Generics to Record Port Types

I did recently start to use records for my port definitions, especially if I want to group signals that belong to a certain interface. However, the problem I'm facing here is that I cannot pass, say the width of a std_logic_vector, to the entity by means of a generic. So what I basically want to do is the following:
library ieee;
use ieee.std_logic_1164.all;
use work.math_pkg.all;
package fifo_pkg is
type fifo_in_type is record
data_in : std_logic_vector(DATA_WIDTH_??- 1 downto 0);
rd : std_logic;
wr : std_logic;
end record;
type fifo_out_type is record
data_out : std_logic_vector(DATA_WIDTH_?? - 1 downto 0);
empty : std_logic;
full : std_logic;
end record;
component fifo is
generic
(
MIN_DEPTH : integer;
DATA_WIDTH : integer
);
port
(
clk : in std_logic;
res_n : in std_logic;
i : in fifo_in_type;
o : out fifo_out_type
);
end component fifo;
end fifo_pkg;
So the ideal solutions would be when i can use the same generic in my record as i did in the entity. (So that DATA_WIDTH is the same as DATA_WIDTH_??). I know that this should work somehow with vhdl 2008, however my quartus II 11sp1 does not support generics in records.
Is there an elegant way to achieve that kind of "generic passing" that is synthesizable? I know that one could just store a constant in the package, but then I cannot use the same fifo package to instantiate several fifo's with different widths.
Thanks a million,
T
Can you use type generics with Quartus?
Then you leave the type completely unspecified, so that you can create a FIFO of integers or any other data type:
package fifo_pkg is
generic (type element_type);
type fifo_in_type is record
data_in : element_type;
rd : std_logic;
wr : std_logic;
end record;
type fifo_out_type is record
data_out : element_type;
empty : std_logic;
full : std_logic;
end record;
component fifo is
generic
(
MIN_DEPTH : integer;
DATA_WIDTH : integer
);
port
(
clk : in std_logic;
res_n : in std_logic;
i : in fifo_in_type;
o : out fifo_out_type
);
end component fifo;
end fifo_pkg;
Then when you want to use it:
package wide_fifo_pkg is new fifo_pkg
generic map (type => std_logic_vector(31 downto 0));
and then you can use fifo_in_type and fifo_out_type:
signal i : fifo_in_type;
If you have more than one FIFO in a design unit you can create several versions of the package and use the package prefix to get the right type:
package narrow_fifo_pkg is new fifo_pkg
generic map (type => std_logic_vector(3 downto 0));
signal i32 : wide_fifo_pkg.fifo_in_type;
signal i4 : narrow_fifo_pkg.fifo_in_type;
Another VHDL 2008 option: you can have an unconstrained record type:
type fifo_in_type is record
data_in : std_logic_vector;
rd : std_logic;
wr : std_logic;
end record;
which you can then create subtypes of for your various uses:
subtype fifo1_data_type is fifo_in_type(data_in(31 downto 0));
subtype fifo2_data_type is fifo_in_type(data_in(15 downto 0));
No idea if Quartus supports either of those options - please let us know!
Generics in packages is supported in Xilinx's Vivado toolset currently. Ref their document UG901, the section titled "Generics in Packages" for details and a code sample. Need to make sure the source code properties are set up for VHDL-2008, as explained elsewhere in the same document.

Resources