1

I have done very simple module where I assign new value on posedge of clock:

module block_entry(
    input logic clk, 
    input entry entry_write,
    output entry entry_this
);
always_ff @(posedge clk)
begin
    entry_this <= entry_write;
    display("value of entry_write.add = %b", entry_write.address);
    display("value of entry_write.value = %b", entry_write.value);
end
endmodule

when i test this module, it works fine, new value is assigned, but in more advanced architecture, the new value is not set in time to be written at posedge, even though modelsim shows that it is set

this is my test module:

module entry_tst ();
    logic clk;
    entry entry_write, entry_this;
    block_entry entry (.*);

initial begin
    #10 clk = 1; entry_write = '0; 
end
endmodule

this is the outcome -> wave and dataflow

when testing the block, outcome is:

value of entry_write.add = 0000000000000000

value of entry_write.value = 0000000000000000

as you can see, clk transitions from x to 1 in the same time as input value changes - as result, output value is overwritten

but problem is when i use this module in my architecture, it doesnt behave the same - inputs are the same, but the value is not overwritten, as if the posedge is not triggered, but actually it appears that the value is not set in time of posedge. my architecture includes:

  • entry block

  • control block ('brain' of my architecture, chooses which value should be written to entry block, generates signal 'cont' to mux, also generates signal 'clk' to entry block when to assign value from mux, 'clk' is logic, so default value is x at the beginning)

  • mux (multiplexor that chooses what value will be written to entry block based on signal from control block)

initially i want to set entry value to 0, so I have an 'init' signal, when is init equal to 1, control sets 'cont' signal accordingly, so mux chooses stream that is set to 0 and sets 'clk' so entry block will rewrite old value to new (0)

always_ff @(posedge init) 
    if (init)
    begin   
    cont <= 2'b00;
    clk <= 1;
end

everything is ok - to entry block arrives new value and 'clk' signal is set, but new value is ignored this depicts the wave behavior of entry block as a part of architecture: wave and dataflow

when testing whole architecture, outcome is:

value of entry_write.add = xxxxxxxxxxxxxxxx

value of entry_write.value = xxxxxxxxxxxxxxxx

What is wrong? I am really hopeless, I am a systemverilog newbie.

Can timescale change something (it is set to default 1ns/1ns)? Also sometimes when i observe the dataflow, in the moment of change, clk is set to 1 but the value to be written is not set to 0 - can this be the problem? that the change of clk and value is not in fact happening in the same time, and when posedge is triggered value is still old?

How come the value is not distributed in time and how can I fix it? Also, why the wave and dataflow look OK?

EDIT:

I figured that the problem is racing condition, and that basically, the value is not in time there to be written: problem

i created a diagram that shows my implementation, how can i achieve that the entry_write is there in time before clk?? diagram

Turbotrdlo
  • 49
  • 9
  • Two clarifying questions: 1) Where in the code thats having an issue is `entry_write` assigned? 2) Are you attempting to make an asynchronous circuit (because if this is supposed to be a synchronous design, you have a number of errors)? – Unn Apr 12 '18 at 18:38
  • Could you please take a look at my diagram, that shows how i assigned each value? (in edit section of my post) Would be greatly grateful for any help that will lead the entry_this to be correct. – Turbotrdlo Apr 13 '18 at 16:04

1 Answers1

0

The following expression in your code creates race condition:

always_ff @(posedge init) 
    if (init)
        clk <= 1;

if combined with

always_ff @(posedge clk)
    entry_this <= entry_write;

it causes a race int the NBA block and the results of the assignment here are unpredictable.

The rule of thumb is to never use non-blocking assignments in clocks.

Serge
  • 11,616
  • 3
  • 18
  • 28
  • Yeah, I think that I was very wrong about purpose of blocking and non-blocking assignments (I simply thought that blocking is used in always_comb block and non-blocking in always_ff - which is stupid). But basically this is my problem: https://prnt.sc/j4tsrv Please see edited post with new dataflow diagram, because my problem is still persisting after changing <= to = and I can't fix it. link also here: https://prnt.sc/j4uasd – Turbotrdlo Apr 13 '18 at 15:57
  • is 'init' changed with nonblocking assignment as well? – Serge Apr 13 '18 at 16:48
  • as you can see in diagram, no: #10 init =1; – Turbotrdlo Apr 13 '18 at 16:57
  • `clk` should **not** be assigned with non-blocking, actually it should **not** be an output of the flop. `always_comb clk = init;` is what you really need. The rest of the signals in flops **must** be non-blocking. According to diagram you changed them as well. This was wrong. Also you do not need `if (init)` in your code. Posdge already takes care of it. – Serge Apr 13 '18 at 17:13
  • this is not all code, only the part I have a problem with, beside init I have other signals, so if is needed - I need to achieve this: on posedge of any of signals _init_, _ins_, and _del_, I have to set _cont_ and **decide** whether _clk_ will be set, because not everytime I want to write new value, therefore I dont think comb is suitable – Turbotrdlo Apr 13 '18 at 18:21
  • clock is a special entity in the model and it is used to trigger flops and latches in the whole design. You need a special generator for the clock which will toggle it according to a pattern. In your design you can decide to gate the clock, using something like a simple 'and' `gatedClk = clk & enable;` . You have to be very careful with modeling it. Your case violates the requirements. – Serge Apr 13 '18 at 19:33
  • i changed it according to your instruction, i hope, can you please check whats wrong? the problem is still there: https://prnt.sc/j4zucz – Turbotrdlo Apr 13 '18 at 22:58
  • you need to post all your code then or at least all which is relevant. – Serge Apr 14 '18 at 11:18
  • i thought i have fixed the problem but it occured again, i have one crucial question: i read on other thread that it is not correct or recommended to have some signals change in the exact time as clock posedge -if this is true, which i think is my problem, how could i achieve the delay of clock, given that you said i should gate the clock - no delay there because clock will be active at the moment init will be active and when i have to handle cont signal as well – Turbotrdlo Apr 16 '18 at 14:15
  • the idea of flopped design is that all signal changes are triggered by flops. The flops are controlled by an edge of the clock, i.e. posede. Clocks are always created using blocking assignments, outputs of the flops are always non-blocking. This removes the race. Now, if you do not use flops, i.e. in initial blocks, you should make sure that your signal changes before the clock edge, i.e. when clock is low before the posedge. Otherwise you race between clock edge and change of the input of the flop. And yes, i did not pay much attention to your initial block. Sorry for that. – Serge Apr 16 '18 at 15:25