I'm new to VHDL and am having a bit of an issue with the synthesis tool crashing when I have certain stuff in my code (developing in Xilinx ISE).
Below is the gist of what is making the program crash.
signal enteredDigit1 : std_logic_vector(3 downto 0);
begin
u3: entity work.module port map (x,y, enteredDigit1)
process(asyncClock, enteredDigit1) begin
ssegDigit <= enteredDigit1
end process
If I do the ssegDigit <= enteredDigit1 outside that process, its fine. However due to me needing to write an asynchronous bit of code, I figured it would be easier to keep track of states and such in a process.
Any ideas why it would just crash? I get no indication from the program console.
EDIT: It seems to be crashing because I'm assigning ssegDigit a new value. If I instead give enteredDigit1 to a variable in the process it compiles
Without seeing the error message and/or the declaration for ssegDigit it may be impossible to provide a definitive answer.
This analyzes:
library ieee;
use ieee.std_logic_1164.all;
entity module is
port (
signal x: in std_logic_vector (3 downto 0);
signal y: in std_logic_vector (3 downto 0);
signal enteredDigit1: out std_logic_vector (3 downto 0)
);
end entity;
architecture foo of module is
begin
end architecture;
library ieee;
use ieee.std_logic_1164.all;
entity ssegDigit_tb is
end entity;
architecture foo of ssegDigit_tb is
signal asyncClock: std_logic;
signal x: std_logic_vector(3 downto 0);
signal y: std_logic_vector(3 downto 0);
signal ssegDigit: std_logic_vector(3 downto 0);
signal enteredDigit1 : std_logic_vector(3 downto 0);
begin
u3: entity work.module port map (x,y, enteredDigit1);
process(asyncClock, enteredDigit1)
begin
ssegDigit <= enteredDigit1;
end process;
end architecture;
Notice that ssegDigit has the same index range of enteredDigit1, and I corrected the declaration for enteredDigit1 which was:
signal enteredDigit1 : std_logic_vector(3 down 0);
Where the VHDL reserved word downto was not complete and should be:
signal enteredDigit1 : std_logic_vector(3 downto 0);
Without knowing your exact methodology for causing the ISE tool to crash there's an outside possibility that it's parser isn't robust enough.
In general a simulator's analyzer is going to be more robust than one found in a synthesis tool. Synthesizers are written anticipating a valid VHDL design specification, which also points to the utility of validating your design before synthesis.
If neither the declaration for ssegDigit having a matching element for each element in enteredDigit1 nor fixing the reserved word downto in declaration for enteredDigit1 is your problem, by definition you haven't provided enough information. Also notice the semicolon following the assignment statement in the process and after end process.
Let us know, and elaborate the question if needed.
Noted you corrected the downto in your example but not the missing semicolons.
After your comment:
... The sseg digits are declared as you expected, and port mapped to the same range. I was thinking maybe its a case of the synthesizer flipping out because the signal enteredDigit1 is being modified in a few places. Any idea why it would work outside the process? synchronous issues?
It appears that ssegDigit is declared as a signal and connected to a port. This points to the futility of playing twenty questions in comments, where each time around a bit more information is revealed (we'd eventually get a message suggesting moving dialogs to a wiki chat if nothing else).
Perhaps you could show port declarations including mode, signal declarations for the involved elements and any assignment statements for the signals particularly enteredDigit1.
It might also be useful for you to demonstrate the indications leading you to conclude the synthesis tool 'crashing'.
See How do I ask a good question? , Help others reproduce the problem, "Include just enough code to allow others to reproduce the problem. For help with this, read How to create a Minimal, Complete, Valid Example" (How to create a Minimal, Complete, and Verifiable example).
Related
I've been having this debate for years... What's the correct why to infer a single port ram with synchronous read.
Let's Suppose the interface for my inferred memory in VHDL is:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity sram1 is
generic(
aw :integer := 8; --address width of memory
dw :integer := 8 --data width of memory
);
port(
--arm clock
aclk :in std_logic;
aclear :in std_logic;
waddr :in std_logic_vector(aw-1 downto 0);
wdata :in std_logic_vector(dw-1 downto 0);
wen :in std_logic;
raddr :in std_logic_vector(aw-1 downto 0);
rdata :out std_logic_vector(dw-1 downto 0)
);
end entity;
is this this way: Door #1
-- I LIKE THIS ONE
architecture rtl of sram1 is
constant mem_len :integer := 2**aw;
type mem_type is array (0 to mem_len-1) of std_logic_vector(dw-1 downto 0);
signal block_ram : mem_type := (others => (others => '0'));
begin
process(aclk)
begin
if (rising_edge(aclk)) then
if (wen = '1') then
block_ram(to_integer(unsigned(waddr))) <= wdata(dw-1 downto 0);
end if;
-- QUESTION: REGISTERING THE READ DATA (ALL OUTPUT REGISTERED)?
rdata <= block_ram(to_integer(unsigned(raddr)));
end if;
end process;
end architecture;
Or this way: Door #2
-- TEXTBOOKS LIKE THIS ONE
architecture rtl of sram1 is
constant mem_len :integer := 2**aw;
type mem_type is array (0 to mem_len-1) of std_logic_vector(dw-1 downto 0);
signal block_ram : mem_type := (others => (others => '0'));
signal raddr_dff : std_logic_vector(aw-1 downto 0);
begin
process(aclk)
begin
if (rising_edge(aclk)) then
if (wen = '1') then
block_ram(to_integer(unsigned(waddr))) <= wdata(dw-1 downto 0);
end if;
-- QUESTION: REGISTERING THE READ ADDRESS?
raddr_dff <= raddr;
end if;
end process;
-- QUESTION: HOT ADDRESS SELECTION OF DATA
rdata <= block_ram(to_integer(unsigned(raddr_dff)));
end architecture;
I'm a fan of the first version because I think its good practice to register all of the output of your vhdl module. However, many textbook list the later version as the correct way to infer a single port ram with synchronous read.
Does it really matter from a Xilinx or Altera synthesis point of view, as long as you already have taken into account the different between delaying the data verses the address (and determined it doesn't matter for your application.)
I mean...they both still give you block rams in the FPGA? right?
or does one give you LUTS and the other Block rams?
Which would infer a better timing and better capacity in an FPGA, door #1 or door #2?
Unfortunately, the synthesis tool vendors have made the RAM inference functions so that they typically recognize both styles, regardless of the physical implementation of the RAM in the FPGA in question.
So even if you specify registered output, the syntesis tool may silently ignore that and infer a RAM with registered inputs instead. This is not functionally equivalent, so it may actually lead to undesired behaviour, particularly in the case of dual port RAMs.
To avoid this pitfall, you can add vendor specific attributes telling the syntehsis tool exactly which kind of RAM you need.
In general, most FPGAs have mandatory registered inputs on the physical RAM, and can add a additional optional register on the output.
So using the code style code with registered inputs will probably make simulation match reality, which is typically a good thing.
The differences can matter, and it really depends on the specific family you are targeting. Most modern FPGAs have options for the block ram that allow them to function either way, but I wouldn't count on that in practice.
If I am inferring RAM, I typically start with the example design provided with the tools (there's almost always a "how to infer ram" section of the user guide). If targeting cross-platform (eg: Altera + Xilinx) I'd stick with a "minimal common supported" set of features, merging the two example designs.
All that said, I typically register BOTH the address and the data. It's one more clock, but it helps close timings and I'm usually more concerned with throughput vs. overall latency. I also typically use wrapper functions (eg: My_Simple_Dual_Port_RAM) and directly instantiate the low-level block rams using primitives which makes it easy to switch between FPGA vendors (or swap out the inferred logic if/when needed). I just drop the modules in a directory (eg: Altera, Lattice, Xilinx) and include the appropriate directory in the project file. I also do the same thing with dual clock FIFOs, where you're typically a LOT better off using the library parts vs. trying to build your own.
You can take a look at the results of the synthesis. My Vivado gives me the following reports after synthesizing your solutions (default settings).
First solution:
BRAM: 0.5 (from 60 Blocks)
IO: 34
BUFG: 1
And the schematic looks like this
Second solution:
BRAM: 0.5 (from 60 Blocks)
IO: 34
BUFG: 1
With the following result:
So you see that the synthesis will generate the same output for both variants. It is up to you which one you want to use. I prefer the first variant because the second is slightly more code.
My project is design of 32bit MAC(Multiply and Accumlate) unit using reversible logic. For the project , i have designed 32bit mulitplier and 64 bit adder using reversible logic. Now, in the next step i want to design a 64 bit accumlator which takes the value from the adder and stores it and adds with the previous value present in it. I am not getting any idea how to design Accumlator.
Please help in completion of my project.
A basic VHDL accumulator can be implemented in only a few lines of code. How you decide to implement it, and any additional features necessary are going to depend on your specific requirements.
For example:
Are the inputs signed or unsigned?
What is the type of the inputs?
Does the accumulator saturate, or will it roll over?
Here is a sample unsigned accumulator to give you an idea of what you need to implement (based on this source):
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity accumulator is
port (
DIN: in std_logic_vector(3 downto 0);
CLK: in std_logic;
RST: in std_logic;
DOUT: out std_logic_vector(3 downto 0)
);
end entity accumulator;
architecture behave of accumulator is
signal acc_value : std_logic_vector(3 downto 0);
begin
process(CLK)
begin
if rising_edge(CLK) then
if RST='1' then
acc_value <= (others => '0'); -- reset accumulated value to 0
else
acc_value <= std_logic_vector( unsigned(acc_value) + unsigned(DIN) );
end if;
end if;
end process;
-- Assign output
DOUT <= acc_value;
end behave;
To describe what this design does in words: Every clock cycle on the rising edge, the data input DIN is interpreted as an unsigned value, and added to the currently accumulated value acc_value. If the RST input is asserted, instead of accumulating the DIN input, the accumulated value is cleared back to 0. The value of the accumulator is always presented on the output of the block, DOUT.
Based on what you are interfacing with, you might want to consider the following changes/modifications:
Perhaps DIN should be signed or unsigned types instead of std_logic_vector. I actually recommend this, but it depends on how you are representing your values in other places of your design.
DOUT could also be a signed or unsigned value instead of std_logic_vector - it depends your requirements.
In this case, acc_value, the accumulated value register, will rollover if the values accumulated get too high. Maybe you want to generate an error condition when this happens, or perform a check to ensure that you saturate at the maximum value of acc_value instead.
acc_value need not be the same width as DIN -- it could be twice as wide (or whatever your requirements are). The wider it is, the more you can accumulate before the rollover condition occurs.
--Example 1:
signal x : STD_LOGIC_VECTOR(15 downto 0);
--do something with x(15 downto 8);
--do soemthing else with x(7 downto 0);
--Example 2:
signal x0 : STD_LOGIC_VECTOR(7 downto 0);
signal x1 : STD_LOGIC_VECTOR(7 downto 0);
--do something with x0(7 downto 0);
--do something else with x1(7 downto 0);
Is there any difference in the above with regards to how it would be implemented inside the FPGA, gate/LUT usage, performance, etc.
And what about when an alias is used like.
--Example 3:
signal x : STD_LOGIC_VECTOR(15 downto 0);
alias x0 is x(15 downto 8);
alias x1 is x(7 downto 0);
--do something with x0(7 downto 0);
--do something else with x1(7 downto 0);
I am new to this so couldn't figure out how to verify it myself, because in Xilinx ISE even if I regenerate the bit file on the same exact source code twice, the check-sum of the resulting bit file always changes. I guess it adds a time-stamp or some random number to the bit file?
The VHDL language does not specify how a design is to be implemented in a device, e.g. FPGA, so a synthesis tool can use whatever resources it wants, as long as the resulting implementation is equivalent with the VHDL source.
Tool vendors, e.g. Xilinx or Altera, does usually not specify the implementation method, but the tools are usually very good at optimizing the design, thus resulting in the smallest possible implementation.
The result is that equivalent VHDL designs will usually result in the same optimal implementation, in special if the design is simple so the synthesis algorithm can build complete internal design structures. Based on these reservations, the short answer is:
All 3 designs are assumed to be equivalent, so they will have the same implementation.
The consequence of this is that you can usually prioritize a design structure that is easy to write, read, review, and test, so you minimize the number of bugs and time spend, and then let the synthesis tool handle the implementation.
Finally, the art is then to understand when usually does not apply, and you therefore have write the design to fit the tool and device in order to get maximum performance and fill.
I am trying to come up with a way to estimate the gate count if I were to implement a purely combinational 64-bit division.
I can't get my synthesis tool to generate a combinational 64-bit/64-bit integer division.
a 64bit/64bit divider fully combinational is leading to a huge design. this will use a lot of resources and lead to poor speed achievements. I'd suggest to implement the division with several register stages instead of fully combinational.
however, if you'd like to try, the following code would be synthesisable (as "/" operation is given by numeric_std library). check with a synthesis tool the recources needed for it (for synthesis the use of std_logic_vector in entities is suggested):
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity divideComb is
Port ( a : in STD_LOGIC_VECTOR (63 downto 0);
b : in STD_LOGIC_VECTOR (63 downto 0);
c : out STD_LOGIC_VECTOR (63 downto 0));
end divideComb;
architecture Behavioral of divideComb is
begin
c<=std_logic_vector(signed(a)/signed(b));
end Behavioral;
the above code leads to the following synthesis results with Xilinx ISE 13.4:
inferred 131 Adder/Subtractor(s)
inferred 65 Comparator(s)
inferred 4036 Multiplexer(s)
when using Spartan 6 architecture, this leads to 6982 Slice LUTs (and 0 FlipFlops, of course!)
I'm trying to add '1' to an N-Length STD_LOGIC_VECTOR in VHDL
This is the very first time I'm using VHDL so I'm not at all sure how to add this 1 without bulding a Full-Adder which seems kinda of redundent
We are not allowed to use any more liberaries then then one in the code.
LIBRARY IEEE ;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY cnt IS
GENERIC (n: natural :=3);
PORT( clk: IN std_logic; -- clock
rst: IN std_logic; -- reset
cntNum: IN std_logic_vector(n-1 DOWNTO 0); -- # of counting cycles
cntOut: OUT std_logic_vector(n-1 DOWNTO 0) -- count result
);
END cnt;
architecture CntBhvArc OF cnt IS
signal counta : std_logic_vector(n-1 DOWNTO 0);
begin
process (clk, rst)
begin
if rst='1' then
counta<="0";
elsif (clk'event) and (clk='0') then
counta<= counta+'1';
end if;
cntOut<=counta;
end process;
END CntBhvArc
Also... can anyone point to a VHDL totrial for someone who has very little experince in programing?
Thanks
You should not use library IEEE.STD_LOGIC_UNSIGNED.ALL
This library is deprecated (see VHDL FAQ); use ieee.numeric_std.all instead.
To answer your last point - don't think of it as programming. HDL stands for "hardware description language". You're describing hardware, always keep it in mind when writing your code :)
I've also written at length about not using STD_LOGIC_UNSIGNED, but using NUMERIC_STD instead. If this is homework and you're being taught to use STD_LOGIC_UNSIGNED, then I despair of the educational establishments. It's been years since that made sense.
VHDL is strongly-typed, so if count is representing a number (and with a name like that, it better had be :), use either a signed or unsigned vector, or an integer. Integers don't wrap around in simulation unless you make them (if you add 1 to them when they are at their max value, the simulator will terminate). The vector types do. Sometimes you want one behaviour, sometimes the other.
Finally, I just noted this:
elsif (clk'event) and (clk='0') then
which is better written as:
elsif falling_edge(clk) then
again, this has been so for about a decade or two. Were you intending to use the falling edge - rising edge is more usual.
You need to cast the std_logic_vector to an unsigned value so you can add one, then cast it back so you can assign it to your output.
This looks like a homework assignment, so I'll leave you to figure out exactly how to do the implementation.