Estoy desarrollando el emulador TS-CAN1 en ATF1508AS de Atmel. Una parte de una aplicación es un decodificador de dirección implementado de la siguiente manera (solo quedan partes interesantes):
library ieee;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity can_decoder is
port (
clk: in std_logic;
reset: in std_logic;
isa_addr: in std_logic_vector(9 downto 0);
isa_data: inout std_logic_vector(7 downto 0);
isa_ior: in std_logic;
isa_iow: in std_logic;
isa_irq: out std_logic;
isa_iochrdy: out std_logic;
sja_bus: inout std_logic_vector(7 downto 0);
sja_ior: out std_logic;
sja_iow: out std_logic;
sja_ale: out std_logic;
sja_cs: out std_logic;
sja_irq: in std_logic;
debug: out std_logic);
end can_decoder;
architecture behavioral of can_decoder is
constant SJA_ADDRESS_LOW: integer := 256; -- 0x100
constant SJA_ADDRESS_HIGH: integer := 287; -- 0x11F
constant TSCAN1_ADDRESS_LOW: integer := 336; -- 0x150
constant TSCAN1_ADDRESS_HIGH: integer := 343; -- 0x157
type state_type is (wait_for_isa,
handle_tscan1,
hold_address_and_set_ale,
hold_address_and_clear_ale,
set_read_data,
hold_read_data,
set_write_data,
hold_write_data);
signal current_state: state_type := wait_for_isa;
signal next_state: state_type := wait_for_isa;
signal address : integer;
signal next_page: std_logic_vector(1 downto 0) := "00";
signal page: std_logic_vector(1 downto 0) := "00";
signal mode_control: std_logic_vector(6 downto 0) := "0000000";
signal next_mode_control: std_logic_vector(6 downto 0) := "0000000";
signal sja_enabled: std_logic;
begin
process (clk)
begin
if (rising_edge(clk)) then
if (reset = '0') then
current_state <= wait_for_isa;
page <= "00";
mode_control <= "0000000";
else
current_state <= next_state;
page <= next_page;
mode_control <= next_mode_control;
end if;
end if;
end process;
process (current_state, isa_ior, isa_iow, isa_addr, sja_bus, sja_irq, isa_data, page, mode_control, address, sja_enabled, next_state)
begin
isa_irq <= (not sja_irq) and sja_enabled;
address <= conv_integer('0' & isa_addr);
sja_enabled <= mode_control(6);
-- this is how I know wrong state is selected
if (current_state = handle_tscan1) then
debug <= '1';
else
debug <= '0';
end if;
case current_state is
when wait_for_isa =>
if (isa_ior = '0' or isa_iow = '0') and ((address >= SJA_ADDRESS_LOW) and (SJA_ADDRESS_HIGH >= address)) and sja_enabled = '1' then
-- Address in SJA1000 range
next_state <= hold_address_and_set_ale;
elsif (isa_ior = '0' or isa_iow = '0') and ((address >= TSCAN1_ADDRESS_LOW) and (TSCAN1_ADDRESS_HIGH >= address)) then
-- Address is in TSCAN1 range
next_state <= handle_tscan1;
else
-- Address outside of interesting range (or no triggering signals)
next_state <= wait_for_isa;
end if;
when handle_tscan1 =>
if (isa_ior = '0') then
next_state <= handle_tscan1;
elsif (isa_iow = '0') then
-- next_mode_control and next_page are set here
next_state <= handle_tscan1;
else
next_state <= wait_for_isa;
end if;
when hold_address_and_set_ale =>
next_state <= hold_address_and_clear_ale;
when hold_address_and_clear_ale =>
if (isa_ior = '0') then
next_state <= set_read_data;
elsif (isa_iow = '0') then
next_state <= set_write_data;
else
next_state <= wait_for_isa;
end if;
when set_read_data =>
next_state <= hold_read_data;
when hold_read_data =>
if (isa_ior = '0' and next_state = hold_read_data) then
next_state <= hold_read_data;
else
next_state <= wait_for_isa;
end if;
when set_write_data =>
next_state <= hold_write_data;
when hold_write_data =>
if (isa_iow = '0' and next_state = hold_write_data) then
next_state <= hold_write_data;
else
next_state <= wait_for_isa;
end if;
end case;
end process;
end behavioral;
El problema es que a veces se decodifica una dirección entre 0x100
y 0x11F
, ya que estaría entre 0x150
y 0x157
. La imagen de abajo presenta el análisis de tiempo tomado de los autobuses. La primera fila es una dirección en el bus ISA (esta es la dirección que necesito para decodificar). La cuarta fila ( IOW
) es una señal que, de alta a baja, la transición puede provocar un cambio de estado, si la dirección coincide. La señal DEBUG
es alta cuando se ingresa el estado handle_tscan1
.
Como puede ver, la dirección de 0x114
y IOW = 0
activa la transición. Pero se selecciona la transición incorrecta. Como 0x100 < 0x114 < 0x11f
, se debe seleccionar la transición a hold_address_and_ale
, pero en su lugar se selecciona handle_tscan1
.
Soy bastante nuevo en el mundo de PLD, así que todavía no conozco todos los escollos. Tal vez estoy haciendo algo mal (¿convertir bus a entero, comparando enteros con constantes?). Por favor avise.
Si se necesita más código, por favor, dígame, lo publicaré.