Hi,
I am using Cadence ICADVM20.1-64b.200.21 with SPECTRE20.1.231.isr6 64bit
I am trying to build a VerilogA model for a (lookup_table) with instance name "I_ACCUM_CLK_GEN_LUT" that is addressed by a modulo (mod_counter) with instance name "I_ACCUM_CLK_ADDRESS_GEN". The read value from this lookup table is then used as clock to another instance of the (mod_counter) called "I_LATCH_CLK_GEN".
All three instances are instantiated in a parent module (mth_residue_estimator) as shown below:
<code>// VerilogA for behavioral_blocks, mth_residue_estimator, veriloga
`include "constants.vams"
`include "disciplines.vams"
module mth_residue_estimator(in, sk_corr, sk_mult, clk_fs, clk_fs_o_Rp1, kth_estim_all_done, out, coeff_done);
input in, sk_corr, sk_mult, clk_fs, clk_fs_o_Rp1, kth_estim_all_done;
output out, coeff_done;
electrical in, sk_corr, sk_mult, clk_fs, clk_fs_o_Rp1, kth_estim_all_done, out, coeff_done;
parameter real out_t_delay = 0 from [0:inf);
parameter real out_t_transition = 10f from [0:inf);
parameter real int_clk_skew = out_t_transition from [0:inf);
parameter integer inherent_clock = 1 from [0:1];
parameter real first_sample_t_delay = 0 from [0:inf);
parameter real clk_f = 3e9;
parameter real vdd = 0.8 from [0:5];
parameter real vclk_threshold = 0.4 from [0:vdd];
parameter integer R = 5 from [0:inf);
electrical latch_clk;
electrical accum_clk, address;
lookup_table # (.out_t_delay(out_t_delay), .out_t_transition(out_t_transition), .inherent_clock(inherent_clock), .first_sample_t_delay(first_sample_t_delay+int_clk_skew), .clk_f(clk_f), .vdd(vdd), .vclk_threshold(vclk_threshold), .size(R+1)) I_ACCUM_CLK_GEN_LUT (.address(address), .rst(latch_clk), .sk_n(sk_corr), .accum_clk(accum_clk));
mod_counter # (.out_t_delay(out_t_delay), .out_t_transition(out_t_transition), .inherent_clock(inherent_clock), .first_sample_t_delay(first_sample_t_delay), .clk_f(clk_f), .vdd(vdd), .vclk_threshold(vclk_threshold), .clk_dir(-1), .modulo(R+1)) I_ACCUM_CLK_ADDRESS_GEN (.clk(clk_fs), .out(address));
mod_counter # (.out_t_transition(out_t_transition), .inherent_clock(0), .first_sample_t_delay(0), .clk_f(15e9), .clk_dir(1), .modulo(R+1)) I_LATCH_CLK_GEN (.clk(accum_clk), .carry(coeff_done));
endmodule</code>
The mod_counter child module is capable of being triggered by the positive/negative or both edges of an inherent clock (just timers) or an external clock provided via the "clk" input. This is controlled by the "clk_dir" and "inherent_clk" parameters respectively. A generate construct is used.
A @display is used inside each condition to see its inherited parameter values and how the generated behavior will be. All this is shown below.
<code>// VerilogA for behavioral_blocks, mod_counter, veriloga
`include "constants.vams"
`include "disciplines.vams"
module mod_counter(clk, out, carry);
input clk;
output out, carry;
electrical clk, out, carry;
parameter real out_t_delay = 0 from [0:inf);
parameter real out_t_transition = 10f from [0:inf);
parameter integer inherent_clock = 1 from [0:2];
parameter real first_sample_t_delay = 0 from [0:inf);
parameter real clk_f = 3e9;
parameter real vdd = 0.8 from [0:5];
parameter real vclk_threshold = 0.4 from [0:vdd];
parameter integer clk_dir = 1 from [-1:1];
parameter integer modulo = 6 from [0:inf);
integer out_val = 0, carry_val = 0;
analog @(initial_step) $display("Modcounter %M: Instance parameters inhereted are:\n\t\tout_t_delay = %g\n\t\tout_t_transition = %g\n\t\tinherent_clock = %d\n\t\tfirst_sample_t_delay = %g\n\t\t\clk_f = %g\n\t\t\vdd = %g\n\t\t\vclk_threshold = %g\n\t\tclk_dir = %d\n\t\tmodulo = %d\n", out_t_delay, out_t_transition, inherent_clock, first_sample_t_delay, clk_f, vdd, vclk_threshold, clk_dir, modulo);
generate
if (inherent_clock == 1) begin
analog @(initial_step) $display("Modcounter %M: Entering Inherent clock mode because inherent_clk = %d", inherent_clock);
case (1)
(clk_dir == -1) : begin
analog @(initial_step) $display("Modcounter %M: Inherent clock mode falling edge\n\n");
analog @(timer(first_sample_t_delay+0.5/clk_f,1.0/clk_f)) begin out_val = (out_val + 1) % modulo; carry_val = (out_val == 0); end
end
(clk_dir == 0) : begin
analog @(initial_step) $display("Modcounter %M: Inherent clock mode dual edge\n\n");
analog @(timer(first_sample_t_delay,0.5/clk_f)) begin out_val = (out_val + 1) % modulo; carry_val = (out_val == 0); end
end
(clk_dir == 1) : begin
analog @(initial_step) $display("Modcounter %M: Inherent clock mode rising edge\n\n");
analog @(timer(first_sample_t_delay,1.0/clk_f)) begin out_val = (out_val + 1) % modulo; carry_val = (out_val == 0); end
end
endcase
end
else begin
analog @(initial_step) $display("Modcounter %M: Enterinng External clock mode because inherent_clk = %d", inherent_clock);
if (first_sample_t_delay > 0) begin
analog @(initial_step) $display("Modcounter %M: Delayed External clock mode");
electrical int_del_clk;
analog V(int_del_clk) <+ absdelay(V(clk),first_sample_t_delay);
case (1)
(clk_dir == -1) : begin
analog @(initial_step) $display("Modcounter %M: Delayed External clock mode falling edge\n\n");
analog @(above(vclk_threshold-1e-3-V(int_del_clk))) begin out_val = (out_val + 1) % modulo; carry_val = (out_val == 0); end
end
(clk_dir == 0) : begin
analog @(initial_step) $display("Modcounter %M: Delayed External clock mode dual edge\n\n");
analog @(above(vclk_threshold-1e-3-V(int_del_clk)) or above(V(int_del_clk)-vclk_threshold)) begin out_val = (out_val + 1) % modulo; carry_val = (out_val == 0); end
end
(clk_dir == 1) : begin
analog @(initial_step) $display("Modcounter %M: Delayed External clock mode rising edge\n\n");
analog @(above(V(int_del_clk)-vclk_threshold)) begin out_val = (out_val + 1) % modulo; carry_val = (out_val == 0); end
end
endcase
end
else begin
analog @(initial_step) $display("Modcounter %M: Non delayed External clock mode");
case (1)
(clk_dir == -1) : begin
analog @(initial_step) $display("Modcounter %M: Non delayed External clock mode falling edge\n\n");
analog @(above(vclk_threshold-1e-3-V(clk))) begin out_val = (out_val + 1) % modulo; carry_val = (out_val == 0); end
end
(clk_dir == 0) : begin
analog @(initial_step) $display("Modcounter %M: Non delayed External clock mode dual edge\n\n");
analog @(above(vclk_threshold-1e-3-V(clk)) or above(V(clk)-vclk_threshold)) begin out_val = (out_val + 1) % modulo; carry_val = (out_val == 0); end
end
(clk_dir == 1) : begin
analog @(initial_step) $display("Modcounter %M: Non delayed External clock mode rising edge\n\n");
analog @(above(V(clk)-vclk_threshold)) begin out_val = (out_val + 1) % modulo; carry_val = (out_val == 0); end
end
endcase
end
end
analog begin
V(out) <+ transition(out_val, out_t_delay, out_t_transition, out_t_transition);
V(carry) <+ transition(vdd*carry_val, out_t_delay, out_t_transition, out_t_transition);
end
endgenerate
endmodule</code>
When any number of (mod_counter) modules are tested alone at the top level to see if the module acts as expected, it indeed works correctly for all combinations of "inherent_clk" and "clk_dir".
![]()
![]()
However, when 2 (mod_counters) are instantiated inside the (mth_residue_estimator) as shown above and an instance of (mth_residue_estimator) is tested, I got a weird behavior.
Both counters inside work as if they are in the inherent_clock rising edge mode, i.e., as if "inherent_clock" = 1 and "clk_dir" = 1 which are the default values inside (mod_counter) module, although the values for these parameters are different for both instances during instantiation and the $display statements say that the inherited values are correct.
Basically what is happening is that both instances of (mod_counter) take the parameter values correctly from the parent instantiator module (mth_residue_estimator) and then ignore them totally and use the default values to use in the conditional generate blocks for some unknown reason.
![]()
![]()
This also happens to any module of (mod_counter) instantiated outside (mth_residue_estimator) but in its presence in the netlist.
![]()
![]()
![]()
I hope someone could help.
Best,
Ahmed