module dram(clk,
addr,
data_to_dram,
BS,
RAS_L,
CAS_L,
WE_L,
CKE,
CSA_L,
CSB_L,
CSC_L,
CSD_L);
input clk,RAS_L,CAS_L,WE_L,CKE,CSA_L,CSB_L,CSC_L,CSD_L,BS;
input [10:0] addr;
inout [31:0] data_to_dram;
wire bank_act_cmd,read_cmd,write_cmd,precharge_cmd,register_mode_cmd;
reg refresh_entry_cmd,refresh_exit_cmd ,power_down_entry_cmd,power_down_exit_cmd,burst_stop_cmd,nop;
reg del_read_cmd;
reg [15:0] data0,data1;
reg [4093:0] temp1,temp0,temp_0,temp_1;
reg [4093:0] lsb0,lsb,msb0;
reg [10:0] row_addr;
reg [7:0] col_addr;
reg [7:0] col_addr_temp;
reg [31:0] data_fifo [256:0];
reg [31:0] data_to_proc;
reg [8:0] burst_length;
reg [1:0] cas_latency;
reg [8:0] i;
reg burst_read_write;
reg burst_signal;
integer r,k;
wire [31:0] data_to_dram;
wire [31:0] data_in;
//Time delays
`define tcac = 24
// memory blocks
reg [4093:0] A1_mem_bank0 [2047:0];
reg [4093:0] A1_mem_bank1 [2047:0];
reg [4093:0] A2_mem_bank0 [2047:0];
reg [4093:0] A2_mem_bank1 [2047:0];
reg [4093:0] B1_mem_bank0 [2047:0];
reg [4093:0] B1_mem_bank1 [2047:0];
reg [4093:0] B2_mem_bank0 [2047:0];
reg [4093:0] B2_mem_bank1 [2047:0];
reg [4093:0] C1_mem_bank0 [2047:0];
reg [4093:0] C1_mem_bank1 [2047:0];
reg [4093:0] C2_mem_bank0 [2047:0];
reg [4093:0] C2_mem_bank1 [2047:0];
reg [4093:0] D1_mem_bank0 [2047:0];
reg [4093:0] D1_mem_bank1 [2047:0];
reg [4093:0] D2_mem_bank0 [2047:0];
reg [4093:0] D2_mem_bank1 [2047:0];
//initializing the memory chips
initial begin
for (r=0;r<2048;r=r+1) begin
A1_mem_bank0 [r] = 4094'b0;
A1_mem_bank1 [r] = 4094'b0;
A2_mem_bank0 [r] = 4094'b0;
A2_mem_bank1 [r] = 4094'b0;
B1_mem_bank0 [r] = 4094'b0;
B1_mem_bank1 [r] = 4094'b0;
B2_mem_bank0 [r] = 4094'b0;
B2_mem_bank1 [r] = 4094'b0;
C1_mem_bank0 [r] = 4094'b0;
C1_mem_bank1 [r] = 4094'b0;
C2_mem_bank0 [r] = 4094'b0;
C2_mem_bank1 [r] = 4094'b0;
D1_mem_bank0 [r] = 4094'b0;
D1_mem_bank1 [r] = 4094'b0;
D2_mem_bank0 [r] = 4094'b0;
D2_mem_bank1 [r] = 4094'b0;
//$display(" initialized value A1_mem_bank0 [ %h
] = %h",r,A1_mem_bank0 [r]);
//$display(" initialized value A2_mem_bank0 [ %h
] = %h",r,A2_mem_bank0 [r]);
end
end
//Address decoder
always @(posedge bank_act_cmd) begin
row_addr = addr;
if (~CSA_L ) $display("ACTIVATING BANK => %d
OF CHIP A1 and A2", BS);
else if (~CSB_L ) $display("ACTIVATING BANK =>
%d OF CHIP B1 and B2", BS);
else if (~CSC_L ) $display("ACTIVATING BANK =>
%d OF CHIP C1 and C2", BS);
else if (~CSD_L ) $display("ACTIVATING BANK =>
%d OF CHIP D1 and D2", BS);
end
//Display precharge
always @(posedge precharge_cmd) begin
if (~CSA_L ) $display("PRECHARGING BANK => %d
OF CHIP A1 and A2", BS);
else if (~CSB_L ) $display("PRECHARGING BANK =>
%d OF CHIP B1 and B2", BS);
else if (~CSC_L ) $display("PRECHARGING BANK =>
%d OF CHIP C1 and C2", BS);
else if (~CSD_L ) $display("PRECHARGING BANK =>
%d OF CHIP D1 and D2", BS);
end
//Display Mode register value
always @(posedge register_mode_cmd) begin
$display("MODE REGISTER VALUE = %b",addr );
end
//Display Read operation
always @(posedge read_cmd) begin
$display("READ OPERATION IS GOING ON........");
end
//Display Write operation
always @(posedge write_cmd) begin
$display("WRITE OPERATION IS GOING ON........");
end
always @(posedge read_cmd or posedge write_cmd)
col_addr = addr[7:0];
//Data fetch
always @(posedge read_cmd) begin
#0
col_addr_temp=col_addr;
for (i=1 ; i<=burst_length ;i=i+1) begin
lsb = col_addr_temp * 16;
$display("lsb for read = %d ",lsb);
data0[15:0] = bit_extractor(temp0,lsb);
data1[15:0] = bit_extractor(temp1,lsb);
data_fifo[i] = {data1,data0};
$display (" data_fifo [ %d ] = %h",i,data_fifo[i]);
col_addr_temp = col_addr_temp + 1;
end
end
function [15:0] bit_extractor;
input [4093:0] data;
input [4093:0] lsb;
reg [4093:0] temp;
integer j;
begin
temp = data;
for(j=0;j<lsb;j=j+1) begin
temp = {temp[0],temp[4093:1]};
end
bit_extractor = temp[15:0];
$display("output of the bit extractor for read =
%h",temp);
end
endfunction
always @(posedge write_cmd) begin
#0
lsb0 = col_addr * 16;
msb0 = lsb0 + 15;
$display("lsb0 = %d and msb0 = %d for write ",lsb0,msb0);
$display("temp_0 for write = %h",temp_0);
#2
temp_0 = bit_insert_write(data_in[15:0],lsb0,msb0,temp_0[4093:0]);
$display("temp_0 after write = %h",temp_0);
$display("temp_1 for write = %h",temp_1);
temp_1 = bit_insert_write(data_in[31:16],lsb0,msb0,temp_1[4093:0]);
$display("temp_1 after write = %h",temp_1);
end
function [4093:0] bit_insert_write;
input [15:0] data;
input [4093:0] lsb;
input [4093:0] msb;
input [4093:0] datain; //It will take the register value
from temp_0 or temp_1
reg [4093:0] outdata;
integer j;
begin
outdata = datain;
for(j=lsb;j<=msb;j=j+1) begin
outdata [j] = data [j-lsb];
$display(" outdata [%d] = %h ",j,outdata[j]);
end
bit_insert_write = outdata;
end
endfunction
//data assignment to the processor when read
initial data_to_proc=32'b0;
always @(posedge clk) begin
if (read_cmd) begin
if (cas_latency == 1) begin
for(i=1;i <= burst_length;i=i+1) begin
if (nop)
data_to_proc = data_to_proc ;
else
data_to_proc = data_fifo [i];
@(posedge clk);
$display (" data_to_proc inside = %h",data_to_proc);
end
end
else if (cas_latency == 2) begin
for(i=1;i <= burst_length;i=i+1) begin
@(posedge clk);
if (nop)
data_to_proc = data_to_proc ;
else
data_to_proc = data_fifo [i];
end
end
else if (cas_latency == 3) begin
@(posedge clk);
for(i=1;i <= burst_length;i=i+1) begin
@(posedge clk);
if (nop)
data_to_proc = data_to_proc ;
else
data_to_proc = data_fifo [i];
end
end
else
data_to_proc = 32'hZZZZ_ZZZZ;
end
end
//tristate bus
assign data_to_dram = ((del_read_cmd) &&
(!burst_signal))? data_to_proc : 32'hZZZZ_ZZZZ;
initial del_read_cmd=0;
always @(posedge read_cmd) begin
if (cas_latency == 1) begin
@(posedge clk);
for (k=0;k<burst_length;k=k+1) begin
del_read_cmd = 1;
@(posedge clk);
end
del_read_cmd=0;
end
else if (cas_latency == 2) begin
@(posedge clk);
@(posedge clk);
for (k=0;k<burst_length;k=k+1) begin
del_read_cmd = 1;
@(posedge clk);
end
del_read_cmd=0;
end
else if (cas_latency == 3) begin
@(posedge clk);
@(posedge clk);
@(posedge clk);
for (k=0;k<burst_length;k=k+1) begin
del_read_cmd = 1;
@(posedge clk);
end
del_read_cmd=0;
end
else del_read_cmd=0;
end
//for burst stop
initial burst_signal=0;
always @(posedge burst_stop_cmd) begin
@(posedge clk);
if (burst_length == 6) begin
if (cas_latency == 1)
burst_signal=1;
else if(cas_latency == 2) begin
@(posedge clk);
burst_signal=1;
end
else if(cas_latency == 3) begin
@(posedge clk);
@(posedge clk);
burst_signal=1;
end
else
burst_signal= burst_signal;
end
end
assign data_in = data_to_dram;
//Command decoder
assign bank_act_cmd = (RAS_L == 1'b0 && CAS_L
== 1'b1 && WE_L == 1'b1 && ( ~CSA_L || ~CSB_L || ~CSC_L
|| ~CSD_L) );
assign read_cmd = (RAS_L == 1'b1 && CAS_L ==
1'b0 && WE_L == 1'b1 && addr[10] == 1'b0 && ( ~CSA_L
|| ~CSB_L || ~CSC_L || ~CSD_L));
assign write_cmd = (RAS_L == 1'b1 && CAS_L ==
1'b0 && WE_L == 1'b0 && addr[10] == 1'b0 && ( ~CSA_L
|| ~CSB_L || ~CSC_L || ~CSD_L));
assign precharge_cmd = (RAS_L == 1'b0 && CAS_L
== 1'b1 && WE_L == 1'b0 && addr[10] == 1'b0 &&
( ~CSA_L || ~CSB_L || ~CSC_L || ~CSD_L));
assign register_mode_cmd = (RAS_L == 1'b0 &&
CAS_L == 1'b0 && WE_L == 1'b0 && ( ~CSA_L || ~CSB_L ||
~CSC_L || ~CSD_L));
//assign burst_stop_cmd = (RAS_L == 1'b1 && CAS_L
== 1'b1 && WE_L == 1'b0 && CKE == 1'b0 && ( ~CSA_L
|| ~CSB_L || ~CSC_L || ~CSD_L));
//assign refresh_entry_cmd = (RAS_L == 1'b0 &&
CAS_L == 1'b0 && WE_L == 1'b1 && CKE == 1'b0 &&
( ~CSA_L || ~CSB_L || ~CSC_L || ~CSD_L));
//assign refresh_exit_cmd = (RAS_L == 1'b1 &&
CAS_L == 1'b1 && CKE == 1'b1 && ( ~CSA_L || ~CSB_L || ~CSC_L
|| ~CSD_L)) ;
//assign nop = (RAS_L == 1'b1 && CAS_L == 1'b1
&& WE_L == 1'b1 && CKE == 1'b0 && ( ~CSA_L || ~CSB_L
|| ~CSC_L || ~CSD_L)) ;
//assign power_down_entry_cmd = (RAS_L == 1'b1 &&
CAS_L == 1'b1 && CKE == 1'b0 && ( ~CSA_L || ~CSB_L || ~CSC_L
|| ~CSD_L)) ;
//assign power_down_exit_cmd = (RAS_L == 1'b1 &&
CAS_L == 1'b1 && CKE == 1'b1 && ( ~CSA_L || ~CSB_L || ~CSC_L
|| ~CSD_L));
// asserting power down entry cmd
always begin
#0 power_down_entry_cmd = 0;
@(negedge CKE) ;
repeat (2) @(negedge clk);
if (RAS_L == 1'b1 && CAS_L == 1'b1 &&
( ~CSA_L || ~CSB_L || ~CSC_L || ~CSD_L)) begin
power_down_entry_cmd = 1;
#10
power_down_entry_cmd = 0;
end
else
power_down_entry_cmd = 0;
end
// asserting power down exit cmd
always begin
#0 power_down_exit_cmd = 0;
@(posedge CKE) ;
@(negedge clk) ;
if (RAS_L == 1'b1 && CAS_L == 1'b1 &&
WE_L == 1'b0 && ( ~CSA_L || ~CSB_L || ~CSC_L || ~CSD_L)) begin
power_down_exit_cmd = 1;
#10
power_down_exit_cmd = 0;
end
else
power_down_exit_cmd = 0;
end
// asserting self refresh entry cmd
always begin
#0 refresh_entry_cmd = 0;
@(negedge CKE) ;
repeat (2) @(negedge clk);
if (RAS_L == 1'b0 && CAS_L == 1'b0 &&
WE_L == 1'b1 && ( ~CSA_L || ~CSB_L || ~CSC_L || ~CSD_L)) begin
refresh_entry_cmd = 1;
#10
refresh_entry_cmd = 0;
end
else
refresh_entry_cmd = 0;
end
// asserting self refresh exit cmd
always begin
#0 refresh_exit_cmd = 0;
@(posedge CKE) ;
repeat (2) @(negedge clk);
if (RAS_L == 1'b1 && CAS_L == 1'b1 &&
WE_L == 1'b1 && ( ~CSA_L || ~CSB_L || ~CSC_L || ~CSD_L)) begin
refresh_exit_cmd = 1;
#10
refresh_exit_cmd = 0;
end
else
refresh_exit_cmd = 0;
end
//asserting burst stop cmd
always begin
#0 burst_stop_cmd = 0;
@(posedge clk);
if(CKE && ~power_down_exit_cmd) begin
if(RAS_L == 1'b1 && CAS_L == 1'b1 &&
WE_L == 1'b0 && ( ~CSA_L || ~CSB_L || ~CSC_L || ~CSD_L)) begin
burst_stop_cmd = 1;
#10
burst_stop_cmd = 0;
end
else
burst_stop_cmd = 0;
end
end
// asserting nop cmd
always begin
#0 nop = 0;
@(posedge clk);
if( CKE && ~refresh_exit_cmd) begin
if(RAS_L == 1'b1 && CAS_L == 1'b1 &&
WE_L == 1'b1 && ( ~CSA_L || ~CSB_L || ~CSC_L || ~CSD_L)) begin
nop = 1;
#10
nop = 0;
end
else
nop = 0;
end
end
//Mode register_set command
always @(posedge register_mode_cmd) begin
if (addr [2:0] == 3'b000)
burst_length = 1;
else if (addr [2:0] == 3'b001)
burst_length = 2;
else if (addr [2:0] == 3'b010)
burst_length = 4;
else if (addr [2:0] == 3'b011)
burst_length = 8;
else if (addr [2:0] == 3'b111)
burst_length = 6;
else begin
burst_length = 0;
end
//Burst read and burst write mode checking
if (addr[9] == 0)
burst_read_write = 1;
else
burst_read_write = 0;
//CAS latency checking
if (addr[6:4] == 3'b001)
cas_latency = 1;
else if (addr[6:4] == 3'b010)
cas_latency = 2;
else if (addr[6:4] == 3'b011)
cas_latency = 3;
else
cas_latency = 0;
end // end of the register mode command
//Chip selector
always @(posedge bank_act_cmd) begin
#0
if (CSA_L == 1'b0) begin
if (BS == 1'b0) begin
temp0 = A1_mem_bank0[row_addr] ;
temp1 = A2_mem_bank0[row_addr] ;
end
else begin
temp0 = A1_mem_bank1[row_addr] ;
temp1 = A2_mem_bank1[row_addr] ;
end
end
else if (CSB_L == 1'b0) begin
if (BS == 1'b0) begin
temp0 = B1_mem_bank0[row_addr] ;
temp1 = B2_mem_bank0[row_addr] ;
end
else begin
temp0 = B1_mem_bank1[row_addr] ;
temp1 = B2_mem_bank1[row_addr] ;
end
end
else if (CSC_L == 1'b0) begin
if (BS == 1'b0) begin
temp0 = C1_mem_bank0[row_addr] ;
temp1 = C2_mem_bank0[row_addr] ;
end
else begin
temp0 = C1_mem_bank1[row_addr] ;
temp1 = C2_mem_bank1[row_addr] ;
end
end
else if (CSD_L == 1'b0) begin
if (BS == 1'b0) begin
temp0 = D1_mem_bank0[row_addr] ;
temp1 = D2_mem_bank0[row_addr];
end
else begin
temp0 = D1_mem_bank1[row_addr] ;
temp1 = D2_mem_bank1[row_addr] ;
end
end
temp_0 = temp0;
temp_1 = temp1;
$display(" temp0 = %h and temp1 = %h for read and
write",temp0,temp1);
end
always @(posedge clk) begin
if (write_cmd) begin
if (CSA_L == 1'b0) begin
if (BS == 1'b0) begin
A1_mem_bank0 [row_addr] = temp_0;
$display(" the memory location writen is A1_mem_bank0
[%h] = %h",row_addr,A1_mem_bank0 [row_addr]);
A2_mem_bank0 [row_addr]= temp_1;
$display(" the memory location writen is A2_mem_bank0
[%h] = %h",row_addr,A2_mem_bank0 [row_addr]);
end
else begin
A1_mem_bank1 [row_addr]=temp_0;
A2_mem_bank1 [row_addr]=temp_1;
end
end
else if (CSB_L == 1'b0) begin
if (BS == 1'b0) begin
B1_mem_bank0 [row_addr]=temp_0;
B2_mem_bank0 [row_addr]=temp_1;
end
else begin
B1_mem_bank1 [row_addr]=temp_0;
B2_mem_bank1 [row_addr]=temp_1;
end
end
else if (CSC_L == 1'b0) begin
if (BS == 1'b0) begin
C1_mem_bank0 [row_addr]=temp_0;
C2_mem_bank0 [row_addr]=temp_1;
end
else begin
C1_mem_bank1 [row_addr]=temp_0;
C2_mem_bank1 [row_addr]=temp_1;
end
end
else if (CSD_L == 1'b0) begin
if (BS == 1'b0) begin
D1_mem_bank0 [row_addr]=temp_0;
D2_mem_bank0 [row_addr]=temp_1;
end
else begin
D1_mem_bank1 [row_addr]=temp_0;
D2_mem_bank1 [row_addr]=temp_1;
end
end
end
end
always begin
@(posedge power_down_entry_cmd) ;
$display (" ENTERING POWER DOWN MODE ");
$display (" WAITING FOR POWER DOWN EXIT ");
@(posedge power_down_exit_cmd) ;
$display (" EXITING POWER DOWN MODE ");
end
always begin
@(posedge refresh_entry_cmd) ;
$display (" ENTERING SELF REFRESH MODE ");
$display (" WAITING FOR SELF REFRESH EXIT ");
@(posedge refresh_exit_cmd) ;
$display (" EXITING SELF REFRESH MODE ");
end
endmodule