VHDL design - creating if loop within second process not working - vhdl

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.

Related

Composite Files/ Component Instantiation

I am new(ish) to VHDL. I am trying to understand how to use different component .vhd files to build a complete structure. I am working with a Digilent PmodA7, and want to have two LEDs blink alternately.
What I have tried is Inverter.vhd and LedBlink.vhd
Inverter.vhd:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Inverter is
Port (
Inv_in : in std_logic;
Inv_out : out std_logic
);
end Inverter;
architecture Behavioral of Inverter is
begin
Inv_out <= not Inv_in;
end Behavioral;
Ledblink-1.vhd:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
entity LedBlink is
Port (
clk: in std_logic;
rst: in std_logic;
led_0 : out std_logic;
led_1 : out std_logic
);
end LedBlink;
architecture Behavioral of LedBlink
-- Inverter.vhd
component Inverter is
port (
Inv_in : in std_logic;
Inv_out : out std_logic
);
end component;
constant CLK_FREQ : integer := 12500000;
constant BLINK_FREQ : integer := 1;
constant CNT_MAX : integer := CLK_FREQ/BLINK_FREQ/2 - 1;
signal cnt : unsigned(24 downto 0);
signal blink_0 : std_logic := '1';
signal blink_1 : std_logic := '1';
begin
process(clk)
begin
if (rst = '1') then
blink_0 <= '0';
blink_1 <= '0';
elsif (clk='1' and clk'event ) then
if cnt = CNT_MAX then
cnt <= (others => '0');
-- blink_1 <= blink_0;
A1: Inverter
Port map ( Inv_in => blink_0, Inv_out => blink_1);
blink_0 <= not blink_0;
else
cnt <= cnt + 1;
end if;
end if;
end process;
led_0 <= blink_0;
led_1 <= blink_1;
end Behavioral;
To understand how to combine files, I want to replace the line
blink_1 <= blink_0;
with a inverter component, ie 7404, but can’t figure out how to do this. The example I am following does not use libraries, so I am most interested in that method, although how to a library to accomplish this would be helpful.
What I have is:
You haven't provided a Minimal, Complete, and Verifiable example with an error. Questions asking for programming help on stackoverflow are practical, not theoretical. This implies a specific problem here.
Analysis (compiling) won't complete o with the missing is in the architecture bodyr or component instantiation in the unlabelled process.
You can't instantiate a component (a concurrent statement) in a process (which can only contain sequential statements). Move the component instance outside the process.
The flip flop output blink_0 is inverter's input. It's output blink_1 is then assigned to blink_0 in the process instead of not blink_0.
blink_1 is only assigned in the elaborated process from the concurrent assignment statement in the architecture of inverter. Each process in a design hierarchy has a driver. The value of multiple drivers are resolved during simulation. The equivalent post synthesis is having two devices driving the same signal and would generate a synthesis error.
Analyze Inverter.vhd before elaborating LedBlink.
cnt must be reset for simulation for the increment, adding 1 to all 'U's will result in all 'U's. You don't use package std_logic_unsigned.
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity ledblink is
port (
clk: in std_logic;
rst: in std_logic;
led_0: out std_logic;
led_1: out std_logic
);
end entity ledblink;
architecture behavioral of ledblink is -- ADDED is
component inverter is
port (
inv_in: in std_logic;
inv_out: out std_logic
);
end component;
constant clk_freq: integer := 12500000;
constant blink_freq: integer := 1;
constant cnt_max: integer := clk_freq/blink_freq/2 - 1;
signal cnt: unsigned(24 downto 0);
signal blink_0: std_logic := '1';
signal blink_1: std_logic := '1';
begin
process (clk) -- contains counter cnt and flip flop blink_0
begin
if rst = '1' then
blink_0 <= '0';
-- blink_1 <= '0'; -- ONLY one driver for blink_1, the component
cnt <= (others => '0'); -- ADD cnt to reset
elsif clk = '1' and clk'event then -- OR rising_edge(clk)
if cnt = cnt_max then
cnt <= (others => '0');
-- blink_1 <= blink_0;
-- a1: inverter MOVED to architecture body
-- port map ( inv_in => blink_0, inv_out => blink_1);
-- blink_0 <= not blink_0; CHANGED
blink_0 <= blink_1;
else
cnt <= cnt + 1;
end if;
end if;
end process;
a1:
inverter -- MOVED to architecture body a place for concurrent statements
port map ( inv_in => blink_0, inv_out => blink_1);
led_0 <= blink_0;
led_1 <= blink_1;
end architecture behavioral;
After which your design analyzes and with a testbench providing clock and reset, elaborates and simulates:
Note cnt only requires a length of 23 (22 downto 0), cnt(24) and cnt(23) are always '0' with a 12.5 MHz clock (12500000).
The question notes "The example I am following does not use libraries, so I am most interested in that method, although how to a library to accomplish this would be helpful."
The first clause isn't exactly accurate. See IEEE Std 1076-2008 13.2 Design libraries:
A design library is an implementation-dependent storage facility for previously analyzed design units. A given implementation is required to support any number of design libraries.
...
There are two classes of design libraries: working libraries and resource libraries. A working library is the library into which the library unit resulting from the analysis of a design unit is placed. A resource library is a library containing library units that are referenced within the design unit being analyzed. Only one library is the working library during the analysis of any given design unit; in contrast, any number of libraries (including the working library itself) may be resource libraries during such an analysis.
Every design unit except a context declaration and package STANDARD is assumed to contain the following implicit context items as part of its context clause:
library STD, WORK; use STD.STANDARD.all;
Library logical name STD denotes the design library in which packages STANDARD, TEXTIO, and ENV reside (see Clause 16). (The use clause makes all declarations within package STANDARD directly visible within the corresponding design unit; see 12.4.) Library logical name WORK denotes the current working library during a given analysis. Library logical name IEEE denotes the design library in which the mathematical, multivalue logic and synthesis packages, and the synthesis context declarations reside (see Clause 16).
A design specification is analyzed into the working library which can be referenced by work and can be implementation dependent method redirected.
There are rules for determining the default binding indication (in lieu of a binding indication in a configuration specification as a block declarative item for a block (including an architecture body) containing a component instantiation or in a configuration declaration (not widely used by synthesis tools, if at all). See 11.7 Component instantiation and 3.4.3 Component configuration.
Without an explicit binding indication as here VHDL relies on a default binding indication (7.3.3 Default binding indication):
In certain circumstances, a default binding indication will apply in the absence of an explicit binding indication. The default binding indication consists of a default entity aspect, together with a default generic map aspect and a default port map aspect, as appropriate.
If no visible entity declaration has the same simple name as that of the instantiated component, then the default entity aspect is open. A visible entity declaration is the first entity declaration, if any, in the following list:
a) An entity declaration that has the same simple name as that of the instantiated component and that is directly visible (see 12.3),
b) An entity declaration that has the same simple name as that of the instantiated component and that would be directly visible in the absence of a directly visible (see 12.3) component declaration with the same simple name as that of the entity declaration, or
c) An entity declaration denoted by L.C, where L is the target library and C is the simple name of the instantiated component. The target library is the library logical name of the library containing the design unit in which the component C is declared.
These visibility checks are made at the point of the absent explicit binding indication that causes the default binding indication to apply.
In this case because inverter was analyzed into the same resource library (an unchanging work) following rule b). You can note that these rules are set up to be as painless as possible. There can be only one primary unit (here an entity) with the same name in a library.
Anyway the point is that there are libraries involved in the original post's code. Here without a configuration specification inverter is expected to be found in library work, regardless of what resource library it references in an implementation defined manor.
It's out of the scope of the vhdl tag and the original post does not identify a particular tool implementation, and VHDL tools are varied in methods for associating working and resource libraries with library logical names.
For a resource library made visible by a library clause a use clause of the form 'use library_logical_name.all;' can make all named entities in a resource library directly visible (See 12.4 Use Clauses, 12.3 Visibility, 12.5 The context of overload resolution). Otherwise a selected name for an instantiated entity can be used (8.3 Selected names).

VHDL Cannot Drive Load pins

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.

VHDL behavioural D Flip-Flop with R & S

Hi can any of you with more experience with VHDL Quartus II please set me right on this please.
I have the following Entity and behavioural Architecture for a D Flip-Flop with Set and Reset.
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
ENTITY Q1 IS
PORT (D,R,S,CLK : IN std_logic;
Q : OUT std_logic
);
END ENTITY Q1;
ARCHITECTURE behavioural OF Q1 IS
BEGIN
D_FF : PROCESS (CLK,R,S)
BEGIN
IF R = '0' THEN Q <= '0';
ELSIF S = '0' THEN Q <= '1';
ELSIF (rising_edge(CLK)) THEN Q <= D;
END IF;
END PROCESS D_FF;
END ARCHITECTURE behavioural;
When I compile the code using Quartus II I get the following error message :
Warning (335093): TimeQuest Timing Analyzer is analyzing 1 combinational loops as latches.
I think it is a warning for the incomplete output assignments of the R & S inputs, but when I make a D Flip-Flop latch with only the SET input this error message does not appear when compiled. This leaves me thinking maybe I made an error when writing the architecture? If anyone has any answers or useful info that would be much appreciated.
You have described a clock-edge triggered flip-flop (FF) with both an asynchronous reset and an asynchronous set. Only one of them is supported at the same time because AFAIK, all FFs on Altera FPGAs have only an asynchronous reset.
An asynchronous set is emulated on Altera FPGAs by inverting the FF data input and output and then resetting it to low instead of setting it to high. It looks like this:
Don't overlook the inverter on the D input of the FF. If S is low, then the FF itself is asynchronously reset, but due the negation of the Q output afterwars, it behaves as an asynchronous set of output Q of your entity Q1. If S is high, the FF stores the negated input at the rising clock-edge, which is again negated at the output. As you see, the asynchronous reset port of the FF is already used, and thus, cannot be used for an additional asynchronous reset of your entity Q1.
I recommend to use flip-flops with synchronous set and reset instead:
ARCHITECTURE sync_rs OF Q1 IS
BEGIN
D_FF : PROCESS (CLK)
BEGIN
IF (rising_edge(CLK)) THEN
IF R = '0' THEN Q <= '0';
ELSIF S = '0' THEN Q <= '1';
ELSE Q <= D;
END IF;
END IF;
END PROCESS D_FF;
END ARCHITECTURE sync_rs;
Flip flops in FPGA devices usually have either asynchronous set or reset, but not both, so Altera Quartus tries to make the requested circuit with latches instead of dedicated hardware.
However, for most cases that is not what you want, so instead use flip flops with either asynchronous reset or set, or use synchronous set and and reset as Martin Zabel suggested in his answer.
Note that asynchronous reset have an advantage over synchronous reset in high speed designs, since the asynchronous reset does not add any login in the main synchronous data path, which is usually the critical path for high-speed designs.
Finally, for asynchronous reset, it is a good habit to use two if separate statements, with reset last, so clocking is not dependent on assertion of reset. It is not an issue for a single bit flip flop, but if more signals are controlled in the same process, and reset does not apply to all signals, then clocking should not be dependent on reset for those signal without reset, since that will infer latches. Code like:
D_FF : PROCESS (CLK, R)
BEGIN
IF rising_edge(CLK) THEN
Q <= D;
END IF;
IF R = '0' THEN
Q <= '0';
END IF;
END PROCESS D_FF;
Thanks for the reply, I made the R & S inputs asynchronous on purpose. I have been working through a VHDL text book "Free Range VHDL" and have come across the following question in the Exercises:
The question asks for both inputs to be asynchronous. You say this can be emulated with Altera by inverting the input and output and resetting it to low instead of high. Can you expand on this a little? Thanks

Modelsim/Questasim: Unknown entity <entity_name>. Use expanded name

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).

I don't understand what's wrong with this VHDL code?

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.

Resources