Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20641 Discussions

weird behaviour of fitter in quartus for SDRAM project

omar_ibrahim
Beginner
365 Views

I've been working on SDRAM controller project using verilog using cyclone v 5cefa5f23i7.

The SDRAM have four bank , 3 cas latency and 166 Mhz clock.

I start design with a goal of having lowest possible latency for controller but as i expect timing failure start  appearing at first compile , so i start debugging and change the hdl code

I also use compile at aggressive performance setting,

the main problem is the io is far from other so the routing delay is huge (up to 5ns) leaving small roam for logic delay.

here is the code it not complete and i still beginner 

module controller(
input clk,clk_2,rst,
inout wire [31:0] data_bus,
output reg [12:0] addr_out,
output reg [1:0] bank_out,
output reg [3:0] DQ,
output reg cke,cas,ras,we,cs,
output wire clk_out,
		//control_port
input wire [23:0] addr_in,
input wire [31:0] data_w_in,
output reg [31:0] data_r_in,
input wire write_in,read_in,
output reg ready,
output reg [3:0] busy
);
integer i,j,k,h;
integer num [3:0];
integer num_2 [3:0];

clock_out	clock_out_inst (
	.datain_h (1'b1),
	.datain_l (1'b0),
	.outclock (clk_2),
	.dataout (clk_out)
	);


///////////////////sync

always_ff @(posedge clk or negedge rst)
if(~rst)
	data_r_in <= 0;
else	
	data_r_in <= data_bus;

reg act_write = 0;
reg [1:0] read_delay = 3;
always_ff @(negedge clk_2 or negedge rst)//output enable
if(~rst)
	act_write <= 0;
else
	act_write <= (read_delay<2) ? 0 : 1 ;

reg [31:0] data_out = 0;
assign data_bus = act_write ? data_out : 32'bz;
////////////////end_sync



////////////////////////////////////main_state_machine
reg [1:0] main_s = 0;
parameter initial_ = 0 ,work = 2'h1 ,refresh = 2'h2;
reg [1:0] counter = 0;
reg [3:0] ref_delay = 0;
reg [11:0] ref_counter = 0;
reg [3:0] ref_act = 0;

initial begin
addr_out = 0;
bank_out = 0;
data_r_in = 0;
ready = 0;
cke = 1;
cas = 1;
ras = 1;
we = 1;
cs = 1;
DQ = 4'hf;
end
///////////////////////////////////comb_logic_registers
reg [1:0] main_s_wire;
reg [1:0] counter_wire;
reg [3:0] ref_delay_wire;
reg [11:0] ref_counter_wire;
reg [3:0] ref_act_wire;
reg [12:0] addr_out_wire;
reg [1:0] bank_out_wire;
reg [3:0] DQ_wire;
reg [31:0] data_out_wire;
reg [1:0] read_delay_wire;
reg ready_wire;
reg cke_wire;
reg cas_wire;
reg ras_wire;
reg we_wire;
reg cs_wire;

/*
counter_wire = counter_wire;
ref_delay_wire = ref_delay;
addr_out_wire = addr_out;
bank_out_wire = bank_out;
DQ_wire = DQ;
cke_wire = cke;
cas_wire = cas;
ras_wire = ras;
we_wire = we;
cs_wire = cs;
*/

///////////////////////////////////bank_state_machine
reg [1:0] state [3:0];
parameter idle = 2'h0 ,active = 2'h1 ,read_write = 2'h2 ,precharge = 2'h3;
//////////////////////instructure coder
reg [1:0] ins [3:0];
parameter active_i = 2'h0 ,read_i = 2'h1 ,write_i = 2'h2 ,pre_charge_i = 2'h3;
reg [3:0] ins_r [3:0];
//////////////////////delay control
reg [3:0] delay [3:0];//active to write or read to precharge
reg delay_pre [3:0];	 //write to precharge
//////////////////////data_latch
reg [31:0] data [3:0];
reg [21:0] addr [3:0];
parameter read_con = 0 , write_con = 1'b1;
reg r_w [3:0];
/////////////////////globa_variables
reg [3:0] delay_ab = 0;  //delay from read or write in different bank
reg [1:0] global_act = 0;//delay from active to active in diffrent bank
reg [3:0] run = 0; //reg to control "chip select"



always_comb begin

if(ref_counter >= 1200)begin
	ref_counter_wire = 0;
	ref_act_wire = ref_act+1;
	end
else begin
	ref_counter_wire = ref_counter+1;
	ref_act_wire = ref_act;
	end

if(read_delay == 0)begin
	ready_wire = 1;
	read_delay_wire = 3;
	end
else begin
	ready_wire = 0;
	if(read_delay < 3)
		read_delay_wire = read_delay-1;
	else
		read_delay_wire = read_delay; 
	end
	
	
	
case(main_s)

initial_:begin
			counter_wire[0] = 1;
			counter_wire[1] = counter[0];
			ras_wire = 0;//precharge all banks
			we_wire = 0;
			bank_out_wire = 0;//mode register set
			if(counter[0])begin
				cas_wire = 0;
				addr_out_wire = 13'b0001000110000;//refer to mode register table
				end
			else begin
				cas_wire = 1'b1;
				addr_out_wire = 13'b0010000000000;//bank precharge
				end

			if(counter[1])begin
				ref_act_wire = 8;
				main_s_wire = refresh;
				cs_wire = 1;
				end
			else begin
				main_s_wire = main_s;
				ref_act_wire = ref_act;
				cs_wire = 0;
				end
			data_out_wire = data_out;
			ref_delay_wire = ref_delay;
			DQ_wire = DQ;
			cke_wire = cke;
			end
			
work:begin/////normal_operatoin
			counter_wire = counter;
			ref_delay_wire = ref_delay;
			DQ_wire = DQ;
			cke_wire = cke;		
			addr_out_wire = addr_out;//should be removed
			
		if(ins_r[0][2] == 1)begin // here is the problem
			data_out_wire = data[0];
			end else
		if(ins_r[1][2] == 1)begin
			data_out_wire = data[1];
			end else
		if(ins_r[2][2] == 1)begin
			data_out_wire = data[2];
			end else
			data_out_wire = data[3];			
				
			
		if((ins_r[0][0] == 1)|(ins_r[1][0] == 1)|(ins_r[2][0] == 1)|(ins_r[3][0] == 1)|(ins_r[0][2] == 1)|(ins_r[1][2] == 1)|(ins_r[2][2] == 1)|(ins_r[3][2] == 1))begin//active
			we_wire = 1;
			end else
			we_wire = 0;
		////////////////////
		/*
			if((ins[0] == active_i)&(run[0]))
				addr_out_wire = addr[0][12:0];
			else
			if((ins[1] == active_i)&(run[1]))
				addr_out_wire = addr[1][12:0];
			else
			if((ins[2] == active_i)&(run[2]))
				addr_out_wire = addr[2][12:0];
			else
			if((ins[3] == active_i)&(run[3]))
				addr_out_wire = addr[3][12:0];
			else
			if((ins[0] == write_i)&(run[0]))
				addr_out_wire = addr[0][12:0];
			else
			if((ins[1] == write_i)&(run[1]))
				addr_out_wire = addr[1][12:0];
			else
			if((ins[2] == write_i)&(run[2]))
				addr_out_wire = addr[2][12:0];
			else
			if((ins[3] == write_i)&(run[3]))
				addr_out_wire = addr[3][12:0];
			else
			if((ins[0] == read_i)&(run[0]))
				addr_out_wire = addr[0][12:0];
			else
			if((ins[1] == read_i)&(run[1]))
				addr_out_wire = addr[1][12:0];
			else
			if((ins[2] == read_i)&(run[2]))
				addr_out_wire = addr[2][12:0];
			else
			if((ins[3] == read_i)&(run[3]))
				addr_out_wire = addr[3][12:0];
			else
			if((ins[0] == pre_charge_i)&(run[0]))
				addr_out_wire = addr[0][12:0];
			else
			if((ins[1] == pre_charge_i)&(run[1]))
				addr_out_wire = addr[1][12:0];
			else
			if((ins[2] == pre_charge_i)&(run[2]))
				addr_out_wire = addr[2][12:0];
			else
			if((ins[3] == pre_charge_i)&(run[3]))
				addr_out_wire = addr[3][12:0];
			*/
		
		////////////////////
		if((ins_r[0][0] == 1)|(ins_r[1][0] == 1)|(ins_r[2][0] == 1)|(ins_r[3][0] == 1))begin//active
			main_s_wire = main_s;
			cas_wire = 1'b1;
			ras_wire = 0;
			if(ins_r[0][0] == 1)begin
				bank_out_wire = 0;
				end else
			if(ins_r[1][0] == 1)begin
				bank_out_wire = 1;
				end else
			if(ins_r[2][0] == 1)begin
				bank_out_wire = 2;
				end else
				bank_out_wire = 3;
			end
		else	
		if((ins_r[0][2] == 1)|(ins_r[1][2] == 1)|(ins_r[2][2] == 1)|(ins_r[3][2] == 1))begin//write
			main_s_wire = main_s;
			ras_wire = 1'b1;
			cas_wire = 0;
			if(ins_r[0][2] == 1)begin
				bank_out_wire = 0;
				end else
			if(ins_r[1][2] == 1)begin
				bank_out_wire = 1;
				end else
			if(ins_r[2][2] == 1)begin
				bank_out_wire = 2;
				end else
				bank_out_wire = 3;
			end
		else
		if((ins_r[0][1] == 1)|(ins_r[1][1] == 1)|(ins_r[2][1] == 1)|(ins_r[3][1] == 1))begin
			main_s_wire = main_s;
			ras_wire = 1'b1;
			cas_wire = 0;
			read_delay_wire = 2'd2;
			if(ins_r[0][1] == 1)begin
				bank_out_wire = 0;
				end else
			if(ins_r[1][1] == 1)begin
				bank_out_wire = 1;
				end else
			if(ins_r[2][1] == 1)begin
				bank_out_wire = 2;
				end else
				bank_out_wire = 3;
			end
		else
		if((ins_r[0][3] == 1)|(ins_r[0][3] == 1)|(ins_r[0][3] == 1)|(ins_r[0][3] == 1))begin
			main_s_wire = main_s;
			ras_wire = 0;
			cas_wire = 1'b1;
			if(ins_r[0][3] == 1)
				bank_out_wire = 0;
				else
			if(ins_r[1][3] == 1)
				bank_out_wire = 1;
				else
			if(ins_r[2][3] == 1)
				bank_out_wire = 2;
				else
				bank_out_wire = 3;
			end
		else begin
			ras_wire = ras;
			cas_wire = cas;
			bank_out_wire = bank_out;
			if(ref_act!=0)
				main_s_wire = refresh;
			else
				main_s_wire = main_s;
			end
		if(run[0]|run[1]|run[2]|run[3])
			cs_wire = 0;
		else
			cs_wire = 1;	
		end
		
		
refresh: begin///////////////////////refresh_part
			cas_wire = 0;
			ras_wire = 0;
			we_wire = 1;
			if(ref_delay == 0)begin
				if(ref_act!=0)begin
					main_s_wire = main_s;
					ref_delay_wire = 9;
					ref_act_wire = ref_act-1'd1;
					cs_wire = 0;
					end
				else begin
					main_s_wire = work;
					ref_delay_wire = ref_delay;
					ref_act_wire = ref_act;
					cs_wire = 1;
					end
				end
			else begin
				main_s_wire = main_s;
				ref_act_wire = ref_act;
				ref_delay_wire = ref_delay-1;
				cs_wire = 1;
				end
			data_out_wire = data_out;
			counter_wire = counter;
			addr_out_wire = addr_out;
			bank_out_wire = bank_out;
			DQ_wire = DQ;
			cke_wire = cke;
			end
			
default: main_s_wire = initial_;
endcase
end

always_ff @(negedge clk_2 or negedge rst)
if(~rst)begin/////////////////reset
	main_s <= initial_;
	counter <= 0;
	cs <= 1;
	ras <= 1;
	cas <= 1;
	we <= 1;
	bank_out <= 0;
	ref_act <= 0;
	ref_delay <= 0;
	read_delay <= 3;
	ref_counter <= 0;
	addr_out <= 0;
	data_out <= 0;
	ready <= 0;
	DQ <= 4'hf;
end else begin////////////end_reset
	main_s <= main_s_wire;
	counter <= counter_wire;
	cs <= cs_wire;
	ras <= ras_wire;
	cas <= cas_wire;
	we <= we_wire;
	bank_out <= bank_out_wire;
	ref_act <= ref_act_wire;
	ref_delay <= ref_delay_wire;
	read_delay <= read_delay_wire;
	ref_counter <= ref_counter_wire;
	addr_out <= addr_out_wire;
	data_out <= data_out_wire;
	ready <= ready_wire;
	DQ <= DQ_wire;
end


////////////////////////////////////////////////////////banks/////////////////////////////////////
initial
for(i = 0; i <= 3; i = i+1)begin
state [i] = idle;
ins [i] = active_i;
delay [i] = 4'd9;
delay_pre [i] = 0;//fix
data[i] = 0;
addr[i] = 0;
r_w[i] = read_con;
busy[i] = 1;
ins_r[i] = 4'h0;
end

wire [8:0] colum = addr_in [8:0];  
wire [12:0] row = addr_in [21:9];
wire [1:0] bank =  addr_in [23:22];


always_ff @(negedge clk or negedge rst)
for(i = 0; i <= 3; i = i+1)begin
	for(j = 0; j <= 3; j = j+1)begin
	k = j;
	if (k == i)
		k = k+1;
	if(k == 4)
		k = 32'd0;
	num[j]=k;
end
if (~rst) begin
state[i] <= idle;
ins[i] <= active_i;
data[i] <= 0;
addr[i] <= 0;
r_w[i] <= read_con;
busy[i] <= 1;
ins_r[i] <= 0;
///////////////delays
delay[i] <= 4'd9;
delay_pre[i] <= 0;
///////////////global
global_act <= 0;
delay_ab[i] <= 0;
run[i] <= 0;
end/////////////////////end reset
else begin


if((read_in|write_in)&(ref_act == 0))//fix fix
	global_act <= 2'd3;
else
	if(global_act!=0)
		global_act <= global_act-1;
	else
		global_act <= global_act;//i don't know why it give error when i delete this line
		
case(state[i])

	idle:begin							//idle
			////////////////////////////////counter_part
			if(delay[i]!=0)
				delay[i] <= delay[i]-1'd1;
			if(delay_pre[i]!=0)
				delay_pre[i] <= 0;
			if(delay_ab[i]!=0)
				delay_ab[i] <= 0;
			////////////////////////////////counters_end
			if (( bank == i ) & ( read_in | write_in ) & ( ref_act == 0 ))begin
				data[i] <= data_w_in;
				addr[i] <= {colum,row};
				r_w[i] <= ~read_in;
				state[i] <= active;
				busy[i] <= 1;
				end
			else begin
				if(ref_act == 0)
					busy[i] <= 0;
				end
			run[i] <= 0;
			end
			
	active:begin						//active
			////////////////////////////////counter_part
			if(delay_pre[i] != 0)
				delay_pre[i] <= 0;
			if(delay_ab[i] != 0)
				delay_ab[i] <= 0;
			////////////////////////////////counters_end
			if((delay[i] == 0)&(global_act == 0))begin
				delay[i] <= 4'd9;
				ins[i] <= active_i;
				ins_r[i] <= 4'b0001;
				run[i] <= 1;
				addr[i][12:0] <= {4'h0,addr[i][21:13]};
				state[i] <= read_write;
				end
			else begin
				run[i] <= 0;
				if(delay[i] != 0)
					delay[i] <= delay[i]-1;
				end
			end
			
	read_write: if (r_w[i] == read_con) begin				//read
			////////////////////////////////counter_part
			if(delay[i] != 0)
				delay[i] <= delay[i]-1'd1;
			if(delay_pre[i]!=0)
				delay_pre[i] <= 0;
			////////////////////////////////counters_end
			if((delay[i] <= 4'd7)&({delay_ab[num[0]],delay_ab[num[1]],delay_ab[num[2]],delay_ab[num[3]]} ==  0))begin
				ins[i] <= read_i;
				ins_r[i] <= 4'b0010;
				state[i] <= precharge;
				delay_ab[i] <= 1'b1;
				run[i] <= 1;
				end
			else begin
				run[i] <= 0;
				delay_ab[i] <= 0;
				end
			end
			
		else begin											//write
			////////////////////////////////counter_part
			if(delay[i]!=0)
				delay[i] <= delay[i]-1'd1;
			////////////////////////////////counters_end
			if((delay[i] <= 4'd7)&({delay_ab[num[0]],delay_ab[num[1]],delay_ab[num[2]],delay_ab[num[3]]} ==  0)&(read_delay!=1))begin
				ins[i] <= write_i;
				ins_r[i] <= 4'b0100;
				state[i] <= precharge;
				delay_pre[i] <= 1'b1;
				delay_ab[i] <= 1'b1;
				run[i] <= 1;
				end
			else begin
					run[i] <= 0;
					delay_pre[i] <= 0;
					delay_ab[i] <= 0;
				end
			end
			
	precharge:begin					//pre_charge
			////////////////////////////////counter_part
			delay_pre[i] <= 0;
			delay_ab[i] <= 0;
			////////////////////////////////counters_end
			run[i] <= 0;
			if((delay[i] <= 2)&(~delay_pre[i]))begin
				ins[i] <= pre_charge_i;
				ins_r[i] <= 4'b1000;
				delay[i] <= 4'd2;
				state[i] <= idle;
				run[i] <= 1;
				end
			else begin
				run[i] <= 0;
				if(delay[i]!=0)
					delay[i] <= delay[i]-1'd1;
				end
			end
	default:state[i] <= idle;

endcase

end end


endmodule

the problem in data_out register at line 189 the fitter have two option to do that 

first is to use 7 input alm to read 3 ins_r register and four data register.

second is use 5 input with help of multiplexer at input of data_out register.

the second option is better and this what fitter choose but for some reason the fitter use another alm to making the multiplexer which lead to bigger delay and timing failaure 

Iam using io reg so iam sure the multiplexer is free to use 

Thanks in advance and sorry for any error in typing 

 

 

0 Kudos
4 Replies
sstrell
Honored Contributor III
347 Views

Any reason why you are not using the included EMIF IP instead of trying to reinvent the wheel?

0 Kudos
AdzimZM_Intel
Employee
328 Views

Hi omar_ibrahim,


Thank you for using Intel Community.


I'm not familiar with your module and not much I can help you here unless you're using Intel EMIF IP.

I can provide the Example Design for the EMIF IP later.


Regards,

Adzim


0 Kudos
AdzimZM_Intel
Employee
309 Views

I'm attaching the example design for the EMIF IP.

The design should be a good reference to you.

 

0 Kudos
AdzimZM_Intel
Employee
253 Views

We do not receive any response from you to the previous reply that I have provided. This thread will be transitioned to community support. If you have a new question, feel free to open a new thread to get the support from Intel experts. Otherwise, the community users will continue to help you on this thread. Thank you.


0 Kudos
Reply