Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

migrating a design from Lattice to Altera

Status
Not open for further replies.

shaiko

Advanced Member level 5
Joined
Aug 20, 2011
Messages
2,644
Helped
303
Reputation
608
Reaction score
297
Trophy points
1,363
Activity points
18,302
Hello,

I'm trying to migrate an existing legacy project from Lattice to an Altera.
Everything is successful except a dual port RAM IP core that serves as a Tx/Rx buffer for UARTs.
The Lattice FPGA used a "Pseudo Dual Port RAM" (whatever that means).

See section 9.10
**broken link removed**

This is the instantiation for the LATTICE IP:

Code:
library IEEE;
use IEEE.std_logic_1164.all;
library xp;
use xp.components.all;

entity uart_rx_dpr is
    port (
        WrAddress: in  std_logic_vector(6 downto 0); 
        RdAddress: in  std_logic_vector(6 downto 0); 
        Data: in  std_logic_vector(7 downto 0); 
        RdClock: in  std_logic; 
        RdClockEn: in  std_logic; 
        Reset: in  std_logic; 
        WrClock: in  std_logic; 
        WrClockEn: in  std_logic; 
        WE: in  std_logic; 
        Q: out  std_logic_vector(7 downto 0));
end uart_rx_dpr;

architecture Structure of uart_rx_dpr is

    -- internal signal declarations
    signal scuba_vhi: std_logic;
    signal scuba_vlo: std_logic;


    component PDP8KA

        generic (CSDECODE_R : in String; CSDECODE_W : in String; 
                DATA_WIDTH_R : in Integer; DATA_WIDTH_W : in Integer; 
                RESETMODE : in String; GSR : in String; 
                REGMODE : in String);

        port (CEW: in  std_logic; CLKW: in  std_logic; 
            CSW0: in  std_logic; CSW1: in  std_logic; 
            CSW2: in  std_logic; WE: in  std_logic; CER: in  std_logic; 
            CLKR: in  std_logic; CSR0: in  std_logic; 
            CSR1: in  std_logic; CSR2: in  std_logic; RST: in  std_logic; 
            DI0: in  std_logic; DI1: in  std_logic; DI2: in  std_logic; 
            DI3: in  std_logic; DI4: in  std_logic; DI5: in  std_logic; 
            DI6: in  std_logic; DI7: in  std_logic; DI8: in  std_logic; 
            DI9: in  std_logic; DI10: in  std_logic; DI11: in  std_logic; 
            DI12: in  std_logic; DI13: in  std_logic; 
            DI14: in  std_logic; DI15: in  std_logic; 
            DI16: in  std_logic; DI17: in  std_logic; 
            DI18: in  std_logic; DI19: in  std_logic; 
            DI20: in  std_logic; DI21: in  std_logic; 
            DI22: in  std_logic; DI23: in  std_logic; 
            DI24: in  std_logic; DI25: in  std_logic; 
            DI26: in  std_logic; DI27: in  std_logic; 
            DI28: in  std_logic; DI29: in  std_logic; 
            DI30: in  std_logic; DI31: in  std_logic; 
            DI32: in  std_logic; DI33: in  std_logic; 
            DI34: in  std_logic; DI35: in  std_logic; 
            ADW0: in  std_logic; ADW1: in  std_logic; 
            ADW2: in  std_logic; ADW3: in  std_logic; 
            ADW4: in  std_logic; ADW5: in  std_logic; 
            ADW6: in  std_logic; ADW7: in  std_logic; 
            ADW8: in  std_logic; ADW9: in  std_logic; 
            ADW10: in  std_logic; ADW11: in  std_logic; 
            ADW12: in  std_logic; ADR0: in  std_logic; 
            ADR1: in  std_logic; ADR2: in  std_logic; 
            ADR3: in  std_logic; ADR4: in  std_logic; 
            ADR5: in  std_logic; ADR6: in  std_logic; 
            ADR7: in  std_logic; ADR8: in  std_logic; 
            ADR9: in  std_logic; ADR10: in  std_logic; 
            ADR11: in  std_logic; ADR12: in  std_logic; 
            DO0: out  std_logic; DO1: out  std_logic; 
            DO2: out  std_logic; DO3: out  std_logic; 
            DO4: out  std_logic; DO5: out  std_logic; 
            DO6: out  std_logic; DO7: out  std_logic; 
            DO8: out  std_logic; DO9: out  std_logic; 
            DO10: out  std_logic; DO11: out  std_logic; 
            DO12: out  std_logic; DO13: out  std_logic; 
            DO14: out  std_logic; DO15: out  std_logic; 
            DO16: out  std_logic; DO17: out  std_logic; 
            DO18: out  std_logic; DO19: out  std_logic; 
            DO20: out  std_logic; DO21: out  std_logic; 
            DO22: out  std_logic; DO23: out  std_logic; 
            DO24: out  std_logic; DO25: out  std_logic; 
            DO26: out  std_logic; DO27: out  std_logic; 
            DO28: out  std_logic; DO29: out  std_logic; 
            DO30: out  std_logic; DO31: out  std_logic; 
            DO32: out  std_logic; DO33: out  std_logic; 
            DO34: out  std_logic; DO35: out  std_logic);
    end component;
    component VHI
        port (Z: out  std_logic);
    end component;
    component VLO
        port (Z: out  std_logic);
    end component;
    attribute MEM_LPC_FILE : string; 
    attribute MEM_INIT_FILE : string; 
    attribute CSDECODE_R : string; 
    attribute CSDECODE_W : string; 
    attribute GSR : string; 
    attribute RESETMODE : string; 
    attribute REGMODE : string; 
    attribute DATA_WIDTH_R : string; 
    attribute DATA_WIDTH_W : string; 
    attribute MEM_LPC_FILE of uart_rx_dpr_0_0_0 : label is "uart_rx_dpr.lpc";
    attribute MEM_INIT_FILE of uart_rx_dpr_0_0_0 : label is "";
    attribute CSDECODE_R of uart_rx_dpr_0_0_0 : label is "000";
    attribute CSDECODE_W of uart_rx_dpr_0_0_0 : label is "000";
    attribute GSR of uart_rx_dpr_0_0_0 : label is "DISABLED";
    attribute RESETMODE of uart_rx_dpr_0_0_0 : label is "ASYNC";
    attribute REGMODE of uart_rx_dpr_0_0_0 : label is "NOREG";
    attribute DATA_WIDTH_R of uart_rx_dpr_0_0_0 : label is "9";
    attribute DATA_WIDTH_W of uart_rx_dpr_0_0_0 : label is "9";

begin

    scuba_vhi_inst: VHI
        port map (Z=>scuba_vhi);

    scuba_vlo_inst: VLO
        port map (Z=>scuba_vlo);

    uart_rx_dpr_0_0_0: PDP8KA

        generic map (CSDECODE_R=> "000", CSDECODE_W=> "000", GSR=> "DISABLED", 
        RESETMODE=> "ASYNC", REGMODE=> "NOREG", DATA_WIDTH_R=>  9, 
        DATA_WIDTH_W=>  9)

        port map (CEW=>WrClockEn, CLKW=>WrClock, CSW0=>scuba_vlo, 
            CSW1=>scuba_vlo, CSW2=>scuba_vlo, WE=>WE, CER=>RdClockEn, 
            CLKR=>RdClock, CSR0=>scuba_vlo, CSR1=>scuba_vlo, 
            CSR2=>scuba_vlo, RST=>Reset, DI0=>Data(0), DI1=>Data(1), 
            DI2=>Data(2), DI3=>Data(3), DI4=>Data(4), DI5=>Data(5), 
            DI6=>Data(6), DI7=>Data(7), DI8=>scuba_vlo, DI9=>scuba_vlo, 
            DI10=>scuba_vlo, DI11=>scuba_vlo, DI12=>scuba_vlo, 
            DI13=>scuba_vlo, DI14=>scuba_vlo, DI15=>scuba_vlo, 
            DI16=>scuba_vlo, DI17=>scuba_vlo, DI18=>Data(0), 
            DI19=>Data(1), DI20=>Data(2), DI21=>Data(3), DI22=>Data(4), 
            DI23=>Data(5), DI24=>Data(6), DI25=>Data(7), DI26=>scuba_vlo, 
            DI27=>scuba_vlo, DI28=>scuba_vlo, DI29=>scuba_vlo, 
            DI30=>scuba_vlo, DI31=>scuba_vlo, DI32=>scuba_vlo, 
            DI33=>scuba_vlo, DI34=>scuba_vlo, DI35=>scuba_vlo, 
            ADW0=>scuba_vlo, ADW1=>scuba_vlo, ADW2=>scuba_vlo, 
            ADW3=>WrAddress(0), ADW4=>WrAddress(1), ADW5=>WrAddress(2), 
            ADW6=>WrAddress(3), ADW7=>WrAddress(4), ADW8=>WrAddress(5), 
            ADW9=>WrAddress(6), ADW10=>scuba_vlo, ADW11=>scuba_vlo, 
            ADW12=>scuba_vlo, ADR0=>scuba_vlo, ADR1=>scuba_vlo, 
            ADR2=>scuba_vlo, ADR3=>RdAddress(0), ADR4=>RdAddress(1), 
            ADR5=>RdAddress(2), ADR6=>RdAddress(3), ADR7=>RdAddress(4), 
            ADR8=>RdAddress(5), ADR9=>RdAddress(6), ADR10=>scuba_vlo, 
            ADR11=>scuba_vlo, ADR12=>scuba_vlo, DO0=>Q(0), DO1=>Q(1), 
            DO2=>Q(2), DO3=>Q(3), DO4=>Q(4), DO5=>Q(5), DO6=>Q(6), 
            DO7=>Q(7), DO8=>open, DO9=>open, DO10=>open, DO11=>open, 
            DO12=>open, DO13=>open, DO14=>open, DO15=>open, DO16=>open, 
            DO17=>open, DO18=>open, DO19=>open, DO20=>open, DO21=>open, 
            DO22=>open, DO23=>open, DO24=>open, DO25=>open, DO26=>open, 
            DO27=>open, DO28=>open, DO29=>open, DO30=>open, DO31=>open, 
            DO32=>open, DO33=>open, DO34=>open, DO35=>open);

end Structure;

library xp;
configuration Structure_CON of uart_rx_dpr is
    for Structure
        for all:PDP8KA use entity xp.PDP8KA(V); end for;
        for all:VHI use entity xp.VHI(V); end for;
        for all:VLO use entity xp.VLO(V); end for;
    end for;
end Structure_CON;

This is my hand coded substitute:
Quartus successfully infers a DPR with that code.

Code:
library IEEE;
use IEEE.std_logic_1164.all;

entity xp_dpr_uart is
    port (
        WrAddress: in  std_logic_vector(6 downto 0); 
        RdAddress: in  std_logic_vector(6 downto 0); 
        Data: in  std_logic_vector(9 downto 0); 
        RdClock: in  std_logic; -- unused in my design
        RdClockEn: in  std_logic; -- unused in my design
        Reset: in  std_logic; 
        WrClock: in  std_logic; 
        WrClockEn: in  std_logic; -- unused in my design
        WE: in  std_logic; 
        Q: out  std_logic_vector(9 downto 0));
end xp_dpr_uart;

architecture Structure of xp_dpr_uart is

	type matrix is array ( 0 to 127 ) of std_logic_vector ( 9 downto 0 ) ; 
	signal memory : matrix ;

begin 

   process ( WrClock ) is
   begin 
       if rising_edge ( WrClock ) then
           Q <= Data ( RdAddress ) ;
           if WE = '1' then
               memory <= Data ( WrAddress ) ; 
           end if ;	
       end if ;	
   end process ;

end Structure;

With my code, the UART's transmit a byte of zeroes as if no access to the RAM occurs.
Did I do something wrong?
 

If this is real code, it wouldn't even compile. Errors:
Accessing an array with a std_logic_vector.
Accessing the input data with the write address.

Assuming these are just poor code posted to the forum, have you got a testbench for the lattice design you could use to debug the new design?
 

Very sorry,

This is the code as compiled:

Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity xp_dpr_uart is
    port (
        WrAddress: in  std_logic_vector(6 downto 0); 
        RdAddress: in  std_logic_vector(6 downto 0); 
        Data: in  std_logic_vector(9 downto 0); 
        RdClock: in  std_logic; -- unused in my design
        RdClockEn: in  std_logic; -- unused in my design
        Reset: in  std_logic; 
        WrClock: in  std_logic; 
        WrClockEn: in  std_logic; -- unused in my design
        WE: in  std_logic; 
        Q: out  std_logic_vector(9 downto 0));
end xp_dpr_uart;

architecture Structure of xp_dpr_uart is

	type matrix is array ( 0 to 127 ) of std_logic_vector ( 9 downto 0 ) ; 
	signal memory : matrix ;

begin 

	process ( WrClock ) is
	begin 
		if rising_edge ( WrClock ) then
			Q <= memory ( conv_integer ( RdAddress ) ) ;
			if WE = '1' then
				memory ( conv_integer ( WrAddress ) ) <= Data  ; 
			end if ;	
		end if ;	
	end process ;

end Structure
;

Regarding the testbench - no I don't. Other then that, the FPGA is connected to an external CPU. So I don't really know what's being sent from the upper hierarchies.
I do know however, that the Lattice code works fine.

1. Looking at the waveforms of the Lattice datasheet - I think my design behaves the same way (timing wise).
2. When connecting the address and data buses, the original designer didn't start at bit #0. Don't think it should make any difference - but it seems a little strange.

What do you think? Why isn't my RAM code working?
 
Last edited:

How do you know that the code malfunction is related to the xp_dpr_uart entity?

You can expect that it's working according to the HDL description, including ignorance of the unconnected ports.
 

How do you know that the code malfunction is related to the xp_dpr_uart entity?
I don't know for certain - I'm saying that it's my main suspect:

1. This part of the code has been altered.
2. When driven with a constant value - the UART transmits it correctly.

You can expect that it's working according to the HDL description, including ignorance of the unconnected ports
.
Sure it does.
But can you point to a possible difference in functional behavior between my code and the Lattice IP (other then the unused pins) ?
 

The most obvious difference is that the original design uses seperate clocks. Are you sure that both clocks are identical in the actual instantiation?
 

Yes, I'm positive. The same clock goes into both domains.
Also, in the original design - RdClockEn & WrClockEn are driven by a constant '1', this is why I ignored it in my code.
 

At first sight, the Lattice RAM block parameters look similar to Altera, particularly it has non-registered outputs.

To find out how the original design exactly works, you probably need to install a Lattice toolchain with simulation capability, or a simulator with Lattice support.

Presuming you can't or don't want to, there's no alternative to understanding at least the next hierachy level something better and include it in the analysis and simulation.
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
Presuming you can't or don't want to, there's no alternative to understanding at least the next hierachy level something better and include it in the analysis and simulation.
I wish I could - there's no time for that. The problem has to be solved ASAP. I'll try to implant my RAM in the Lattice design instead of the Pseudo RAM IP and see if it works there...
 

The problem with this attitude is you will probably end up with a botched solution, if you get to a solution at all. And it will probably never be fixed properly.

building a testbench and fully understanding the problem should lead to the best solution overall.
 

TrickyDicky,

I agree with you completely and by no means is it "my attitude" towards a design verification process.
The thing is, I need to deliver a solution TODAY. Simulating an FPGA that's communicating with an external CPU whose stimuli is unknown to me isn't a matter of hours.

I'm aware that my unorthodox approach may not yield a solution at all - However, considering the urgency, I see no better option. This is the hand I've been dealt...
 

The problem with this attitude is you will probably end up with a botched solution, if you get to a solution at all. And it will probably never be fixed properly.

building a testbench and fully understanding the problem should lead to the best solution overall.

Got it working.

First I tried the old Lattice project with my RAM substitute - Surprisingly, it worked flawlessly.

The above proved to me that the code is good (logic wise) and I returned to the Altera.

As you can see, the Lattice design used both: "WrClock" & "RdClock" (even though they're both driven by THE SAME clock from the upper entity.

However, in the new Altera design I used "WrClock" for both read and write operations.

The fix:
I simply returned the RdClock to the port map and everything started to work...

I think that the use of 2 names for the same clock input somehow caused both signal to be routed differently. This inferred a delay between them which actually helped to achieve proper timing.
What do you think?
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top