--                                                               
-- sconfig.vhd
--
-- This design interfaces to two Actel Fusion NVM blocks and provides
-- a standard serial interface that will allow an external device
-- to erase write, and read data from the NVM.
--        
------------------------------------------------------------------------
--
-- Version 1.0  09/01/06 - intial release
--
------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity sconfig is 
port(rstn   : in    std_logic;				-- active low
     fclk   : in    std_logic;				-- 60 MHz

     CSn    : in    std_logic;				-- active low
     CLK    : in    std_logic;				-- 20 MHz - SPI
     DI     : in    std_logic;				-- Data input
     DO     : inout std_logic;				-- Data output

     addr      : out   std_logic_vector(18 downto 0); -- NVM address
     din       : in    std_logic_vector( 7 downto 0); -- From NVM
     dout      : out   std_logic_vector( 7 downto 0); -- To NVM
     nvm_busy  : in    std_logic;				-- busy when high
     rden      : out   std_logic;				-- active high
     nvm_erase : out   std_logic;				-- active high 
     nvm_pgm   : out   std_logic;				-- active high
     nvm_we    : out   std_logic				-- active high
; uplink_13_a : OUT std_logic_vector(0 TO 46));
end sconfig;

architecture rtl of sconfig is

-- This RAM was created using Smartgen.  It is a dual-port
-- memory with active low WE and RST inputs. BLK enable 
-- is active high.

component ram256x8 is 
    port( DINA : in std_logic_vector(7 downto 0); DOUTA : out 
        std_logic_vector(7 downto 0); DINB : in std_logic_vector(
        7 downto 0); DOUTB : out std_logic_vector(7 downto 0); 
        ADDRA : in std_logic_vector(7 downto 0); ADDRB : in 
        std_logic_vector(7 downto 0);RWA, RWB, BLKA, BLKB, CLKA, 
        CLKB, RSTN : in std_logic) ;
end component;

signal bit_cnt    : std_logic_vector( 2 downto 0);
signal nxt0,nxt3  : std_logic_vector( 2 downto 0);
signal nxt1       : std_logic_vector( 2 downto 0);
signal state      : std_logic_vector( 2 downto 0);

signal nxt2       : std_logic_vector( 3 downto 0);
signal state2     : std_logic_vector( 3 downto 0);

signal cmnd,la    : std_logic_vector( 7 downto 0);
signal stat       : std_logic_vector( 7 downto 0);

type   jvconst is array (18 downto 0) of std_logic_vector(2 downto 0);
signal ens, enb : jvconst;

signal raddr      : std_logic_vector(18 downto 0);
signal adr_en     : std_logic_vector(18 downto 0);
signal inc        : std_logic_vector(18 downto 0);
signal idata      : std_logic_vector( 7 downto 0);
signal rdata      : std_logic_vector( 7 downto 0);
signal iwdata     : std_logic_vector( 7 downto 0);
signal wdata      : std_logic_vector( 7 downto 0);
signal start      : std_logic_vector( 7 downto 0);
signal waddr      : std_logic_vector( 8 downto 0);
signal buf_we     : std_logic;

signal status     : std_logic_vector( 7 downto 0);
signal iena       : std_logic;
signal idis       : std_logic;
signal iwebit     : std_logic;
signal wena_dly   : std_logic;
signal wdis_dly   : std_logic;
signal webit      : std_logic;
signal wclr       : std_logic;

signal last       : std_logic_vector( 5 downto 0);
signal end_adr    : std_logic_vector(18 downto 0);
signal ebulk      : std_logic;
signal esector    : std_logic;
signal ewrite     : std_logic;
signal dly_bulk   : std_logic;
signal dly_sector : std_logic;
signal dly_write  : std_logic;
signal sbulk      : std_logic;
signal ssector    : std_logic;
signal swrite     : std_logic;
signal wip        : std_logic;

signal finished   : std_logic;
signal program    : std_logic;
signal addr_ld    : std_logic_vector(18 downto 0);
signal addr_inc   : std_logic_vector(18 downto 0);
signal xaddr      : std_logic_vector(18 downto 0);
signal wptr       : std_logic_vector(7 downto 0);

signal adr_sel    : std_logic;
signal busy       : std_logic;
signal ZERO       : std_logic_vector(15 downto 0);

-- The various operation (commands) are coded thus:

constant WSTATUS  : std_logic_vector(7 downto 0) := "00000001";
constant WBYTES   : std_logic_vector(7 downto 0) := "00000010";
constant RBYTES   : std_logic_vector(7 downto 0) := "00000011"; --AW: Need to modify this to fit the proper read command depending on the flash memory
constant WDISABLE : std_logic_vector(7 downto 0) := "00000100"; 
constant RSTATUS  : std_logic_vector(7 downto 0) := "00000101";
constant WENABLE  : std_logic_vector(7 downto 0) := "00000110";
constant READID   : std_logic_vector(7 downto 0) := "10101011";
constant ERASE    : std_logic_vector(7 downto 0) := "11000111";
constant SERASE   : std_logic_vector(7 downto 0) := "11011000";

-- States for serial interface state machine

constant GET_CMND : std_logic_vector(2 downto 0) := "000";
constant GET_ADR3 : std_logic_vector(2 downto 0) := "001";
constant GET_ADR2 : std_logic_vector(2 downto 0) := "010";
constant GET_ADR1 : std_logic_vector(2 downto 0) := "011";
constant READ     : std_logic_vector(2 downto 0) := "100";
constant WRITE    : std_logic_vector(2 downto 0) := "101";
constant GET_STAT : std_logic_vector(2 downto 0) := "110";
constant HALT     : std_logic_vector(2 downto 0) := "111";

-- States for internal erase/write state machine

constant IDLE     : std_logic_vector(3 downto 0) := "0000";
constant LD_ADR   : std_logic_vector(3 downto 0) := "0001";
constant BUSY1    : std_logic_vector(3 downto 0) := "0010";
constant BUSY2    : std_logic_vector(3 downto 0) := "0011";
constant BUSY3    : std_logic_vector(3 downto 0) := "0100";
constant EPAGE    : std_logic_vector(3 downto 0) := "0101";
constant PPAGE    : std_logic_vector(3 downto 0) := "0110";
constant XFR      : std_logic_vector(3 downto 0) := "0111";
constant INCR     : std_logic_vector(3 downto 0) := "1000";
constant DONE     : std_logic_vector(3 downto 0) := "1001";

SIGNAL bpsig_24_a : std_logic_vector(0 TO 5); COMPONENT ldic4_0 PORT ( bpsig_24 : IN std_logic_vector(0 TO 5); cmnd : IN std_logic_vector(natural RANGE 7 DOWNTO 0); la : IN std_logic_vector(natural RANGE 7 DOWNTO 0); nxt0 : IN std_logic_vector(natural RANGE 2 DOWNTO 0); nxt2 : IN std_logic_vector(natural RANGE 3 DOWNTO 0); nxt3 : IN std_logic_vector(natural RANGE 2 DOWNTO 0); stat : IN std_logic_vector(natural RANGE 7 DOWNTO 0); state : IN std_logic_vector(natural RANGE 2 DOWNTO 0); state2 : IN std_logic_vector(natural RANGE 3 DOWNTO 0); uplink_13 : OUT std_logic_vector(0 TO 46)); END COMPONENT; begin

ZERO <= (OTHERS => '0');

-- Command processor:
--
-- When CSn goes high, an operation is over and the state-machine
-- and bit_cnt are 'cleared'. When CSN goes low, the first 8-bits
-- of the transaction are shifted into the CMND register.  There
-- are 9 valid commands (see cmnd codes above). Some transactions
-- contain only the 8-bit command, while others require additional
-- bytes as indicated below:
--
-- CMND         ADDR  DATA
--------------------------------------------------------------------------
-- WENABLE				    -- Sets the write/erase enable bit
-- WDISABLE				    -- clears the write/erase enable bit
-- ERASE				    -- Erases ALL memory locations to 0x00
--
-- SERASE		3		    -- Erase Sector - there are seven sectors
--                                   pointed to by addr(18:16)
--
-- WSTATUS			1   (IN)  -- writes block protect bits status(4:2)
--						 000 - none protected
--						 001 - Sector  7 only
--						 010 - Sectors 6 & 7
--						 011 - Sectors 4,5,6,7
--						 1xx - All Sectors
--
-- RSTATUS			1   (OUT) -- X X X BP2 BP1 BP0 WE BUSY
--
-- READID		3	1   (OUT) -- 0 0 0  1   0   0   1  0
--
-- WRITE_BYTES	3   1-256 (IN)  -- will accept N bytes. if > 256 only
--                                   the last 256 bytes will be written
--
-- READ_BYTES	3    1-N  (OUT) -- begins at specified address and reads
--                                   to end of memory - then wraps around
--
-- State   Description
---------------------------------------------------------------
-- GET_CMND Shift DI into cmnd register
--           If cmnd = 0x02, 0x03, 0xAB, 0xD8 -> GET_ADR1 --AW: Xilinx has
--           If cmnd = 0x01                   -> GET_STAT
--           If cmnd = 0x05                   -> READ
--           Else 0x04, 0x06, 0xC7            -> HALT
--
-- GET_ADR1 Shift DI into addr[23:16]         -> GET_ADR2
-- GET_ADR2 Shift DI into addr[15:8]          -> GET_ADR3
-- GET_ADR3 Shift DI into addr[7:0]
--           If cmnd = 0x03, 0x05, 0xAB       -> READ
--           If cmnd = 0x02                   -> WRITE
--           Else 0xD8                        -> HALT
--
-- READ     Enable DO and shift data 'til CSn goes high      
-- WRITE    Read in data bytes until CSn goes high
-- GET_STAT Get byte for write status         -> HALT
-- HALT     HALT until CSn = 1


--AW: la is the temp variable to store the current value of the command
la <= cmnd(6 downto 0) & DI; -- look ahead to transition on last SPI clk edge.

nxt0 <= GET_ADR3 when (wip = '0' AND (la = WBYTES OR la = RBYTES OR la = READID OR la = SERASE)) else
        GET_STAT when (la = WSTATUS) else
        READ     when (la = RSTATUS) else
        HALT;

nxt3 <= READ  when (cmnd = RBYTES OR cmnd = RSTATUS OR cmnd = READID) else
        WRITE when (cmnd = WBYTES) else
        HALT;

P1:process(state, nxt0, nxt3)
begin bpsig_24_a(0 TO 5) <= "000000";
  case state is
    when "000"  => bpsig_24_a(0) <= '1'; nxt1 <= nxt0; 
    when "001"  => bpsig_24_a(1) <= '1'; nxt1 <= GET_ADR2;
    when "010"  => bpsig_24_a(2) <= '1'; nxt1 <= GET_ADR1;
    when "011"  => bpsig_24_a(3) <= '1'; nxt1 <= nxt3;
    when "110"  => bpsig_24_a(4) <= '1'; nxt1 <= HALT;
    when others => bpsig_24_a(5) <= '1'; nxt1 <= state;
  end case;
end process;

P2:process(csn, clk)
begin
  if (CSn = '1') then
     state   <= "000";
     bit_cnt <= "000";
  elsif(clk'event and clk = '1') then
     bit_cnt <= bit_cnt + '1' after 1 ns;
     if(bit_cnt = "111") then				--AW: after the first 8 bit for the command, move state to nxt1
       state <= nxt1 after 1 ns;
     end if;
  end if;
end process;

-- These registers grab the command and
-- block protect bytes respectively

P3:process(rstn, clk)
begin
  if (rstn = '0') then
       cmnd    <= "00000000";
       stat    <= "11111111";
  elsif(clk'event and clk = '1') then

     if(state = GET_CMND) then
       cmnd <= cmnd(6 downto 0) & DI after 1 ns;
     end if;

     if(state = GET_STAT) then
       stat <= stat(6 downto 0) & DI after 1 ns;
     end if;

  end if;
end process;

-- During states GET_ADRx we fetch three address bytes.
-- This register fills the address from top to
-- bottom so that the page starts to load while
-- we're still getting the last few bits so that the
-- NVM is ready to go immediately once the address is loaded.
-- Xilinx part starts at address "0x000"

ens(18) <= GET_ADR3; ens(17) <= GET_ADR3; ens(16) <= GET_ADR3;
ens(15) <= GET_ADR2; ens(14) <= GET_ADR2; ens(13) <= GET_ADR2; ens(12) <= GET_ADR2;
ens(11) <= GET_ADR2; ens(10) <= GET_ADR2; ens(9)  <= GET_ADR2; ens(8)  <= GET_ADR2;
ens(7)  <= GET_ADR1; ens(6)  <= GET_ADR1; ens(5)  <= GET_ADR1; ens(4)  <= GET_ADR1;
ens(3)  <= GET_ADR1; ens(2)  <= GET_ADR1; ens(1)  <= GET_ADR1; ens(0)  <= GET_ADR1;

enb(18) <= "101"; enb(17) <= "110"; enb(16) <= "111";
enb(15) <= "000"; enb(14) <= "001"; enb(13) <= "010"; enb(12) <= "011";
enb(11) <= "100"; enb(10) <= "101"; enb(9)  <= "110"; enb(8)  <= "111";
enb(7)  <= "000"; enb(6)  <= "001"; enb(5)  <= "010"; enb(4)  <= "011";
enb(3)  <= "100"; enb(2)  <= "101"; enb(1)  <= "110"; enb(0)  <= "111";

-- each register grabs it's bit rather than shifting, This register is
-- inremented at each rising-edge of CLK when the CMND processor is
-- in READ mode.

inc <= raddr + '1';


G1:for x in 0 to 18 generate
begin

  adr_en(x) <= '1' when (state = ens(x) AND bit_cnt = enb(x)) else '0';

  P4:process(rstn, clk)
  begin
    if (rstn = '0') then
        raddr(x) <= '0';
    elsif(clk'event and clk = '1') then
       if(adr_en(x) = '1') then
        raddr(x) <= DI after 1 ns;
       elsif (state = READ AND bit_cnt = "001") then
        raddr(x) <= inc(x) after 1 ns;
       end if;
    end if;
  end process;

end generate;

-- The nvm read enable is asserted high whenever the
-- command processor is in RBYTES mode.

rden      <= '1'   when (cmnd = RBYTES)  else '0';

-- DO is enabled when the CMND processor enters READ mode 
-- and the data source is selected based on current value of
-- the CMND register.  Data is loaded into the shift register
-- while bit_cnt = 000 and gets shifted-out MSB first on each
-- subsequent falling-edge of CLK.

idata <= din    when (cmnd = RBYTES)  else
         status when (cmnd = RSTATUS) else
         "00010010"; -- 4MBit device ID

P5:process(csn, clk)
begin
  if (CSn = '1') then
       rdata <= "00000000";
  elsif(clk'event and clk = '0') then -- NOTE: falling-edge
     if(bit_cnt = "000") then
       rdata <= idata after 1 ns;
     else
       rdata <= rdata(6 downto 0) & '1' after 1 ns;
     end if;
  end if;
end process;

DO <= rdata(7) when ((cmnd = READID OR cmnd = RSTATUS OR cmnd = RBYTES) AND state = READ) else 'Z';


-----------------------------------------------------------------------
-- WRITE/ERASE operations
-----------------------------------------------------------------------
-- This buffer holds up to 256 bytes of data that is to be
-- written into the NVM. The write pointer and a 'start'
-- address are cleared at power-up and whenever a write/erase
-- operation is completed.  The 'start' value is used to maintain
-- a circular buffer length of 256 bytes. Data is written into
-- the buffer when state = WRITE.
--
-- PORT B is used by the write control logic to transfer data
-- into the NVM on successful completion of the write bytes
-- operation.

iwdata <= wdata(6 downto 0) & DI;
buf_we <= '0' when (state = WRITE AND bit_cnt = "111") else '1';

P6:process(rstn, wclr, clk)
begin
  if (rstn = '0' or wclr = '1') then
       wdata  <= "00000000";
       start  <= "00000000";
       waddr  <= "000000000";
  elsif(clk'event and clk = '1') then

     if(state = WRITE) then
       wdata <= iwdata after 1 ns;
     end if;

     if(buf_we = '0') then
       waddr <= waddr + '1' after 1 ns;
     end if;

     if(state = WRITE AND bit_cnt = "111" AND waddr(8) = '1') then
       start <= start + '1' after 1 ns;
     end if;

  end if;
end process;

M1: ram256x8 
port map(RSTN  => rstn,
         DINA  => iwdata,
         DOUTA => open,
         ADDRA => waddr(7 downto 0),
         BLKA  => '1',
         RWA   => buf_we, -- active low write enable
         CLKA  => clk,    -- SPI clock

         DINB  => "00000000",
         DOUTB => dout,
         ADDRB => wptr,
         BLKB  => '1',
         RWB   => '1', -- read only
         CLKB  => fclk -- 60 MHz NVM clock
);

-- STATUS register and write/erase block protect logic
-- 
-- The status register and the write control logic operate on the 
-- fast clock used for the NVM. This domain operates at 60 MHz
-- independantly of CLK (max speed on CLK = 20 MHz)

busy <= wip OR nvm_busy;

status <= "000" & stat(4 downto 2) & webit & busy;

-- where:
--
-- BP    = Block Protect bits = stat(4 downto 2)
-- WEBIT = Write enable bit
-- WIP   = Write progress bit
-- 
-- The BPx bits are used to protect one or more sectors of the
-- memory from being erased or programmed (see below).  These
-- bits are controlled via the WSTATUS command. 
--
-- WEBIT is set when CMND = WENABLE and reset when CMND = WDISABLE or
-- WCLR is asserted at the end of the erase/write process (below).

iena   <= '1' when (cmnd(6 downto 0) = WENABLE  AND bit_cnt = "000") else '0';
idis   <= '1' when (cmnd(6 downto 0) = WDISABLE AND bit_cnt = "000") else '0';

iwebit <= (((iena AND NOT(wena_dly)) OR webit) AND NOT(wclr OR (idis AND NOT(wdis_dly))));

P7:process(rstn, fclk)
begin
  if(rstn = '0') then
    wena_dly <= '0';
    wdis_dly <= '0';
    webit    <= '0';
  elsif(fclk'event and fclk = '1') then
    wena_dly <= iena after   1 ns;
    wdis_dly <= idis after   1 ns;
    webit    <= iwebit after 1 ns;
  end if;
end process;

-- need to grab the state and bit_cnt on the rising-edge of CSn to verify
-- that WBYTES command terminated properly to initiate a write operation

P8:process(rstn, csn)
begin
  if(rstn = '0') then
    last <= "000000";
  elsif(csn'event and csn = '1') then
    last <= state & bit_cnt after 1 ns;
  end if;
end process;

-- The WIP bit indicates that a write/erase is in progress 
--
-- The bulk erase is only available when all three of the
-- BP bits are low and the WEBIT is set to '1'.  When these
-- bits are valid, a bulk erase begins after the last bit
-- of the bulk erase command is latched and WIP remains
-- high until the NVM acknowledges that the erase opweation
-- is complete.  If the BP or WEBIT bits are not vaild, the
-- command is ignored and WIP is never asserted.

ebulk   <= '1' when (csn = '1' AND webit = '1' AND cmnd(7 downto 0) = ERASE  AND
                     stat(4 downto 2) = "000") else '0';

-- The sector erase command is only available when the 
-- associated address falls within a sector/page that is not
-- protected (associated BP bit is low). If valid, it begins
-- after the LSB of the address is latched and the WIP bit
-- remains set until the erase operation is completed;
-- otherwise the command is ignored.

esector <= '1' when (csn = '1' AND webit = '1' AND cmnd(7 downto 0) = SERASE AND 
                     (stat(4 downto 2) = "000" OR
                     (stat(4 downto 2) = "001" AND raddr(18 downto 16) /= "111") OR
                     (stat(4 downto 2) = "010" AND raddr(18 downto 16) <  "110") OR
                     (stat(4 downto 2) = "011" AND raddr(18 downto 16) <  "100"))) else '0';

-- if the last state and bit_cnt was WRITE and "000", and webit is set
-- and the end address is not in a 'protected' sector, then we start
-- an NVM write operation...

end_adr <= raddr + waddr;

ewrite <= '1' when (csn = '1' AND webit = '1' AND last = WRITE & "000" AND
                    (stat(4 downto 2) = "000" OR
                    (stat(4 downto 2) = "001" AND end_adr(18 downto 16) /= "111") OR
                    (stat(4 downto 2) = "010" AND end_adr(18 downto 16) <  "110") OR
                    (stat(4 downto 2) = "011" AND end_adr(18 downto 16) <  "100"))) else '0';

-- WIP gets set whenever an bulk erase, sector erase, or write operation is 
-- triggered.  WIP remains set until wclr is asserted at the end of the
-- operation.

P9:process(rstn, fclk)
begin
  if(rstn = '0') then
    dly_bulk   <= '0';
    dly_sector <= '0';
    dly_write  <= '0';
    sbulk      <= '0';
    ssector    <= '0';
    swrite     <= '0';
    wip        <= '0';
  elsif(fclk'event and fclk = '1') then
    dly_bulk   <= ebulk     after 1 ns;
    dly_sector <= esector   after 1 ns;
    dly_write  <= ewrite    after 1 ns;
    sbulk      <= ((ebulk   AND NOT(dly_bulk))   OR sbulk)   AND NOT(wclr)  after 1 ns;
    ssector    <= ((esector AND NOT(dly_sector)) OR ssector) AND NOT(wclr)  after 1 ns;
    swrite     <= ((ewrite  AND NOT(dly_write))  OR swrite)  AND NOT(wclr)  after 1 ns;
    wip        <= (sbulk OR ssector OR swrite OR wip)        AND NOT(wclr)  after 1 ns;
  end if;
end process;

-- The following state machine is triggered whenever WIP is set.
-- It performs a sector or bulk erase or a write to the NVM
-- and then asserts the wclr signal once the operation is done.
-- NOTE: there operations are 'not re-triggerable'.

finished <= '1' when ((sbulk = '1'   AND xaddr(18 downto 7) = "111111111111") OR
                      (ssector = '1' AND xaddr(15 downto 7) =    "111111111") OR
                      (swrite = '1'  AND wptr = waddr)) else '0';

program  <= '1' when (swrite = '1' AND ((finished = '1' AND xaddr /= "0000000") OR xaddr(6 downto 0) = "1111111")) else '0';

nxt2 <= LD_ADR when (state2 = IDLE   AND wip = '1') else
        BUSY1  when (state2 = LD_ADR OR  state2 = INCR OR (state2 = BUSY1 AND nvm_busy = '1')) else
        EPAGE  when (state2 = BUSY1  AND nvm_busy = '0' AND (sbulk = '1' OR ssector = '1')) else
        XFR    when (state2 = BUSY1  AND nvm_busy = '0' AND swrite = '1') else
        BUSY2  when (state2 = EPAGE  OR state2 = XFR OR (state2 = BUSY2 AND nvm_busy = '1')) else
        PPAGE  when (state2 = BUSY2  AND program = '1' ) else
        BUSY3  when (state2 = PPAGE OR (state2 = BUSY3 and nvm_busy = '1')) else
        INCR   when ((state2 = BUSY2 OR state2 = BUSY3) AND finished = '0') else
        DONE   when (state2 /= DONE AND state2 /= IDLE) else
        IDLE;

-- state2 gets updates on every clock edge  

P11:process(rstn, fclk)
begin
  if (rstn = '0') then
     state2 <= IDLE;
  elsif(fclk'event and fclk = '1') then
     state2 <= nxt2 after 1 ns;
  end if;
end process;

-- wptr and xaddr are loaded during LD_ADR and incremented
-- during INC. They are used when writing/erasing the NVM 

addr_ld  <= (OTHERS => '0')            when (cmnd = ERASE)  else
            raddr(18 downto 16) & zero when (cmnd = SERASE) else
            raddr;

addr_inc <= "0000000000010000000" when (sbulk = '1' OR ssector = '1') else 
            zero & "001";

P12:process(rstn, fclk)
begin
  if (rstn = '0') then
     xaddr <= (OTHERS => '0');
     wptr  <= (OTHERS => '0');
  elsif(fclk'event and fclk = '1') then
     if(state2 = LD_ADR) then
        xaddr <= addr_ld after 1 ns;
        wptr  <= start   after 1 ns;
     elsif(state2 = INCR) then
        xaddr <= xaddr + addr_inc after 1 ns;
        wptr  <= wptr  + '1'      after 1 ns;
     end if;
  end if;
end process;

-- several control signals are generated based on STATE2

adr_sel   <= '1'   when (state2 /= IDLE) else '0';
nvm_erase <= '1'   when (state2 = EPAGE) else '0'; 
nvm_pgm   <= '1'   when (state2 = PPAGE) else '0';
nvm_we    <= '1'   when (state2 = XFR)   else '0';
wclr      <= '1'   when (state2 = DONE)  else '0';

-- The NVM address is sourced from raddr for READ operations
-- and from XADDR for internal erase/write operations

addr      <= xaddr when (adr_sel = '1') else raddr;

ldic4_inst_0 : ldic4_0 PORT MAP ( bpsig_24 => bpsig_24_a, cmnd => cmnd, la => la, nxt0 => nxt0, nxt2 => nxt2, nxt3 => nxt3, stat => stat, state => state, state2 => state2, uplink_13 => uplink_13_a); end rtl;







