Error (10395): VHDL Conditional Signal Assignment error at (146): conditional waveforms must have same number of elements - vhdl

Error (10395): VHDL Conditional Signal Assignment error at vga.vhd(146): conditional waveforms must have same number of elements.
in this line show me error
R<=intensity WHEN red_switch='0' AND dena='1' ELSE (OTHERS=>'1');
I really don't know what's wrong vhdl Altera code error but it didn't solve my problem. thanks in advance.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
LIBRARY lpm;
USE lpm.lpm_components.all;
----------------------------------------------------------
ENTITY vga IS
GENERIC (
Ha: INTEGER := 96; --Hpulse
Hb: INTEGER := 144; --Hpulse+HBP
Hc: INTEGER := 784; --Hpulse+HBP+Hactive
Hd: INTEGER := 800; --Hpulse+HBP+Hactive+HFP
Va: INTEGER := 2; --Vpulse
Vb: INTEGER := 35; --Vpulse+VBP
Vc: INTEGER := 515; --Vpulse+VBP+Vactive
Vd: INTEGER := 525); --Vpulse+VBP+Vactive+VFP
PORT (
clk: IN STD_LOGIC; --50MHz in our board
red_switch, green_switch, blue_switch: IN STD_LOGIC;
pixel_clk: BUFFER STD_LOGIC;
Hsync, Vsync: BUFFER STD_LOGIC;
R, G, B: OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
nblanck, nsync : OUT STD_LOGIC);
END vga;
----------------------------------------------------------
ARCHITECTURE vga OF vga IS
SIGNAL Hactive, Vactive, dena: STD_LOGIC;
SIGNAL address: STD_LOGIC_VECTOR(8 DOWNTO 0);
SIGNAL intensity: STD_LOGIC_VECTOR(9 DOWNTO 0);
BEGIN
-------------------------------------------------------
--Part 1: CONTROL GENERATOR
-------------------------------------------------------
--Static signals for DACs:
nblanck <= '1'; --no direct blanking
nsync <= '0'; --no sync on green
--Create pixel clock (50MHz->25MHz):
PROCESS (clk)
BEGIN
IF (clk'EVENT AND clk='1') THEN
pixel_clk <= NOT pixel_clk;
END IF;
END PROCESS;
--Horizontal signals generation:
PROCESS (pixel_clk)
VARIABLE Hcount: INTEGER RANGE 0 TO Hd;
BEGIN
IF (pixel_clk'EVENT AND pixel_clk='1') THEN
Hcount := Hcount + 1;
IF (Hcount=Ha) THEN
Hsync <= '1';
ELSIF (Hcount=Hb) THEN
Hactive <= '1';
ELSIF (Hcount=Hc) THEN
Hactive <= '0';
ELSIF (Hcount=Hd) THEN
Hsync <= '0';
Hcount := 0;
END IF;
END IF;
END PROCESS;
--Vertical signals generation:
PROCESS (Hsync)
VARIABLE Vcount: INTEGER RANGE 0 TO Vd;
BEGIN
IF (Hsync'EVENT AND Hsync='0') THEN
Vcount := Vcount + 1;
IF (Vcount=Va) THEN
Vsync <= '1';
ELSIF (Vcount=Vb) THEN
Vactive <= '1';
ELSIF (Vcount=Vc) THEN
Vactive <= '0';
ELSIF (Vcount=Vd) THEN
Vsync <= '0';
Vcount := 0;
END IF;
END IF;
END PROCESS;
---Display enable generation:
dena <= Hactive AND Vactive;
-------------------------------------------------------
--Part 2: IMAGE GENERATOR
-------------------------------------------------------
PROCESS (Hsync, Vsync, Vactive, dena, red_switch,
green_switch, blue_switch)
VARIABLE line_counter: INTEGER RANGE 0 TO Vc;
BEGIN
IF (Vsync='0') THEN
line_counter := 0;
ELSIF (Hsync'EVENT AND Hsync='1') THEN
IF (Vactive='1') THEN
line_counter := line_counter + 1;
END IF;
END IF;
IF (dena='1') THEN
IF (line_counter=1) THEN
R <= (OTHERS => '1');
G <= (OTHERS => '0');
B <= (OTHERS => '0');
ELSIF (line_counter>1 AND line_counter<=3) THEN
R <= (OTHERS => '0');
G <= (OTHERS => '1');
B <= (OTHERS => '0');
ELSIF (line_counter>3 AND line_counter<=6) THEN
R <= (OTHERS => '0');
G <= (OTHERS => '0');
B <= (OTHERS => '1');
ELSE
R <= (OTHERS => red_switch);
G <= (OTHERS => green_switch);
B <= (OTHERS => blue_switch);
END IF;
ELSE
R <= (OTHERS => '0');
G <= (OTHERS => '0');
B <= (OTHERS => '0');
END IF;
END PROCESS;
--END vga;
-------------------------------------------
--ROM instantiation:
myrom: lpm_rom
GENERIC MAP (
lpm_widthad => 9, --address width
lpm_outdata => "UNREGISTERED",
lpm_address_control => "REGISTERED",
lpm_file => "pic_6.mif", --data file
lpm_width => 10) --data width
PORT MAP (
inclock=>NOT pixel_clk, address=>address, q=>intensity);
--Create address (row number):
PROCESS (Vsync, Hsync)
VARIABLE line_counter: INTEGER RANGE 0 TO Vd;
BEGIN
IF (Vsync='0') THEN
line_counter := 0;
ELSIF (Hsync'EVENT AND Hsync='1') THEN
IF (Vactive='1') THEN
line_counter := line_counter + 1;
END IF;
END IF;
address <= conv_std_logic_vector(line_counter, 9);
END PROCESS;
-- --Assign color values to R/G/B:
R<=intensity WHEN red_switch='0' AND dena='1' ELSE (OTHERS=>'1');
G<=intensity WHEN green_switch='0' AND dena='1' ELSE (OTHERS=>'1');
B<=intensity WHEN blue_switch='0' AND dena='1' ELSE (OTHERS=>'1');
END vga;

Signal R is 8 bits wide:
R, G, B: OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
while signal intensity is 10 bits wide:
SIGNAL intensity: STD_LOGIC_VECTOR(9 DOWNTO 0);
This is not allowed in VHDL. Both must be the same width; you must either explicitly truncate intensity or extend R.

Related

PWM controlled LED using VHDL

I've written the following VHDL code and test-bench to control the brightness of LEDs. Then tried with Altera ModelSim to simulate the code. However, I'm facing some technical difficulties. It would be really nice if someone will compile the code and share me the simulated result with me. Thanks in advance.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity main_testbench is
end main_testbench;
architecture behavior of main_testbench is
component led_controller is
Port ( clk, reset: in std_logic; -- system clock is assumed 10KHz
in_word: in std_logic_vector(7 downto 0); -- LS 4 bits - frequency & MS 4 bits - duty-cycle
LEDs: out std_logic_vector(3 downto 0));
end component;
signal clk, reset: std_logic := '0';
signal in_word: std_logic_vector(7 downto 0) := "00010001"; -- 0.2 Hz, 10% duty cycle
signal LEDs: std_logic_vector(3 downto 0) := "0000";
type in_word_commands is array (0 to 15) of std_logic_vector(7 downto 0);
signal in_words: in_word_commands := ("00010001", "00010010", "00010100", "00011000", -- 10% duty cycle with 0.2Hz, 0.5Hz, 1Hz, 2Hz
"00100001", "00100010", "00100100", "00101000", -- 30% duty cycle with 0.2Hz, 0.5Hz, 1Hz, 2Hz
"01000001", "01000010", "01000100", "01001000", -- 60% duty cycle with 0.2Hz, 0.5Hz, 1Hz, 2Hz
"10000001", "10000010", "10000100", "10001000"); -- 85% duty cycle with 0.2Hz, 0.5Hz, 1Hz, 2Hz
signal command_num : integer := 0;
begin
dut: led_controller port map (clk, reset, in_word, LEDs);
clk <= not clk after 50 us; -- 0.1ms/2 = 50us
command_num <= command_num + 1 after 5000 ms; -- 5000ms = 5s
in_word <= in_words(command_num);
end behavior;
controller:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.all;
entity led_controller is
Port ( clk, reset: in std_logic;
in_word: in std_logic_vector(7 downto 0);
LEDs: out std_logic_vector(3 downto 0));
end led_controller;
architecture behavior of led_controller is
--------------------- signals ---------------------
type freq is array (0 to 3) of integer range 0 to 50000;
signal frq: freq := (25000, 10000, 5000, 2500);
signal led_freq_count: integer range 0 to 50000 := frq(0);
type d is array (0 to 3) of integer range 0 to 100;
signal duty: d := (10, 30, 60, 85);
signal duty_cycle: integer range 0 to 100 := duty(0);
signal LED_switch, new_command: std_logic := '0';
begin
--------- clock process / sync reset configuration ---------------
process (clk)
variable duty_counter: integer range 0 to 100 := 100;
variable freq_counter: integer range 0 to 50000 := led_freq_count;
begin
if rising_edge(clk) then
------- if reset was high or new in_word were arrived --------
if reset = '1' or new_command = '1' then
LEDs <= "0000";
duty_counter := 100;
freq_counter := led_freq_count;
new_command <= '0';
else
------- blinking process --------
if freq_counter = 0 then
freq_counter := led_freq_count;
LED_switch <= not LED_switch;
end if;
freq_counter := freq_counter - 1;
if duty_counter = 0 then
duty_counter := 100;
end if;
duty_counter := duty_counter - 1;
------ output assignment -------
if LED_switch = '1' and duty_counter < duty_cycle then
LEDs <= "1111";
else
LEDs <= "0000";
end if;
end if;
end if;
end process;
--------- input process---------------
process (in_word)
begin
case in_word(3 downto 0) is
when "0001" => led_freq_count <= frq(0);
when "0010" => led_freq_count <= frq(1);
when "0100" => led_freq_count <= frq(2);
when "1000" => led_freq_count <= frq(3);
when others => led_freq_count <= frq(0);
end case;
case in_word(7 downto 4) is
when "0001" => duty_cycle <= duty(0);
when "0010" => duty_cycle <= duty(1);
when "0100" => duty_cycle <= duty(2);
when "1000" => duty_cycle <= duty(3);
when others => duty_cycle <= duty(0);
end case;
new_command <= '1';
end process;
end behavior;
if freq_counter = 0 then
freq_counter := led_freq_count;
LED_switch <= not LED_switch;
else
freq_counter := freq_counter - 1;
end if;
if duty_counter = 0 then
duty_counter := 100;
else
duty_counter := duty_counter - 1;
end if;

Interface DHT22 to FPGA - elbert v2

Now i make a circuit to measure temperature and humidity, then display on LCD. This is my code for DHT22, i use Elbert V2.
After genarating my project, it did not go right.
I tested and my program did not to come to "end_sl"( last state). And i dont know why?. Any suggestions for me? thank you.
my code
----------------------------------------------------------------------------------------------------------------------------------------------------------------
entity DHT11 is
generic (
CLK_PERIOD_NS : positive := 83; -- 12MHz
N: positive:= 40);
port(
clk,rst : in std_logic ;
singer_bus: inout std_logic;
dataout: out std_logic_vector (N-1 downto 0);
tick_done: out std_logic
);
end DHT11;
architecture Behavioral of DHT11 is
constant DELAY_1_MS: positive := 1*10**6/CLK_PERIOD_NS+1;
constant DELAY_40_US: positive := 40*10**3/CLK_PERIOD_NS+1;
constant DELAY_80_US: positive := 80*10**3/CLK_PERIOD_NS+1;
constant DELAY_50_US: positive := 50*10**3/CLK_PERIOD_NS+1; --
constant TIME_70_US: positive := 80*10**3/CLK_PERIOD_NS+1; --bit > 70 us
constant TIME_28_uS: positive := 30*10**3/CLK_PERIOD_NS+1; -- bit 0 > 28 us
constant MAX_DELAY : positive := 5*10**6/CLK_PERIOD_NS+1; -- 5 ms
type state_type is (reset,start_m,wait_res_sl,response_sl,delay_sl,start_sl,consider_logic,end_sl);
signal index, next_index : natural range 0 to MAX_DELAY;
signal state, next_state : state_type;
signal data_out,next_data_out: std_logic_vector (N-1 downto 0);
signal bit_in, next_bit_in: std_logic;
signal number_bit,next_number_bit: natural range 0 to 40;
signal oe: std_logic; -- help to set input and output port.
begin
--register
regis_state:process (clk,rst) begin
if rst = '1' then
state <= reset;
index <= MAX_DELAY;
number_bit <= 0;
bit_in <= '1';
data_out <= (others => '0');
elsif rising_edge(clk) then
state <= next_state;
index <= next_index;
number_bit <= next_number_bit;
bit_in <= next_bit_in;
data_out <= next_data_out;
end if;
end process regis_state;
proces_state: process (singer_bus,index,state,bit_in,number_bit,data_out) begin
tick_done <= '0';
next_data_out <= data_out;
next_number_bit <= number_bit;
next_state <= state;
next_data_out <= data_out;
next_index <= index;
dataout <= (others => '0');
oe <= '0';
next_bit_in <= bit_in;
case(state) is
when reset => -- initial
if index = 0 then
next_state <= start_m;
next_index <= DELAY_1_MS;
next_number_bit <= N-1;
else
next_state <= reset;
next_index <= index - 1;
end if;
when start_m => -- master send '1' in 1ms
if index = 0 then
next_state <= wait_res_sl;
next_index <= DELAY_40_US;
else
oe <= '1';
next_state <= start_m;
next_index <= index -1;
end if ;
when wait_res_sl => -- wait for slave response in 40us --
next_bit_in <= singer_bus;
if bit_in ='1' and next_bit_in = '0' then --
next_state <= response_sl;
else
next_state <= wait_res_sl;
end if;
when response_sl => -- slave response in 80us
next_bit_in <= singer_bus;
if bit_in ='0' and next_bit_in = '1' then
next_state <= delay_sl;
else
next_state <= response_sl;
end if;
when delay_sl => -- wait for slave delay in 80us
if bit_in = '1' and next_bit_in ='0' then
next_state <= start_sl;
else
next_state <= delay_sl;
end if;
when start_sl => -- start to prepare in 50us
if (bit_in = '0') and (next_bit_in = '1') then
next_state <= consider_logic;
next_index <= 0;
elsif number_bit = 0 then
next_state <= end_sl;
next_index <= DELAY_50_US;
else
next_state <= start_sl;
end if;
when consider_logic => -- determine 1 bit-data of slave
next_index <= index + 1;
next_bit_in <= singer_bus;
if bit_in = '1' and next_bit_in = '0' then -- the end of logic state
next_number_bit <= number_bit -1;
if (index < TIME_28_uS) then -- time ~ 28 us - logic = '0'
next_data_out <= data_out(N-2 downto 0) & '0';
elsif (index < TIME_70_US) then -- time ~70 us - logic ='1'
next_data_out <= data_out(N-2 downto 0) & '1';
end if;
next_state <= start_sl;
next_index <= DELAY_50_US;
elsif bit_in ='1' and next_bit_in ='1' then
next_state <= consider_logic;
end if;
when end_sl => -- tick_done = '1' then dataout has full 40 bit.
if index = 0 then
next_index <= MAX_DELAY;
next_state <= reset;
else
tick_done <= '1';
dataout <= data_out;
next_index <= index -1;
next_state <= end_sl;
end if;
end case;
end process proces_state;
--tristate IOBUFFER
singer_bus <= '0' when oe ='1' else 'Z';
end Behavioral;
There are many errors in your code. How did you debug exactly? Because it seems like you did not.
Why wait for 60 ms after the reset? you waste (valuable) simulation time. 6 ms is more then enough.
Looking at the simulation output, you can see the state does not advance at all: it's stuck ini wait_res_sl. The problem is that you have not added all the signals read in the process to the sensitivity list. I.e.
bit_in ='1' and next_bit_in = '0'
Will not detect a change if next_bit_in is not in the sensitivity list.
A problem -a common mistake made- is that your 'test bench' only provides input stimuli.... But it does not actually test anything.
And then the counters. Why is the delay counter called index? It doesn't index anything.
Why do your time delays not match their label? 70us -> 80 us. 28us -> 30 us.
Small thing don't call a RTL architecture behavioral
I tried to clean your code, seems to work now.
library ieee;
use ieee.std_logic_1164.all;
entity dht2 is
generic (
clk_period_ns : positive := 83; -- 12mhz
data_width: positive:= 40);
port(
clk,rst : in std_logic ;
singer_bus: inout std_logic;
dataout: out std_logic_vector(data_width-1 downto 0);
tick_done: out std_logic
);
end entity;
architecture rtl of dht2 is
constant delay_1_ms: positive := 1*10**6/clk_period_ns+1;
constant delay_40_us: positive := 40*10**3/clk_period_ns+1;
constant delay_80_us: positive := 80*10**3/clk_period_ns+1;
constant delay_50_us: positive := 50*10**3/clk_period_ns+1; --
constant time_70_us: positive := 70*10**3/clk_period_ns+1; --bit > 70 us
constant time_28_us: positive := 28*10**3/clk_period_ns+1; -- bit 0 > 28 us
constant max_delay : positive := 5*10**6/clk_period_ns+1; -- 5 ms
signal input_sync : std_logic_vector(0 to 2);
type state_type is (reset,start_m,wait_res_sl,response_sl,delay_sl,start_sl,consider_logic,end_sl);
signal state : state_type;
signal delay_counter : natural range 0 to max_delay;
signal data_out : std_logic_vector (data_width-1 downto 0);
signal bus_rising_edge, bus_falling_edge : boolean;
signal number_bit : natural range 0 to data_width;
signal oe: std_logic; -- help to set input and output port.
begin
input_syncronizer : process(clk) begin
if rising_edge(clk) then
input_sync <= to_x01(singer_bus)&input_sync(0 to 1);
end if;
end process;
bus_rising_edge <= input_sync(1 to 2) = "10";
bus_falling_edge <= input_sync(1 to 2) = "01";
--register
regis_state:process (clk) begin
if rising_edge(clk) then
case(state) is
when reset => -- initial
if delay_counter = 0 then
number_bit <= data_width;
oe <= '1';
delay_counter <= delay_1_ms;
state <= start_m;
else
delay_counter <= delay_counter - 1;
end if;
when start_m => -- master send '1' in 1ms
if delay_counter = 0 then
oe <= '0';
delay_counter <= delay_40_us;
state <= wait_res_sl;
else
delay_counter <= delay_counter -1;
end if ;
when wait_res_sl => -- wait for slave response in 40us --
if bus_falling_edge then --
state <= response_sl;
end if;
when response_sl => -- slave response in 80us
if bus_rising_edge then
state <= delay_sl;
end if;
when delay_sl => -- wait for slave delay in 80us
if bus_falling_edge then
state <= start_sl;
end if;
when start_sl => -- start to prepare in 50us
if bus_rising_edge then
delay_counter <= 0;
state <= consider_logic;
elsif number_bit = 0 then
delay_counter <= delay_50_us;
state <= end_sl;
end if;
when consider_logic => -- determine 1 bit-data of slave
if bus_falling_edge then -- the end of logic state
number_bit <= number_bit - 1;
if (delay_counter < time_28_us) then -- time ~ 28 us - logic = '0'
data_out <= data_out(data_width-2 downto 0) & '0';
elsif (delay_counter < time_70_us) then -- time ~70 us - logic ='1'
data_out <= data_out(data_width-2 downto 0) & '1';
end if;
delay_counter <= delay_50_us;
state <= start_sl;
end if;
delay_counter <= delay_counter + 1;
when end_sl => -- tick_done = '1' then dataout has full 40 bit.
if delay_counter = 0 then
delay_counter <= max_delay;
state <= reset;
else
tick_done <= '1';
dataout <= data_out;
delay_counter <= delay_counter - 1;
end if;
end case;
if rst = '1' then
number_bit <= 0;
data_out <= (others => '0');
delay_counter <= max_delay;
state <= reset;
end if;
end if;
end process regis_state;
--tristate iobuffer
singer_bus <= '0' when oe ='1' else 'Z';
end architecture;
And test bench: I added one check, but you should make more checks: every time you do something, it should have an effect. You should test if that effect actually happens.
entity dht2_tb is end dht2_tb;
library ieee;
architecture behavior of dht2_tb is
use ieee.std_logic_1164.all;
--inputs
signal clk : std_logic := '0';
signal rst : std_logic := '0';
--bidirs
signal singer_bus : std_logic := 'H';
--outputs
signal tick_done : std_logic;
-- clock period definitions
constant clk_period : time := 83.33 ns; -- 12mhz
use ieee.math_real.all;
-- This function generates a 'slv_length'-bit std_logic_vector with
-- random values.
function random_slv(slv_length : positive) return std_logic_vector is
variable output : std_logic_vector(slv_length-1 downto 0);
variable seed1, seed2 : positive := 65; -- required for the uniform function
variable rand : real;
-- Assume mantissa of 23, according to IEEE-754:
-- as UNIFORM returns a 32-bit floating point value between 0 and 1
-- only 23 bits will be random: the rest has no value to us.
constant rand_bits : positive := 23;
-- for simplicity, calculate remaining number of bits here
constant end_bits : natural := slv_length rem rand_bits;
use ieee.numeric_std.all;
begin
-- fill sets of 23-bit of the output with the random values.
for i in 0 to slv_length/rand_bits-1 loop
uniform(seed1, seed2, rand); -- create random float
-- convert float to int and fill output
output((i+1)*rand_bits-1 downto i*rand_bits) :=
std_logic_vector(to_unsigned(integer(rand*(2.0**rand_bits)), rand_bits));
end loop;
-- fill final bits (< 23, so above loop will not work.
uniform(seed1, seed2, rand);
if end_bits /= 0 then
output(slv_length-1 downto slv_length-end_bits) :=
std_logic_vector(to_unsigned(integer(rand*(2.0**end_bits)), end_bits));
end if;
return output;
end function;
-- input + output definitions
constant test_data_length : positive := 32;
constant test_data : std_logic_vector(test_data_length-1 downto 0) := random_slv(test_data_length);
signal data_out : std_logic_vector(test_data_length-1 downto 0);
begin
-- instantiate the unit under test (uut)
uut: entity work.dht2 -- use entity instantiation: no component declaration needed
generic map (
clk_period_ns => clk_period / 1 ns,
data_width => test_data_length)
port map (
clk => clk,
rst => rst,
singer_bus => singer_bus,
dataout => data_out,
tick_done => tick_done
);
-- clock stimuli
clk_process: process begin
clk <= '0', '1' after clk_period/2;
wait for clk_period;
end process;
-- reset stimuli
rst_proc : process begin
rst <= '1', '0' after 100 us;
wait;
end process;
-- bidir bus pull-up
-- as you drive the bus from the uut and this test bench, it is a bidir
-- you need to simulate a pull-up ('H' = weak '1'). slv will resolve this.
singer_bus <= 'H';
-- stimulus process
bus_proc: process
-- we use procedures for stimuli. Increases maintainability of test bench
-- procedure bus_init initializes the slave device. (copied this from your code)
procedure bus_init is begin
-- singer_bus <= 'Z'; -- initial
wait for 6 ms;
-- singer_bus <= '0'; -- master send
-- wait for 1 ms;
singer_bus <= 'Z'; -- wait response for slave
wait for 40 us;
singer_bus <= '0'; -- slave pull low
wait for 80 us;
singer_bus <= 'Z'; -- slave pull up
wait for 80 us;
end procedure;
function to_string(input : std_logic_vector) return string is
variable output : string(1 to input'length);
variable j : positive := 1;
begin
for i in input'range loop
output(j) := std_logic'image(input(i))(2);
j := j + 1;
end loop;
return output;
end function;
-- procedure send_data
procedure send_data(data : std_logic_vector) is begin
-- we can now send a vector of data,length detected automatically
for i in data'range loop
singer_bus <= '0'; -- slave start data transmission
wait for 50 us;
singer_bus <= 'Z'; -- slave send bit;
-- I found the only difference between sending bit '0'
-- and '1' is the length of the delay after a '0' was send.
case data(i) is
when '0' => wait for 24 us;
when '1' => wait for 68 us;
when others =>
report "metavalues not supported for bus_proc send_data"
severity failure;
end case;
singer_bus <= '0';
end loop;
-- next is VHDL-2008 (else use ieee.std_logic_textio.all;)
report "transmitted: "&to_string(data);
end procedure;
begin
wait until rst = '0';
bus_init; -- call procedure
send_data(test_data); -- call procedure
wait for 100 us; -- final delay
singer_bus <= 'Z'; -- release bus
report "received: "&to_string(data_out);
-- test correctness of output
assert data_out = test_data
report "data output does not match send data"
severity error;
report "end of simulation" severity failure;
end process;
end architecture;

VHDL Sending Data from FPGA to TTL

I'm newbie in FPGAs and VHDL. This time, I m trying to send Data from FPGA to TTL. I' m using GPIO pins for TX and GND and Data can be changed with switch on FPGA. My issue is whenever i press the button on FPGA, I always see FF on terminal. I couldn't find where the problem is.
Here is TX code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
entity UART_Tx is
port(
CLK : in std_logic;
Reset : in std_logic;
Button : in std_logic;
Data : in std_logic_vector(7 downto 0);
Out_Tx : out std_logic
);
end entity;
Architecture Behavioral of UART_Tx is
constant Baudrate : integer := 9600;
constant CLK_Hiz : integer := 50000000;
constant CLK_Bit : integer := (CLK_Hiz / Baudrate) + 1;
signal tx_Data_ind : integer range 0 to 7;
signal counter_baud : integer range 0 to (CLK_Bit - 1) := 0;
signal shift_button : std_logic_vector (3 downto 0) := (others => '0');
signal button_out : std_ulogic := '1';
signal baud_pulse : std_ulogic := '0';
signal tx_enable : std_ulogic := '0';
signal tx_Data : std_logic_vector (7 downto 0) := (others => '0');
signal tx_cikis : std_ulogic;
signal tx_tamam : std_ulogic := '0';
signal counter_sil : std_ulogic := '0';
begin
process(CLK, Reset)
begin
if (Reset = '0') then
baud_pulse <= '0';
counter_baud <= 0;
elsif (rising_edge(CLK)) then
if (counter_baud < (CLK_Bit - 1)) then
counter_baud <= counter_baud + 1;
baud_pulse <= '0';
else
counter_baud <= 0;
baud_pulse <= '1';
end if;
if (counter_sil = '1') then
counter_baud <= 0;
end if;
end if;
end process;
process(CLK, Reset)
begin
if (Reset = '0') then
tx_Data <= (others => '0');
tx_data_ind <= 0;
tx_enable <= '0';
elsif (rising_edge(CLK)) then
tx_cikis <= '1';
out_tx <= tx_cikis;
shift_button(3) <= button;
shift_button(2 downto 0) <= shift_button(3 downto 1);
if shift_button(3 downto 0) = "001" then
button_out <= '0';
end if;
if (button_out = '0') then
counter_sil <= '1';
tx_cikis <= '0';
if (tx_cikis = '0') then
tx_enable <= '1';
end if;
if (tx_enable = '1') then
counter_sil <= '0';
tx_Data <= Data;
if (baud_pulse = '1') then
tx_cikis <= tx_Data(tx_Data_ind);
if (tx_data_ind < 7) then
tx_Data_ind <= tx_Data_ind + 1;
else
tx_tamam <= '1';
end if;
if (tx_tamam = '1') then
tx_Data <= (others => '0');
tx_Data_ind <= 0;
tx_enable <= '0';
button_out <= '1';
tx_cikis <= '1';
end if;
end if;
end if;
end if;
end if;
end process;
end Architecture;
Here is Testbench code:
library ieee;
use ieee.std_logic_1164.all;
entity tb_UART_Tx is
end tb_UART_Tx;
architecture tb of tb_UART_Tx is
component UART_Tx
port (CLK : in std_logic;
Reset : in std_logic;
Button : in std_logic;
Data : in std_logic_vector (7 downto 0);
Out_Tx : out std_logic);
end component;
signal CLK : std_logic:='0';
signal Reset : std_logic:='1';
signal Button : std_logic:='1';
signal Data : std_logic_vector (7 downto 0);
signal Out_Tx : std_logic;
constant TbPeriod : time := 20 ns;
signal TbSimEnded : std_logic := '0';
begin
dut : UART_Tx
port map (CLK => CLK,
Reset => Reset,
Button => Button,
Data => Data,
Out_Tx => Out_Tx);
clk_process: process
begin
CLK <= '0';
wait for TbPeriod/2;
CLK <= '1';
wait for TbPeriod/2;
end process;
stimuli : process
begin
Reset <= '0';
wait for 20 ns;
Button <= '1';
Data <= "00110000";
wait for 30 ns;
Button <= '0';
wait for 50 ns;
Button <= '1';
wait for 1000 ns;
-- Button <= '0';
-- wait for 30 ns;
-- Button <= '1';
TbSimEnded <= '1';
wait;
end process;
end tb;
configuration cfg_tb_UART_Tx of tb_UART_Tx is
for tb
end for;
end cfg_tb_UART_Tx;
Added Testbench results
EDIT: HERE is the working code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
entity UART_Tx is
port(
CLK: in std_logic;
nReset: in std_logic;
nButton: in std_logic;
Data: in std_logic_vector (7 downto 0);
Data_Tx: out std_logic
);
end UART_Tx;
architecture Behavioral of UART_Tx is
constant Baudrate: integer:= 9600;
constant CLK_Hiz: integer:= 50000000;
constant CLK_Bit: integer:= (CLK_Hiz / Baudrate) + 1;
signal tx_counter: integer range 1 to 9:= 1;
signal counter_baud: integer range 0 to (CLK_Bit - 1):= 0;
signal shift_nButton:std_logic_vector (3 downto 0):= (others => '1');
signal tx_reg: std_logic_vector (7 downto 0):= (others => '0');
signal nButton_out: std_ulogic:= '1';
signal baud_pulse: std_ulogic;
signal tx_out: std_ulogic:= '1';
signal counter_del: std_ulogic;
signal start_bit: std_ulogic:='0';
signal data_bit: std_ulogic:='0';
signal stop_bit: std_ulogic:='0';
begin
process(CLK,nReset)
begin
if(nReset = '0') then
baud_pulse <= '0';
counter_baud <= 0;
elsif(rising_edge(CLK)) then
if(counter_baud < (CLK_Bit - 1)) then
counter_baud <= counter_baud + 1;
baud_pulse <= '0';
else
counter_baud <= 0;
baud_pulse <= '1';
end if;
if(counter_del = '1') then
counter_baud <= 0;
end if;
end if;
end process;
process(CLK, nReset)
begin
Data_Tx <= tx_out;
if(nReset = '0') then
tx_reg <= (others => '0');
tx_counter <= 1;
elsif(rising_edge(CLK)) then
shift_nButton(3) <= nButton;
shift_nButton(2 downto 0) <= shift_nButton(3 downto 1);
if shift_nButton(2 downto 0) = "001" then
nButton_out <= '0';
counter_del <= '1';
start_bit <= '1';
end if;
if(nButton_out = '1') then
tx_out <= '1';
elsif(nButton_out = '0') then
counter_del <= '0';
if(start_bit = '1') then
tx_out <= '0';
tx_reg <= Data;
if(baud_pulse = '1') then
start_bit <= '0';
data_bit <= '1';
end if;
end if;
if(data_bit = '1')then
if(tx_counter > 0 and tx_counter < 10) then
tx_out <= tx_reg((tx_counter)-1);
if(baud_pulse = '1') then
tx_counter <= tx_counter + 1;
if(tx_counter = 9)then
data_bit <= '0';
stop_bit <= '1';
end if;
end if;
end if;
end if;
if(stop_bit = '1') then
tx_out <= '1';
tx_counter <= 1;
if(baud_pulse = '1') then
stop_bit <= '0';
nButton_out <= '1';
tx_reg <= (others => '0');
end if;
end if;
end if;
end if;
end process;
end Behavioral;

VHDL VGA interface

I've been modelling a VGA interface on the DE0 board. I have the following model for a 640x480 display which refreshes at 60Hz:
Main model:
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
ENTITY VGA is
PORT (clk : IN std_logic; -- demo had 2 bit vector
vga_hs, vga_vs : OUT std_logic;
vga_r, vga_g, vga_b : OUT std_logic_vector(3 DOWNTO 0));
END ENTITY VGA;
ARCHITECTURE A1 OF VGA IS
SIGNAL rst, clk25 : std_logic; -- rst only resets pixel clock
BEGIN
SYNC1 : ENTITY work.sync(A1)
PORT MAP (clk25, vga_hs, vga_vs, vga_r, vga_g, vga_b);
CLK_25 : ENTITY work.PLL(rtl)
PORT MAP (clk, rst, clk25);
END ARCHITECTURE A1;
Sync model:
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
ENTITY SYNC IS
PORT(
clk : IN std_logic;
h_sync, v_sync : OUT std_logic;
r, g, b : OUT std_logic_vector(3 DOWNTO 0)
);
END ENTITY SYNC;
ARCHITECTURE A1 OF SYNC IS
SIGNAL h_pos: integer RANGE 0 TO 800:=0;
SIGNAL v_pos : integer RANGE 0 TO 520:=0;
BEGIN
TIMING :PROCESS(clk) IS
BEGIN
IF rising_edge(clk) THEN
IF (h_pos = 480 or v_pos = 280) THEN -- middle of the screen is pic res/2 + (FP + sync + BP)
r <= (OTHERS => '1');
g <= (OTHERS => '1');
b <= (OTHERS => '1');
ELSE
r <= (OTHERS => '0');
g <= (OTHERS => '0');
b <= (OTHERS => '0');
END IF;
IF (h_pos < 800) THEN
h_pos <= h_pos + 1;
ELSE
h_pos <= 1;
IF (v_pos < 520) THEN
v_pos <= v_pos + 1;
ELSE
v_pos <= 1;
END IF;
END IF;
IF (h_pos > 16 and h_pos < 112 ) THEN -- H_POS between end of FP and the end of H_SYNC
h_sync <= '0'; -- H_SYNC needs to stay low during display
ELSE
h_sync <= '1';
END IF;
IF (v_pos > 8 and v_pos < 10 ) THEN --V_POS between end of FP and the end of V_SYNC
v_sync <= '0'; -- V_SYNC needs to stay low during display
ELSE
v_sync <= '1';
END IF;
IF ((h_pos > 0 and h_pos < 160) or (v_pos > 0 and v_pos < 40 )) THEN--During all of SYNC i.e FP + SYNC + BP colour signals stay low
r <= (OTHERS => '0');
g <= (OTHERS => '0');
b <= (OTHERS => '0');
END IF;
END IF;
END PROCESS TIMING;
END ARCHITECTURE A1;
----------Amendments made to model 09/02 13:42----------
The other direct instantiation is for PLL generated from Quartus II it seems to work fine.. thank you Mr Zilmer :). The model compiles fine. I load it into the DE0. Then connect this to a monitor and get nothing on the display. It should display a cross in the centre of the screen. The display I am using is a Samsung with 1920x1080. Would this stop my model from displaying anything? Or have I made a obvious mistake in my model. I have changed some of the standard timing values to fit a 60Hz refresh with 25Mz clk.
Thanks
D
Your VHDL code for entity sync doesn't analyze. You are missing an end if and your initial values for h_sync and v_sync violate the subtype constraint:
signal h_pos: integer range 1 to 800 := 0;
signal v_pos: integer range 1 to 520 := 0;
Where 0 is outside the bounds of 1 to 800 or 1 to 520.
This raises the question of whether or not you have another architecture for entity sync, or whether sync is simply unbound. Either of which might give you an incorrect indication (and the error isn't demonstrated in your question).
We can use a testbench to demonstrate what sync does in simulation with a 25 MHz clock:
library ieee;
use ieee.std_logic_1164.all;
--use ieee.numeric_std.all;
entity sync is
port (
clk: in std_logic;
h_sync, v_sync: out std_logic;
r, g, b: out std_logic_vector(3 downto 0)
);
end entity sync;
architecture a1 of sync is
signal h_pos: integer range 1 to 800 := 1; -- was := 0;
signal v_pos: integer range 1 to 520 := 1; -- was := 0;
begin
timing:
process (clk) is
begin
if rising_edge(clk) then
if h_pos = 480 or v_pos = 280 then -- middle of the screen
r <= (others => '1');
g <= (others => '1');
b <= (others => '1');
else
r <= (others => '0');
g <= (others => '0');
b <= (others => '0');
end if;
if h_pos < 800 then
h_pos <= h_pos + 1;
else
h_pos <= 1;
if v_pos < 520 then
v_pos <= v_pos + 1;
else
v_pos <= 1;
end if;
if h_pos > 16 and h_pos < 112 then
h_sync <= '0'; -- h_sync low during display
else
h_sync <= '1';
end if;
if v_pos > 8 and v_pos < 10 then
v_sync <= '0'; -- v_sync low during display
else
v_sync <= '1';
end if;
if (h_pos > 1 and h_pos < 160) or
(v_pos > 1 and v_pos < 40 ) then -- black during blanking
r <= (others => '0');
g <= (others => '0');
b <= (others => '0');
end if;
end if;
end if; -- added misssing end if
end process timing;
end architecture a1;
library ieee;
use ieee.std_logic_1164.all;
entity sync_tb is
end entity;
architecture foo of sync_tb is
signal clk: std_logic := '0';
signal h_sync: std_logic;
signal v_sync: std_logic;
signal r, g, b: std_logic_vector (3 downto 0);
begin
DUT:
entity work.sync
port map (
clk => clk,
h_sync => h_sync,
v_sync => v_sync,
r => r,
g => g,
b => b
);
CLOCK:
process
begin
wait for 20 ns; -- clock period 25 MHz = 40 ns;
clk <= not clk;
if now > 20 ms then -- one frame time plus a bit
wait;
end if;
end process;
end architecture;
And now we get to troubleshoot:
The first thing we notice is h_sync is wrong. Also note that v_sync appears to be around 16.667 ms (1/60th of a second).
We can add the h_pos and v_pos counters so we can look at h_sync, we do know the h_pos counter is running to get a v_sync we can see in the right neighborhood of 60 Hz.
So I picked the wrong place to add the end if. Correcting that also separates operating the counters from operating on their outputs (h_sync, v_sync and r,g,b).
timing:
process (clk) is
begin
if rising_edge(clk) then
if h_pos = 480 or v_pos = 280 then -- middle of the screen
r <= (others => '1');
g <= (others => '1');
b <= (others => '1');
else
r <= (others => '0');
g <= (others => '0');
b <= (others => '0');
end if;
if h_pos < 800 then
h_pos <= h_pos + 1;
else
h_pos <= 1;
if v_pos < 520 then
v_pos <= v_pos + 1;
else
v_pos <= 1;
end if;
end if; -- separate the counters for what they produce
-- HSYNC
if h_pos > 16 and h_pos < 112 then
h_sync <= '0'; -- h_sync low during display
else
h_sync <= '1';
end if;
-- VSYNC
if v_pos > 8 and v_pos < 10 then
v_sync <= '0'; -- v_sync low during display
else
v_sync <= '1';
end if;
-- BLANKING
if (h_pos > 1 and h_pos < 160) or
(v_pos > 1 and v_pos < 40 ) then
r <= (others => '0');
g <= (others => '0');
b <= (others => '0');
end if;
end if;
end process timing;
We have h_sync now:
Notice we can see the vertical blanking interval now too.
Zooming in we can see there a horizontal white line at v_pos 280:
Along with a vertical line at h_pos 480 (+1):
And this looks like it just might work.
The only design change I might be tempted to make would be to start the visible portion of the line at h_pos = 0 and the the visible portion of the frame at v_pos = 0. This would allow something else to address pixels for writing in a frame buffer without adding additional pixel counters or having to do offset arithmetic. (Pixel addressing usually starts at 0 for x and y axis).

How to send some data 10 times with a delay of 10 ms between chunks of databits to the TX port of uart

I have an sensor it has an unlocked byte sequence which needs to be sent to it to unlock it and then it can receive the other command data.
The sensor receive data at a baudrate of 115200 bps, 8 data bits, even parity, 2 stop bits.
and before receiving any command data( used to set parameters) It needs to recieve d4 (hexadecimal number, byte) 10 times at an interval of 1ms.
I send the d4 converted into bits 11010100 added with parity and stop bits becomes 11010100011 to the TX port of uart at the baud rate of 115200 but how to create a delay between two d4 data byte sent ? I am writing the code if not clear please let me know I would put more details.
entity Uart_tx is
port (
TX : out std_logic;
clk_in : in std_logic;
but_div_clk : out std_logic;
clk_in_2 : in std_logic
);
end Uart_tx;
architecture Behavioral of Uart_tx is
signal tx_clk : std_logic := '0';
signal clk_1Khz : std_logic := '0';
signal q : unsigned(8 downto 0) := (others => '0');
signal p : unsigned(8 downto 0) := (others => '0');
type state_type is (idle, start);
signal state : state_type;
signal tick_in : std_logic := '0';
subtype byte is std_logic_Vector(7 downto 0);
type byte_array is array(natural range <>) of byte;
signal data_byte_array : byte_array(1 to 8);
-- signal curr_byte : std_logic_vector(7 downto 0);
signal byte_index : unsigned(2 downto 0) := "000";
subtype reg is std_logic_Vector(10 downto 0);
type reg_array is array(natural range <>) of reg;
signal TxDataReg_array : reg_array(1 to 8);
signal cur_Tx_reg : std_logic_vector(10 downto 0);
signal current_reg : unsigned(3 downto 0) := "0001";
signal count : unsigned (4 downto 0) := (others => '0');
signal count_d : unsigned (4 downto 0) := (others => '0');
signal sent_d4 : unsigned (3 downto 0) := (others => '0');
signal send_d4 : std_logic := '1';
signal D_4 : std_logic_vector(10 downto 0) :="11000101011";
begin
-- below are random entry ..actual data will come from slv_reg registers.
data_byte_array(1) <= "10101010"; -- slv_reg0(7 downto 0);
data_byte_array(2) <= "10101011"; -- slv_reg0(15 downto 8);
data_byte_array(3) <= "10101010"; -- slv_reg0(23 downto 16);
data_byte_array(4) <= "10101011"; -- slv_reg0(31 downto 24);
data_byte_array(5) <= "10101010"; -- slv_reg1(39 downto 32);
data_byte_array(6) <= "10101011"; -- slv_reg1(47 downto 40);
data_byte_array(7) <= "10101010"; -- slv_reg1(55 downto 48);
data_byte_array(8) <= "10101011"; -- slv_reg1(63 downto 56);
tick_in <= '1';
---------------------------------------Clk_div-----------------------------------------
process ( clk_in ) is
begin
if clk_in'event and clk_in = '1' then
q <= q + 1;
tx_clk <= q(8); --- 58.gdfg/2^8 =~ 230Khz baud rate = 115200
but_div_clk <= tx_clk;
end if;
end process;
---------------------------------------Clk_div------------------------------------------
---------------------------------------Clk_div------------------------------------------
process( clk_in_2 ) is
begin
if clk_in_2'event and clk_in_2 = '1' then
p <= p + 1;
clk_1Khz <= p(7);
end if;
end process;
---------------------------------------------------------------------------------------
--------------------------------------TX_Process----------------------------------------
process( state, tx_clk , tick_in) is
variable parity : std_logic := '0';
variable curr_byte : std_logic_vector(7 downto 0) := (others => '0');
begin
case state is
when idle => TX <= '1';
if tick_in = '1' then
state <= start;
else
TX <= '1';
end if;
when start =>
if send_d4 = '1' then
if (rising_edge(clk_1Khz)) then
case count_d is
when "00000" => TX <= D_4(0);
when "00001" => TX <= D_4(1);
when "00010" => TX <= D_4(2);
when "00011" => TX <= D_4(3);
when "00100" => TX <= D_4(4);
when "00101" => TX <= D_4(5);
when "00110" => TX <= D_4(6);
when "00111" => TX <= D_4(7);
when "01000" => TX <= D_4(8);
when "01001" => TX <= D_4(9);
when "01010" => TX <= D_4(10);
when others => TX <= '1';
end case;
count_d <= count_d +1;
sent_d4 <= sent_d4 + 1;
if to_integer(count_d) = 11 then
count_d <= "00000";
end if;
if to_integer(sent_d4) = 10 then
send_d4 <= '0' ;
end if;
end if;
else
for i in 1 to 8 loop
curr_byte := data_byte_array(i);
parity := '0';
for j in curr_byte'range loop
parity := parity xor curr_byte(j);
end loop;
if parity = '0' then
TxDataReg_array(i) <= "110" & curr_byte ;
else
TxDataReg_array(i) <= "111" & curr_byte ;
end if;
end loop;
cur_Tx_reg <= TxDataReg_array(to_integer(byte_index)+1);
byte_index <= byte_index + 1;
if rising_edge(tx_clk) then
case count is
when "00000" => TX <= cur_Tx_reg(0);
when "00001" => TX <= cur_Tx_reg(1);
when "00010" => TX <= cur_Tx_reg(2);
when "00011" => TX <= cur_Tx_reg(3);
when "00100" => TX <= cur_Tx_reg(4);
when "00101" => TX <= cur_Tx_reg(5);
when "00110" => TX <= cur_Tx_reg(6);
when "00111" => TX <= cur_Tx_reg(7);
when "01000" => TX <= cur_Tx_reg(8);
when "01001" => TX <= cur_Tx_reg(9);
when "01010" => TX <= cur_Tx_reg(10);
when others => TX <= '1';
end case;
count <= count+1;
if to_integer(count) = 11 then
count <= "00000";
state <= idle;
-- TX <= '1';
end if;
end if;
end if;
when others => TX <= '1';
end case;
end process;
end Behavioral;
To get a timed delay you have to implement a counter that ticks off a computed number of clock cycles equal to 1 ms. You then need to insert states into your FSM that activate the counter and wait for it to complete when needed. It is possible to manually calculate the counter value but you can make the tools do the work for you and avoid having magic numbers in your code.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
...
constant CLOCK_FREQ : real := 50.0e6; -- 50 MHz system clock
constant SENSOR_DELAY : real := 1.0e-3; -- 1 ms delay
constant DELAY_COUNT : natural := integer(CLOCK_FREQ * SENSOR_DELAY);
-- This could be auto calculated with a ceil_log2() function
constant TIMER_SIZE : natural := 16;
signal timer : unsigned(TIMER_SIZE-1 downto 0);
constant DELAY_INIT : unsigned(timer'range)
:= to_unsigned(DELAY_COUNT, timer'length);
...
-- Initialize the timer sometime before you want the delay
timer <= DELAY_INIT;
...
-- Somewhere in your FSM
when WAIT_1MS =>
timer <= timer - 1;
if timer = 0 then
state <= WHATEVER_YOU_WANT_NEXT;
end if;
This method of using real constants to compute integer values is subject to rounding errors and general floating-point inaccuracies. For these sort of long delays, the small error (typically off-by-one) that could happen isn't usually of concern.
Note that you need to rework your state machine to follow more conventional patterns. You have created a process that mixes pure combinational logic with synchronous. You should not mix the two. You should not have the rising_edge() tests inside your FSM case statement but rather there should be a single if-block evaluating rising_edge() that contains your FSM.
If you need a clock sensitive process then it should only have the clock and an (optional) asynchronous reset in its sensitivity list. Any other pure combinational code should be put in a separate process. In a design such as this that shouldn't be necessary though.
VHDL allows what you have now but synthesis tools expect the use of a more limited style when describing the hardware. You risk having unexpected results if they can handle your code at all.

Resources