Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
14 years ago

CPLD VHDL problem

HI,

I am trying to understand the operation of the following VHDL code.

The cpld EPM2210 is attached to a processor bus (d0-d15 and A0-A15).

When I do a double read 'word aligned' address range 0xXXXXX40 to 0xXXXXXX5A

I get:

0xXXXXXX52 = 2357 2357

0xXXXXXX54 = 5678 5678

0xXXXXXX54 = EB67 EB67

0xXXXXXX58 = 08FC 08FC

0xXXXXXX5A = C438 C438

At address 0xXXXXXX58 I expected 1267 and then F23C but I get 08FC and 08FC

WHY!!!!

Any help will be appreciated.

====================================

library IEEE;

use IEEE.std_logic_1164.all;

use ieee.std_logic_arith.all;

use IEEE.std_logic_unsigned.all;

entity Top is

port (

-----------------------------------------------------------------------------------------------------

-- MICROCONTROLLER BUS

-----------------------------------------------------------------------------------------------------

clk : in std_logic;

reset_n : in std_logic;

proc_cs2_n : in std_logic;

proc_rw_n : in std_logic;

proc_oe_n : in std_logic;

proc_addr : in std_logic_vector(17 downto 0);

proc_data : inout std_logic_vector(15 downto 0);

);

end Top;

architecture Structure of Top is

--3631

--4862

--32c5

--35a9

--3072

constant CPLD_Version_word: ROM_Array2 := (

0 => "0011011000110001",-- Suppose ROM has

2 => "0100100001100010", -- prestored value

4 => "0011001011000101", -- like this table

6 => "0011010110101001", -- like this table

8 => "0011000001110010", -- like this table

OTHERS => "1111111111111111" --

);

----------------------------------------------

-- states for reading fifo 24 bits

----------------------------------------------

type read_fifo_24_bits is (

idle_state,

read_top_16);

signal state_rd_fifo : read_fifo_24_bits;

--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

begin

--------------------------------------------------------------------------------

-- main process

--------------------------------------------------------------------------------

process(reset_n, clk,state_rd_fifo,

proc_data(15 downto 0),

proc_addr(15 downto 0),

proc_cs2_n,

proc_rw_n,

--------------------------------------------------------------------------------

-- variable must be here

--------------------------------------------------------------------------------

variable state_fifo: integer range 0 to 4:= 0;

begin

--------------------------------------------------------------------------------

-- main reset

--------------------------------------------------------------------------------

if reset_n='0' then

proc_data <= "ZZZZZZZZZZZZZZZZ";

pwm_data0 <= "0000000000000000";

port_out11 <= "00000011"; -- for serial port comms

state_fifo := 0;

--------------------------------------------------------------------------------

-- start decode chip select and decode address input with a READ

--------------------------------------------------------------------------------

elsif (proc_cs2_n='0' and proc_rw_n='1' ) then

case proc_addr(15 downto 0) is

when "0000001100100000" =>proc_data(15 downto 0) <=

CPLD_Version_word(conv_integer(proc_addr(3 downto 0)));

when "0000001100100010"=>proc_data(15 downto 0) <=

CPLD_Version_word(conv_integer(proc_addr(3 downto 0)));

when "0000001100100100"=>proc_data(15 downto 0) <=

CPLD_Version_word(conv_integer(proc_addr(3 downto 0)));

when "0000001100100110"=>proc_data(15 downto 0) <=

CPLD_Version_word(conv_integer(proc_addr(3 downto 0)));

when "0000001100101000"=>proc_data(15 downto 0) <=

CPLD_Version_word(conv_integer(proc_addr(3 downto 0)));

when "0000000001010010" => proc_data (15 downto 0) <= X"2357";

when "0000000001010011" => proc_data (15 downto 0) <= X"5678";

when "0000000001010100" => proc_data (15 downto 0) <= X"eb67";

when "0000000001010101" => proc_data (15 downto 0) <= X"e8fd";

when "0000000001010110" => proc_data (15 downto 0) <= X"1ba5";

when "0000000001011000" =>

if(state_fifo = 0) then

proc_data (15 downto 0) <= X"1267";

state_fifo := 1;

else

proc_data (15 downto 0) <= X"abcd";

state_fifo := 1;

end if;

if(state_fifo = 1) then

proc_data (15 downto 0) <= X"f23c";

state_fifo := 2;

else

proc_data (15 downto 0) <= X"2784";

state_fifo := 2;

end if;

if(state_fifo = 2) then

proc_data (15 downto 0) <= X"982b";

state_fifo := 0;

else

proc_data (15 downto 0) <= X"08fc";

state_fifo := 0;

end if;

when "0000000001011010" =>

proc_data (15 downto 0) <= X"c438";

when others =>

proc_data (15 downto 0) <= "ZZZZZZZZZZZZZZZZ";

end case;

end if;

end process;

5 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    At address 0xXXXXXX58 I expected 1267 and then F23C but I get 08FC and 08FC

    WHY!!!!

    --- Quote End ---

    Look sharp. According to your code, either X"982b" or X"08fc" are send. Only the code starting with if(state_fifo = 2) then is active.

    I also noticed, that the CPLD will possibly drive the bus, although not addressed. The output is only correctly tri-stated, if an "others" address is omitted before cs or rd are deasserted. Otherwise the last output word is hold permanently.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thanks FvM,

    Your right I need to open my eyes and wakeup!!

    I changed the code so that at the same address (0xxxxxx42) I could read in 24 alternative words. i.e. in this case 24 off (0x1234 and 0x789a).

    Can anyone think of why this code does not do this simple task.

    when "0000000001000010" => -- read 24 double words

    case state_rd_fifo is

    when idle_state =>

    fifo_enable_read <= '1';

    proc_data (15 downto 0) <= X"1234";

    fifo_enable_write <= '0';

    state_rd_fifo <= read_top_16;

    when read_top_16 =>

    end_fifo_24_words:= end_fifo_24_words+1;

    state_rd_fifo <= idle_state;

    proc_data (15 downto 0) <= "789a;

    fifo_enable_read <= '0';

    if end_fifo_24_words >= 24 then

    state_rd_fifo <= idle_state;

    end_fifo_24_words:= 0;

    end if;

    when others =>

    state_rd_fifo <= idle_state;

    end_fifo_24_words:= 0;

    proc_data (15 downto 0) <=

    "ZZZZZZZZZZZZZZZZ";

    end case;

    when others => proc_data (15 downto 0) <=

    "ZZZZZZZZZZZZZZZZ";

    end case;
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I would primarly ask what kind of process and trigger condition is including the FIFO counter and assignments of state_rd_fifo. A counter or a state variable register can only work under a clock edge sensitive condition, e.g if rising_edge(clk).

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Here is the code I am trying to to get to work:

    I am interested in the read condition when state_rd_fifo changes state:

    process(reset_n,clk,state_rd_fifo,

    proc_data(15 downto 0),

    proc_addr(15 downto 0),

    proc_cs2_n,

    proc_rw_n,

    state_rd_fifo)

    variable end_fifo_24_words : integer range 0 to 30 := 0;

    begin

    --------------------------------------------------------------------------------

    -- main reset

    --------------------------------------------------------------------------------

    if reset_n='0' then

    proc_data <= "ZZZZZZZZZZZZZZZZ";

    state_rd_24bits <= idle_state;

    read_uart_24 <= '0';

    fifo_enable_read <= '0';

    fifo_enable_write <= '0';

    end_fifo_24_words := 0;

    state_rd_fifo <= state1;

    --------------------------------------------------------------------------------

    -- start decode chip select and decode address input with a WRITE

    --------------------------------------------------------------------------------

    elsif rising_edge(clk) then

    if (proc_cs2_n='0' and proc_rw_n='0') then

    case proc_addr(15 downto 0) is

    when "0000000000001110" =>

    case state_wr_24bits is

    when write_byte_1 =>

    temp_word_24_0(23 downto 8) <= proc_data (15 downto 0);

    state_wr_24bits <= write_byte_2;

    when write_byte_2=>

    temp_word_24_1(23 downto 8) <= proc_data (15 downto 0);

    if(tx_ready_0 ='1') then -- now write the 24 bits to uart

    start_tx_0 <= '1';

    tx_data_register_24bit_0 <= temp_word_24_1(23 downto 8) &

    temp_word_24_1(7 downto 0);

    tx_write0 <='1' ;

    state_wr_24bits <= write_byte_1;

    end if;

    end case;

    --------------------------------------------------------------------------------

    -- start decode chip select and decode address input with a READ

    --------------------------------------------------------------------------------

    elsif (proc_cs2_n='0' and proc_rw_n='1' ) then

    case proc_addr(15 downto 0) is

    when "0000000001010010" => proc_data (15 downto 0) <= X"2357";

    when "0000000001010011" => proc_data (15 downto 0) <= X"5678";

    when "0000000001010100" => proc_data (15 downto 0) <= X"eb67";

    when "0000000001010101" => proc_data (15 downto 0) <= X"e8fd";

    when "0000000001010110" => proc_data (15 downto 0) <= X"1ba5";

    when "0000000001011000" =>

    case state_rd_fifo is

    when state1 =>

    proc_data (15 downto 0) <= X"1267"; --temp_word_24_0(23 downto 8);

    state_rd_fifo <= state2;

    when state2 =>

    proc_data (15 downto 0) <= X"f23c"; --temp_word_24_0(23 downto 8);

    state_rd_fifo <= state1;

    when others =>

    proc_data (15 downto 0) <= "ZZZZZZZZZZZZZZZZ";

    end case;

    when "0000000001011010" => proc_data (15 downto 0) <= X"c438";

    when others => proc_data (15 downto 0) <= "ZZZZZZZZZZZZZZZZ";

    end case;

    end if;

    end process;
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    It's not clear to me, what the code is expected to do. As coded, the state machine advances on every clock cycle while read is active. The result depends on the relation of clock and processor bus timing.