Issue with port buffering (inout) Spartan7 board

Status
Not open for further replies.

Hello @ads-ee

this limnit is in my Spartan7 FPGA board - some IO banks have 3.3 V voltages and some 1.8 V powering. I tried construct constraint file in the way all pins to external SRAM IC to be 3.3V level standard.

Best regards
 

Hello @ads-ee

this limnit is in my Spartan7 FPGA board - some IO banks have 3.3 V voltages and some 1.8 V powering. I tried construct constraint file in the way all pins to external SRAM IC to be 3.3V level standard.

Best regards
Yes, I know that. I was responding to another post that was asking if you properly check the SRAM could use both 1.8V and 3.3V, to which I replied that you did correctly assign pins and that the 1.8V ready which was (poorly) located next to the SRAM control signals was not part of the SRAM device pins.

What you haven't addressed is how you plan on exercising the SRAM with the host side interface going to FPGA pins and not having something inside the FPGA to exercise the SRAM.
 

Hello @ads-ee ,

I rewrite some part of VHDL code in order to be able to test this project on real hardware. I described hardware PCB I am going to use for test in earlier post :

https://www.edaboard.com/threads/static-ram-ic-selection-for-full-hd-resolution-frame-buffer.395013/

this is PCB board with SRAM IC CY7C1041CV33-10ZSXI - (256K x 16bit) Parallel 10ns in 44-TSOP case.

On photo below is my hardware test circuit (QMTECH Spartan7 FPGA board and external PCB with SRAM IC):



Current VHDL code of "sram_ctrl.vhd" is like this:

Code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY sram_ctrl IS
    PORT (
        clk, reset : IN std_logic;
        mem : BUFFER std_logic;
        rw : BUFFER std_logic;
        addr : BUFFER std_logic_vector(17 DOWNTO 0);
        data_f2s : BUFFER std_logic_vector(7 DOWNTO 0);
        ready : OUT std_logic;
        data_s2f_r : OUT std_logic_vector(7 DOWNTO 0);
        --data_s2f_ur : OUT std_logic_vector(7 DOWNTO 0);
        ad : OUT std_logic_vector(17 DOWNTO 0);
        we_n, oe_n : OUT std_logic;
        dio : INOUT std_logic_vector(7 DOWNTO 0);
        ce_n : OUT std_logic;
        SRAM_UB_N   : out std_logic; -- upper byte mask
        SRAM_LB_N   : out std_logic; -- lower byte mask   
        btn : IN std_logic_vector(1 DOWNTO 0);
        LED1, LED2 : OUT std_logic       
    );
END sram_ctrl;

ARCHITECTURE arch OF sram_ctrl IS
    TYPE state_type IS (idle, r1, r2, w1, w2);
    SIGNAL state_reg, state_next : state_type;
    SIGNAL data_f2s_reg, data_f2s_next :
    std_logic_vector(7 DOWNTO 0);
    SIGNAL data_s2f_reg, data_s2f_next :
    std_logic_vector(7 DOWNTO 0);
    SIGNAL addr_reg, addr_next :
    std_logic_vector(17 DOWNTO 0);
    SIGNAL we_buf, oe_buf, tri_buf : std_logic;
    SIGNAL we_reg, oe_reg, tri_reg : std_logic;
    SIGNAL db_btn : std_logic_vector(2 DOWNTO 0);

BEGIN

    debounce_unit0 : ENTITY work.debounce
    PORT MAP(
        clk => clk, reset_n => reset, button => btn(0),
        result => db_btn(0)
    );
    
    debounce_unit1 : ENTITY work.debounce
    PORT MAP(
        clk => clk, reset_n => reset, button => btn(1),
        result => db_btn(1)
    );
    
    -- address
    addr <= "000000000000000001";
    
    -- command for test
    PROCESS (db_btn, data_s2f_reg)
        BEGIN
            --data_f2s_reg <= (OTHERS => '0');
            IF (db_btn(0) = '0') THEN -- write sw1
                mem <= '1';
                rw <= '0';
                data_f2s <= "00001111";
                LED1 <= '1';
                LED2 <= '1';
            ELSIF (db_btn(1) = '0') THEN -- read P4
                mem <= '1';
                rw <= '1';
            ELSE
                mem <= '0'; --IDLE
                rw <= '1';
                --compare if read data is valid
                if (data_s2f_reg = "00001111") then
                   LED1 <= '1';
                   LED2 <= '1';
                else
                   LED1 <= '0';
                   LED2 <= '0';
                end if;
            END IF;
    END PROCESS;
    
---- from here impl. of SRAM CTRL ------------------------------------------------------   

    PROCESS (clk, reset)
    BEGIN
        IF (reset = '1') THEN
            state_reg <= idle;
            addr_reg <= (OTHERS => '0');
            data_f2s_reg <= (OTHERS => '0');
            data_s2f_reg <= (OTHERS => '0');
            tri_reg <= '1';
            we_reg <= '1';
            oe_reg <= '1';
            SRAM_LB_N <= '1'; -- mask low byte
            SRAM_UB_N <= '1'; -- mask high byte
            --LED1 <= '0';
            --LED2 <= '0';
        ELSIF (clk'event AND clk = '1') THEN
            state_reg <= state_next;
            addr_reg <= addr_next;
            data_f2s_reg <= data_f2s_next;
            data_s2f_reg <= data_s2f_next;
            tri_reg <= tri_buf;
            we_reg <= we_buf;
            oe_reg <= oe_buf;
            SRAM_LB_N <= '0'; -- unmask low byte
            SRAM_UB_N <= '0'; -- unmask high byte
        END IF;
    END PROCESS;
    
    -- next state logic
    PROCESS (state_reg, mem, rw, dio, addr, data_f2s,
    data_f2s_reg, data_s2f_reg, addr_reg)
        BEGIN
            addr_next <= addr_reg;
            data_f2s_next <= data_f2s_reg;
            data_s2f_next <= data_s2f_reg;
            ready <= '0';
            CASE state_reg IS
                WHEN idle =>
                    IF (mem = '0') THEN
                        state_next <= idle;
                    ELSE
                        addr_next <= addr;
                        IF (rw = '0') THEN -- write
                            state_next <= w1;
                            data_f2s_next <= data_f2s;
                        ELSE
                            state_next <= r1;
                        END IF;
                    END IF;
                    ready <= '1';
                WHEN w1 =>
                    state_next <= w2;
                WHEN w2 =>
                    state_next <= idle;
                WHEN r1 =>
                    state_next <= r2;
                WHEN r2 =>
                    data_s2f_next <= dio;
                    state_next <= idle;
            END CASE;
        END PROCESS;
        
        -- look-ahead output logic
        PROCESS (state_next)
            BEGIN
                tri_buf <= '1';
                we_buf <= '1';
                oe_buf <= '1';
                CASE state_next IS
                    WHEN idle =>
                    WHEN w1 =>
                        tri_buf <= '0';
                        we_buf <= '0';           
                    WHEN w2 =>
                        tri_buf <= '0';
                    WHEN r1 =>
                        oe_buf <= '0';
                    WHEN r2 =>
                        oe_buf <= '0';
                END CASE;
            END PROCESS;
            
            -- to main system
            data_s2f_r <= data_s2f_reg;
            --data_s2f_ur <= dio;
            -- to SRAM
            we_n <= we_reg;
            oe_n <= oe_reg;
            ad <= addr_reg;
            -- I/O for SRAM chip
            ce_n <= '0';
            dio <= data_f2s_reg WHEN tri_reg = '0'
                   ELSE (OTHERS => 'Z');
END arch;

After running it on hardware two LEDS shine what means that read data is not equal data written to memory. So it doesn't work properly. Tommorow I am going to debug it with Logic analyser.

Best Regards
 

Run a simulation, debugging with a logic analyzer will take significantly longer.
 
Hello,

Yes I am going to run simulation before debugging with logic analyzer.

BTW: Don't you think that these cables connecting FPGA board with external PCB are too long for 50 MHz or 100MHz clock in design?

Best regards
 
Last edited:

Don't know where the clock is located.

If you have it on the ribbon cables then you would probably want to separated any control/data signals from the clock by putting a ground between them. If it's in the rats nest of yellow wires It's probably not going to be a problem as none of those wires are running very parallel with each other.
 
The problem can be in:
1. Error in wires connections.
2. Error on PCB.
3. Setup and hold times violations regarding data and clock. Refer to a datasheet of that SRAM. Then check Xilinx docs haw in constraints set that times for FPGA.
 
Hello,

today I have a some time to spend on this project. In code described in post #23 (on this thread) was mistake related to active reset level (reset was HIGH level active, but have to be low). There was also a little mess in steering LEDs showing if comparison is successful (data written to memory comparing to data red from mmemory. After changes top entity (sram_ctrl.vhd) looks like:

Code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY sram_ctrl IS
    PORT (
        clk, reset : IN std_logic;
        mem : BUFFER std_logic;
        rw : BUFFER std_logic;
        addr : BUFFER std_logic_vector(17 DOWNTO 0);
        data_f2s : BUFFER std_logic_vector(7 DOWNTO 0);
        ready : OUT std_logic;
        data_s2f_r : OUT std_logic_vector(7 DOWNTO 0);
        --data_s2f_ur : OUT std_logic_vector(7 DOWNTO 0);
        ad : OUT std_logic_vector(17 DOWNTO 0);
        we_n, oe_n : OUT std_logic;
        dio : INOUT std_logic_vector(7 DOWNTO 0);
        ce_n : OUT std_logic;
        SRAM_UB_N   : out std_logic; -- upper byte mask
        SRAM_LB_N   : out std_logic; -- lower byte mask   
        btn : IN std_logic_vector(1 DOWNTO 0);
        LED1, LED2 : OUT std_logic       
    );
END sram_ctrl;

ARCHITECTURE arch OF sram_ctrl IS
    TYPE state_type IS (idle, r1, r2, w1, w2);
    SIGNAL state_reg, state_next : state_type;
    SIGNAL data_f2s_reg, data_f2s_next :
    std_logic_vector(7 DOWNTO 0);
    SIGNAL data_s2f_reg, data_s2f_next :
    std_logic_vector(7 DOWNTO 0);
    SIGNAL addr_reg, addr_next :
    std_logic_vector(17 DOWNTO 0);
    SIGNAL we_buf, oe_buf, tri_buf : std_logic;
    SIGNAL we_reg, oe_reg, tri_reg : std_logic;
    SIGNAL db_btn : std_logic_vector(2 DOWNTO 0);

BEGIN

    debounce_unit0 : ENTITY work.debounce
    PORT MAP(
        clk => clk, reset_n => reset, button => btn(0),
        result => db_btn(0)
    );
    
    debounce_unit1 : ENTITY work.debounce
    PORT MAP(
        clk => clk, reset_n => reset, button => btn(1),
        result => db_btn(1)
    );
    
    -- address
    addr <= "000000000000000001";
    
    -- command for test
    PROCESS (db_btn, data_s2f_reg)
        BEGIN
            --data_f2s_reg <= (OTHERS => '0');
            IF (db_btn(0) = '0') THEN -- write sw1
                mem <= '1';
                rw <= '0';
                data_f2s <= "00001111";
                LED1 <= '1';
                LED2 <= '1';
            ELSIF (db_btn(1) = '0') THEN -- read P4
                mem <= '1';
                rw <= '1';
                if (dio = "00001111") then
                   LED1 <= '0';
                   LED2 <= '0';
                else
                   LED1 <= '1';
                   LED2 <= '1';
                end if;
            ELSE
                mem <= '0'; --IDLE
                rw <= '1';
                --compare if read data is valid
--                if (data_s2f_reg = "00001111") then
--                   LED1 <= '1';
--                   LED2 <= '1';
--                else
--                   LED1 <= '0';
--                   LED2 <= '0';
--                end if;
            END IF;
    END PROCESS;
    
---- from here impl. of SRAM CTRL ------------------------------------------------------   

    PROCESS (clk, reset)
    BEGIN
        IF (reset = '0') THEN
            state_reg <= idle;
            addr_reg <= (OTHERS => '0');
            data_f2s_reg <= (OTHERS => '0');
            data_s2f_reg <= (OTHERS => '0');
            tri_reg <= '1';
            we_reg <= '1';
            oe_reg <= '1';
            SRAM_LB_N <= '1'; -- mask low byte
            SRAM_UB_N <= '1'; -- mask high byte
            --LED1 <= '0';
            --LED2 <= '0';
        ELSIF (clk'event AND clk = '1') THEN
            state_reg <= state_next;
            addr_reg <= addr_next;
            data_f2s_reg <= data_f2s_next;
            data_s2f_reg <= data_s2f_next;
            tri_reg <= tri_buf;
            we_reg <= we_buf;
            oe_reg <= oe_buf;
            SRAM_LB_N <= '0'; -- unmask low byte
            SRAM_UB_N <= '0'; -- unmask high byte
        END IF;
    END PROCESS;
    
    -- next state logic
    PROCESS (state_reg, mem, rw, dio, addr, data_f2s,
    data_f2s_reg, data_s2f_reg, addr_reg)
        BEGIN
            addr_next <= addr_reg;
            data_f2s_next <= data_f2s_reg;
            data_s2f_next <= data_s2f_reg;
            ready <= '0';
            CASE state_reg IS
                WHEN idle =>
                    IF (mem = '0') THEN
                        state_next <= idle;
                    ELSE
                        addr_next <= addr;
                        IF (rw = '0') THEN -- write
                            state_next <= w1;
                            data_f2s_next <= data_f2s;
                        ELSE
                            state_next <= r1;
                        END IF;
                    END IF;
                    ready <= '1';
                WHEN w1 =>
                    state_next <= w2;
                WHEN w2 =>
                    state_next <= idle;
                WHEN r1 =>
                    state_next <= r2;
                WHEN r2 =>
                    data_s2f_next <= dio;
                    state_next <= idle;
            END CASE;
        END PROCESS;
        
        -- look-ahead output logic
        PROCESS (state_next)
            BEGIN
                tri_buf <= '1';
                we_buf <= '1';
                oe_buf <= '1';
                CASE state_next IS
                    WHEN idle =>
                    WHEN w1 =>
                        tri_buf <= '0';
                        we_buf <= '0';           
                    WHEN w2 =>
                        tri_buf <= '0';
                    WHEN r1 =>
                        oe_buf <= '0';
                    WHEN r2 =>
                        oe_buf <= '0';
                END CASE;
            END PROCESS;
            
            -- to main system
            data_s2f_r <= data_s2f_reg;
            --data_s2f_ur <= dio;
            -- to SRAM
            we_n <= we_reg;
            oe_n <= oe_reg;
            ad <= addr_reg;
            -- I/O for SRAM chip
            ce_n <= '0';
            dio <= data_f2s_reg WHEN tri_reg = '0'
                   ELSE (OTHERS => 'Z');
END arch;

Other files in project had been unchanged. Currently after push 'reset' button then Button(0) (write to memory) and then Button(1) (read from memory and comparison) LEDs shine - what means that data read and written are equal.
 

Hello,

So it seems that external SRAM memory works OK, but I am going to make more detailed tests. Next steps I would like to do:

1) Make more advanced test: writing series of data (different) to for example 10 adresses of SRAM and then reading them all and comparing with original.

2) Handle all 16-bit of data (high and low bytes) from SRAM IC

3) Increase speed of clock of SRAM controller - from 50 MHz to 100Mhz

4) Design of PCB board for 2Mega x 16-bit SRAM memory ( IS61WV204816BLL-10TLI IC)

5) To launch that PCB board (with 2Mega x 16-bit SRAM) together with Spartan7 FPGA board

6) Connect parallel interface camera (1600x1200 pixel resolution) to Spartan7 FPGA board (with 2Mega SRAM buffer)

Best Regards
 

4) Design of PCB board for 2Mega x 16-bit SRAM memory ( IS61WV204816BLL-10TLI IC)

5) To launch that PCB board (with 2Mega x 16-bit SRAM) together with Spartan7 FPGA board

If you intend to make a new SRAM PCB, take care that you provide a suitable digital ground. Presuming you are using 2-layer PCB as in your previous design https://www.edaboard.com/threads/static-ram-ic-selection-for-full-hd-resolution-frame-buffer.395013/, you should at least implement a combination of copper pours and multiple meshed ground traces. The external connector and cable should have multiple ground connections in parallel.

I didn't contribute to the original io-buffer question of this thread because I'm not familar with Xilinx tools. I'm a bit shocked how difficult the implementation seems to be. I made many Quartus FPGA designs involving external SRAM over the years, just wrote behavioral code without thinking about buffers...
 

    FlyingDutch

    Points: 2
    Helpful Answer Positive Rating

Thanks for hint - I thought about it and it new design I take it into account (and implement these recommendations).


It is most likely my lack of experience, but I also had been a little depressed that subject that seems to be rather simply turned out quite complicated.

Best Regards
 

Hello @FvM

if you have any archives of these projects with "SRAM Controllers" for Altera FPGAs (made with Quartus) and you can/wish share some of them it would be great for me. i have two FPGA boards with Altera FPGAs - one with Cyclone IV and second with MAX10, and it would be very interesting to me to try implement "SRAM controller" on one of them.

Best Regards
 

Hello after same time,

I had been looking for IP Cores implementing SRAM memory controller and I found Xilinx "AXI EMC IP Core" (exactly: LogiCORE IP AXI External Memory Controller). Here is link to its description:
https://www.xilinx.com/support/documentation/ip_documentation/axi_emc/v1_03_a/ds762_axi_emc.pdf

I have few questions related to this IP Core:

1) Can I implement using this IP core "SRAM Memory Controller" for IC described in this thread ( CY7C1041DV33 )
2) Is this IP core free, or I have to pay for using it
3) On the list for "Supported family Devices" there is lack of Spartan7 FPGAS (there is Spartan6 or Artix7)
3) Are there different versions (newer) of this IP core
4) IS it available in Vivado 2020.x IP Cores

Thanks in advance and Regards
 

Hello,

I am studying documentation for "AXI EMC v3.0 LogiCore" - see link:
https://www.xilinx.com/support/documentation/ip_documentation/axi_emc/v3_0/pg100-axi-emc.pdf

I am wondering what is time unit for parameters (right side) in window "Memory Bank 1" - see screenshot:


Are them pico-seconds or nano-seconds - I don't know (I wasn't able to fing this information in documentation for this ip cORE.
Could someone to help me with this?

Thanks and Regards
 

It says "Timing Parameters (In Pico Seconds), which makes sense as the parameters for an SRAM are 15ns for say read address to data valid.

Usually the issue with IP made for a specific device is the IP probably has device specific primitives, which the device you are using may not have. I've only had success porting such IP when the IP is in the same family of parts.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…