// VerilogA for behavioral_blocks, lookup_table, veriloga `include "constants.vams" `include "disciplines.vams" module lookup_table(address, clk, rst, sk_n, accum_clk); input address, clk, rst, sk_n; output accum_clk; electrical address, clk, rst, sk_n, accum_clk; 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: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 size = 6 from [0:inf); integer saved_value[0:size-1]; integer address_val = 0; integer set_val = 1; integer sk_n_val = 0; integer data_read_val = 0; integer accum_clk_val = 0; integer k = 0; generate if (inherent_clock == 1) begin analog begin @(timer(first_sample_t_delay+0.5/clk_f,1.0/clk_f)) begin if (V(rst) < vclk_threshold && set_val) saved_value[address_val] = 1; // If read data was low and sk is high (i.e, setval is high) --> set the addressed register high. address_val = V(address); // Update the address register data_read_val = saved_value[address_val]; // Read the data from the new address (not clocked in reality) sk_n_val = V(sk_n); // Update the sk info you have (not clocked in reality) (needs to be done for both clock edges as it will be read during both) set_val = sk_n_val && (!data_read_val); // Update the setval register accordingly (needs to be done for both clock edges as it will be read during both) accum_clk_val = 0; // Lower the accum_clk_val as the clock is now supposed to be low (gated by the clock) end @(timer(first_sample_t_delay,1.0/clk_f)) begin sk_n_val = V(sk_n); // Update the sk info you have (not clocked in reality) (needs to be done for both clock edges as it will be read during both) set_val = sk_n_val && (!data_read_val); // Update the setval accordingly (not clocked with this edge in reality) (needs to be done for both clock edges as it will be accum_clk_val = set_val; // Calculate Whether to clock the accumulator or not end end end else begin if (first_sample_t_delay > 0) begin electrical int_del_clk; analog begin V(int_del_clk) <+ absdelay(V(clk),first_sample_t_delay); @(above(vclk_threshold-1e-3-V(int_del_clk))) begin if (V(rst) < vclk_threshold && set_val) saved_value[address_val] = 1; // If read data was low and sk is high (i.e, setval is high) --> set the addressed register high. address_val = V(address); // Update the address register data_read_val = saved_value[address_val]; // Read the data from the new address (not clocked in reality) sk_n_val = V(sk_n); // Update the sk info you have (not clocked in reality) (needs to be done for both clock edges as it will be read during both) set_val = sk_n_val && (!data_read_val); // Update the setval register accordingly (needs to be done for both clock edges as it will be read during both) accum_clk_val = 0; // Lower the accum_clk_val as the clock is now supposed to be low (gated by the clock) end @(above(V(int_del_clk)-vclk_threshold)) begin sk_n_val = V(sk_n); // Update the sk info you have (not clocked in reality) (needs to be done for both clock edges as it will be read during both) set_val = sk_n_val && (!data_read_val); // Update the setval accordingly (not clocked with this edge in reality) (needs to be done for both clock edges as it will be accum_clk_val = set_val; // Calculate Whether to clock the accumulator or not end end end else begin analog begin @(above(vclk_threshold-1e-3-V(clk))) begin if (V(rst) < vclk_threshold && set_val) saved_value[address_val] = 1; // If read data was low and sk is high (i.e, setval is high) --> set the addressed register high. address_val = V(address); // Update the address register data_read_val = saved_value[address_val]; // Read the data from the new address (not clocked in reality) sk_n_val = V(sk_n); // Update the sk info you have (not clocked in reality) (needs to be done for both clock edges as it will be read during both) set_val = sk_n_val && (!data_read_val); // Update the setval register accordingly (needs to be done for both clock edges as it will be read during both) accum_clk_val = 0; // Lower the accum_clk_val as the clock is now supposed to be low (gated by the clock) end @(above(V(clk)-vclk_threshold)) begin sk_n_val = V(sk_n); // Update the sk info you have (not clocked in reality) (needs to be done for both clock edges as it will be read during both) set_val = sk_n_val && (!data_read_val); // Update the setval accordingly (not clocked with this edge in reality) (needs to be done for both clock edges as it will be accum_clk_val = set_val; // Calculate Whether to clock the accumulator or not end end end end endgenerate analog begin @(above(V(rst)-vclk_threshold)) for (k = 0; k < size; k = k+1) saved_value[k] = 0; V(accum_clk) <+ transition(vdd*accum_clk_val, out_t_delay, out_t_transition, out_t_transition); end endmodule