Altera_Forum
Honored Contributor
16 years agoVerilog code fails timing analysis for register within same clock domain
Hello--
I've written some code in Verilog to sample data from six ADCs. Some signals in the code must cross clock domains. I have used a synchronizer to ensure that the signals are effectively propagated. Essentially what I am doing is grabbing data from all of the ADCs at the same time, and then using a system of flags to offload the data to another module. The data that is being offloaded in the code below is "adc_data." However, although the code is failing slow classical timing analysis in Quartus II, the code passes fast classical timing analysis. I am using a 30MHz external clock, a 70MHz clock generated from the 30MHz by a PLL, and a 280MHz clock also generated by the same PLL. Strangely enough, the timing analysis is failing for a register that appears to be in the same clock domain:Info: Slack time is -2.175 ns for clock "my_pll:pll|altpll:altpll_component|_clk1" between source register "signal:my_signal|adc:my_adc|ccc" and destination register "signal:my_signal|adc:my_adc|adc_data"
Info: Fmax is 174.03 MHz (period= 5.746 ns)
Info: + Largest register to register requirement is 3.311 ns
Info: + Setup relationship between source and destination is 3.571 ns
Info: + Latch edge is 3.571 ns
Info: Clock period of Destination clock "my_pll:pll|altpll:altpll_component|_clk1" is 3.571 ns with offset of 0.000 ns and duty cycle of 50
Info: Clock offset from Destination is based on specified offset of 0.000 ns and phase shift of 0.000 degrees of the derived clock
Info: Multicycle Setup factor for Destination register is 1
Info: - Launch edge is 0.000 ns
Info: Clock period of Source clock "my_pll:pll|altpll:altpll_component|_clk1" is 3.571 ns with offset of 0.000 ns and duty cycle of 50
Info: Clock offset from Source is based on specified offset of 0.000 ns and phase shift of 0.000 degrees of the derived clock
Info: Multicycle Setup factor for Source register is 1
Info: + Largest clock skew is 0.004 ns
Info: + Shortest clock path from clock "my_pll:pll|altpll:altpll_component|_clk1" to destination register is 2.515 ns
Info: 1: + IC(0.000 ns) + CELL(0.000 ns) = 0.000 ns; Loc. = PLL_1; Fanout = 1; CLK Node = 'my_pll:pll|altpll:altpll_component|_clk1'
Info: 2: + IC(0.916 ns) + CELL(0.000 ns) = 0.916 ns; Loc. = CLKCTRL_G2; Fanout = 126; COMB Node = 'my_pll:pll|altpll:altpll_component|_clk1~clkctrl'
Info: 3: + IC(0.933 ns) + CELL(0.666 ns) = 2.515 ns; Loc. = LCFF_X14_Y4_N15; Fanout = 2; REG Node = 'signal:my_signal|adc:my_adc|adc_data'
Info: Total cell delay = 0.666 ns ( 26.48 % )
Info: Total interconnect delay = 1.849 ns ( 73.52 % )
Info: - Longest clock path from clock "my_pll:pll|altpll:altpll_component|_clk1" to source register is 2.511 ns
Info: 1: + IC(0.000 ns) + CELL(0.000 ns) = 0.000 ns; Loc. = PLL_1; Fanout = 1; CLK Node = 'my_pll:pll|altpll:altpll_component|_clk1'
Info: 2: + IC(0.916 ns) + CELL(0.000 ns) = 0.916 ns; Loc. = CLKCTRL_G2; Fanout = 126; COMB Node = 'my_pll:pll|altpll:altpll_component|_clk1~clkctrl'
Info: 3: + IC(0.929 ns) + CELL(0.666 ns) = 2.511 ns; Loc. = LCFF_X16_Y5_N3; Fanout = 26; REG Node = 'signal:my_signal|adc:my_adc|ccc'
Info: Total cell delay = 0.666 ns ( 26.52 % )
Info: Total interconnect delay = 1.845 ns ( 73.48 % )
Info: - Micro clock to output delay of source is 0.304 ns
Info: - Micro setup delay of destination is -0.040 ns
Info: - Longest register to register delay is 5.486 ns
Info: 1: + IC(0.000 ns) + CELL(0.000 ns) = 0.000 ns; Loc. = LCFF_X16_Y5_N3; Fanout = 26; REG Node = 'signal:my_signal|adc:my_adc|ccc'
Info: 2: + IC(0.474 ns) + CELL(0.623 ns) = 1.097 ns; Loc. = LCCOMB_X16_Y5_N20; Fanout = 26; COMB Node = 'signal:my_signal|adc:my_adc|Add2~3'
Info: 3: + IC(1.892 ns) + CELL(0.624 ns) = 3.613 ns; Loc. = LCCOMB_X15_Y3_N8; Fanout = 4; COMB Node = 'signal:my_signal|adc:my_adc|ShiftLeft0~30'
Info: 4: + IC(1.141 ns) + CELL(0.624 ns) = 5.378 ns; Loc. = LCCOMB_X14_Y4_N14; Fanout = 1; COMB Node = 'signal:my_signal|adc:my_adc|adc_data~141'
Info: 5: + IC(0.000 ns) + CELL(0.108 ns) = 5.486 ns; Loc. = LCFF_X14_Y4_N15; Fanout = 2; REG Node = 'signal:my_signal|adc:my_adc|adc_data'
Info: Total cell delay = 1.979 ns ( 36.07 % )
Info: Total interconnect delay = 3.507 ns ( 63.93 % )What could I do to improve timing analysis? Here is the code for my module: module adc( // inputs
rst,
set,
clk,
hs_clk,
vhs_clk,
sc_enable,
miso,
rs_offload_flag,
// outputs
tr_adc,
sclk_adc,
adc_data,
offload_flag
);
// Inputs
input rst; // reset
input set; // helps to ensure state
input clk; // main clk for the system (30 MHz)
input hs_clk; // High speed 70 MHz clock for ADCs
input vhs_clk; // Very high speed clock for sampling SPI (280MHz)
input sc_enable; // samples will occcur on sample_clk
input miso; // six (6) inputs for each ADC
input rs_offload_flag; // resets the offload_flag
// Outputs
output tr_adc; // used to trigger ADCs
output sclk_adc; // sclk line for the ADCs
// data from the ADCs
output adc_data; // this is the freeze register
output offload_flag; // Data offloaded from the ADCs
// Regs
reg tr_adc; // six (6) triggers for each ADC
reg sample_flag; // flag to indicate the beginning of each sample
// ADC data register holds the output from the ADCs
reg adc_data;
reg offload_flag = 0;
reg ccc; // ccc = 20, so this is the maximum number
reg sclk_adc;
// Flags
reg collect_data = 0;
// Shift registers
reg miso_sr;
reg adc_sclk_sr;
// determine the falling edge of MISO
// note the use of the reduction OR | operator
// which is used to check if all of MISO from each
// ADC is low
always @(posedge vhs_clk)
miso_sr <= { miso_sr, |miso };
wire falling_edge_miso = (miso_sr == 2'b10);
// determine the rising and falling edges of sclk_adc
always @(posedge vhs_clk)
adc_sclk_sr <= { adc_sclk_sr, hs_clk };
wire rising_edge_sclk_adc = (adc_sclk_sr == 2'b01);
wire falling_edge_sclk_adc = (adc_sclk_sr == 2'b10);
// initiate the conversion by toggling tr_adc
always @(posedge clk) begin
if( rst || !set ) begin
sample_flag <= 1'b0;
tr_adc <= 5'b0;
end
else begin
if(sc_enable && !sample_flag) begin
tr_adc <= 6'b111111;
sample_flag <= 1'b1;
end
else begin
tr_adc <= 6'b0;
end
if(!sc_enable) begin
sample_flag <= 1'b0;
tr_adc <= 6'b0;
end
end
end
// these signals are cascaded to ensure that we pass timing analysis
reg rloc_set;
Signal_CrossDomain my_first_crossdomain(
.clkA(clk),
.SignalIn(set),
.clkB(hs_clk),
.SignalOut(rloc_set)
);
wire loc_set;
Signal_CrossDomain my_second_crossdomain(
.clkA(hs_clk),
.SignalIn(rloc_set),
.clkB(vhs_clk),
.SignalOut(loc_set)
);
wire loc_rs_offload_flag;
Signal_CrossDomain my_third_crossdomain(
.clkA(hs_clk),
.SignalIn(rs_offload_flag),
.clkB(vhs_clk),
.SignalOut(loc_rs_offload_flag)
);
// sample all of the ADCs at the same time
always @(posedge vhs_clk) begin
if( (rst || !loc_set) ) begin
collect_data <= 0;
end
else begin
// wait until the falling edge of miso
if(falling_edge_miso && !collect_data) begin
collect_data <= 1;
end
if(collect_data) begin
if(rising_edge_sclk_adc) begin
sclk_adc <= 6'b111111;
ccc <= ccc + 1'b1;
if( ccc >= 1 )
adc_data <= (adc_data | (miso << (6 * (ccc-1) )));
end
if(falling_edge_sclk_adc) begin
sclk_adc <= 6'b000000;
if(ccc == 19) begin
collect_data <= 0;
offload_flag <= 1;
end
end
end // collect_data
// clear the offload_flag and the adc_data in preparation
// for the next measurement
if( loc_rs_offload_flag ) begin
offload_flag <= 0;
adc_data <= 0;
ccc <= 0;
end
end //else
end // posedge vhs_clk
// ends the module
endmodule