VHDL Altera Qartus random data in unsigned register after (others => 0) + 1 - vhdl

I'm having trouble figuring out why I'm getting problems with my clock enable timer in a UART controller. The counter is cntR. It should start counting from zero after a condition is met, yet it starts at zero and then switches to a random number instead of incrementing 0 to 1. Here's the process code where something bad happens:
process(reset, clock)
begin
if reset = '1' then
cntR <= (others => '0');
elsif rising_edge(clock) then
if rcv_reg = r_idle and rxd = '1' then
cntR <= (others => '0');
else
if cntR = DIVVALUE then
cntR <= (others => '0');
else
cntR <= cntR + 1;
end if;
end if;
end if;
end process;
here are the declarations (probably not that important):
entity SART is
generic(
INCLK : natural := 50000000;
BAUDRATE : natural := 9600;
CNT_WIDTH : natural := 14
);
port(
clock : in std_logic;
reset : in std_logic;
send : in std_logic;
rxd : in std_logic;
data_in : in std_logic_vector(7 downto 0);
data_ready : out std_logic;
clear_to_send : out std_logic;
txd : out std_logic;
data_out : out std_logic_vector(7 downto 0)
);
end SART;
-- Receiver FSM states
type RCV_STATE_TYPE is (
r_idle,
r_start,
r_data1,r_data2,r_data3,r_data4,r_data5,r_data6,r_data7,r_data8,
r_stop1
);
signal rcv_reg, rcv_next : RCV_STATE_TYPE;
signal cntR : unsigned(CNT_WIDTH-1 downto 0);
This is what I get from Signal Tap:
For the record, I'm using Altera Quartus 13.0.0 and a DE0-Nano with a Cyclone IV FPGA.
Thank you in advance for your input.

I managed to fix this problem. It turns out, that I didn't have an SDC file in the project and hence the TimeQuest Timing Analyzer report stated that my maximum clock frequency is 10 times higher that when I had the SDC file attached. After writing an SDC file containing only clock declarations I got a maximum clock frequency of about 7 MHz from TimeQuest. I generated a PLL to get a 5 MHz frequency clock and now everything works flawlessly.

Related

Why won't a VHDL "inout" signal be assigned a value when used as an output

I have a VHDL description for a bridge, and the bidirectional signal "mem_data_port0" is not getting assigned any value regardless of what I write to it. The pins on the FPGA are assigned accordingly, but no output.
I have the code below (its for an FPGA going into a larger system, so comments will reflect other system components that are not the FPGA)
FYI: The FPGA is a Lattice LCMXO2-7000HC
Any tips on assigning "mem_data_port0"?
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
--use ieee.std_logic_signed.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
library machxo2;
use machxo2.all;
entity SinglePhasePowerAnalyzerBridge is
port(
output0 : out std_logic; -- dummy, unassigned outputs
output1 : out std_logic;
output2 : out std_logic;
output3 : out std_logic;
output4 : out std_logic;
output5 : out std_logic;
output6 : out std_logic;
output7 : out std_logic;
accq_data_in : in std_logic_vector (15 downto 0); -- accquisition data in
accq_clk : in std_logic; -- accquisition clock in
accq_data_ready : in std_logic; -- data ready in 0: sending voltage/current data, 1: sending frequency data
accq_reset : in std_logic; -- accquisition reset (active low)
accq_voltage_current : in std_logic; -- accquisition select for voltage and current 0: voltage, 1: current
buffer_data_port0 : out std_logic_vector (15 downto 0); -- buffer data
buffer_address_port0 : in std_logic_vector(12 downto 0); -- buffer address low bits
buffer_address_high_port0 : in std_logic_vector(2 downto 0); -- buffer address high bits
buffer_high_byte_en_port0 : in std_logic; -- high byte enable
buffer_low_byte_en_port0 : in std_logic; -- low byte enable
buffer_write_en_port0 : in std_logic; -- write enable
buffer_output_en_port0 : in std_logic; -- output enable
buffer_memory_en_port0 : in std_logic; -- memory enable
buffer_interrupt_out : out std_logic;
-- pins going to external SRAM memory
mem_data_port0 : inout std_logic_vector (15 downto 0);
mem_address_port0 : out std_logic_vector(12 downto 0);
mem_address_high_port0 : out std_logic_vector (3 downto 0);
mem_memory_en_port0 : out std_logic := '1';
mem_output_en_port0 : out std_logic := '1';
mem_write_en_port0 : out std_logic := '1';
mem_high_byte_en_port0 : out std_logic := '0';
mem_low_byte_en_port0 : out std_logic := '0';
debug_out : out std_logic -- debug output
);
end SinglePhasePowerAnalyzerBridge;
architecture rtl of SinglePhasePowerAnalyzerBridge is
signal frequency_storage_buffer : std_logic_vector (15 downto 0); -- frequency buffer
signal voltage_storage_pointer : integer range 0 to 8191;
signal current_storage_pointer : integer range 0 to 8191;
signal signal_accq_data_in : std_logic_vector (15 downto 0);
signal signal_accq_clk : std_logic;
signal signal_inverse_accq_clk : std_logic;
signal signal_accq_data_ready : std_logic;
signal signal_accq_reset : std_logic;
signal signal_accq_voltage_current : std_logic;
signal signal_delayed_inverse_accq_clk : std_logic;
signal signal_buffer_data_port0 : std_logic_vector (15 downto 0);
signal signal_buffer_address_port0 : std_logic_vector(12 downto 0);
signal signal_buffer_address_high_port0 : std_logic_vector(2 downto 0);
signal signal_buffer_high_byte_en_port0 : std_logic;
signal signal_buffer_low_byte_en_port0 : std_logic;
signal signal_buffer_write_en_port0 : std_logic;
signal signal_buffer_output_en_port0 : std_logic;
signal signal_buffer_memory_en_port0 : std_logic;
begin
signal_accq_data_in <= accq_data_in; -- connect all the pins to internal signals
signal_accq_clk <= accq_clk;
signal_accq_data_ready <= accq_data_ready;
signal_accq_reset <= accq_reset;
signal_accq_voltage_current <= accq_voltage_current;
signal_inverse_accq_clk <= not signal_accq_clk;
--debug_out <= signal_delayed_inverse_accq_clk;
signal_buffer_address_port0 <= buffer_address_port0;
signal_buffer_address_high_port0 <= buffer_address_high_port0;
signal_buffer_high_byte_en_port0 <= buffer_high_byte_en_port0;
signal_buffer_low_byte_en_port0 <= buffer_low_byte_en_port0;
signal_buffer_write_en_port0 <= buffer_write_en_port0;
signal_buffer_output_en_port0 <= buffer_output_en_port0;
signal_buffer_memory_en_port0 <= buffer_memory_en_port0;
buffer_interrupt_out <= not signal_accq_data_ready;
output2 <= signal_accq_data_ready; -- dummy outputs, so the input pins are not left uncommected
output3 <= signal_accq_clk;
output4 <= signal_accq_reset;
output5 <= signal_accq_voltage_current;
general_event : process(signal_accq_clk, signal_accq_data_ready, signal_accq_data_in, signal_accq_voltage_current, signal_accq_reset,
signal_buffer_memory_en_port0, signal_buffer_output_en_port0, signal_buffer_write_en_port0, signal_buffer_address_high_port0, signal_buffer_address_port0,
signal_buffer_data_port0, frequency_storage_buffer, signal_accq_reset, signal_accq_data_ready, voltage_storage_pointer, current_storage_pointer)
begin
if(signal_accq_data_ready = '0') then -- when data from the acquisition controller comes in
mem_output_en_port0 <= '1'; -- disable memory output
mem_memory_en_port0 <= '0'; -- enable memory
mem_write_en_port0 <= signal_inverse_accq_clk; -- send the acquisition clock to the memory write enable pin
if(signal_accq_reset = '1') then -- if reset is not activated...
accq_clk_edge : if(rising_edge(signal_accq_clk)) then -- process on clock rising edge
if(signal_accq_voltage_current = '1') then -- if sending current data
mem_data_port0 <= signal_accq_data_in; -- store the data in the current buffer
mem_address_port0 <= std_logic_vector(to_unsigned(current_storage_pointer, 13));
mem_address_high_port0 <= "0001"; -- sending current data to memory
current_storage_pointer <= (current_storage_pointer + 1); -- increment the counter
elsif (signal_accq_voltage_current = '0') then -- do the same if sending voltage data
--mem_data_port0 <= signal_accq_data_in; -- store the data in the voltage buffer
mem_data_port0 <= "1111111111111111";
mem_address_port0 <= std_logic_vector(to_unsigned(voltage_storage_pointer, 13));
mem_address_high_port0 <= "0000"; -- sending voltage data to memory
voltage_storage_pointer <= (voltage_storage_pointer + 1); -- increment the counter
end if;
end if accq_clk_edge;
else -- if reset is activated...
voltage_storage_pointer <= 0; -- reset everything to 0
current_storage_pointer <= 0; -- reset everything to 0
end if;
--end process accq_event;
elsif (signal_accq_data_ready = '1') then -- if data ready is high, the buffer is in read mode
mem_data_port0 <= "ZZZZZZZZZZZZZZZZ"; -- set memory data lines to input, or read mode
mem_write_en_port0 <= '1'; -- disable writing to the memory
mem_output_en_port0 <= '0'; -- enable memory output
mem_address_port0 <= signal_buffer_address_port0; -- select the appropriate addreess
mem_address_high_port0 (2 downto 0) <= signal_buffer_address_high_port0; -- do the same with the high bits
if(rising_edge(signal_accq_clk) and signal_accq_reset = '1') then -- if the accquisition MCU is writing with the data ready pin high
frequency_storage_buffer <= signal_accq_data_in; -- store the frequency value that it's sending
end if;
if(signal_accq_reset = '0') then -- reset as before if reset is enabled
voltage_storage_pointer <= 0; -- reset everything to 0
current_storage_pointer <= 0; -- reset everything to 0
end if;
if(signal_buffer_memory_en_port0 = '0' and signal_buffer_write_en_port0 = '1' and signal_accq_data_ready = '1' and signal_accq_reset = '1') then -- memory enabled and write enable high...
case signal_buffer_address_high_port0 is
when "000" => signal_buffer_data_port0 <= mem_data_port0; -- output data to downstream MCUs as needed
when "001" => signal_buffer_data_port0 <= mem_data_port0;
when "010" => signal_buffer_data_port0 <= frequency_storage_buffer;
when "011" => signal_buffer_data_port0 <= std_logic_vector(to_unsigned(voltage_storage_pointer, 16));
when "100" => signal_buffer_data_port0 <= std_logic_vector(to_unsigned(current_storage_pointer, 16));
when "111" => signal_buffer_data_port0 <= "1010000001010110"; -- 0xA056
when others=>
end case;
end if;
if(signal_buffer_output_en_port0 = '0') then
--buffer_data_port0(7 downto 0) <= signal_buffer_data_port0 (15 downto 8);
--buffer_data_port0(15 downto 8) <= signal_buffer_data_port0 (7 downto 0);
buffer_data_port0 <= signal_buffer_data_port0;
else
buffer_data_port0 <= "ZZZZZZZZZZZZZZZZ";
end if;
end if;
end process general_event;
output6 <= signal_buffer_high_byte_en_port0;
output7 <= signal_buffer_low_byte_en_port0;
end rtl;
I've tried your code on Modelsim. Although I can't comment on the correctness of mem_data_port0's behavior, it does get assigned values depending on the other relevant signals, so for the out direction it works.
If you're talking about the fact that you cannot assign values to it from outside, all I could think of is that you forgot to assign it the high impedance in input mode, but you do, so that's out.
An explanation could be that your entity is not the top level entity, which would render inout ports unusable (inout has no meaning inside the FPGA, only at the design's top level).

Weird behaviour in vhdl average using Microsemi FPGA

Good Afternoon, I am working on some code of averaging with a sliding window using VHDL language.
The problem is that the accumulator takes sometimes wrong values. (generally after restart)
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.std_logic_unsigned.all;
entity cc_rssi_avr is
port (
nrst : in std_logic;
clk : in std_logic; --
ena : in std_logic;
data_in : in std_logic_vector(9 downto 0);
data_out : out std_logic_vector(9 downto 0)
);
end cc_rssi_avr;
architecture rtl of cc_rssi_avr is
constant buffer_size : natural :=8;
type MEM is array(0 to buffer_size-1) of std_logic_vector(9 downto 0);
signal shift_LT : MEM:=(others =>(others=>'0'));
signal sum_val:std_logic_vector(12 downto 0);
begin
--shift input data at every clock edge
process(clk,nrst)
begin
if nrst='0' then
shift_LT <= (others => (others => '0'));
sum_val <= (others=>'0');
elsif clk'event and clk='1' then
if ena = '0' then
shift_LT<=(others=>(others=>'0'));
sum_val<=(others=>'0');
else
shift_LT(0) <= data_in;
shift_LT(1 to buffer_size-1) <= shift_LT(0 to buffer_size-2);
sum_val <= sum_val + ("000"&data_in) - ("000"&shift_LT(buffer_size-1));
end if;
end if;
end process;
data_out<=sum_val(sum_val'high downto 3);
end rtl;
The problem is somehow, sum_val adds a value without subtraction or subtracts without addition, in a way that if the input returns to 0, the output returns to 7850 or a random value but not zero.
The design is running # 20 MHz (FPGA : Microsemi Smartfusion M2S050), and consists on an ADC driven by FPGA clock, and its output is routed to the FPGA pins so the samples are processed with this module in order to compute the average on 8 samples.
One last information that might be useful : FPGA is 92.6% Occupied (4LUT).
Can anyone provide some help.
Thanks

using UART in VHDL

I'm trying to use UART communication with a Lattice machox3 and a ft232R. I am trying to use the VHDL file I found on eewiki(Here). For some reason I am not being able to get tx to work when I simulate it. what am I doing wrong? Is there a simple uart implementation I could use? I tried making it myself, scine I just want to transmit, but I wasnt unsuccessful.
here is the waveform Active hdl gives me
this is the top file I am using to get this component to work.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--library machXO3;
--use machXO3.all;
entity UART_TOP is generic (
divisor : integer := 2604 -- Set the Baud Rate Divisor here.
-- Some common values: 300 Baud = 83333, 9600 Baud = 2604, 115200 Baud = 217, 921600 Baud = 27
);
PORT(
reset_n : IN STD_LOGIC; --ascynchronous reset
tx_ena : IN STD_LOGIC; --initiate transmission load on H
tx_busy : OUT STD_LOGIC; --transmission in progress
tx : OUT STD_LOGIC;
CLOCK_UART : in STD_LOGIC;
DIN : IN STD_LOGIC_VECTOR(15 downto 0)
);
end UART_TOP;
architecture Behavior of UART_TOP is
SIGNAL INTERNAL_CLOCK : STD_LOGIC;
SIGNAL MUX_0 : STD_LOGIC_VECTOR(7 downto 0);
SIGNAL MUX_1 : STD_LOGIC_VECTOR(7 downto 0);
SIGNAL MUX_S : STD_LOGIC_VECTOR(1 downto 0);
SIGNAL txEN: STD_LOGIC_VECTOR(0 downto 0);
SIGNAL counter : STD_LOGIC;
SIGNAL DATAsnd : STD_LOGIC_VECTOR(7 downto 0);
SIGNAL LOAD : STD_LOGIC;
---------------------------------------------------
-- Buffer Input --
---------------------------------------------------
COMPONENT NOTM is
PORT(
Input : in STD_LOGIC;
Output : out STD_LOGIC
);
END COMPONENT;
---------------------------------------------------
-- Buffer Input --
---------------------------------------------------
COMPONENT InputBuffer is
generic(n: natural);
PORT(
clk : in STD_LOGIC;
En : in STD_LOGIC; -- 0 is enabled
Input : in STD_LOGIC_VECTOR (n-1 downto 0);
Output : out STD_LOGIC_VECTOR (n-1 downto 0)
);
END COMPONENT;
---------------------------------------------------
-- MUX04_2_1 --
---------------------------------------------------
COMPONENT MUX421 is
generic (
DATAWIDTH : natural := 8
);
port(
A : in STD_LOGIC_VECTOR(DATAWIDTH-1 downto 0);
B : in STD_LOGIC_VECTOR(DATAWIDTH-1 downto 0);
C : in STD_LOGIC_VECTOR(DATAWIDTH-1 downto 0);
D : in STD_LOGIC_VECTOR(DATAWIDTH-1 downto 0);
S : in STD_LOGIC_VECTOR(1 downto 0);
O : OUT STD_LOGIC_VECTOR(DATAWIDTH-1 downto 0)
);
END COMPONENT;
---------------------------------------------------
-- Binary Counter --
---------------------------------------------------
COMPONENT binary_counter is
generic(
MIN_COUNT : natural := 0;
MAX_COUNT : natural := 17
);
port(
clk : in std_logic;
reset : in std_logic;
enable : in std_logic; -- 0 is enabled
q : out STD_LOGIC_VECTOR(MAX_COUNT-1 downto 0)
);
END COMPONENT;
---------------------------------------------------
-- UART. Mach0X3 --
---------------------------------------------------
COMPONENT uart_c IS
GENERIC(
clk_freq : INTEGER := 50_000_000; --frequency of system clock in Hertz
baud_rate : INTEGER := 19_200; --data link baud rate in bits/second
os_rate : INTEGER := 16; --oversampling rate to find center of receive bits (in samples per baud period)
d_width : INTEGER := 8; --data bus width
parity : INTEGER := 1; --0 for no parity, 1 for parity
parity_eo : STD_LOGIC := '0'); --'0' for even, '1' for odd parity
PORT(
clk : IN STD_LOGIC; --system clock
reset_n : IN STD_LOGIC; --ascynchronous reset
tx_ena : IN STD_LOGIC; --initiate transmission load on H
tx_data : IN STD_LOGIC_VECTOR(d_width-1 DOWNTO 0); --data to transmit
rx : IN STD_LOGIC; --receive pin
rx_busy : OUT STD_LOGIC; --data reception in progress
rx_error : OUT STD_LOGIC; --start, parity, or stop bit error detected
rx_data : OUT STD_LOGIC_VECTOR(d_width-1 DOWNTO 0); --data received
tx_busy : OUT STD_LOGIC; --transmission in progress
tx : OUT STD_LOGIC); --transmit pin
END COMPONENT;
begin
-- UART
DATAOUT: UART_c
PORT MAP ( CLK => CLOCK_UART, --system clock
reset_n =>reset_n, --ascynchronous reset
tx_ena => tx_ena,--txEN(0), --initiate transmission
tx_data => DIN(7 downto 0), --data to transmit
rx =>'0' , --receive pin
tx => tx, --transmit pin
tx_busy => tx_busy
);
--UART LOAD
--LOADER: NOTM
--PORT MAP (INPUT => LOAD, OUTPUT => counter);
-- DATA to MUX
--MUX: MUX421
--PORT MAP (s => MUX_S, A => MUX_0, B => MUX_1, C => X"0D", D => X"0A", O => DO-- DATAsnd
--); -- C => X"0D", D => X"0A" cartidge return and line feed
-- Counter to mux
--cntr: binary_counter
--generic map (MAX_COUNT => 2)
--PORT MAP (
--clk => counter,
--reset => RESET,
--enable => ENABLE,
--q => MUX_S
--);
-- Counter to load
--Load_UART: binary_counter
--generic map (MAX_COUNT => 1)
--PORT MAP (
--clk => CLOCK_UART,
--reset => RESET,
--enable => LOAD,
--q => txEN
--);
--DATA to UART
--UARTBUFFER_0: InputBuffer
--generic map (N => 8)
--PORT MAP ( clk => CLOCK_UART, En =>ENABLE, Input => DIN(15 downto 8), OUTPUT => MUX_0);
--DATA to UART
--UARTBUFFER_1: InputBuffer
--generic map (N => 8)
--PORT MAP ( clk => CLOCK_UART, En =>ENABLE, Input => DIN(7 downto 0), OUTPUT => MUX_1);
end Behavior;
this is the UART itself
--------------------------------------------------------------------------------
--
-- FileName: uart_c.vhd
-- Dependencies: none
-- Design Software: Quartus II 64-bit Version 13.1.0 Build 162 SJ Web Edition
--
-- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY
-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
--
-- Version History
-- Version 1.0 5/26/2017 Scott Larson
-- Initial Public Release
--
--------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY uart_c IS
GENERIC(
clk_freq : INTEGER := 50_000_000; --frequency of system clock in Hertz
baud_rate : INTEGER := 19_200; --data link baud rate in bits/second
os_rate : INTEGER := 16; --oversampling rate to find center of receive bits (in samples per baud period)
d_width : INTEGER := 8; --data bus width
parity : INTEGER := 1; --0 for no parity, 1 for parity
parity_eo : STD_LOGIC := '0'); --'0' for even, '1' for odd parity
PORT(
clk : IN STD_LOGIC; --system clock
reset_n : IN STD_LOGIC; --ascynchronous reset
tx_ena : IN STD_LOGIC; --initiate transmission
tx_data : IN STD_LOGIC_VECTOR(d_width-1 DOWNTO 0); --data to transmit
rx : IN STD_LOGIC; --receive pin
rx_busy : OUT STD_LOGIC; --data reception in progress
rx_error : OUT STD_LOGIC; --start, parity, or stop bit error detected
rx_data : OUT STD_LOGIC_VECTOR(d_width-1 DOWNTO 0); --data received
tx_busy : OUT STD_LOGIC; --transmission in progress
tx : OUT STD_LOGIC); --transmit pin
END uart_c;
ARCHITECTURE logic OF uart_c IS
TYPE tx_machine IS(idle, transmit); --tranmit state machine data type
TYPE rx_machine IS(idle, receive); --receive state machine data type
SIGNAL tx_state : tx_machine; --transmit state machine
SIGNAL rx_state : rx_machine; --receive state machine
SIGNAL baud_pulse : STD_LOGIC := '0'; --periodic pulse that occurs at the baud rate
SIGNAL os_pulse : STD_LOGIC := '0'; --periodic pulse that occurs at the oversampling rate
SIGNAL parity_error : STD_LOGIC; --receive parity error flag
SIGNAL rx_parity : STD_LOGIC_VECTOR(d_width DOWNTO 0); --calculation of receive parity
SIGNAL tx_parity : STD_LOGIC_VECTOR(d_width DOWNTO 0); --calculation of transmit parity
SIGNAL rx_buffer : STD_LOGIC_VECTOR(parity+d_width DOWNTO 0) := (OTHERS => '0'); --values received
SIGNAL tx_buffer : STD_LOGIC_VECTOR(parity+d_width+1 DOWNTO 0) := (OTHERS => '1'); --values to be transmitted
BEGIN
--generate clock enable pulses at the baud rate and the oversampling rate
PROCESS(reset_n, clk)
VARIABLE count_baud : INTEGER RANGE 0 TO clk_freq/baud_rate-1 := 0; --counter to determine baud rate period
VARIABLE count_os : INTEGER RANGE 0 TO clk_freq/baud_rate/os_rate-1 := 0; --counter to determine oversampling period
BEGIN
IF(reset_n = '0') THEN --asynchronous reset asserted
baud_pulse <= '0'; --reset baud rate pulse
os_pulse <= '0'; --reset oversampling rate pulse
count_baud := 0; --reset baud period counter
count_os := 0; --reset oversampling period counter
ELSIF(clk'EVENT AND clk = '1') THEN
--create baud enable pulse
IF(count_baud < clk_freq/baud_rate-1) THEN --baud period not reached
count_baud := count_baud + 1; --increment baud period counter
baud_pulse <= '0'; --deassert baud rate pulse
ELSE --baud period reached
count_baud := 0; --reset baud period counter
baud_pulse <= '1'; --assert baud rate pulse
count_os := 0; --reset oversampling period counter to avoid cumulative error
END IF;
--create oversampling enable pulse
IF(count_os < clk_freq/baud_rate/os_rate-1) THEN --oversampling period not reached
count_os := count_os + 1; --increment oversampling period counter
os_pulse <= '0'; --deassert oversampling rate pulse
ELSE --oversampling period reached
count_os := 0; --reset oversampling period counter
os_pulse <= '1'; --assert oversampling pulse
END IF;
END IF;
END PROCESS;
--receive state machine
PROCESS(reset_n, clk)
VARIABLE rx_count : INTEGER RANGE 0 TO parity+d_width+2 := 0; --count the bits received
VARIABLE os_count : INTEGER RANGE 0 TO os_rate-1 := 0; --count the oversampling rate pulses
BEGIN
IF(reset_n = '0') THEN --asynchronous reset asserted
os_count := 0; --clear oversampling pulse counter
rx_count := 0; --clear receive bit counter
rx_busy <= '0'; --clear receive busy signal
rx_error <= '0'; --clear receive errors
rx_data <= (OTHERS => '0'); --clear received data output
rx_state <= idle; --put in idle state
ELSIF(clk'EVENT AND clk = '1' AND os_pulse = '1') THEN --enable clock at oversampling rate
CASE rx_state IS
WHEN idle => --idle state
rx_busy <= '0'; --clear receive busy flag
IF(rx = '0') THEN --start bit might be present
IF(os_count < os_rate/2) THEN --oversampling pulse counter is not at start bit center
os_count := os_count + 1; --increment oversampling pulse counter
rx_state <= idle; --remain in idle state
ELSE --oversampling pulse counter is at bit center
os_count := 0; --clear oversampling pulse counter
rx_count := 0; --clear the bits received counter
rx_busy <= '1'; --assert busy flag
rx_state <= receive; --advance to receive state
END IF;
ELSE --start bit not present
os_count := 0; --clear oversampling pulse counter
rx_state <= idle; --remain in idle state
END IF;
WHEN receive => --receive state
IF(os_count < os_rate-1) THEN --not center of bit
os_count := os_count + 1; --increment oversampling pulse counter
rx_state <= receive; --remain in receive state
ELSIF(rx_count < parity+d_width) THEN --center of bit and not all bits received
os_count := 0; --reset oversampling pulse counter
rx_count := rx_count + 1; --increment number of bits received counter
rx_buffer <= rx & rx_buffer(parity+d_width DOWNTO 1); --shift new received bit into receive buffer
rx_state <= receive; --remain in receive state
ELSE --center of stop bit
rx_data <= rx_buffer(d_width DOWNTO 1); --output data received to user logic
rx_error <= rx_buffer(0) OR parity_error OR NOT rx; --output start, parity, and stop bit error flag
rx_busy <= '0'; --deassert received busy flag
rx_state <= idle; --return to idle state
END IF;
END CASE;
END IF;
END PROCESS;
--receive parity calculation logic
rx_parity(0) <= parity_eo;
rx_parity_logic: FOR i IN 0 to d_width-1 GENERATE
rx_parity(i+1) <= rx_parity(i) XOR rx_buffer(i+1);
END GENERATE;
WITH parity SELECT --compare calculated parity bit with received parity bit to determine error
parity_error <= rx_parity(d_width) XOR rx_buffer(parity+d_width) WHEN 1, --using parity
'0' WHEN OTHERS; --not using parity
--transmit state machine
PROCESS(reset_n, clk)
VARIABLE tx_count : INTEGER RANGE 0 TO parity+d_width+3 := 0; --count bits transmitted
BEGIN
IF(reset_n = '0') THEN --asynchronous reset asserted
tx_count := 0; --clear transmit bit counter
tx <= '1'; --set tx pin to idle value of high
tx_busy <= '1'; --set transmit busy signal to indicate unavailable
tx_state <= idle; --set tx state machine to ready state
ELSIF(clk'EVENT AND clk = '1') THEN
CASE tx_state IS
WHEN idle => --idle state
IF(tx_ena = '1') THEN --new transaction latched in
tx_buffer(d_width+1 DOWNTO 0) <= tx_data & '0' & '1'; --latch in data for transmission and start/stop bits
IF(parity = 1) THEN --if parity is used
tx_buffer(parity+d_width+1) <= tx_parity(d_width); --latch in parity bit from parity logic
END IF;
tx_busy <= '1'; --assert transmit busy flag
tx_count := 0; --clear transmit bit count
tx_state <= transmit; --proceed to transmit state
ELSE --no new transaction initiated
tx_busy <= '0'; --clear transmit busy flag
tx_state <= idle; --remain in idle state
END IF;
WHEN transmit => --transmit state
IF(baud_pulse = '1') THEN --beginning of bit
tx_count := tx_count + 1; --increment transmit bit counter
tx_buffer <= '1' & tx_buffer(parity+d_width+1 DOWNTO 1); --shift transmit buffer to output next bit
END IF;
IF(tx_count < parity+d_width+3) THEN --not all bits transmitted
tx_state <= transmit; --remain in transmit state
ELSE --all bits transmitted
tx_state <= idle; --return to idle state
END IF;
END CASE;
tx <= tx_buffer(0); --output last bit in transmit transaction buffer
END IF;
END PROCESS;
--transmit parity calculation logic
tx_parity(0) <= parity_eo;
tx_parity_logic: FOR i IN 0 to d_width-1 GENERATE
tx_parity(i+1) <= tx_parity(i) XOR tx_data(i);
END GENERATE;
END logic;
and this is the test bench
-- VHDL Test Bench Created from source file UART_TOP.vhd -- Sun Aug 19 12:41:55 2018
--
-- Notes:
-- 1) This testbench template has been automatically generated using types
-- std_logic and std_logic_vector for the ports of the unit under test.
-- Lattice recommends that these types always be used for the top-level
-- I/O of a design in order to guarantee that the testbench will bind
-- correctly to the timing (post-route) simulation model.
-- 2) To use this template as your testbench, change the filename to any
-- name of your choice with the extension .vhd, and use the "source->import"
-- menu in the ispLEVER Project Navigator to import the testbench.
-- Then edit the user defined section below, adding code to generate the
-- stimulus for your design.
-- 3) VHDL simulations will produce errors if there are Lattice FPGA library
-- elements in your design that require the instantiation of GSR, PUR, and
-- TSALL and they are not present in the testbench. For more information see
-- the How To section of online help.
--
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY testbench IS
END testbench;
ARCHITECTURE behavior OF testbench IS
COMPONENT UART_TOP
PORT(
reset_n : IN std_logic;
tx_ena : IN std_logic;
CLOCK_UART : IN std_logic;
DIN : IN std_logic_vector(15 downto 0);
tx_busy : OUT std_logic;
tx : OUT std_logic
);
END COMPONENT;
SIGNAL reset_n : std_logic;
SIGNAL tx_ena : std_logic;
SIGNAL tx_busy : std_logic;
SIGNAL tx : std_logic;
SIGNAL CLOCK_UART : std_logic;
SIGNAL DIN : std_logic_vector(15 downto 0);
constant half_period : time := 10 ns;
BEGIN
-- Please check and add your generic clause manually
uut: UART_TOP PORT MAP(
reset_n => reset_n,
tx_ena => tx_ena,
tx_busy => tx_busy,
tx => tx,
CLOCK_UART => CLOCK_UART,
DIN => DIN
);
-- *** Test Bench - User Defined Section ***
tb : PROCESS
BEGIN
reset_n <= '1';
tx_ena <= '0';
DIN <= B"0101010101010101";
CLOCK_UART <= '1';
wait for half_period ;
CLOCK_UART <= '0';
wait for half_period ;
CLOCK_UART <= '1';
wait for half_period ;
CLOCK_UART <= '0';
wait for half_period ;
tx_ena <= '1';
loop
CLOCK_UART <= '1';
wait for half_period ;
tx_ena <= '0';
CLOCK_UART <= '0';
wait for half_period ;
end loop;
END PROCESS;
-- *** End Test Bench - User Defined Section ***
END;

Why does incrementing a std_logic_vector give unknown value?

I'm attempting to write a I2C bus master in VHDL - and thoroughly test it to ensure it works etc. In doing so, I've written the module and a subsequent test-bench to test it under different stimuli - namely changing addresses and data input after each sending cycle (which is when the busy goes low).
To do this, I first attempted to increment the value in the data bus and decrement the values in the address bus, using the techniques described in this question here. However, when I did this, rather than the address bus taking the new value, it takes an uninitialised value and the assignment statement doesnt seem to execute.
I then attempted to use an intermediate integer signal, however this produced the same results, however this means that the address & data buses take the correct value for the first cycle - but then don't increment and instead take a unknown state!
Ultimately my question is why do these errors occur - and how do I fix/avoid them?
My code for the I2C master module can be found here and the code for the I2CBus (testbench) can be found here. Any other information I can provide to help please just say!
Thanks very much,
David
-----Code using intermediate signals------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY I2CBus IS
END I2CBus;
ARCHITECTURE behavior OF I2CBus IS
COMPONENT IIC_Master
PORT(
CLOCK : IN std_logic;
RESET_N : IN std_logic;
ENA : IN std_logic;
ADR : IN std_logic_vector(6 downto 0);
RW : IN std_logic;
DAT_WR : IN std_logic_vector(7 downto 0);
DAT_RD : OUT std_logic_vector(7 downto 0);
BUSY : OUT std_logic;
SCL : INOUT std_logic;
SDA : INOUT std_logic;
ACK_ERR : BUFFER std_logic
);
END COMPONENT;
--Inputs
signal CLOCK : std_logic := '0';
signal RESET_N : std_logic; --active high
signal ENA : std_logic; --active high
signal ADR : std_logic_vector(6 downto 0);
signal RW : std_logic; --read high write low
signal DAT_WR : std_logic_vector(7 downto 0);
--BiDirs
signal SCL : std_logic;
signal SDA : std_logic;
--Outputs
signal DAT_RD : std_logic_vector(7 downto 0);
signal BUSY : std_logic;
signal ACK_ERR : std_logic;
-- Clock period definitions
constant CLOCK_period : time := 5 ns;
--Signals to vary
signal address : integer := 127;
signal input_data : integer := 0;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut : IIC_Master PORT MAP(
CLOCK => CLOCK,
RESET_N => RESET_N,
ENA => ENA,
ADR => ADR,
RW => RW,
DAT_WR => DAT_WR,
DAT_RD => DAT_RD,
BUSY => BUSY,
SCL => SCL,
SDA => SDA,
ACK_ERR => ACK_ERR
);
-- Clock process definitions
CLOCK_process : process
begin
CLOCK <= '0';
wait for CLOCK_period / 2;
CLOCK <= '1';
wait for CLOCK_period / 2;
end process;
-- Reset process
reset : process
begin
reset_n <= '0';
ADR <= "1111111"; --This doesn't seem to happen the first time?
DAT_WR <= "00000000"; --Nor does this?
RW <= '0';
wait for 50 ns;
reset_n <= '1';
ENA <= '1';
wait;
end process;
stim_proc : process
begin
DAT_WR <= std_logic_vector(to_unsigned(input_data, 8));
ADR <= std_logic_vector(to_unsigned(address, 7));
if input_data < 127 then
address <= address - 1;
input_data <= input_data + 1;
wait until BUSY = '0' and RESET_N = '1';
elsif unsigned(DAT_WR) > 126 then
wait;
end if;
end process;
end behavior;
------1st Stimulus Process w/out intermediate signals
stim_proc : process
begin
if input_data < 127 then
wait until BUSY = '0' and RESET_N = '1';
ADR <= std_logic_vector(unsigned(ADR) + 1);
DAT_WR <= std_logic_vector(unsigned(DAT_WR) + 1);
elsif unsigned(DAT_WR) > 126 then
wait;
end if;
end process;
Results from second simulation using intermediate signals
The usual cause of this is the resolution of multiple assignments to signals like ADR in several different processes. In hardware terms. this is equivalent to short circuiting together the output of several different ICs. (It doesn't work without special care, and can destroy your ICs).
So check that you are assigning ADR and similar signals in only one process, and if necessary, rewrite to combine those processes into one process.
If you need to connect several outputs together, there are 2 ways that work successfully, though I don't think it's the right approach here.
Wired-OR outputs (or Wired-AND). In Wired-OR scheme the signal is permanently pulled weakly low by an assignment like ADR <= (others -> 'L'); and this can be overridden by each output driving either 'Z' for low or '1' for high. This works because multiple outputs can safely drive the signal at once.
Tri-state outputs, with arbitration to make sure only one process drives the output at any time. The others all drive 'Z' or (others => 'Z') onto the same signal, to signify they are inactive.
The answer from Brian Drummond is correct. I just wand to explain in at your example. At time 0, both the reset as well as the stim_proc process assign the same value:
reset : process
begin
...
ADR <= "1111111";
...
end process;
and
stim_proc : process
begin
ADR <= std_logic_vector(to_unsigned(address, 7)); -- with address = 127
...
end process;
So, the result for ADR is "1111111". But after decrementing address (in original code with intermediate version), the stim_proc process assigns a different value (than the reset process) after it starts over. You see this in the waveform. When address gets 126, which is "1111110", only the lowest bit of ADR gets X because only this bit differs from "1111111" assigned in the reset process.
Solution 1
If you just want to initialize a signal, assign the initialization value at the signal declaration. (I think, this is what you want according to your VHDL comment.) That is:
signal ADR : std_logic_vector(6 downto 0) := (others => '1');
Solution 2
If you (really) want to assign "1111111" only for the first 50 ns seconds from the reset process, then you have to assign (others => 'Z') (tri-state), (others => 'Z') (weak pull-down) or (others => 'H') (weak pull-up) afterwards in this process to allow an "overriding" by the stim_proc process, e.g.:
reset : process
begin
ADR <= "1111111";
wait for 50 ns;
ADR <= (others => 'Z');
wait;
end process;

Why Does This VHDL Work in Sumulation and Does not Work on the Virtex 5 Device

I have spent the whole day trying to solve the following problem. I am building a small averaging multichannel oscilloscope and I have the following module for storing the signal:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
entity storage is
port
(
clk_in : in std_logic;
reset : in std_logic;
element_in : in std_logic;
data_in : in std_logic_vector(11 downto 0);
addr : in std_logic_vector(9 downto 0);
add : in std_logic; -- add = '1' means add to RAM
-- add = '0' means write to RAM
dump : in std_logic;
element_out : out std_logic;
data_out : out std_logic_vector(31 downto 0)
);
end storage;
architecture rtl of storage is
component bram is
port
(
clk : in std_logic;
we : in std_logic;
en : in std_logic;
addr : in std_logic_vector(9 downto 0);
di : in std_logic_vector(31 downto 0);
do : out std_logic_vector(31 downto 0)
);
end component bram;
type state is (st_startwait, st_add, st_write);
signal current_state : state := st_startwait;
signal next_state : state := st_startwait;
signal start : std_logic;
signal we : std_logic;
signal en : std_logic;
signal di : std_logic_vector(31 downto 0);
signal do : std_logic_vector(31 downto 0);
signal data : std_logic_vector(11 downto 0);
begin
ram : bram port map
(
clk => clk_in,
we => we,
en => en,
addr => addr,
di => di,
do => do
);
process(clk_in, reset, start)
begin
if rising_edge(clk_in) then
if (reset = '1') then
current_state <= st_startwait;
else
start <= '0';
current_state <= next_state;
if (element_in = '1') then
start <= '1';
end if;
end if;
end if;
end process;
process(current_state, start, dump)
variable acc : std_logic_vector(31 downto 0);
begin
element_out <= '0';
en <= '1';
we <= '0';
case current_state is
when st_startwait =>
if (start = '1') then
acc(11 downto 0) := data_in;
acc(31 downto 12) := (others => '0');
next_state <= st_add;
else
next_state <= st_startwait;
end if;
when st_add =>
if (add = '1') then
acc := acc + do;
end if;
we <= '1';
di <= acc;
next_state <= st_write;
when st_write =>
if (dump = '1') then
data_out <= acc;
element_out <= '1';
end if;
next_state <= st_startwait;
end case;
end process;
end rtl;
Below is the BRAM module as copied from the XST manual. This is a no-change type of BRAM and I believe there is the problem. The symptom is that, while this simulates fine, I read only zeroes from the memory when I use the design on the device.
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity bram is
port
(
clk : in std_logic;
we : in std_logic;
en : in std_logic;
addr : in std_logic_vector(9 downto 0);
di : in std_logic_vector(31 downto 0);
do : out std_logic_vector(31 downto 0)
);
end bram;
architecture rtl of bram is
type ram_type is array (0 to 999) of std_logic_vector (31 downto 0);
signal buf : ram_type;
begin
process(clk, en, we)
begin
if rising_edge(clk) then
if en = '1' then
if we = '1' then
buf(conv_integer(addr)) <= di;
else
do <= buf(conv_integer(addr));
end if;
end if;
end if;
end process;
end rtl;
What follows is a description of the chip use and the expected output. "clk_in" is a 50 MHz clock. "element_in" is '1' for 20 ns and '0' for 60 ns. "addr_in" iterates from 0 to 999 and changes every 80 ns. "element_in", "data_in", and "addr" are all aligned and synchronous. Now "add" is '1' for 1000 elements, then both "add" and "dump" are zero for 8000 elements and, finally "dump" is '1' for 1000 elements. Now, if I have a test bench that supplies "data_in" from 0 to 999, I expect data_out to be 0, 10, 20, 30, ..., 9990 when "dump" is '1'. That is according to the simulation. In reality I get 0, 1, 2, 3, ..., 999....
Some initial issues to address are listed below.
The process(current_state, start, dump) in storage entity looks like it is
intended to implement a combinatorial element (gates), but the signal (port)
data_in is not in the sensitivity list.
This is very likely to cause a difference between simulation and synthesis
behavior, since simulation will typically only react to the signals in the
sensitivity list, where synthesis will implement the combinatorial design and
react on all used signals, but may give a warning about incomplete sensitivity
list or inferred latches. If you are using VHDL-2008 then use can use a
sensitivity list of (all) to have the process sensitivity to all used
signals, and otherwise you need to add missing signals manually.
The case current_state is in process(current_state, start, dump) lacks an
when others => ..., so the synthesis tool has probably given you a warning
about inferred latches. This should be fixed by adding the when others =>
with and assign all signals driven by the process to the relevant value.
The use clause lists:
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
But both of these should not be used at the same time, since they declare some
of the same identifiers, for example is unsigned declared in both. Since the
RAM uses std_logic_unsigned I suggest that you stick with that only, and
delete use of numeric_std. For new code I would though recommend use of
numeric_std.
Also the process(clk_in, reset, start) in storage entity implements a
sequential element (flip flop) sensitive to only rising edge of clk_in, so
the two last signals in sensitivity list ..., reset, start) are unnecessary,
but does not cause a problem.

Resources