Hi!We are looking at a project where we need to interface a TI C6713 to a Cyclone III. For simplicity in this discussion, let's say that the FPGA design will only include a PIO port (as an Avalon slave) to drive some LED's (consider this as the alpha-config). Obviously, the FPGA will do more than this simple task, but the focus for now is on the EMIF interface and how to design this in the Altera environment (SOPC Builder). Goal: to have an emif component acting as an avalon-mm master SOPC Builder does not have any readily available EMIF Megacore. So I guess we are required to do the design from the beginning and incorporate it in the SOPC project. Any piece of advice is most welcome in this discussion concerning the best way when designing this component. As we see it, it would be good to keep this as one component which has
- an Avalon-MM master interface
- a small portion of logic to drive the Avalon-MM master signals properly based on the EMIF interface.
This is actually a pretty straigtforward task you are trying to do. You need to create your own SOPC Builder component that interfaces to the EMIF on one side and has an Avalon Memory-Mapped master on the other. The glue logic between the two should be minimal.1 - Let's assume you know and understand the EMIF specification well. 2 - Study the Avalon Memory-Mapped bus interface http://www.altera.com/literature/manual/mnl_avalon_spec.pdf 3 - Write HDL code for your module. Obviously this will include: a - Avalon Master port signals b - EMIF port signals c - Bus translation logic. You might wire straight across but more likely your are going to register signals between the two interfaces. 4 - Either : Create an SOPC builder component. Use the Component Editor to import your HDL file. Assign your Avalon Master signals accordingly and create a "conduit" interface to export your EMIF signals. This will make your EMIF signals show up in the port list of your SOPC system. or ... Your other option is to do as you stated. Create a component using the Avalon Master template without any HDL code. This will export all of the Avalon Master signals outside of SOPC builder. Then you can write all of your HDL code outside of SOPC builder. Jake
Thanks for the hints. We did design the component using a HDL-file which we imported in the component editor. The signals in the interface follows the convention so the editor knows what's in the conduit, master and cleck/reset. It worked out really well, and we have done the first run in ModelSim using this component along with a PIO. All successful!Many thanks for the qucik and good reply. I have attached the code if you're interested. The glue logic might change, cosnider it as a basic setup to get things in the right place and right order. library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; library altera; use altera.altera_europa_support_lib.all; library std; use std.textio.all; entity EMIF_Bridge is port ( -- The EMIF interface (conduit) --signal cos_emif_eclkout : IN STD_LOGIC; --signal cos_emif_eclkin : OUT STD_LOGIC; signal cos_emif_ed : INOUT STD_LOGIC_VECTOR (31 DOWNTO 0); signal cos_emif_ea : IN STD_LOGIC_VECTOR (21 DOWNTO 2); signal cos_emif_ce_n : IN STD_LOGIC_VECTOR (3 DOWNTO 0); --signal cos_emif_be_n : IN STD_LOGIC_VECTOR (3 DOWNTO 0); signal cos_emif_aoe_n : IN STD_LOGIC; signal cos_emif_are_n : IN STD_LOGIC; signal cos_emif_awe_n : IN STD_LOGIC; --signal cos_emif_hold_n : OUT STD_LOGIC; --signal cos_emif_holda_n : IN STD_LOGIC; --signal cos_emif_busreq : IN STD_LOGIC; -- Global clock and reset signal csi_clk : IN STD_LOGIC; signal csi_reset_n : IN STD_LOGIC; -- The Avalon-MM master interface (to the fabric) signal avm_m0_address : OUT STD_LOGIC_VECTOR (31 DOWNTO 0); signal avm_m0_read_n : OUT STD_LOGIC; signal avm_m0_waitrequest : IN STD_LOGIC; signal avm_m0_readdata : IN STD_LOGIC_VECTOR (31 DOWNTO 0); signal avm_m0_write_n : OUT STD_LOGIC; signal avm_m0_writedata : OUT STD_LOGIC_VECTOR (31 DOWNTO 0) ); end entity EMIF_Bridge; architecture InterfaceLogic of EMIF_Bridge is begin avm_m0_address(31 downto 0) <= "000000000000" & cos_emif_ea(21 DOWNTO 2); avm_m0_read_n <= cos_emif_are_n; avm_m0_write_n <= cos_emif_awe_n; tristate_control: process(csi_clk) begin if rising_edge(csi_clk) then if cos_emif_aoe_n = '1' then cos_emif_ed(31 DOWNTO 0) <= (others => 'Z'); -- Never drive bus when output enable is inactive from DSP -- Decode DSP write access to Avalon-MM master if (cos_emif_ce_n(0) = '0' OR cos_emif_ce_n(1) = '0' OR cos_emif_ce_n(2) = '0' OR cos_emif_ce_n(3) = '0') THEN avm_m0_writedata(31 DOWNTO 0) <= cos_emif_ed(31 DOWNTO 0); end if; else -- Decode DSP read access from Avalon-MM master cos_emif_ed(31 DOWNTO 0) <= avm_m0_readdata(31 DOWNTO 0); end if; end if; end process tristate_control; end architecture InterfaceLogic; So we are on track I believe, and all looks good! :) /Andreas
I just had to do this for a client. I'm surprised the only reference designs I could find were ones that read and write to a FIFO rather than the Avalon switch fabric.If you run the Avalon switch fabric using the EMIF clock, the design is much simpler since they are synchronized. If running at different clock speeds, it is more complex. For example, the avm_m0_read_n and avm_m0_write_n signals must be synchronous to the Avalon switch fabric, as indicated in the specs. Be advised that the above example will read or write multiple times as it directly ties avm_m0_read_n, and avm_m0_write_n to the EMIF signals, as these signals are active for at least 3 clocks. Not a problem for most peripherials, but a problem if trying to access a FIFO. Also, there is no checking for the dataready signal from Avalon. If you have a NIOS II processor connected to peripherials shared by the EMIF avalon master, the data may not be ready in time if the arbitrator is allowing the NIOS II access at the same time you want an EMIF master access. It is also a problem if you have a component that has a long, multi-cycle, or variable read duration. A provision for setting EMA_WAIT is necessary for this to be bullet-proof. In the end, I managed to work out a solution that incorporated some asyncronous logic for latching write data from the EMIF (deferring the write cycle to operate after the chip-select was inactive), made the Avalon master syncronous to the switch fabric, transfered the EMIF chipselect into the Avalon clock domain, and made the EMIF data bus tri-stated (when necessary, i.e. EMA_OEn), and the high/low 16 bits of output data control logic output asyncronously through a wire assignment, in Verilog. I also ended up pre-setting the EMA_WAIT pin making the EMIF bus always wait until data is available from the read (and releasing it when a EMIF write cycle was in progress), rather than have it only happen within an active chip-select. This was because the EMIF strobe period needed to be set to at least 5 clocks for it to properly see and extend the wait cycle. These methods all combined to allow the EMIF and Avalon to be operated at any speed independently, and at the fastest possible EMIF settings. I also wrote a simple interrupt controller to route the interrupts from the peripherials attached to the EMIF Avalon master back out to a common TI DSP interrupt input, and another avalon slave interface so the DSP could interrogate which peripherial is causing the interrupt. I wish I could give the code away, but gave anyone with the know-how the essential details to do it properly. Actually, I wish Altera would have had a component I could have used. Surely, using an Altera FPGA and the SOPC builder tool for peripherial expansion for TI DSPs is a common thing to do. Isn't it????? As a side note, it is nice to add a NIOS processor to your design, even if you aren't going to use it (you can remove it later), attach it to all the peripherial your DSP chip is going to use, and generate a BSP in the NIOS II IDE. You get a nicely generated system.h file you can use for your TI program to reference the base addresses and IRQs of your peripherials.....You still need to port the drivers to the TI side, but this gets you a head start in that direction. If you modify io.h to add the base EMIF address and modify IORD and IOWR macros, some of the simpler drivers, such as SYSID/TIMESTAMP don't even need any modifications at all for use on the TI DSP side. Edit: Also, you should copy over alt_types.h to your TI project, and modify alt_u16, alt_u32, etc to apprioriate types, as TI's compiler's definition of long, for example, is 64 bits, and not 32 bits...This caused me some problems.