1
votes

Is it possible to synthesize an enable signal that asserts on a cycle if and only if an interface method/task is invoked on that cycle? Something similar to the following is desired:

interface RAM (logic clk);
  logic enable;
  // ...

  always_ff @(posedge clk) enable = 0;

  task Read(input address_t address);
    enable = 1;
    // ...
  endtask

  //...

  modport server(input clk, input enable, ...);
  modport client(input clk, export Read, ...);
endinterface

Clearly the above is illegal. The only idea I've had is to save the previous state, compare if the current and previous assignment are the same or not in the always_ff, and negate in the task invocation. That doesn't seem practical though - it's very specific and thus less likely to be optimized away during P&R. What I really need is a logic element with the semantics that when assign to it takes the value assigned, otherwise it goes to a default value.

1
Can you explain when task Read is called? Is Read a blocking task, or is it really a function? - dave_59
Read would be called in the control user logic. So you would have a module somewhere with an always_ff block in it. Then imagine a conditional with two paths, one where Read is called and another where it is not. I'm not sure if that answers your question. - sudoer
When exactly is read called? Can you guarantee that enable is set either before or after the always that wants to clear it, or is there a race? Can you draw a circuit diagram of what you want to happen? - EML
I want everything registered with clk. So enable must be asserted before the setup time for clk. Imagine that Read is only ever called or not called from a single always_ff block, e.g. there's a case or if statement. I would like to infer a deassertion of enable on any path in that always_ff where Read is not called. Ideally I would also have both Read and Write functions so there would be three cases, write, read, or do not enable the RAM. - sudoer

1 Answers

2
votes

You can only write to a signal from a single process. But you can write the the same variable multiple times from the same process, last write wins. So you can do

always_ff @(posedge clk) 
    begin 
    enable <= 0;
    case(opcode)
    READ_OP: Read(...);
    WRITE_OP: Write(...);
    endcase

Note that you must always use NBA <= to assign to enable inside your tasks (and use void functions instead of tasks if Read/Write do not consume time.