Your IP : 216.73.216.213
// Verilog HDL for "LIB", "hadd" "_functional"
module hadd (clock, A_in, B_in, carry, sum);
// Default values for the timing parameters
parameter
delay_carry = 33,
delay_sum = 37,
t_hold = 1,
t_setup = 31,
t_sep = 11,
warning_file = 2;
// Declaration of data types
input
clock,
A_in,
B_in;
output
carry,
sum;
reg
trig,
carry,
sum,
data_A,
data_B,
extra_A,
extra_B; // Multi-pulse indicators
integer
current_time,
holdtime,
sep_time,
left_bound,
right_bound,
time_A,
time_B;
initial
begin // Initialization
trig = 0;
left_bound = 0;
{data_A, data_B} = 0;
{carry, sum} = 0;
#0 holdtime = (t_hold < 0) ? 0 : t_hold;
end // initial
always @(posedge A_in)
begin
// Store the time position of the data (center of the pulse)
time_A = $time + 1;
// Store the value of the data input
data_A = A_in;
// Display warning if more than 1 data pulse comes in 1 clock cycle
if (extra_A == 'b1)
$fdisplay(warning_file, "Extra pulse detected in module %m at input A at %0d ps.\n", time_A);
extra_A = 1; // Set after 1 data pulse comes
end // always
always @(posedge B_in)
begin
// Store the time position of the data (center of the pulse)
time_B = $time + 1;
// Store the value of the data input
data_B = B_in;
// Display warning if more than 1 data pulse comes in 1 clock cycle
if (extra_B == 'b1)
$fdisplay(warning_file, "Extra pulse detected in module %m at input B at %0d ps.\n", time_B);
extra_B = 1; // Set after 1 data pulse comes
end // always
always @(posedge clock)
// Trigger after clock+holdtime
trig <= #(holdtime-1) 1;
always @(posedge trig)
begin
current_time = $time+1-(holdtime-1); // Present time of clock
// Delay = 0.5 so that clock cycles do not overlap
#0.5 trig = 0;
// Generate output only if there are input pulses
if ((data_A !== 'b0) | (data_B !== 'b0))
begin
// Reset to receive data input in a new clock cycle
extra_A = 0;
extra_B = 0;
// Determine the right boundary of the time range in which there is no timing violation
right_bound = current_time - t_setup;
casex ({(data_A !== 'b0), (data_B !== 'b0), ((time_A >= left_bound) & (time_A <= right_bound)), ((time_B >= left_bound) & (time_B <= right_bound))})
// Two data inputs and no timing violation
4'b1111:
begin
sep_time = time_A - time_B;
sep_time = (sep_time < 0) ? -sep_time : sep_time;
// Separation time violation?
if (sep_time < t_sep)
begin
carry <= #(delay_carry - holdtime) 'bx;
sum <= #(delay_sum - holdtime) 'bx;
$fdisplay(warning_file, "Violation of separation time in module %m.\nInput A at %0d ps, input B at %0d ps.\n", time_A, time_B);
end
else
carry <= #(delay_carry - holdtime) (data_A & data_B);
// Reset to receive new data values in a new clock cycle
{data_A, data_B} = 0;
end
// One data input and no timing violation
4'b101x:
begin
sum <= #(delay_sum - holdtime) data_A;
data_A = 0;
end
// One data input and no timing violation
4'b01x1:
begin
sum <= #(delay_sum - holdtime) data_B;
data_B = 0;
end
// Two data inputs and there is timing violation
4'b1100:
begin
carry <= #(delay_carry - holdtime) 'bx;
sum <= #(delay_sum - holdtime) 'bx;
// Issue a warning
if ((time_A > right_bound) & (time_B > right_bound))
$fdisplay(warning_file, "Violation of hold/setup time in module %m. \nInput A at %0d ps, input B at %0d ps, clock at %0d ps.\n", time_A, time_B, current_time);
else if (time_A > right_bound)
begin
$fdisplay(warning_file, "Violation of hold/setup time in module %m. \nInput A at %0d ps, clock at %0d ps.\n", time_A, current_time);
data_B = 0;
end
else if (time_B > right_bound)
begin
$fdisplay(warning_file, "Violation of hold/setup time in module %m. \nInput B at %0d ps, clock at %0d ps.\n", time_B, current_time);
data_A = 0;
end
// If a warning has been issued before
else
{data_A, data_B} = 0;
end
// One data input and there is timing violation
4'b100x:
begin
sum <= #(delay_sum - holdtime) 'bx;
// Issue a warning
if (time_A > right_bound)
$fdisplay(warning_file, "Violation of hold/setup time in module %m. \nInput A at %0d ps, clock at %0d ps.\n", time_A, current_time);
// If a warning has been issued before
else
data_A = 0;
end
// One data input and there is timing violation
4'b01x0:
begin
sum <= #(delay_sum - holdtime) 'bx;
// Issue a warning
if (time_B > right_bound)
$fdisplay(warning_file, "Violation of hold/setup time in module %m. \nInput B at %0d ps, clock at %0d ps.\n", time_B, current_time);
// If a warning has been issued before
else
data_B = 0;
end
// Two data inputs and there is timing violation
4'b1110:
begin
carry <= #(delay_carry - holdtime) 'bx;
sum <= #(delay_sum - holdtime) 'bx;
// Issue a warning
if (time_A > right_bound)
$fdisplay(warning_file, "Violation of hold/setup time in module %m. \nInput A at %0d ps, clock at %0d ps.\n", time_A, current_time);
// If a warning has been issued before
else
data_A = 0;
end
// Two data inputs and there is timing violation
4'b1101:
begin
carry <= #(delay_carry - holdtime) 'bx;
sum <= #(delay_sum - holdtime) 'bx;
// Issue a warning
if (time_B > right_bound)
$fdisplay(warning_file, "Violation of hold/setup time in module %m. \nInput B at %0d ps, clock at %0d ps.\n", time_B, current_time);
// If a warning has been issued before
else
data_B = 0;
end
endcase
// Reset the outputs after 2ps
carry <= #(delay_carry - holdtime + 2) 0;
sum <= #(delay_sum - holdtime + 2) 0;
end // if
// Determine the left boundary of the time range in which there is no timing violation
left_bound = current_time + t_hold;
end // always
endmodule