EDK: choices for simple internal control

Dear EDK experts,

I have a top-level ISE project with an EDK subsystem. In that top-level design I have a state machine, which has very little to do with the processor subsystem, but requires several bits for control. What would be the most natural way of doing this? The options I am aware of are as follows:

  1. Make the state machine a custom OPB peripheral;
  2. Control it with an OPB_GPIO module;
  3. Control it through DCR;
  4. Fully-custom control logic on the OPB bus.

The GPIO approach seems the easiest to me (perhaps because I've never tried using DCR), but I would like to know what others do in such cases.

Thanks, /Mikhail

Reply to
MM
Loading thread data ...

If it's microblaze, FSL can be a choice (for DCR on microblaze you would require a opb2dcr bridge iirc so fsl is lighter).

Sylvain

Reply to
Sylvain Munaut

It's PPC...

/Mikhail

Reply to
MM

If it's just a few bits, then the GPIO is probably the easiest to implement. The OPB_IPIF and PLB_IPIF are good options for more complicated designs.

--
Joe Samson
Reply to
Joseph Samson

For one project, the GPIO approach might be easiest. But it is a pain when every time a new signal is desired, the EDK portion has to be recompiled.

What I did was to start with the GPIO core and then modify it to output signals for address, read data, write data, and read/write control. Then I have a register implementation as part of my ISE project, and that is the only place I need to make changes. A little extra work up front, but well worth it in my opinion.

Reply to
Duane Clark

It's an interesting idea, but isn't the DCR doing essentially the same thing?

What I don't like about GPIO or DCR for that matter is that I can't for example implement a self-clearing write-only bit... Well, on the other hand, perhaps, it's a bad design practice...

/Mikhail

Reply to
MM

It is certainly very similar to the DCR interface. But a separate bus is not needed. I would think something like this for both the PLB and OPB buses would be simple and useful enough for others to be part of the EDK pcores.

I'm not sure what a write-only bit is ;) But the register method I use certainly allows all sorts of flexibility, and having a a bit be self clearing is easy to do this way. I am not sure where that would be difficult with the DCR bus, but then, I have not used the DCR bus.

Partly my going this direction is driven by the method I use for performing VHDL simulations. I don't bother with the complex BFM PPC models provided by Xilinx, and don't simulate the processor memory. Instead, I wrote a simple functional model of my own which correctly handles the basic read and write bus operations on the PLB bus. I do use the Xilinx supplied models for the PLB and OPB buses, arbiters, etc. It is accurate enough that the components always work in the real system, and is simple to use and simulates fast. In part, I ended up with a system like that because it is the way I handle all bus models (PCI, VME, etc). I have over time developed a style for this kind of thing that I am comfortable with, and so I stick with it.

Reply to
Duane Clark

Duane,

A write-only bit can be something as simple as this (please ignore syntax errors if any :)):

process () begin if rising_edge(clk) then wr_only_bit Partly my going this direction is driven by the method I use for

I've been using a similar approach when simulating local bus of a PCI controller in my previous designs... However, I am again a little confused about what exactly you are doing. On one hand you are saying that you wrote a simple model of your own that handles basic PLB read/write operations. On the other hand you are saying that you are using Xilinx supplied bus models... I guess I am missing something, perhaps because I haven't looked at the Xilinx models yet... But I would appreciate if you could explain what you are doing in a little more detail...

Thanks, /Mikhail

Reply to
MM

I started with the GPIO core in part for historical reasons, because initially I was adding signals to it and outputting them along the lines of option 1 of the original post. I did this for awhile, until I finally became tired of what a pain it was to use ;) So I made a copy of it, stripped all the registers out of it, and moved them to a file outside of the EDK portion of my design. And as I mentioned, then just output the address, data, and control signals, similar to the DCR.

So in my ISE portion of the design, I have this: -- The write registers datai_p: process (Clk) begin if rising_edge(Clk) then if RSelect = '1' and RNW = '0' then case ABus(22 to 29) is when MISC_REG_C =>

MISC_REG_I(15 downto 0) LOAD_TIME end case; else LOAD_TIME

The EDK code outputs a bunch of wrapper files, including a wrapper for the PPC. The wrapper just instantiates the PPC. I wrote my own PPC module. Many of the signals I don't care about, so I set them to constant values, for example: -- Clock and Power Management Interface / CPU Control Interface C405CPMCORESLEEPREQ M_RNW(0), M_abort => M_abort(0), M_busLock => M_busLock(0), M_compress => M_compress(0), M_guarded => M_guarded(0), M_lockErr => M_lockErr(0), M_MSize => M_MSize, M_ordered => M_ordered(0), M_priority => M_priority, M_rdBurst => M_rdBurst(0), M_request => M_request(0), M_size => M_size, M_type => M_type, M_wrBurst => M_wrBurst(0), M_wrDBus => M_wrDBus(0 to C_PLB_DWIDTH-1), PLB_MAddrAck => PLB_MAddrAck(0), PLB_MRdDAck => PLB_MRdDAck(0), PLB_MRdDBus => PLB_MRdDBus(0 to C_PLB_DWIDTH-1), PLB_MWrDAck => PLB_MWrDAck(0), PLB_Clk => PLB_Clk ); The test code has procedures for reads and writes: testit: process is

procedure sread(addr : in std_logic_vector(0 to C_PLB_AWIDTH-1)) is

-- data : in unsigned(7 downto 0)) is begin end procedure sread;

procedure swrite(addr : in std_logic_vector(0 to 31); data : in std_logic_vector(0 to 31)) is begin end procedure swrite;

Along with some helper procedures:

procedure reg_read(reg : in std_logic_vector(0 to 7)) is begin sread(REG_BASE_C & "00" & reg & "00"); end procedure reg_read;

procedure reg_write(reg : in std_logic_vector(0 to 7); data : in std_logic_vector(0 to 31)) is begin swrite(REG_BASE_C & "00" & reg & "00", data); end procedure reg_write;

Then I can write very simple statements to test things:

-- test writing and reading some registers reg_write(MISC_REG_C, X"00000000"); -- clear reg_write(TIME_REG_C, X"12345678"); -- clear

wait for 500 nS; reg_read(MISC_REG_C);

-- assert RD_DATA=X"00000000" report "Bad register readback 1"; reg_read(TIME_REG_C); assert RD_DATA=X"12345678" report "Bad register readback 2";

Back to the EDK top level system file, it instantiates the PPC wrapper, along with all the other EDK pieces. The PPC is now using my code. I don't care about things like the plb_bram_if_cntlr, so I write a dummy entity that doesn't do anything except tie outputs to constant values (the constant values need to be the right value so that the PLB/OPB buses will not hang). In many cases, I am not interested in the stuff on the OPB bus, so I write a dummy plb2opb bus module.

In most cases I have devices on both the PLB and OPB buses that I am interested in, so I include in my project the Xilinx supplied models for plb_v34, opb_v20, plb2opb_bridge, etc, along with the other pcore models of interest such as the opb_emc for external memory uses. And so I have a fairly complete system with a good level of fidelity, but not at the level of complexity of the Xilinx BFM.

Reply to
Duane Clark

Duane,

Thanks a lot for sharing your ideas. I will certainly be using some of your them:) The main thing is that it helps me to overcome initial fear of ripping the EDK portion of the design up :)

In the meantime I decided to try a DCR approach. One of my concerns with DCR was that it woud require using special assembler commands to access the registers, however apparently Xilinx has thought of that too and they created the OPB-to-DCR bridge to make devices on the DCR bus addressable in a normal way. All of this is nice and good but so far I couldn't figure out how to properly use the core... I added the bridge to my design and then I figured (perhaps wrongly?) that I had to add the DCR bus as well. I made the bridge a slave on the OPB and a master on the DCR bus. I made the slave DCR signals of the DCR bus module external in my design and tried generating the netlist. The thing complains that there are no slaves on the DCR bus... Can someone point me to an example and/or an appnote describing how this is supposed to be done?

Thanks, /Mikhail

please

confused

wrote

On

looked

what

Reply to
MM

the

DCR

the

In case someone is following this thread, it looks as I was actually wrong when adding the DCR bus on the secondary side of the bridge. It seems that all I had to do was to pull the bridge DCR pins out...

/Mikhail

Reply to
MM

I have already posted this in a different thread, but I thought it might be worth repeating the result. Bringing out the secondary side of the bridge wasn't enough. In the end I had to create a custom IP, which I called dcr_plug. It simply connects to the DCR master on one side and exposes the same pins on the other side. This finally made the tool happy... So, now I have the DCR bus in my top level design and I can do anything I want with it!

/Mikhail

Reply to
MM

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.