Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
21 years ago

Interface to User Logic and DMA...

Hi All,

I've got a situation where the IUL and/or DMA components don't fit well.

My chip (a USB controller) requires substancially different timing for Read and Write. Additionally this chip requires Read and Write "Recovery" times. (the minimum time before another read or write can be performed after the last one)

I don't know how common recovery times are, but it would be nice to at least specify separate Read and Write timings in the IUL.

The other elegant solution would be to have the dma controller accept a delay between reads/writes - preferably at runtime. This would allow specification of a "recovery time" between accesses.

Anyone know a better workaround right now? I'm thinking about creating a separate IUL for read and write.

Thanks,

Ken

8 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    For something like this, I've always had to fall back on custom logic driving the waitrequest line to the IUL.

    The only other thing I can think of is creating the IUL, then editing the system.ptf file (not sure that would work, though) or creating a custom component type (based on the IUL-generated module). There are a lot of settings in the PTF files that you can't get to from the IUL GUI. As I'm still learning how to do just that, I'm afraid I can't be of more help.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Mike,

    Thanks. I'm not very handy with creating my own external logic. I can do very simple things with the graphical editor and I can write simple VHDL.

    Anyway, I look in the .ptf and you're right there are separate Read_Wait_States and Write_Wait_States. I think I'll edit the IUL to use clocks instead of ns and play with these

    two values.

    I guess I could also edit the dma.v file to insert the recovery time perhaps. (Maybe with the HW Engineer&#39;s help http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/smile.gif )

    Any additional ideas or insights appreciated. I&#39;ll post my findings.

    Thanks,

    Ken
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Well, it sounds like all you need for recovery time is a counter that counts down to 0 and then stops, which gets triggered (loaded) after an access. Then, when a new access comes in, if that counter isn&#39;t 0 yet, you assert waitrequest.

    Here&#39;s some Verilog code that shows what I&#39;m getting at. I can&#39;t guarantee this code, because I haven&#39;t tested (or even compiled) it.

    This also doesn&#39;t properly handle the case where one or more of the delay constants is 0, and it might stuff in an extra clock. There are also various failure cases (Avalon bus aborting the transfer?) that aren&#39;t taken into account, so caveat programmer...

    module USBInterface
    (
      // From Avalon bus.  All are active high.
      input clk,
      input reset,
      input read,
      input write,
      input chipselect,
      output reg waitrequest
    );
    // Timing values, in CPU clocks.
    localparam kReadWaitStates = 2; // I&#39;m making all these numbers up.
    localparam kWriteWaitStates = 4; // Set them to realistic values.
    localparam kReadRecoveryClocks = 20;
    localparam kWriteRecoveryClocks = 60;
    wire doRead, doWrite;
    assign doRead = read & chipselect;
    assign doWrite = write & chipselect;
    // Delay counter
    reg  delay, newDelay; // or however many bits you need.
    reg start;
    always @(posedge clk, posedge reset)
      if(reset)
        delay <= 0;
      else if(start)
        delay <= newDelay;
      else if(delay > 0)
        delay <= delay - 1;
    // State Machine
    reg  accessState, nextState;
    localparam sIdle = 0;
    localparam sWaiting = 1;
    localparam sActive = 3;
    localparam sRecovering = 2;
    always @(posedge clk, posedge reset)
      if(reset)
        accessState <= 0;
      else
        accessState <= nextState;
    always @* begin
      // Defaults
      nextState = accessState;
      start = 0;
      waitrequest = 0;
      newDelay = 8&#39;bxxxxxxxx;
      // States
      case(accessState)
        sIdle: begin
          nextState = sWaiting;
          start = 1;
          waitrequest = 1;
          if(doRead)
            newDelay = kReadWaitStates - 1;
          else if(doWrite)
            newDelay = kWriteWaitStates - 1;
          else begin // Nothing to do, stand down.
            nextState = sIdle;
            start = 0;
            waitrequest = 0;
          end
        end
        sWaiting: begin
          if(delay == 0)
            nextState = sActive;
          waitrequest = 1;
        end
        sActive: begin
          nextState = sRecovering;
          start = 1;
          if(doRead)
            newDelay = kReadRecoveryClocks;
          else
            newDelay = kWriteRecoveryClocks;
        end
        sRecovering: begin
          if(delay == 0)
            nextState = sIdle;
          waitrequest = doRead | doWrite;
        end
      endcase
    end
    wire interfaceActive; // This goes high for one clock after the wait states expire.
    interfaceActive = accessState == sActive;
    endmodule
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Mike,

    Wow, thanks!

    Can&#39;t say I have the talent to put it to use right away, but if my .ptf file tweaking doesn&#39;t work out I&#39;ll certainly give it a whirl. I&#39;m sure there are many here that will make immediate use of your ideas and code.

    I didn&#39;t get a chance to work on this today, hopefully tomorrow. Maybe someone who knows if the Read_Wait_States and Write_Wait_States are honored will chime in before I waste much time. I&#39;m a little skepitcal since it would have been trivial yet very useful to surface these to the SOPC wizard.

    Ken
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Did this solve the problem?

    If not tell us and we&#39;ll see if we can figure something out.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Kerri,

    I just tightened my joint Read and Write timing as much as I could. It would really be nice though to either (or both) specify separate Read and Write timings or have a wait time (in cpuclocks) in between dma transfers.

    Maybe in a future release?

    My biggest problem now is getting 8MB/s of data streamed into my Nios system.

    Thanks,

    Ken
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    hello

    is there a way to acess to data from SRAM to implement this tado to the principal programm in web server program?

    i use DE2

    thanks