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
EDK: choices for simple internal control
Started by ●March 3, 2006
Reply by ●March 3, 20062006-03-03
MM wrote:> 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.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 by ●March 3, 20062006-03-03
"Sylvain Munaut" <com.246tNt@tnt> wrote in message news:4408d793$0$29227$ba620e4c@news.skynet.be...> If it's microblaze, FSL can be a choice (for DCR on microblaze you would > require a opb2dcr bridge iirc so fsl is lighter).It's PPC... /Mikhail
Reply by ●March 3, 20062006-03-03
MM wrote:> 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.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 by ●March 4, 20062006-03-04
MM wrote:> 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.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 by ●March 4, 20062006-03-04
"Duane Clark" <dclark@junkmail.com> wrote in message news:ZMjOf.18743$2O6.14086@newssvr12.news.prodigy.com...> 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.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 by ●March 4, 20062006-03-04
MM wrote:> "Duane Clark" <dclark@junkmail.com> wrote in message > news:ZMjOf.18743$2O6.14086@newssvr12.news.prodigy.com... >> 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. > > 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... >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 by ●March 5, 20062006-03-05
Duane, "Duane Clark" <dclark@junkmail.com> wrote in message news:stpOf.27023$_S7.14217@newssvr14.news.prodigy.com...> > 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.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 <= bus_address_match and write_en else; end; end process; If it needs to cross the clock domains it can be resynchronized to another clock. You got me confused. You said you started with the GPIO core and you are saying that you can do self-clearing bits with it somehow. Could you please elaborate a little bit?> 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.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 by ●March 6, 20062006-03-06
MM wrote:> Duane, > > ... > You got me confused. You said you started with the GPIO core and you are > saying that you can do self-clearing bits with it somehow. Could you please > elaborate a little bit?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) <= WRDATA(16 to 31); when TIME_REG_C => LOAD_TIME <= '1'; when others => end case; else LOAD_TIME <= '0'; end if; end if; end process datai_p; Ah, I just noticed that right there I seem to have something along the lines of the write only bit, in the signal LOAD_TIME. I guess that is similar to what you were looking 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...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 <= '1'; C405CPMMSRCE <= '1'; C405CPMMSREE <= '1'; C405CPMTIMERIRQ <= '1'; C405CPMTIMERRESETREQ <= '1'; C405XXXMACHINECHECK <= '1'; The important signals are the ones controlling reads and writes on the bus, and they are driven (and read) from my test code: TST: entity work.bd_test generic map ( C_PLB_NUM_MASTERS => C_PLB_NUM_MASTERS, C_PLB_AWIDTH => C_PLB_AWIDTH, C_PLB_DWIDTH => C_PLB_DWIDTH ) port map ( M_ABus => M_ABus(0 to C_PLB_AWIDTH-1), M_BE => M_BE, M_RNW => 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 by ●March 6, 20062006-03-06
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 "Duane Clark" <dclark@junkmail.com> wrote in message news:sFZOf.19239$rL5.7566@newssvr27.news.prodigy.net...> MM wrote: > > Duane, > > > > ... > > You got me confused. You said you started with the GPIO core and you are > > saying that you can do self-clearing bits with it somehow. Could youplease> > elaborate a little bit? > > 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) <= WRDATA(16 to 31); > when TIME_REG_C => > LOAD_TIME <= '1'; > when others => > end case; > else > LOAD_TIME <= '0'; > end if; > end if; > end process datai_p; > > Ah, I just noticed that right there I seem to have something along the > lines of the write only bit, in the signal LOAD_TIME. I guess that is > similar to what you were looking 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 littleconfused> > about what exactly you are doing. On one hand you are saying that youwrote> > 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'tlooked> > at the Xilinx models yet... But I would appreciate if you could explainwhat> > you are doing in a little more detail... > > 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 <= '1'; > C405CPMMSRCE <= '1'; > C405CPMMSREE <= '1'; > C405CPMTIMERIRQ <= '1'; > C405CPMTIMERRESETREQ <= '1'; > C405XXXMACHINECHECK <= '1'; > > The important signals are the ones controlling reads and writes on the > bus, and they are driven (and read) from my test code: > TST: entity work.bd_test > generic map ( > C_PLB_NUM_MASTERS => C_PLB_NUM_MASTERS, > C_PLB_AWIDTH => C_PLB_AWIDTH, > C_PLB_DWIDTH => C_PLB_DWIDTH > ) > port map ( > M_ABus => M_ABus(0 to C_PLB_AWIDTH-1), > M_BE => M_BE, > M_RNW => 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.




