I have the following code:
entity wave_select is
port( address:in std_logic_vector(6 downto 0);
ws1: in std_logic;
ws0: in std_logic;
wave_out: out std_logic_vector(6 downto 0));
end wave_select;
architecture choose_arch of wave_select is
signal internal_sine:std_logic_vector(6 downto 0);
signal internal_tri:std_logic_vector(6 downto 0);
signal internal_sqr:std_logic_vector(6 downto 0);
begin
U0: entity sine_tbl port map(addr=>address, sine_val=>internal_sine);
U1: entity triangle_tbl port map(addr=>address, tri_val=>internal_tri);
U2: entity square_tbl port map(addr=>address, square_val=>internal_sqr);
process (std_logic_vector'(ws1, ws0))
begin
case ws_combo is
when "01" => wave_out<=internal_sine;
when "10" => wave_out<=internal_tri;
when "11" => wave_out<=internal_sqr;
when others =>wave_out<=(others => '-');
end case;
end process;
end choose_arch;`
Whenever I try to compile this, I get the following errors:
Identifier/keyword expected (for the process line)
Keyword end expected (for the when "10" line)
Design unit declaration expected (for the same line as keyword error)
FIXED THE QUESTION
As it stands right now, this has a number of problems, mostly with fairly basic syntax.
Although it seems likely you mean the combination of ws0 and ws1 to be treated as ws_combo, you haven't done anything to tell the synthesizer that, so it treats ws_combo as simply undefined.
At least as far as I know, you can't combine signals in the process sensitivity list like you've done. The sensitivity list is to tell what external signals this process responds to, not much else.
You don't have a definition of wave_out (unless it's also in your entity declaration).
You don't have definitions of internal_sine, internal_tri, or internal_sqr. Hard to guess what type they should be without knowing the type of wave_out.
As an interim idea of how this might turn out, I've fixed some of the syntax errors, added an entity declaration that declares ws0, ws1 and wave_out, then sets wave_out to values suitable to the type I've given it (in this case, just took binary input and produced Grey code output).
entity controller1 is
port (
ws1 : in std_logic;
ws0 : in std_logic;
wave_out : out std_logic_vector(1 downto 0)
);
end;
architecture whatever of controller1 is
begin
impl: process(ws0, ws1)
begin
case std_logic_vector'(ws1,ws0) is
when "01" => wave_out<="01";
when "10" => wave_out<="11";
when "11" => wave_out<="10";
when others =>wave_out<=(others => '-');
end case;
end process;
end whatever;
Of course, this also needs the typical library and using to get declarations for std_logic and std_logic_vector, but with those added the synthesizer seems to accept it. Of course, some other synthesizer (I'm checked it with Synplify) might find a problem I missed, but I think that probably covers at least most of the obvious problems.
What are you attempting to achieve with the std_logic_vector' in this line?
process (std_logic_vector'(ws1, ws0))
If you just change that for the more conventional
process (ws1, ws0)
I imagine it will help.
But I assume ws_combo is a signal like
ws_combo = ws1&ws0;
so
process (ws_combo)
would be better still.
Related
This is perhaps more of a hypothetical VHDL question as opposed to a real-life/case study question.
Say I have a component declaration as follows...
component my_comp is
port (
A : in std_logic;
--...other input/outputs
B : out std_logic_vector(9 downto 0)
);
end component my_comp;
And within the same entity containing my_comp i have the signals
signal my_comp_full_scale_output : std_logic_vector(9 downto 0);
signal my_comp_8_scale_output : std_logic_vector(7 downto 0);
Is there a way which I can assign these two signals both the value of B in the port map statement of the component instantiation? Something like this maybe...
my_comp_isnt : my_comp
port map (
A => some_signal,
-- other signal assignments
B => my_comp_full_scale_output,
B(9 downto 2) => my_comp_8_scale_output
);
Once again I stress that this is totally playing with VHDL's logic and I am not using this in any design!!! I do know that this can easily be done with an assignment of my_comp_full_scale_output to my_comp_8_scale_output outside of the component instantiation such as below and this is simply a sake of code for code's sake.
my_comp_isnt : my_comp
port map (
A => some_signal,
-- other signal assignments
B => my_comp_full_scale_output
);
my_comp_8_scale_output <= my_comp_full_scale_output(9 downto 2);
No.
1076-2008 - IEEE Standard VHDL Language Reference Manual states:
Each association element in an association list associates one
actual designator with the corresponding interface element in the
interface list of a subprogram declaration, component declaration,
entity declaration, block statement, or package.
So you can only map it once.
I've written a VHDL design that halves the clock's frequency and outputs this 'data clock' onto the sclk pin. I also have a data pin called 'sda' that I'd like to send data out of. The following code works fine. I see the clock signal out of sclk and sda is permanently set to high. Enable is attached to a push button.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
-- For Main Clock --
library machXO3l;
use machXO3l.all;
--------------------
entity top is
-- entity's pin out.
port(
enable : in std_logic;
sda : out std_logic := '0';
sclk : out std_logic := '0'
);
end entity;
architecture top_behav of top is
signal temp_sclk : std_logic := '0';
signal clk : std_logic;
signal temp_sda : std_logic := '1';
signal stdby : std_logic := '0';
component OSCH
-- Component description that is being used within the entity.
-- synthesis translate_off
generic (NOM_FREQ: string := "24.18");
-- synthesis translate_on
port(
STDBY : in std_logic;
OSC : out std_logic
);
end component;
attribute NOM_FREQ : string;
attribute NOM_FREQ of OSCinst0 : label is "24.18";
begin
OSCinst0: OSCH
-- synthesis translate_off
generic map( NOM_FREQ => "24.18" )
-- synthesis translate_on
-- mapping the OSCH component to our entity pin out.
port map(
OSC => clk,
STDBY => stdby
);
-- DATA CLOCK GENERATION
sclk_p : process(clk, enable)
begin
if (enable = '0') then
temp_sclk <= '0';
elsif (clk'event and clk = '1') then
temp_sclk <= NOT temp_sclk;
end if;
end process;
sclk <= temp_sclk;
sda <= temp_sda;
end top_behav;
The problem is when I create the following process within the architecture, both lines are permanently set to 0. I don't understand why. Simulation works fine. I'm able to synthesize my code and program it on to the FPGA. But when monitoring the pins using a scope, they're just set to low.
sda_p : process(clk, enable)
begin
if (enable = '0') then
temp_sda <= '0';
else
temp_sda <= '1';
end if;
end process;
The following works fine too:
sda_p : process(clk, enable)
begin
temp_sda <= '1';
end process;
I'm using lattice diamond and machx03l evk
In Lattice Diamond, first of all, look at the netlist analyzer (icon and image shown below)
Check to see that the synthesized logic is correct. If the netlist analyzer shows the correct logic, then you need to believe that this is what is going to be synthesized. Then you have removed your uncertainty and there are no more doubts.
Does it indeed show that you are connecting to ground or does it show the correct intended logic to be synthesized?
If it shows that it is correct, then your problem can only be because of your external hardware or your output settings. Please check:
Output settings (red box below)
Pull mode matches your external world (Purple highlight below)
Drive strength (red highlight below)
Check where your pin output is going to. What is your load? Is it affecting what you are driving?
You mentioned that you monitored the signals using a scope, is it the Lattice logic analyzer? or an actual oscilloscope?
If it is using the Lattice Logic Analyzer where you instantiate the analyzer as a logic block inside the FPGA, then the only other reason I can think of is that your clock is not correctly functioning.
If using an oscilloscope, there could still be a problem which can be plausibly explained by the above symptoms and potential problems
In the end, my code was correct but since the machx03l only allows limited RAM flash programming (compared to the machx03lf board), I am using the SPI flash programming interface. Using this interface is a pain - many a times, I have to keep doing a 'Background, flash, erase, verify' when programming the board. Other times the IDE complaints I've got a 'CHECK_ID' error, in which case I resort to use the 'Flash, erase, verify' method. If the latter does work and the board does nothing, always do the former and it should work, given one is confident of their code.
Using the first snippet of code, I have been getting this error that a bunch of my signals drove no pins. I am pretty certain that this is because in the first snippet of code, the first if statement is never reached. Why would this be so? In the second snippet I modified the code, and all of my problems have been fixed. I made the change as an intuitive impulse, I have no idea why that fixed everything. Could someone explain maybe how the Synthesizer generates the circuit?
First Snippet:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity DataReg is
generic(N: integer := 8);
port(DIN: in std_logic_vector(N - 1 downto 0);
DOUT: out std_logic_vector(N - 1 downto 0);
CLK: in std_logic;
ENABLE: in std_logic;
RESET: in std_logic);
end DataReg;
architecture Behavioral of DataReg is
begin
process(CLK, ENABLE)
begin
if rising_edge(CLK) and ENABLE = '1' then
DOUT <= DIN;
end if;
if rising_edge(CLK) and RESET = '1' then
DOUT <= (others => '0');
end if;
end process;
end Behavioral;
Second snippet: (Fixed code)
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity DataReg is
generic(N: integer := 8);
port(DIN: in std_logic_vector(N - 1 downto 0);
DOUT: out std_logic_vector(N - 1 downto 0);
CLK: in std_logic;
ENABLE: in std_logic
RESET: in std_logic);
end DataReg;
architecture Behavioral of DataReg is
begin
process(CLK, ENABLE)
begin
if rising_edge(CLK) then
if ENABLE = '1' then
DOUT <= DIN;
elsif RESET = '1' then
DOUT <= (others => '0');
end if;
end if;
end process;
end Behavioral;
Because HDL code must be able to represent existing hardware. Therefore when you write RTL (Register Transfer Level) code you have to stick to certain structures. Even the second code you wrote is not correct.
I can't explain all the rules but basically, to use an edge (rising or falling) you can have only one signal. Not OR-es or And-es etc.:
if rising_edge(CLK) then
In such a clocked section your process can have one or two more sensitivity signals. Often there is an asynchronous reset in some exceptional cases there is also an asynchronous set. For those to work you have to place the condition before the clock. Therefore your code is wrong. Your ENABLE and RESET are only looked at when there is a clock edge. Thus putting ENABLE in the sensitivity list is superfluous. You might just as well leave it out.
Furthermore the ENABLE if is before the RESET. Thus if the ENABLE is high your RESET will be ignored. Probably not what you want!
The code for a clocked section is sooo terribly standard that I often copy a template I have laying around. (I always use asynchronous active low reset)
process(clk, reset_n)
begin
if (reset_n='0') then
elsif rising_edge(clk) then
end if; -- reset/clocked
end process;
First of all, the two pieces of code that you present are not even equivalent in the simulator because when ENABLE and RESET are both 1 on a clock edge, the first snippet results in DOUT being 00000000 whereas in the second one it evaluates to DIN.
It is my impression that the sensitivity lists (the part in parentheses after process) are ignored during synthesis by Xilinx Vivado. I consider them a relic from times when simulation tools could not afford deducing which variables should be monitored to determine when variables should be updated. I don't know what other synthesis tools do with them.
Anyway, you specified ENABLE in your sensitivity list, which means that you want to evaluate the process statements if ENABLE changes value. All if-statements evaluate to false unless a rising clock edges is taking place. Therefore, CLK alone in the sensitivity list is sufficient for simulation.
All that being said, you should restrict your code to formats that are explicitly recommended by the synthesis tool vendor. Synthesis tools can only implement a subset of everything that you can write in VHDL. For Vivado, you can find suggested code structure in the synthesis manual (This one is for Vivado 2017.3). On page 71, you will see that they recommend flip-flops of the form:
process(clk) is
begin
if rising_edge(clk) then
if clr = '1' then
dout <= "00000000";
elsif ce = '1' then
dout <= d_in;
end if;
end if;
end process;
You can rename the variables as needed of course. On page 69, you will also see that Xilinx recommends using synchronous implementations (putting everything inside the rising_edge if-statement) over asynchronous implementations. There is much more in the manual, for example about how to write shift registers or RAMs, which you should become familiar with if you want to write code to be synthesized with Vivado. Other vendors have similar documentation with recommended code.
I'm using QuestaSim, which is supposedly the same thing as ModelSim but 64-bit. I'm trying to run a test bench for an assignment due in class tomorrow. The assignment is done and all I need is the test bench, but QuestaSim is being annoying as usual.
For some reason, the test bench file just WILL NOT compile. I cannot for the life of me figure out why, though I recall it working on ModelSim the last time I tried this.
Here's the code for the test bench.
library ieee;
use ieee.std_logic_1164.all;
entity test_bench is
end entity test_bench;
architecture lab1atest of test_bench is
signal X, Y, M: std_logic_vector (7 downto 0);
signal s: std_logic;
begin
dut : entity lab1a
port map ( X=>X, Y=>Y, s=>s, M=>M);
stimulus : process is
begin
X <= "10101010"; Y <= "01010101"; s <= '0'; wait for 20 ns;
s <= '1'; wait for 20 ns;
X <= "11110000"; wait for 20 ns;
s <= '0'; wait for 20 ns;
Y <= "00001111";
wait;
end process stimulus;
end architecture lab1atest;
The code for lab1a.vhd I can't post because it's to be submitted for an assignment and I don't want to get nailed for plagiarizing myself, but know that the entity "lab1a" most certainly exists in that file and I am making sure to compile that file first (though I have tried the other way around, just in case).
In addition to the standard selecting of the files and hitting compile, I've also tried the following:
vlib work;
vmap work work;
vcom lab1a.vhd;
vcom lab1atest.vhdl;
vsim work.lab1atest;
Both produce the same error.
If any of you have any idea why I am getting the error highlighted in the title, please let me know. I feel like this is an incredibly simple fix and I am currently cursing the designers of said product for making it so unintuitive.
I genned a dummy entity/architecture for lab1a that does nothing but has proper connectivity.
The immediate issue why it won't 'analyze' is that the entity lab1a isn't made visible to test_bench.
dut : entity lab1a
port map ( X=>X, Y=>Y, s=>s, M=>M);
should be
dut: entity work.lab1a
port map ( ...
or you should make the contents of your working directory visible in your context clause by adding a use clause:
use work.all; -- or some variant form
After implementing the selected name (work.lab1a, an expanded name is a form of selected name, see IEEE Std 1076-2008, 8.3 Selected names, paragraph 7) the code analyzed with a previously analyzed lab1a:
library ieee;
use ieee.std_logic_1164.all;
entity lab1a is
port (
X: in std_logic_vector (7 downto 0);
Y: in std_logic_vector (7 downto 0);
s: in std_logic;
M: out std_logic_vector (7 downto 0)
);
end entity;
architecture foo of lab1a is
begin
end architecture;
And why the dummy lab1a works is because an architecture isn't required to contain concurrent statements:
architecture_body ::=
architecture identifier of entity_name is
architecture_declarative_part
begin
architecture_statement_part
end [ architecture ] [ architecture_simple_name ] ;
architecture_statement_part ::=
{ concurrent_statement }
IEEE Std 1076-2008. 1.3.2 Synaptic description, f):
Braces enclose a repeated item or items on the right-hand side of a
production. The items may appear zero or more times; the repetitions
occur from left to right as with an equivalent left-recursive rule.
Extended Backus-Naur Form text found in the numbered clauses of the standard is normative.
And there's another solution, the use of a component declaration and component instantiation instead of direct entity instantiation.
This would count on default binding indication to find a previously analyzed lab1a during elaboration. (7.3.3 Default binding indication).
How can one handle this case:
entity foo is
generic (
num_instances : natural := 8
);
port (
data_in_per_instance : in std_logic_vector(num_instances-1 downto 0);
data_out_per_instance : out std_logic_vector(num_instances-1 downto 0)
);
end foo;
architecture bar of foo is
component do_stuff is
port(
din : in std_logic;
dout : out std_logic
);
end component do_stuff;
signal sig_per_instance : std_logic_vector(num_instances-1 downto 0);
begin
L1: for i in 0 to num_instances-1 generate
L2: do_stuff
port map(
din => data_in_per_instance(i),
dout => data_out_per_instance(i)
);
end generate;
end bar;
The problem here is that if num_instances is reduced to 0 there will be an error when the signal ranges (num_instances-1 downto 0) are evaluated....
Is there an elegant way around this? All I can come up with is using a function like max(num_instances-1,0) to prevent this problem (but then synthesis may not give me exactly what I want, i.e. nothing).
Is there some way to handle this case a little more seamless?
A simple answer is to wrap the for-generate statement in an if-generate, if num_instances /= 0 generate ... Unfortunately if-generates have no else part, however there is nothing to stop you adding a second if num_instances = 0 generate ... statement to handle that special case.
Alternatively you can wrap the problem part of the for-generate using if-generate.
EDIT: re the need for a correct signal declaration guarded by the if ... generate.
AHA! You may have discovered a legitimate use for VHDL's (in my experience) rarely used "block" statement!
A block statement may contain signal declarations, and can be wrapped in a generate.
So this is valid VHDL:
Normality : block is
-- signal declarations here
begin
-- concurrent code here
end block Normality;
and it can be legally wrapped in a generate statement...
A std_logic_vector with an empty range (for example 3 downto 4) is perfectly legitimate - it's called a "null range" by the LRM. If you create one, then (at least with Modelsim) you will get warnings, which is usually considered poor form. To eliminate those, then Brian's block suggestion is what you'll have do.
Similarly the for..generate will result in an empty loop and no instances. No warnings for this.
I'm intrigued why you'd want a block with no instances in? I'd make num_instances a positive to force at least one of them, but that may not actually what you want!