Signal <signal> cannot be synthesized, bad synchronous description - vhdl

I'm trying to implement a component that takes in input a base clock and as output a pattern accordingly to this scheme:
I'm getting this error, and i've tried to fix it in many ways following various suggestion also from stackoverflow, but nothing...
ERROR:Xst:827 - "E:/Progetti/nuovi/Clock_generator/CG_ex_3/clock_ex3.vhd" line 34: Signal check_0 cannot be synthesized, bad synchronous description. The description style you are using to describe a synchronous element (register, memory, etc.) is not supported in the current software release.
Some times the same error refer to pre_forma_clk
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity clock_ex3 is
Port ( base_clk : in STD_LOGIC;
forma_clk : out STD_LOGIC);
end clock_ex3;
architecture Behavioral of clock_ex3 is
signal pre_forma_clk : std_logic := '0';
begin
forma_clk <= pre_forma_clk;
pattern_generator : process(base_clk) --line 34
variable check_0 : natural := 0;
variable check_1 : natural := 0;
variable check_2 : natural := 0;
variable check_3 : natural := 0;
begin
if (rising_edge(base_clk)) then
check_0 := check_0 + 1;
if (check_0 = 15) then
pre_forma_clk <= not pre_forma_clk;
end if;
end if;
if (falling_edge(base_clk) and check_0 >= 15) then
check_1 := check_1 + 1;
if (check_1 = 10) then
pre_forma_clk <= not pre_forma_clk;
end if;
end if;
if (falling_edge(base_clk) and check_1 >= 10) then
check_2 := check_2 + 1;
if (check_2 = 15) then
pre_forma_clk <= not pre_forma_clk;
end if;
end if;
if (rising_edge(base_clk) and check_2 >= 15) then
check_3 := check_3 + 1;
if (check_3 = 10) then
pre_forma_clk <= not pre_forma_clk;
check_0 := 0;
check_1 := 0;
check_2 := 0;
check_3 := 0;
end if;
end if;
end process;
end Behavioral;
I've already tried to separate IF conditions in different IFs...
thanks for help

Your question is pretty well answered here. The difference between that question and yours, is that the specific error in your code is that you have multiple if (rising_edge(clk)) then structures inside one process; a synthesis-eligible process can only contain one edge detector of this type.
Looking at your functional requirement, I would implement this using two separate rising and falling edge counters, each with their own process, then write another process implementing a state machine that works with these counters to implement the required state transitions and counter resets.

Related

VHDL code to read the inputs of a parallel AD converter

I was wondering if someone could help me to find the error I am making when reading the analog input introduced to the AD7822 converter by a potentiometer capable of varying its voltage in a range of 0 to 5V.
As far as I understand what I have to do is to generate a 20ns wide pulse for the CONVST bit every 10MHz at most (starting from a clock operating at a maximum frequency of 50 MHz), then wait for the DR to be set to 0 and the value of the digital inputs could be taken.
Timeline for working with AD7822 in automatic mode
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity db_read is
generic
(
div : natural := 5
);
port
(
-- Input ports
clk_in : in std_logic;
rd : in std_logic;
db_input : in std_logic_vector (7 downto 0) := (others => '0');
-- Output ports
convst : out std_logic := '1';
db_output : out std_logic_vector (7 downto 0) := (others => '0')
);
end db_read;
-- Library Clause(s) (optional)
-- Use Clause(s) (optional)
architecture arch1 of db_read is
begin
----------------------------------------------------------------------
-- Send CONVST each div/50MHz ms.
----------------------------------------------------------------------
process(clk_in)
variable cont_convst : integer range 0 to div := 0;
begin
if (rising_edge(clk_in)) then
cont_convst := cont_convst + 1;
if (cont_convst = 1) then
convst <= '0';
else
convst <= '1';
end if;
if (cont_convst = div) then
cont_convst := 0;
end if;
end if;
end process;
----------------------------------------------------------------------
-- Read digital inputs when ready
----------------------------------------------------------------------
process(clk_in)
variable cont_rd : integer := 0;
begin
if (rising_edge(clk_in)) then
-- Detect if RD takes '0' value
if (rd = '0') then
cont_rd := cont_rd + 1;
end if;
if (cont_rd = 1) then
db_output <= db_input;
end if;
if (rd = '1') then
cont_rd := 0;
end if;
end if;
end process;
end arch1;
When I simulate it on a board what I see is that I always have all the outputs at high state regardless of the voltage that I introduce to the input of the converter.

Why does the output signals post-synthesis not work as usual?

I had written a small VHD file for simulating the behavior of a quadrature decoder, enclosed below. Simulating the design with a generic testbench works as expected. But after generating a synthesizable design with Quartus, I run into one of two problems (while playing with using unsigned, for example)
1. The position and direction signal are always at a constant 0 value throughout the post-synthesis simulation.
2. The position value seems to jump 10 values every 3-4 clock cycles, which I attribute to some jitter in data.
Does anyone have any recommendations to solve this issue? Is this mainly a timing problem or is there a major flaw in my design?
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.NUMERIC_STD.ALL;
entity quad_decoder is
port(rst : in std_logic;
clk : in std_logic;
a : in std_logic;
b : in std_logic;
direction : out std_logic;
position : out std_logic_vector(8 DOWNTO 0));
end quad_decoder;
architecture behavioral of quad_decoder is
begin
process(clk)
variable counter : integer range 0 to 360 := 0;
variable chanA,chanB : std_logic;
variable int_direction : std_logic;
begin
if (rst = '0') then
int_direction := '0';
counter := 0;
elsif (rising_edge(clk)) then
chanA := a;
chanB := b;
if (chanA = '1') and (chanB = '0') then
if (counter = 360) then
counter := 0;
else
counter:= counter + 1;
end if;
int_direction := '1';
elsif (chanA = '0') and (chanB = '1') then
if (counter = 0) then
counter := 360;
else
counter := counter-1;
end if;
int_direction := '0';
else
counter := counter;
int_direction := int_direction;
end if;
position <= std_logic_vector(to_unsigned(counter,9));
direction <= int_direction;
end if;
end process;
end behavioral;
The expected pre-synthesis snap is here.
I've linked an example snap of the post-synthesis simulation here. As seen, no change to position nor direction in multiple clock cycles.
If anyone is inquisitive, doing assignments right at the clock edge as well as turning the reset signal high proved to introduce all kinds of timing issues, which passed the multi-corner timing analysis test, but failed other tests in Quartus that I had failed to notice.
I can go into more details if my answer is vague.

Do I need increment pwm_count variable?

I'm learning VHDL language right now and I have some problems of understanding a part of the code in my course. I don't understand in process freq_counter this statement -> if(pwm_count < max_pwm_count), because we don't know the value of max_pwm_count and also I don't see any incrementation of variable pwm_count.
Thank you, guys!
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
entity PWM is
generic (
freq : integer := 50; --50Hz
INPUT_CLK : integer := 50000000; --50MHz
BITH_DEPTH : integer := 8
);
Port (
ENABLE : in std_logic;
CLK : in std_logic;
PWM_OUT : out std_logic;
DUTY_CYCLE : in std_logic_vector(BITH_DEPTH-1 downto 0)
);
end PWM;
architecture behavioral of PWM is
constant max_freq_count : integer:= INPUT_CLK/freq;
constant pwm_step : integer := max_freq_count/2**BITH_DEPTH;
signal PWM_value : std_logic := '0';
signal freq_count : integer range from 0 to max_freq_count := 0;
signal pwm_count : integer range from 0 to 2**BITH_DEPTH := 0;
signal max_pwm_count : integer range from 0 to 2**BITH_DEPTH := 0;
signal pwm_step_count : integer range from 0 to max_freq_count := 0;
begin
max_pwm_count <= TO_INTEGER(unsigned(DUTY_CYCLE));
PWM_OUT <= PWM_value;
freq_counter: process(CLK)
begin
if rising_edge(CLK) then
if(ENABLE='0') then
if(freq_count < max_freq_count) then
freq_count <= freq_count + 1;
if(pwm_count < max_pwm_count) then
PWM_value<='1';
if(pwm_step_count<pwm_step) then
pwm_step_count<=pwm_step_count+1;
else
pwm_step_count<=0;
pwm_count<=0;
end if;
else
pwm_value<='0';
end if;
else
freq_count <= 0;
pwm_count <= 0;
end if;
else
PWM_value <= '0';
end if;
end if;
end process freq_counter;
end PWM;
We DO know the value of max_pwm_count : it is initialised to 0 and never re-assigned. Therefore the IF can never be true and ... so on.
As far as incrementing PWM_Count is concerned, your understanding seems to be better than the author's, which puts you in a reasonable position for the necessary re-write.
I recommend first writing a testbench so you can observe its behaviour, and get it correct in simulation.

Self implemented UART in VHDL always skips second character

I am learning VHDL right now and I tried to implement UART (1 start bit, 8 data bits, 1 stop bit) to periodically send a hardcoded string.
Everything works as expected - I receive string every 1 second. However, there is no second character.
No matter how long the string is, which character it is. I checked this fact on a oscilloscope and there is no waveform for this particular character. 1 start bit, 8 bits for first character, stop bit, start bit and 8 bits for third character, not the second one.
Following code is for 10 MHz clock divided to send with ~38 400 bits per second, I also tried with 9600 bits per second, both the same problem.
I'm using Altera MAX10 dev board: http://maximator-fpga.org/
Short video how it works:
https://gfycat.com/JoyousIlliterateGuillemot
UART.vhd:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.ALL;
use ieee.std_logic_arith.all;
entity UART is
port (
clk_10mhz: in STD_LOGIC;
txPin: out STD_LOGIC
);
end entity;
architecture Test of UART is
signal txStart: STD_LOGIC;
signal txIdle: STD_LOGIC;
signal txData: STD_LOGIC_VECTOR(7 downto 0);
component TX is
port (
clk_in: in STD_LOGIC;
start: in STD_LOGIC;
data: in STD_LOGIC_VECTOR(7 downto 0);
tx: out STD_LOGIC;
txIdle: out STD_LOGIC
);
end component TX;
begin
process (clk_10mhz, txIdle)
variable clkDividerCounter : integer range 0 to 10000000;
variable textToSend : string(1 to 31) := "Hello darkness my old friend!" & CR & LF;
variable currentCharacterIndex : integer range 0 to 31;
begin
if (rising_edge(clk_10mhz)) then
if (clkDividerCounter < 10000000) then
clkDividerCounter := clkDividerCounter + 1;
else
clkDividerCounter := 0;
currentCharacterIndex := 1;
end if;
if (txIdle = '1' and currentCharacterIndex > 0) then
txData <= CONV_STD_LOGIC_VECTOR(character'pos(textToSend(currentCharacterIndex)),8);
txStart <= '1';
if (currentCharacterIndex < 31) then
currentCharacterIndex := currentCharacterIndex + 1;
else
currentCharacterIndex := 0;
txStart <= '0';
end if;
end if;
end if;
end process;
u1: TX port map (clk_10mhz, txStart, txData, txPin, txIdle);
end Test;
TX.vhd:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.ALL;
entity TX is
port (
clk_in: in STD_LOGIC;
start: in STD_LOGIC;
data: in STD_LOGIC_VECTOR(7 downto 0);
tx: out STD_LOGIC;
txIdle: out STD_LOGIC
);
end entity;
architecture Test of TX is
signal idle: STD_LOGIC;
begin
process (clk_in)
variable bitIndex : integer range 0 to 9;
variable clkDividerCounter : integer range 0 to 260;
variable dataFrame : STD_LOGIC_VECTOR(9 downto 0);
variable dataFrameCurrentIndex : integer range 0 to 9;
begin
if (rising_edge(clk_in)) then
if (start = '1' and idle = '1') then
dataFrame(0) := '0';
dataFrame(8 downto 1) := data;
dataFrame(9) := '1';
dataFrameCurrentIndex := 0;
idle <= '0';
end if;
if (idle = '0') then
if (clkDividerCounter < 260) then
clkDividerCounter := clkDividerCounter + 1;
else
if (dataFrameCurrentIndex <= 9) then
tx <= dataFrame(dataFrameCurrentIndex);
dataFrameCurrentIndex := dataFrameCurrentIndex + 1;
else
idle <= '1';
end if;
clkDividerCounter := 0;
end if;
end if;
txIdle <= idle;
end if;
end process;
end Test;
Move the line
txIdle <= idle;
from TX.vhd outside the process. Signals take their new value after the process ends.
For example:
idle <= '0';
txIdle <= idle;
Will set txIdle to '1' if idle was '1' when the two statements were executed inside a process. You should notice that this means that txIdle will be '1' for two consecutive cycles and causes currentCharacterIndex to increment twice at the start.
Note that contrary to signals, variable take their new value when the assigning statement is encountered, and not at the end of the process as signals do.
While your code is not that terrible for a beginner, I recommend to use only signal when you start learning VHDL. It is much easier to make mistake with variables, or describe sub-optimal or broken implementation.
Also, as Brian mentioned, don't use std_logic_arith, especially when using numeric_std. They are conflicting with each other (some tools deal with it though) and std_logic_arith is not a IEEE standard, while numeric_std is.
Finally, simulation is a crucial part of hardware design. To avoid uninitialized pin, add a reset to your circuit, which is generally a good idea.

VHDL infinite loop

I'm writing a small piece of code to take a 32 bit input and output 2 bits at a time. I believe I'm having infinite loop problems from the while loop, based on simulation attempts. Everything looks right to me, compared to other examples of loops I've looked at. Any clue what I could be doing wrong?
library ieee;
use ieee.std_logic_1164.all;
entity regA is
port(mpcnd: in std_logic_vector(31 downto 0);
clk: in std_logic;
twobits: out std_logic_vector(1 downto 0));
end regA;
architecture behavior of regA is
begin
process
variable count: integer;
begin
count := 0;
while (count < 32) loop
if rising_edge(clk) then
twobits(0) <= mpcnd(count);
twobits(1) <= mpcnd(count+1);
count := count + 2;
end if;
end loop;
end process;
end behavior;
for a process you need either a sensitivity list or a wait statement within. a (not synthesisable but simulatable) version of your process could look as follows:
process
variable count: integer;
begin
count := 0;
while (count < 32) loop
wait until rising_edge(clk);-- if rising_edge(clk) then
twobits(0) <= mpcnd(count);
twobits(1) <= mpcnd(count+1);
count := count + 2;
--end if;
end loop;
end process;

Resources