Hierarchical access in Mixed Language Simulation - vhdl

I have a Testbench that uses VHDL-2008's hierarchical accesses to test the good behaviour of my architecture, which I wrote in VHDL.
Like this :
TEST_SIGNAL <= << signal uut_0.signal_to_test : std_logic_vector(7 downto 0) >>;
This worked great but now what I want is to use the same testbench to simulate a verilog netlist corresponding to my synthesized design :
VHDL Testbench
Verilog netlist
Corresponding library
However, my hierarchical accesses don't work now ("Target of VHDL external name is not a vhdl object." error).
This is normal (I guess) but do you have any idea how I could work my way around this, i.e. still observe internal entities of my design? (Other than declaring everything I want to watch as outputs of my UUT...)
(I use ModelSim SE 10.3c to simulate)

Related

VHDL ATTRIBUTE keep

I am currently studying VHDL about SR Latch, and there comes to a part which I don't understand.
Can anyone explain What does ATTRIBUTE keep: boolean mean and what does it do in VHDL?
Thank you.
Warning heavy Xilinx bias...
The attributes for the VHDL are different for different tools and even change between versions of the same tools. The "keep" attribute for Xilinx used to insure that in the Vivado synthesis process the signal is not optimized away. It has been renamed recently to "syn_keep" to avoid confusion. I've used similar attributes to fix build issues before in which the tools make false assumptions.
NOTE: In order to avoid optimization during the implementation for Xilinx use "dont_touch".
Example:
A clock coming into the FPGA needs to be buffer through the Xilinx BUFG, but I needed the raw signal for a specific IP core. So I split the route, buffer the clock and fed the raw clock signal to the IP. The Vivado 2016.4 tool optimized out the unbuffered route creating a time constraint critical warnings and misbehavior on the hardware. The issue was found by tracing through the synthesis design schematics, observing the proper routing, and then viewing the implementation design schematic and seeing the route is altered. I fixed this by adding the dont_touch attribute to the unbuffered signal.
attribute dont_touch : boolean;
attribute clock_signal : string;
attribute dont_touch of clk_in : signal is true;
attribute clock_signal of clk_in : signal is "yes";
...
CLK_BUFG: component BUFG
port map (
I => clk_in,
O => buf_clk_in
);
It is a user defined attribute, thus not part of the VHDL standard itself. It is typically used to instruct the synthesis tool that it should keep a certain signal, for example being a flip-flop, even through the synthesis tool may determine that the signal can be removed during optimization.
For Altera Quartus synthesis tool, see this description: keep VHDL Synthesis Attribute

Altera Quartus II "Error (12061): Can't synthesize current design -- Top partition does not contain any logic"

I recently started working with FPGAs and have been trying to get a basic VHDL program up and running. My code is intended to take the inputs from 10 switches and map them to 10 LED outputs on my dev board, but when I attempt to run analysis/synthesis I get the error in the title. Analyzing the file individually by running "Analyze Current File" yields no errors. A similar post was made here, but the solution there does not help me. I have only one file in my project and I am certain that it has been specified as the top-level entity.
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity sw_to_led is port(
SW: in bit_vector(9 downto 0);
LED: out bit_vector(9 downto 0));
end sw_to_led;
architecture behavior of sw_to_led is
begin
LED <= SW after 5ns;
end behavior;
I thought that the top-level file had to have the same name as the specified "top-level design entity", instead of the entity itself. I learned to read and changed the name of the actual entity to match what was specified and it fixed the issue.
1) Is the name of the vhdl file the same as the entity name sw_to_led.vhd ?
2) Are there already partitions in your design? If yes, you can try making a new Quartus-Project with the help of the "New Project Wizard" and add only the file sw_to_led.vhd.
By the way, after 5ns is not synthesizable. It should only be used in the simulation. But for Quartus it's not an error.

Inferred RAM doesn't initialize in ModelSim Altera edition

I have a memory module for an Altera FPGA target that I've written to be inferred into one of Altera's ALTSYNCRAM blocks. The memory is 1024x16 and I have a memory initialization file specified with an attribute.
When synthesizing, the synthesis report indicates that it generated the type of RAM block that I wanted, and it notes that the initialization file is the one I specified.
When trying to simulate with Altera's edition of ModelSim, the data signal starts out completely uninitialized, and I can't figure out why.
I looked on forums and such and some people mentioned that ModelSim might not support the ".mif" format that I was using, but would support ".hex" so I changed my initialization file to ".hex". I also read that relative file paths can be an issue, but I checked my simulation directory and it looks like QuartusII copied the initialization file into that directory when I tried to simulate.
Any ideas on why the memory isn't being initialized and how to make it do so?
A heavily trimmed model that contains the inferred memory:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
--use work.types.all;
entity CPU is
--...
end entity CPU;
architecture rtl of CPU is
--these types are actually included in a package
subtype reg is std_logic_vector(15 downto 0);
type mem is array (0 to 1023) of reg;
--...
--memory read port
signal MR : reg;
signal MRA : std_logic_vector(9 downto 0); --flops
--memory write port
signal MW : reg; --flops
signal MWA : std_logic_vector(9 downto 0); --flops
signal MWE : std_logic; --flop
signal data : mem;
attribute ram_init_file : string;
attribute ram_init_file of data : signal is "RAM_init.hex";
attribute ramstyle : string;
attribute ramstyle of data : signal is "no_rw_check";
begin
--...
--memory spec
MR <= data(to_integer(unsigned(MRA(9 downto 0))));
memory_process : process(clk)
begin
if (clk'event and clk = '1') then
if(MWE = '1') then
data(to_integer(unsigned(MWA(9 downto 0)))) <= MW;
end if;
end if;
end process;
end architecture rtl; --CPU
Modelsim does not show any warnings or errors while compiling CPU.vhd, nor does it have any indication of loading the initialization file.
This is my first design using Altera software or memory initialization files, and it wouldn't surprise me if the problem was something really basic, or I'm approaching this from a fundamentally incorrect angle.
I'd normally define the memory with a constant in a package, but this is for a class, and it requires that I have a memory initialization file (it requires .mif format too, but that's only a 3 character change between simulation and synthesis file).
It looks like Modelsim may have a "mem load" command you can use at the start of your simulation in order to initialize the memory. Take a look at the end of this thread:
Initialization altsyncram
Being able to initialize RAM on an FPGA depends on both the synthesizer and the specific FPGA you are using. Some FPGA families support this, others don't. I know this is not the answer you want to hear, but you'll need to check the documentation from Altera.
Modelsim does not pay attention to synthesis attributes. That is a vendor specific convention. You can refer to them in simulation as with any other user-defined attribute but it doesn't know that some attributes invoke special behavior in various third-party synthesizers.
If you want to initialize the RAM for simulation you will need to do one of the following:
Write a function that reads the contents of the memory file and call it during initialization of the data signal.
Convert the memory contents to a VHDL constant defined in a separate package and assign the constant to the data signal as the initializer. This can be automated with a script.
Use the Verilog system task $readmemh (requires Modelsim with mixed language license)
For option 1, the function should be of the form:
impure function read_mem(fname : string) return mem is
variable data : mem;
begin
-- ** Perform read with textio **
...
return data;
end function;
signal data : mem := read_mem(data'ram_init_file);
The Quartus documentation on RAM initialization is sparse and only demonstrates initialized data assigned from within a VHDL process rather than reading from a file. The Xilinx documentation on RAM/ROM inferencing (p258) provides examples for doing this with general purpose VHDL. The same technique can be used for simulating a design targeted to Altera. XST supports this use of file I/O for synthesis but Quartus may choke on it. If that is the case you will have to use a configuration to swap between a synthesis oriented RAM model and one specifically for simulation that initializes with the function.
The Xilinx example only shows how to read files with ASCII binary. I have a general purpose ROM component that reads hex as well as binary which you can adapt into a RAM for what you need.

How to effectively utilize a VHDL module?

There's a few questions in here, so bear with me, and thanks for taking the time to read this...
I recently wrote an SPI master, and have fully simulated it to make sure it works as expected.
From here I'd like to use it in another design where I've already got a 7 segment display component set up to take the value received from an ADC on the SPI bus, however I think I've confused myself with things at this point.
I need to send a pulse with other parameters to the SPI master to initiate a transfer, and wait on a busy signal to be de-asserted before I can send anything else. I'm not really sure how best way to implement the SPI master within the new design.
Would I use it in the design as a component? is there a better way?
If it has to be a component, is there any way I can set it up to directly output from that component to pins rather than me having to map to new inputs/outputs in the top level design?
For example, I have SCLK, MOSI, MISO, and CS; Can I not just have them output directly rather than having to be mapped through the top level? Seems like it'd simplify the top level and make it less clunky.
Also, would it be possible to set up a function to just say "Send this data over SPI and then return what's received"?
I'm still getting my head around how to put these things together so help/examples would be greatly appreciated. It seems like all the examples/tutorials available are based on things like using two half-adders, logic gates, etc. which only help to a point when they're so simple.
edit: Entity of my SPI Master
entity SPI_master is
generic(data_width: integer := 8;
clock_select: integer := 0);
port(SCLK: out std_logic;
MOSI: out std_logic;
MISO: in std_logic;
CS: out std_logic;
Mclk_in: in std_logic;
RST: in std_logic;
CPOL: in std_logic;
CPHA: in integer;
send_packet: in std_logic;
busy: out std_logic;
Tx_data: in std_logic_vector(data_width-1 downto 0);
Rx_data: out std_logic_vector(data_width-1 downto 0));
end SPI_master;
Your entity looks reasonable, though better names or comments on CPOL,CPHA would be useful!
Partial answers :
1) You CAN use it in your design as a component, but as previously mentioned, direct entity instantiation is simpler and less verbose.
2) No you can't directly output from deep in the hierarchy, and even if you could it would be a terrible idea!
Are you familiar with "Design Patterns" from C++, Ada or Java programming? If so, think of your top level design as the "Facade" pattern.
It's the only thing the external world needs to know about your design. And it will often be written as structural HDL, instantiating your other entities, and making interconnections between sub-units and connections to external ports.
There are ways to reduce the pain of these interconnections, especially across multiple layers of hierarchy, but ultimately you must break out the SPI signals to individual pins on the top level design, so that they can be connected to the correct wires on the PCB!
3) would it be possible to set up a function to just say "Send this data over SPI and then return what's received" ... not a function, no.
But certainly you can introduce a hardware wrapper to provide the rest of your design with a simple view of a complex task. For example, (assuming "send_packet" is asserted to write a byte on SPI, and "busy" goes high until the write is complete) you can create an entity taking an array of bytes and a "start" signal as inputs. Its architecture contains a process to count the bytes, outputting each in turn to SPI and waiting while "busy", and it can signal to its "caller" when done.

How do User Constraint Files actually work?

I got WebPack up and running on my machine again and after synthesizing a simple design and uploading it to my FPGA, I encountered quite a problem with my understanding.
When there is a line like this in the user constraint file:
NET "W1A<0>" LOC = "P18" ;
How exactly does the synthesis software determine how this pin gets assigned to by the VHDL code?
For instance, take this example code I've been provided with:
entity Webpack_Quickstart is
Port (
W1A : out STD_LOGIC_VECTOR(15 downto 0);
rx : in STD_LOGIC;
tx : inout STD_LOGIC;
clk : in STD_LOGIC
);
end Webpack_Quickstart;
architecture Behavioral of Webpack_Quickstart is
signal counter : STD_LOGIC_VECTOR(47 downto 0) := (others => '0');
begin
W1A(0) <= '1';
end;
How exactly does this code make the WIA0 pin on my FPGA turn on? What is the link? Is it just the name of the port in the entity declaration is there more magic involved?
Your .ucf constraints are applied in the implementation phase. At this point your design has been synthesized, and the available top-level nets are thus "known". So yes, it is only a matter of matching equally named nets to equally named constraints.
The syntax is slightly different though (using <> instead of () for indexing vectors for instance), but otherwise it's just a simple string match.
The easiest way to initially configure your pin constraints, especially for large designs, is to just use one of the graphical tools (PlanAhead, if it's included in the WebPack) to assign the pins, and generate an initial .ucf file.
I find that making small changes later on is easiest to do by hand using the standard ISE text editor directly though.

Resources