I can explain why the simulator behaves the way it does.
Remember that the always construct
always statement;
is a process that executes a
statement, and when it is done, it executes the
statement again in an infinite loop.
People sometimes think that when they see
always @(event) statement;
it means execute the
statement at every
event. It does not mean that. The event control is just part of the
statement. The
statement has to complete before it starts executing the whole thing over again.
A
begin/end block is just a compound
statement made up of a serial sequence of other
statements. When you use the
disable block statement in your example, that causes the block to jump to its
end. However your next statement is to trigger
inp_rise. This is technically a race condition, but most simulators will trigger the event first, then go back to the top of the loop and wait for another
@(posedge inp). At that point, the simulator will switch to the other always block and repeat it loop waiting for another inp_rise, which has already been triggered and missed.
One way to avoid this race is to delay the trigger. You could easily do this if you were using SystemVerilog, but if you have to stick with Verilog, you can use a toggle as I have attached here:
Code:
module top;
reg inp_pulse,inp_rise=0;
reg inp;
parameter pulse_width = 50;
always begin : pulse_gen
@(inp_rise)
inp_pulse = 1;
#pulse_width
inp_pulse = 0;
end
always @(posedge inp) begin
disable pulse_gen;
inp_rise <= ! inp_rise;
end
initial begin
inp = 0;
#10 inp = 1;
#10 inp = 0;
#100;
#10 inp = 1;
#10 inp = 0;
#10;
#10 inp = 1;
#10 inp = 0;
#50;
#10 inp = 1;
#10 inp = 0;
end // initial begin
endmodule // top
You can find other modeling suggestion by searching for "Verilog re-triggerable one-shot"