Output value conflict of signals in VHDL - vhdl

I have written a simple vhdl code to enable/disable an output port by some control signals under some conditions. Problem is that the output signal is either U or X while the code looks fine.
The main entity is shown below. the first process is sensitive to rst and will disable oe when it is 1. The second process is sensitive to clk and will enable the oe on clock transition. The output value is also set to 5.
entity test2 is
port( clk: in std_logic;
rst: in std_logic;
num: out integer range 0 to 7;
oe: out std_logic );
end;
architecture behav of test2 is
begin
process( rst )
begin
if rst = '1' then
oe <= '0';
end if;
end process;
process( clk )
begin
if (clk'event and clk = '1') then
num <= 5;
oe <= '1';
end if;
end process;
end;
Now consider the testbench file. As can be seen, in the main process, I set r which is connected to rst to 1 and then 0.
entity test2_tb is
end;
architecture behav of test2_tb is
component test2 port( clk: in std_logic;
rst: in std_logic;
num: out integer range 0 to 7;
oe: out std_logic );
end component;
signal c: std_logic := '0';
signal r: std_logic;
signal n: integer range 0 to 7 := 2;
signal o: std_logic;
begin
u1: test2 port map( c, r, n, o );
process( c )
begin
c <= not c after 2ns;
end process;
process
begin
r <= '1';
wait for 4 ns;
r <= '0';
wait for 8 ns;
end process;
end;
While r is 1, the o which is connected to oe is set to U. Why? Moreover, on the raising edge of the clock, the value of o becomes X. Why? please see the waves below

To make it short: your oe port should probably not be of type std_logic but std_ulogic (same for clk and rst) and it should probably be driven by one single process instead of two:
process(clk)
begin
if clk'event and clk = '1' then
if rst = '1' then
oe <= '0';
else
num <= 5;
oe <= '1';
end if;
end if;
end process;
Or, if you prefer an asynchronous reset:
process(clk, rst)
begin
if rst = '1' then
oe <= '0';
elsif clk'event and clk = '1' then
num <= 5;
oe <= '1';
end if;
end process;
In case your tools do not support std_ulogic properly (unfortunately there are logic synthesizers that do not support std_ulogic, at least in the top level), use std_logic but be very careful to always drive your output ports (and internal signals) in one single process, except in very specific situations where you really want several pieces of hardware to concurrently drive the same hardware wire, which is quite rare (tri-state logic, high impedance...)

The processes will continue to drive their values even after you made the assignment to oe (because you never told them to do anything else). One driving 0 an one driving 1 gives an X. Merge the two processes into one with an if-elsif statement. With only one driver there's no conflict. Initially the are both driving U.

Related

VHDL - Adding/Removing Pipeline Register with Generics

Let's assume I have two processes PROC_A and PROC_B, and they share a signal between them. Let me write a dummy example:
library ieee;
use ieee.std_logic_1164.all;
entity example is
port (
clk : in std_logic;
rst_n : in std_logic;
a : in std_logic;
b : in std_logic;
c : in std_logic;
z_out : out std_logic);
end entity example;
architecture rtl of example is
signal a_and_b : std_logic;
signal ab_xor_c : std_logic;
begin -- architecture rtl
z_out <= ab_xor_c;
PROC_A : process (clk, rst_n) is
begin -- process PROC_A
if rst_n = '0' then -- asynchronous reset (active low)
a_and_b <= '0';
elsif rising_edge(clk) then -- rising clock edge
a_and_b <= a and b;
end if;
end process PROC_A;
PROC_B : process (clk, rst_n) is
begin -- process PROC_B
if rst_n = '0' then -- asynchronous reset (active low)
ab_xor_c <= '0';
elsif rising_edge(clk) then -- rising clock edge
ab_xor_c <= a_and_b xor c;
end if;
end process PROC_B;
end architecture rtl;
Now, I want to have a pipeline register between a_and_b and ab_xor_c signals, and I want to hardcode it but also enable/disable it with ease. I really want something like a ifdef in C/C++. I could think of a generic to do that but I am also open to any other method (maybe with pragmas?). I am writing an example below, I know that it is so wrong in terms of VHDL but just see it as an idea:
library ieee;
use ieee.std_logic_1164.all;
entity example is
generic (
PIPELINE_EN : std_logic := '1');
port (
clk : in std_logic;
rst_n : in std_logic;
a : in std_logic;
b : in std_logic;
c : in std_logic;
z_out : out std_logic);
end entity example;
architecture rtl of example is
signal a_and_b : std_logic;
signal ab_xor_c : std_logic;
if PIPELINE_EN = '1' then
signal pipeline_reg : std_logic;
end if;
begin -- architecture rtl
z_out <= ab_xor_c;
PROC_A : process (clk, rst_n) is
begin -- process PROC_A
if rst_n = '0' then -- asynchronous reset (active low)
a_and_b <= '0';
elsif rising_edge(clk) then -- rising clock edge
a_and_b <= a and b;
end if;
end process PROC_A;
PROC_B : process (clk, rst_n) is
begin -- process PROC_B
if rst_n = '0' then -- asynchronous reset (active low)
ab_xor_c <= '0';
if PIPELINE_EN = '1' then
pipeline_reg <= '0'
end if;
elsif rising_edge(clk) then -- rising clock edge
if PIPELINE_EN = '1' then
pipeline_reg <= a_and_b;
ab_xor_c <= pipeline_reg xor c;
else
ab_xor_c <= a_and_b xor c;
end if;
end if;
end process PROC_B;
end architecture rtl;
Your example has been modified to removed the register from process A and show a generic controlling the presence of the register. Additional pipeline registers could be added generically as well.
library ieee;
use ieee.std_logic_1164.all;
entity example is
generic ( PIPELINED: BOOLEAN := TRUE);
port (
clk: in std_logic;
rst_n: in std_logic;
a: in std_logic;
b: in std_logic;
c: in std_logic;
z_out: out std_logic
);
end entity example;
architecture genericly_pipelined of example is
signal a_and_b: std_logic;
signal ab_xor_c: std_logic;
begin
NO_PIPELINE:
if not PIPELINED generate
PROC_A:
process (a, b) is
begin
a_and_b <= a and b; -- could be a concurrent statement instead
end process;
end generate;
GEN_PIPELINED:
if PIPELINED generate
PIPELINED_PROC_A:
process (clk, rst_n) is
begin
if rst_n = '0' then
a_and_b <= '0';
elsif rising_edge(clk) then
a_and_b <= a and b;
end if;
end process;
end generate;
PROC_B:
process (clk, rst_n) is
begin
if rst_n = '0' then
ab_xor_c <= '0';
elsif rising_edge(clk) then
ab_xor_c <= a_and_b xor c;
end if;
end process;
end architecture genericly_pipelined;
The granularity using a generate statement is to a concurrent statement. For purposes of changing signal names you can declare intermediary signals in the block statement elaborated by the generate statement's block declarative region. Generate statements can be nested (it's a concurrent statement) which can be used to add more pipeline registers.
A generate statement body can have a block declarative part prior to any concurrent statements in the block statement body. Concurrent statements are delineated by the reserved words begin and end followed by a semicolon when any declarations are present in the block declarative part. E.g. IEEE Std 10786-2008:
11.8 Generate statements
if_generate_statement ::=
    generate_label :
        if [ alternative_label : ] condition generate
            generate_statement_body
        { elsif [ alternative_label : ] condition generate
            generate_statement_body }
        [ else [ alternative_label : ] generate
            generate_statement_body ]
    end generate [ generate_label ] ;
generate_statement_body ::=
        [ block_declarative_part
    begin ]
        { concurrent_statement }
    [ end [ alternative_label ] ; ]
The generate statements in the above VHDL code have no declarations. Braces { } enclosing the item concurrent_statement indicate you can use the 'long form' with the begin and end reserved words with zero or more concurrent statements. You'd declare any intermediary signals used to communicate between statements found in different generate statements in the same design hierarchy. (The block statement elaborated by a generate statement is a separate declarative region.)
The BNF found in the standard's numbered sections is normative.
Note you didn't assign z_out.
Here's an example compatible with the OP's code:
library ieee;
use ieee.std_logic_1164.all;
entity example1 is
generic ( PIPELINES: natural := 1);
port (
clk: in std_logic;
rst_n: in std_logic;
a: in std_logic;
b: in std_logic;
c: in std_logic;
z_out: out std_logic
);
end entity example1;
architecture generic_pipeline_stages of example1 is
signal a_and_b: std_logic;
signal ab_xor_c: std_logic;
begin
NO_PIPELINE:
if PIPELINES = 0 generate
PROC_A:
process (a, b) is
begin
a_and_b <= a and b; -- could be a concurrent statement instead
end process;
end generate;
GEN_PIPELINED:
if PIPELINES > 0 generate
type pipeline is array (0 to PIPELINES - 1) of std_logic;
signal pipeline_reg: pipeline;
begin
PIPELINED_PROC_A:
process (clk, rst_n) is
begin
if rst_n = '0' then
pipeline_reg <= (others => '0');
elsif rising_edge(clk) then
for i in pipeline'range loop
if i = 0 then
pipeline_reg(i) <= a and b;
else
pipeline_reg(i) <= pipeline_reg(i - 1);
end if;
end loop;
end if;
end process;
a_and_b <= pipeline_reg(PIPELINES - 1); -- a separate process
end generate;
PROC_B:
process (clk, rst_n) is
begin
if rst_n = '0' then
ab_xor_c <= '0';
elsif rising_edge(clk) then
ab_xor_c <= a_and_b xor c;
end if;
end process;
end architecture generic_pipeline_stages;
which produces:
And shows the two clock delays using natural generic PIPELINES.
With PIPELINES = 1:
The signals a_and_b and a_xor_b show up one clock earlier. It's compatible with the first VHDL example in this answer with PIPELINED = TRUE.
Note the block declarative part contains a composite signal declaration for the pipeline stages. A generate statement is it's own declarative region which means pipeline_reg wouldn't be visible outside the elaborated block. To access intermediary pipeline stages you'd either move the pipeline_reg declaration to the top level (example1, here) or assign signals declared in the top level assigned in the generate statement.
Principles in the design you wrote are fine, except for the if PIPELINE_EN = '1' then part in the declaration of pipeline_reg, which should be skipped, since the synthesis will then just remove the unused pipeline_reg. Also I would suggest that PIPELINE_EN is declared as type boolean instead, since that is a more obvious choice, and the = '1' can then be skipped in the conditions.
If for some reason you want to avoid declaration of the pipeline signal 'pipeline_reg' in the actual design, then you can declare a variable in the process, with code like below. It is required to assign the variable after use in the code, to get a flip-flop, since it otherwise just becomes combinatorial logic. However, such creation of flip-flops through use of variables is advised against, since it is hard to read and get right, thus error prone, and should be avoided in general. Though here it comes:
PROC_B : process (clk, rst_n) is
variable pipeline_reg_v : std_logic; -- Results in pipeline register if PIPELINE_EN, otherwise removed by synthesis
begin -- process PROC_B
if rst_n = '0' then -- asynchronous reset (active low)
ab_xor_c <= '0';
if PIPELINE_EN then
pipeline_reg_v := '0';
end if;
elsif rising_edge(clk) then -- rising clock edge
if PIPELINE_EN then
ab_xor_c <= pipeline_reg_v xor c;
pipeline_reg_v := a_and_b;
else
ab_xor_c <= a_and_b xor c;
end if;
end if;
end process PROC_B;
An alternative is to use the VHDL block construction, together with generate, whereby you can have signal declarations that are local to the block, as shown below. Though note that the block construction is rarely used in VHDL, thus there is a higher risk of encountering bugs in tools.
PIPELINE_EN_TRUE_GENERATE : if PIPELINE_EN generate
PIPELINE_EN_TRUE_BLOCK : block
signal pipeline_reg : std_logic;
begin
PROC_B : process (clk, rst_n) is
begin -- process PROC_B
if rst_n = '0' then -- asynchronous reset (active low)
ab_xor_c <= '0';
pipeline_reg <= '0';
elsif rising_edge(clk) then -- rising clock edge
pipeline_reg <= a_and_b;
ab_xor_c <= pipeline_reg xor c;
end if;
end process PROC_B;
end block PIPELINE_EN_TRUE_BLOCK;
end generate PIPELINE_EN_TRUE_GENERATE;
PIPELINE_EN_FALSE_GENERATE : if not PIPELINE_EN generate
PROC_B : process (clk, rst_n) is
begin -- process PROC_B
if rst_n = '0' then -- asynchronous reset (active low)
ab_xor_c <= '0';
elsif rising_edge(clk) then -- rising clock edge
ab_xor_c <= a_and_b xor c;
end if;
end process PROC_B;
end generate PIPELINE_EN_FALSE_GENERATE;
With a generic parameter for the pipeline depth:
library ieee;
use ieee.std_logic_1164.all;
entity example is
generic(
depth: natural := 0
);
port(
clk: in std_logic;
rst_n: in std_logic;
a: in std_logic;
b: in std_logic;
c: in std_logic;
z_out: out std_logic
);
end entity example;
architecture rtl of example is
signal a_and_b: std_logic;
signal ab_xor_c: std_logic_vector(0 to depth);
begin
z_out <= ab_xor_c(depth);
process(clk, rst_n) is
begin
if rst_n = '0' then
a_and_b <= '0';
ab_xor_c <= (others => '0');
elsif rising_edge(clk) then
a_and_b <= a and b;
ab_xor_c <= ab_xor_c srl 1;
ab_xor_c(0) <= a_and_b xor c;
end if;
end process;
end architecture rtl;
And then, with depth=2:
use std.env.all;
library ieee;
use ieee.std_logic_1164.all;
entity example_sim is
end entity example_sim;
architecture sim of example_sim is
signal clk: std_logic;
signal rst_n: std_logic;
signal a: std_logic;
signal b: std_logic;
signal c: std_logic;
signal z_out: std_logic;
begin
u0: entity work.example(rtl)
generic map(
depth => 2
)
port map(
clk => clk,
rst_n => rst_n,
a => a,
b => b,
c => c,
z_out => z_out
);
process
begin
clk <= '0';
wait for 1 ns;
clk <= '1';
wait for 1 ns;
end process;
process
begin
rst_n <= '0';
a <= '1';
b <= '1';
c <= '1';
wait until rising_edge(clk);
rst_n <= '1';
for i in 1 to 15 loop
wait until rising_edge(clk);
c <= not c;
end loop;
finish;
end process;
end architecture sim;
Demo:
$ ghdl -a --std=08 example_sim.vhd
$ ghdl -r --std=08 example_sim --vcd=example_sim.vcd
simulation finished #21ns
$ open example_sim.vcd
Of course, if your data type (T) is more complex than a single std_logic you will need some extra work.
Define a vector type of your data type (T_vector).
Define a "zero" constant value for your base type (T_zero), this will be the value that enters on the left when shifting to the right.
Overload the srl operator for the T_vector vector type.
Example with a T type (not tested):
type T_vector is array(natural range <>) of T;
constant T_zero: T := <some zero value for your type>;
...
function "srl"(l: T_vector; r: natural) return T_vector is
constant size: positive := l'length;
constant tmp: T_vector(0 to size - 1) := l;
variable res: T_vector(0 to size - 1);
begin
if r = 0 then
res := tmp;
elsif r = 1 then
res := T_zero & tmp(0 to size - 2);
else
res := (l srl 1) srl (r - 1);
end if;
return res;
end function "srl";

Unexpected result from VHDL design

It should output value of Qpl when all inputs are x and clk = 1 but it does not. What is the problem with the following code;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
--This is a D Flip-Flop with Synchronous Reset,Set and Clock Enable(posedge clk).
--Note that the reset input has the highest priority,Set being the next highest
--priority and clock enable having the lowest priority.
ENTITY syn IS
PORT (
Q : OUT std_logic; -- Data output
CLK : IN std_logic; -- Clock input
Qpl : IN std_logic;
RESET : IN std_logic; -- Synchronous reset input
D : IN std_logic; -- Data input
SET : IN std_logic -- Synchronous set input
);
END syn;
ARCHITECTURE Behavioral OF syn IS --architecture of the circuit.
BEGIN
--"begin" statement for architecture.
PROCESS (CLK) --process with sensitivity list.
BEGIN
--"begin" statment for the process.
IF (CLK'EVENT AND CLK = '1') THEN --This makes the process synchronous(with clock)
IF (RESET = '1') THEN
Q <= '0';
ELSE
IF (SET = '1') THEN
Q <= D;
ELSE
Q <= Qpl;
END IF;
END IF;
END IF;
END PROCESS; --end of process statement.
END Behavioral;
Following diagram is showing the waveform of the above design, and desired operation requirements;
From the waveform diagram, it seems that everything works alright, when the input signal SET becomes U, the if condition cannot be evaluated, thus the output Q also becomes as such, namely U. You can see while SET was 0, the output Q was getting the value of Qpl correctly.
Sorry for the crude drawing, but you can see at the circled clock rising while SET is 0, Q gets the value of Qpl as expected. Only after SET signal becomes U, the output Q also loses its value in the next clock rising event, and also becomes U
You code and comments differ. As does the table/diagram. A D-flipflop/register is a very simple component. Example:
entity dff is
port (
clk : in std_logic;
rst : in std_logic;
set : in std_logic;
load : in std_logic;
d : in std_logic;
q : out std_logic
);
architecture rtl of dff is
begin
dff_proc : process(clk)
begin
if rising_edge(clk) then
if rst='1' then
q <= '0';
elsif set='1' then
q <= '1';
elsif load='1' then
q <= d;
end if;
end if;
end process;
end architecture;

ISim shows U for all outputs

I have a simple VHDL design and test bench that does not produce the expected output. ISim shows 'U' for all the outputs until the 'running' state is achieved (myState='1'). Then they show 0 and X values. The first PROCESS block should set all outputs to '0' when ENABLE is '0'. The test bench toggles ENABLE 0-1-0 to insure an event triggers the process, but the outputs stay at 'U'. Is the problem in the design, the test, or both?
VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity TestHarness1 is
port (
ADAT_WDCLK : in std_logic;
ADAT_BCLK: in std_logic;
ADAT_OUT12: in std_logic;
ENABLE: in std_logic;
PCM_FS : out std_logic;
PCM_CLK : out std_logic;
PCM_DIN : out std_logic
);
end TestHarness1;
architecture Behavioral of TestHarness1 is
--type state is (STOPPED, RUNNING);
signal tmp : std_logic;
signal myState : std_logic;
begin
PCM_DIN <= tmp;
-- State management process
process (ENABLE, ADAT_WDCLK) begin -- Eval on input changes
if (ENABLE = '0') then
myState <= '0'; --STOPPED;
PCM_FS <= '0'; -- All outputs muted
PCM_CLK <= '0';
tmp <= '0';
else
if (myState = '0' and rising_edge(ADAT_WDCLK)) then
-- Move to running state only at start of a frame
myState <= '1'; --RUNNING;
end if;
end if;
end process;
-- Output process
process (ADAT_WDCLK, ADAT_BCLK, myState) variable counter: integer := 0; begin
-- Only do something if we are in running state, process above
-- sets outputs when stopped.
if (myState = '1') then
-- Pass the clocks through, inverting the bit clock
PCM_FS <= ADAT_WDCLK;
PCM_CLK <= not ADAT_BCLK;
-- Generate fixed bit pattern data '11000101'
if rising_edge(ADAT_WDCLK) then
-- This would happen naturally since there are 4 bytes per word clock
counter := 0;
end if;
if falling_edge(ADAT_WDCLK) then
-- This would happen naturally since there are 4 bytes per word clock
counter := 0;
end if;
if rising_edge(ADAT_BCLK) then -- Change data state only on falling edge of output PCM_CLK
if counter = 0 or counter = 1 or counter = 5 or counter = 7 then
tmp <= '1';
else
tmp <= '0';
end if;
if (counter = 7) then
counter := 0; -- Reset counter
else
counter := counter + 1; -- Just inc counter
end if;
end if;
end if;
end process;
end Behavioral;
Test Bench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY TH1TestBench3 IS
END TH1TestBench3;
ARCHITECTURE behavior OF TH1TestBench3 IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT TestHarness1
PORT(
ADAT_WDCLK : IN std_logic;
ADAT_BCLK : IN std_logic;
ADAT_OUT12 : IN std_logic;
ENABLE : IN std_logic;
PCM_FS : OUT std_logic;
PCM_CLK : OUT std_logic;
PCM_DIN : OUT std_logic
);
END COMPONENT;
--Inputs
signal ADAT_WDCLK : std_logic := '0';
signal ADAT_BCLK : std_logic := '0';
signal ADAT_OUT12 : std_logic := '0';
signal ENABLE : std_logic := '0';
--Outputs
signal PCM_FS : std_logic;
signal PCM_CLK : std_logic;
signal PCM_DIN : std_logic;
-- Clock period definitions. Note WDCLK is defined in terms of the bit clock
-- to insure they are exactly in sync.
constant ADAT_BCLK_period : time := 326 ns; -- About 3.072MHz (https://www.sensorsone.com/frequency-to-period-calculator/)
constant ADAT_WDCLK_period : time := ADAT_BCLK_period * 64; -- 48KHz
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: TestHarness1 PORT MAP (
ADAT_WDCLK => ADAT_WDCLK,
ADAT_BCLK => ADAT_BCLK,
ADAT_OUT12 => ADAT_OUT12,
ENABLE => ENABLE,
PCM_FS => PCM_FS,
PCM_CLK => PCM_CLK,
PCM_DIN => PCM_DIN
);
-- Clock process definitions
ADAT_WDCLK_process :process
begin
ADAT_WDCLK <= '0';
wait for ADAT_WDCLK_period/2;
ADAT_WDCLK <= '1';
wait for ADAT_WDCLK_period/2;
end process;
ADAT_BCLK_process :process
begin
ADAT_BCLK <= '1';
wait for ADAT_BCLK_period/2;
ADAT_BCLK <= '0';
wait for ADAT_BCLK_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
wait for 100 ns;
ENABLE <= '1';
wait for 100 ns;
ENABLE <= '0';
wait for 7500 ns;
ENABLE <= '1';
wait for ADAT_WDCLK_period*10;
-- insert stimulus here
wait;
end process;
END;
ISim shows the ENABLE pulse early in the simulation, but the outputs remain 'U' until the rising edge of the WCLK with ENABLE=1. Then they start to change (as designed) but they show some X values.
Modified VHDL
For reference, here is the modified VHDL that resolves the problem of U's and X's in the simulation output. However, there is a functional problem with the PCM_DIN output... seems like it is delayed one (BCLK) cycle. I expected it to be '1' as soon as ADAT_WDCLK goes high the first time after ENABLE. But it does not go to '1' until a BLCK cycle later.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity TestHarness1 is
port (
ADAT_WDCLK : in std_logic;
ADAT_BCLK: in std_logic;
ADAT_OUT12: in std_logic;
ENABLE: in std_logic;
PCM_FS : out std_logic;
PCM_CLK : out std_logic;
PCM_DIN : out std_logic
);
end TestHarness1;
architecture Behavioral of TestHarness1 is
--type state is (STOPPED, RUNNING);
signal tmp : std_logic;
signal myState : std_logic;
begin
PCM_DIN <= tmp;
-- State management process
process (ENABLE, ADAT_WDCLK) begin -- Eval on input changes
if (ENABLE = '0') then
myState <= '0'; --STOPPED;
else
if (myState = '0' and rising_edge(ADAT_WDCLK)) then
-- Move to running state only at start of a frame
myState <= '1'; --RUNNING;
end if;
end if;
end process;
-- Output process
process (ADAT_WDCLK, ADAT_BCLK, myState) variable counter: integer := 0; begin
-- Only do something if we are in running state
if (myState = '0') then
PCM_FS <= '0'; -- All outputs muted
PCM_CLK <= '0';
tmp <= '0';
elsif (myState = '1') then
-- Pass the clocks through, inverting the bit clock
PCM_FS <= ADAT_WDCLK;
PCM_CLK <= not ADAT_BCLK;
if rising_edge(ADAT_BCLK) then -- Generate fixed serial bit pattern
if counter = 0 or counter = 1 or counter = 5 or counter = 7 then
tmp <= '1';
else
tmp <= '0';
end if;
if (counter = 7) then
counter := 0; -- Reset counter
else
counter := counter + 1; -- Just inc counter
end if;
end if;
end if;
end process;
end Behavioral;
ISim of the above (including the internal myState signal)... why is PCM_DIN delayed one BCLK cycle?
Regarding the 'X' (Forcing Unknown) values you are seeing:
You are driving the signals PCM_FS, PCM_CLK and tmp from multiple processes, which results in the simulator being unable to resolve the value being driven. You need to fix this such that they are only being driven from one process, or drive 'Z' when they are not in use.
Regarding the 'U' values, they exist because you have no initial values for the signals. Once you write the signals for the first time (after the enable), they will be assigned for the first time.

How to model two D flip-flops with multiplexing logic

I would like to model two D flip-flops using a multiplexer for some logic. I want to have static outputs of "000" for the three MSB when the multiplexer selects DFF D1 (B = 0) and the three LSB should be fixed to "111" when the multiplexer selects DFF D2 (B = 1).
This is my code -- which I originally typed blindly without checking for obvious syntax errors -- below. I don't know how to solve my problem:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity dff_mux is
Port ( D1, D2 : in STD_LOGIC_VECTOR(11 DOWNTO 0);
clk : in STD_LOGIC;
rst : IN STD_LOGIC;
B : in STD_LOGIC;
data : out STD_LOGIC_VECTOR(11 DOWNTO 0));
end dff_mux;
architecture Behavioral of dff_mux is
signal Q1, Q2 : std_logic_vector(11 downto 0);
begin
process(clk,rst)
begin
if (rst = '1') then
Q1<="000000000000";
elsif (clk'event and clk='1') then
if (B = '0') then
-- I want to fix thee MSB to "000"
-- other bits shall retain their input value
D1(11) <= '0';
D1(10) <= '0';
D1(9) <= '0';
Q1 <= D1;
elsif (B = '1') then
-- fix three LSB to "111"
-- other bits retain their input value
D2(2) <= '1';
D2(1) <= '1';
D2(0) <= '1';
Q2 <= D2;
end if;
end if;
end process;
-- MUX description: select D1 when B = 0, else select D2 when B = 1
MUX : process(B)
begin
data <= Q1 when (B = '0') else
Q2;
end process MUX;
end Behavioral;
Thanks in advance to anybody who can help me.
There are numerous errors in your VHDL design description. The two process statements drive the same signals (Q1 and Q2). The second process has three errors (no process statement label, while a label is specified in closing, concurrent signal assignment statements where sequential signal assignment statements are appropriate). It would appear the second process statement should be eliminated in it's entirety.
If the intent is to have a multiplexer on the inputs to the Q1,Q2 registers the first process is non-functional. You can't assign values to a formal input inside a block.
You should be assigning the B selected values to Q1 and Q2 directly inside the process statement (inside the clk elsif).
Your assignment to D(11) is defective (uses == instead of <=).
It isn't a multiplexer if you only assign one value to a particular signal (e.g. longest static prefix D1 and D2). Note there is no reset value for Q2 provided.
There is no place data is assigned.
If you're doing this for class work there is little benefit in someone providing the answer without learning VHDL a bit more. If you're earnestly trying to learn VHDL you need more and incrementally building exercises.
If I understand what you are trying to do correctly it would look something like this:
architecture Behavioral of basculeD is
-- signal Q1, Q2 : std_logic_vector(11 downto 0);
begin
-- process(clk,rst)
-- begin
-- if (rst='1') then Q1<="000000000000";
-- elsif ( clk'event and clk='1') then
-- if (B='0') then
-- D1(11) =='0'; -- i want to fix the 3MSB of D1 in the "000" ...
-- D1(10) <='0';
-- D1(9) <='0';
-- Q1<= D1;
-- elsif (B='1') then
-- D2(2)<= '1'; -- the 3LSB are fixed to 111 , and defaut value ...
-- D2(1)<='1';
-- D2(0)<='1';
-- Q2<=D2;
-- end if;
-- end if;
-- end process;
-- description MUX : select D1 when B=0, else select D2 when B= 1
-- process( B)
-- begin
-- Q1 <= D1 when B='0' else
-- Q2<=D2 when B='1' ;
-- end process MUX;
MUXED_REG:
process (clk,rst)
begin
if rst = '1' then
data <= (others => '0'); -- equivalent to "000000000000"
elsif clk'event and clk = '1' then
-- the actual multiplexer:
if B = '0' then
data <= ("000" & D1(8 downto 0));
else -- B = '1', or other values
data <= (D2(11 downto 3) & "111");
end if;
end if;
end process;
end Behavioral;
You could of course retain an intermediary signal, say Q and use it in place of data above, with a concurrent signal assignment from Q to data (the output).
Using the above architecture in place of your's analyzes.
With a test bench:
library ieee;
use ieee.std_logic_1164.all;
entity basculeD_test is
end entity;
architecture test of basculeD_test is
component basculeD is
port (
d1, d2: in std_logic_vector(11 downto 0);
clk: in std_logic;
rst: in std_logic;
b: in std_logic;
data: out std_logic_vector(11 downto 0)
);
end component;
signal d1: std_logic_vector(11 downto 0) := (others => '1');
signal d2: std_logic_vector(11 downto 0) := (others => '0');
signal clk: std_logic := '0';
signal rst: std_logic := '1';
signal b: std_logic := '0';
signal data: std_logic_vector(11 downto 0);
begin
CLOCK:
process
begin
wait for 10 ns;
clk <= not clk;
if Now > 100 ns then
wait;
end if;
end process;
RESET:
process
begin
wait for 31 ns;
rst <= '0';
wait;
end process;
DUT:
basculeD
port map (
d1 => d1,
d2 => d2,
clk => clk,
rst => rst,
b => b,
data => data
);
STIMULUS:
process
begin
wait for 65 ns;
b <= '1';
wait;
end process;
end architecture;
And using the replacement architecture for basculeD with the MUXED_REG process:
david_koontz#Macbook: ghdl -a basculeD.vhdl
david_koontz#Macbook: ghdl -e basculeD_test
david_koontz#Macbook: ghdl -r basculeD_test --wave=basculeD_test.ghw
david_koontz#Macbook: open basculeD_test.gtkw (previously saved save file)
Gives:
There's of course the possibility that you are trying to separate storage from multiplexing entirely, which says you could use Q1 and Q2 as registers (and only need 9 bits), a separate multiplexer (as implied in your original basculeD architecture) allowing B to steer between modified Q1 and Q2 register values on output data.
That would look something like this:
architecture Behavioral of basculeD is
signal Q1: std_logic_vector(8 downto 0);
signal Q2: std_logic_vector(11 downto 3);
begin
REGS:
process (clk, rst)
begin
if rst = '1' then
Q1 <= (others => '0');
Q2 <= (others => '0');
elsif clk'event and clk = '1' then
Q1 <= D1 (8 downto 0);
Q2 <= D2(11 downto 3);
end if;
end process;
MUX:
process (B,Q1,Q2)
begin
if B = '0' then
data <= ("000" & Q1);
else
data <= (Q2 & "111");
end if;
end process;
And give you something like this:
VHDL is meant to convey a design specification to the reader, which is made easier when using some convention for capitalization (VHDL isn't case sensitive except in extended identifiers) and indentation.
Welcome to StackOverflow! First off, this is an English Question & Answer site. Please translate all pertinent terms into English, i.e. basculeD => D flip-flop etc. Also, try to describe your problem the best you can without too many spelling mistakes (spell check!) or grammar errors. This will help other people understand you and help you efficiently.
Anyway, your main problem is, that you have input ports D1 and D2 and you try to write to them. Instead, you should just take whatever bits you need and disregard the other bits.
Instead of trying to write to the input, which is not possible, you should try this:
Q2 <= D2(11 downto 3) & "111";
This statement takes bits 11 through 3 from D2 and assigns them to bits 11 through 3 of Q2. Bits 2 through 0 of Q2 are assigned a constant value of "111".
You should remember that you cannot "re-write" input port values. Your last process could also be re-written to a parallel statement.
Also, your design is peculiar in the sense that you want to store the modified value separately.
Consider this:
D1 = x"00A"; D2 = x"00B", B = '0', clk --> rising edge
Now, Q1 = x"00A", Q2 = x"???", data = Q1 = x"00A", B = '0', clk = '1'
Now, Q1 = x"00A", Q2 = x"???", data = Q2 = x"???", B = '1', clk = '1'
You need at least two clock periods to switch your outputs when you want to switch between B = '1' and B = '0', because Q1 resp Q2 will hold old (and possibly uninitialized) values.
Your design might not do what you want it to do. If you want a multiplexer, go for a multiplexer. If you want a flip flop, build a flip flop.
process(clk,rst)
begin
if (rst = '1') then
data <= (others => '0');
elsif (clk'event and clk='1') then
if (B = '1') then
-- Select D2
data <= D2(11 downto 3) & "111";
else
-- Select D1
data <= "000" & D1(8 downto 0);
end if;
end if;
end process;
You might also want to think about whether a reset is really appropriate and whether a synchronous reset might be more beneficial.

Implementing a FSM in VHDL

Just wondering if I'm implementing a finite state machine in VHDL whether or not I need to state what all of the outputs are in every possible state? Even if I know that some outputs won't change from one state to the other and I know that the order of the states will also be in the same order?
For example, in this (forced) example:
entity test is
port (
clk : in std_logic;
a : in std_logic;
b: out std_logic;
c: out std_logic;
);
end test;
architecture Behavioral of test is
type executionStage is (s1,s2,s3);
signal currentstate, nextstate: executionStage;
begin
process (clk)
begin
if(rising_edge(clk)) then
currentstate <= nextstate;
else
currentstate <= currentstate;
end if;
end process;
process(currentstate)
begin
case currentstate is
when s1 =>
if (a = '1') then
b <= '1';
c <= '0';
else
b <= '1';
c <= '1';
end if;
nextstate <= s2;
when s2 =>
-- b doesnt change state from s1 to here, do I need to define what it is here?
if (a = '1') then
b <= '1';
c <= '1';
else
b <= '1';
c <= '0';
end if;
nextstate <= s3;
when s3 =>
if (a = '1') then
b <= '0';
c <= '0';
else
b <= '1';
c <= '1';
end if;
nextstate <= s1;
end case;
end process;
end Behavioral;
From my understanding if I don't do this then latches are created?
It's not a big deal in something like that example but if I have a machine with more than 10 outputs and more than 10 states then my VHDL files start to look incredibly messy and I'm sure it must be bad practice to copy and paste the same thing over and over. Is there a better way of doing this?
edit: Can I define a 'default' state for an ouput? IE set b to be 1 outside of all the processes and then only define what it is in the case statements where it is 0? Would that work?
Yes, you will infer latches if you only drive signals intended to be combinatorial in some branches of the process.
However, you can define a 'default' state for the signal simply by assigning a value to it before the case statement (but within the same process). For example:
process(currentstate, a)
begin
b <= '1';
c <= '1';
case currentstate is
when s1 =>
if (a = '1') then
c <= '0';
end if;
nextstate <= s2;
when s2 =>
-- b doesnt change state from s1 to here, do I need to define what it is here?
if (a /= '1') then
c <= '0';
end if;
nextstate <= s3;
when s3 =>
if (a = '1') then
b <= '0';
c <= '0';
end if;
nextstate <= s1;
end case;
end process;
Three problems with your example code:
The last port in your port list should not have a semicolon:
port (
clk : in std_logic;
a : in std_logic;
b: out std_logic;
c: out std_logic -- no semicolon here!!!
);
In your register process, you should not have an "else" statement. While this will probably be accepted by the tools, it will confuse your fellow-VHDL designers.
process (clk)
begin
if(rising_edge(clk)) then
currentstate <= nextstate;
end if;
end process;
In your combinational logic, the sensitivity list should contain all signals that you read: process(a, currentstate). In this particular case (again) things will probably work out fine, but you are bound to infer latches or cause other problems if your sensitivity list is not correct.
As for your question:
Yes, you need to assign a value (for each state) to each signal in the combinational process.
As Tomi mentions, you can easily do this by assigning a default value in the beginning of the process.
But you can also write the entire state machine in one single synchronous process. This way, you do not have to assign a value to every signal in every state.
Just a note to Philippe's response (can't comment on it directly?)..
I do prefer to write state machines in the two process style. It makes it very clear where you expect inferred flipflops and where you don't. It's also a bit more along the lines of
describing the hardware - imagine building a state machine with board level logic for example.
The registered device matches the state <= next_state process,
and the case statement maps to the and/or array in front of the state register..
Having said that, I typically use one process state machines for small simple tasks, and move over to two process machines for bigger ones.
I will even sometimes use a third process for organizing state outputs into different "task" groups.. but not often. A really large state machine tends to tell me the architecture needs work..
process (clk)
begin
if(rising_edge(clk)) then
currentstate <= nextstate;
end if;
end process;
Hi
the above process is problematic but not due to the sensitivity list. It is ok to only declare clk for sequential process. Both simulation and synthesis tools won't have problems with it. clk is the fastest changing/transitioning signal after all in your code.
However, you should use an (preferrably) asynchronous reset. Of course, vendors nowadays say that for FPGA design, resets are not even necessary; they happen at boot time. Or they propose a synchronous reset.
Still, an asynchronous reset is valuable for a board-based environment.
In short: add a reset to your design and fix its behavior properly.
Kind regards
Nikolaos Kavvadias
The following VHDL code is edge sensitive state machine.
The edge sensitive process in this example will make both “out1” and “out2” in phase with “clk”.
entity main_code is
Port ( clk : in STD_LOGIC;
in1 : in STD_LOGIC;
in2 : in STD_LOGIC;
out1 : out STD_LOGIC;
out2 : out STD_LOGIC);
end main_code;
architecture Behavioral of main_code is
-- here are temp signals to associate or assign output (out1 and out2) values indirectly
signal out1_temp : std_logic := '0';
signal out2_temp : std_logic := '0';
-- counter registers
signal counter : integer range 0 to 255 := 0;
signal counter_8th_clk : integer range 0 to 255 := 0;
-- state machines definition
type state_machine_type is (s0,s1);
signal state : state_machine_type := s0;
begin
-- concurrent assignments
out1 <= out1_temp;
out2 <= out2_temp;
--half clock generator process
half_clock : process (clk) is
begin
if rising_edge(clk) then
--out1_temp <= not out1_temp;
end if;
end process half_clock;
-- max counter = ndiv -1; here ndiv=4; counter starts from zero;
one_fourth_clock : process (clk)
begin
if rising_edge(clk) then
counter <= counter + 1;
if (counter >= 3) then
counter <= 0;
-- out2_temp <= not out2_temp;
end if;
end if;
end process one_fourth_clock;
one_eighth_clock : process (clk)
begin
if rising_edge(clk) then
counter_8th_clk <= counter_8th_clk + 1;
if (counter_8th_clk>=7) then
counter_8th_clk <= 0;
-- out2_temp <= not out2_temp;
end if;
end if;
end process one_eighth_clock;
-- state_process creates two half clock (speed) with out1 out of phase with clk
-- and out2 in-phase with clk
-- following process is sensitive to clk level not edge
state_process_edge_sensitive : process (clk)
begin
if rising_edge (clk) then
case state is
when s0 =>
out1_temp <= not out1_temp;
state <= s1;
when s1 =>
out2_temp <= not out2_temp;
state <= s0;
end case;
end if;
end process state_process_edge_sensitive;
end Behavioral;
here is the test bench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY my_test_bench IS
END my_test_bench;
ARCHITECTURE behavior OF my_test_bench IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT main_code
PORT(
clk : IN std_logic;
in1 : IN std_logic;
in2 : IN std_logic;
out1 : OUT std_logic;
out2 : OUT std_logic
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal in1 : std_logic := '0';
signal in2 : std_logic := '0';
--Outputs
signal out1 : std_logic;
signal out2 : std_logic;
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: main_code PORT MAP (
clk => clk,
in1 => in1,
in2 => in2,
out1 => out1,
out2 => out2
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
-- wait for 100 ns;
--
-- wait for clk_period*10;
-- insert stimulus here
wait;
end process;
END;
The following VHDL code is level sensitive state machine.
The level sensitive process in this example will make “out1” out of phase with “clk” and “out2” in phase with “clk”.
entity main_code is
Port ( clk : in STD_LOGIC;
in1 : in STD_LOGIC;
in2 : in STD_LOGIC;
out1 : out STD_LOGIC;
out2 : out STD_LOGIC);
end main_code;
architecture Behavioral of main_code is
-- here are temp signals to associate or assign output (out1 and out2) values indirectly
signal out1_temp : std_logic := '0';
signal out2_temp : std_logic := '0';
-- counter registers
signal counter : integer range 0 to 255 := 0;
signal counter_8th_clk : integer range 0 to 255 := 0;
-- state machines definition
type state_machine_type is (s0,s1);
signal state : state_machine_type := s0;
begin
-- concurrent assignments
out1 <= out1_temp;
out2 <= out2_temp;
--half clock generator process
half_clock : process (clk) is
begin
if rising_edge(clk) then
--out1_temp <= not out1_temp;
end if;
end process half_clock;
-- max counter = ndiv -1; here ndiv=4; counter starts from zero;
one_fourth_clock : process (clk)
begin
if rising_edge(clk) then
counter <= counter + 1;
if (counter >= 3) then
counter <= 0;
-- out2_temp <= not out2_temp;
end if;
end if;
end process one_fourth_clock;
one_eighth_clock : process (clk)
begin
if rising_edge(clk) then
counter_8th_clk <= counter_8th_clk + 1;
if (counter_8th_clk>=7) then
counter_8th_clk <= 0;
-- out2_temp <= not out2_temp;
end if;
end if;
end process one_eighth_clock;
-- state_process creates two half clock (speed) with out1 out of phase with clk
-- and out2 in-phase with clk
-- following process is sensitive to clk level not edge
state_process_level_sensitive : process (clk)
begin
case state is
when s0 =>
out1_temp <= not out1_temp;
state <= s1;
when s1 =>
out2_temp <= not out2_temp;
state <= s0;
end case;
end process state_process_level_sensitive;
end Behavioral;
here is the test bench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY my_test_bench IS
END my_test_bench;
ARCHITECTURE behavior OF my_test_bench IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT main_code
PORT(
clk : IN std_logic;
in1 : IN std_logic;
in2 : IN std_logic;
out1 : OUT std_logic;
out2 : OUT std_logic
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal in1 : std_logic := '0';
signal in2 : std_logic := '0';
--Outputs
signal out1 : std_logic;
signal out2 : std_logic;
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: main_code PORT MAP (
clk => clk,
in1 => in1,
in2 => in2,
out1 => out1,
out2 => out2
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
-- wait for 100 ns;
--
-- wait for clk_period*10;
-- insert stimulus here
wait;
end process;
END;

Resources