- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Any reason why you are not using the included EMIF IP instead of trying to reinvent the wheel?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page