begin
$display("Error: DRAM at %t rast_l violates tWRP (Write enable setup time)!!", $stime);
end
end
if(~cas_has_been_asserted & we_l)
begin
if((rast_low_cycle - cas_low_cycle) < (`tCRP * ticks_per_ns))
begin
$display("Error: DRAM at %t rast_l violates tCRP (CAS to RAS precharge time)!!", $stime);
end
end
if(first_time_rast_asserted & ~tRP_chkd)
begin
tRP = (rast_low_cycle - rast_high_cycle);
tRP_chkd = 1'b1;
if((rast_low_cycle - rast_high_cycle) < (`tRP * ticks_per_ns))
begin
$display("Error: DRAM at %t rast_l violates tRP(ras precharge time", $stime);
end
end
//********************************************************************************
// For CBR refresh check tCSR
//********************************************************************************
if(cas_has_been_asserted & we_l & (type_op === 3'b100))
begin
if((rast_low_cycle - cas_low_cycle) < (`tCSR * ticks_per_ns))
begin
$display("Error: DRAM at %t tCSR(cas setup time(w.r.t rast_l), CBR refresh) violated", $stime);
end
end
//********************************************************************************
// For single read/write check tRC
//********************************************************************************
if(first_time_rast_asserted & (prev_num_of_cas_cyc === 1'b1)) begin
if ((tRAS > `tRAS_MIN * ticks_per_ns) & (tRP > `tRP * ticks_per_ns))
begin
if((tRAS + tRP) < (`tRC * ticks_per_ns))
begin
$display("Error: DRAM at %t tRC(random read or write cycle time, rast_l) violated", $stime);
end
end
end
ras_init <= #1 1'b1;
end
//##################################################################################################################
// record posedge of rast_l and perform all checks and events that should happen @ posedge of rast_l
//##################################################################################################################
always @(posedge rast_l)
begin
rast_high_cycle = $stime;
if(type_op !== 3'b010)
begin
data_turn_off = 1'b0;
end
else
begin
data_turn_off = 1'b1; // for tREZ monitor
end
first_cas_low_after_ras_low = 1'b0;
rast_has_been_asserted = 1'b0;
tRP_chkd = 1'b0;
//********************************************************************************
// For turning of read data and parity with respect of posedge of rast_l
//********************************************************************************
if((type_op === 3'b010)) // read operation and data is not equal to Z
begin
data_valid <= #((ticks_per_ns * `tREZ_MIN)) 1'b0;
rd_data <= #((ticks_per_ns * `tREZ_MIN)) 64'bx;
rd_parity <= #((ticks_per_ns * `tREZ_MIN)) 64'bx;
end
//********************************************************************************
// For paged mode read/write check tRSH and tRASP
//********************************************************************************
if(first_time_rast_asserted & (num_of_cas_cyc !== 1'b1))
begin
if((rast_high_cycle - rast_low_cycle) < (`tRASP_MIN * ticks_per_ns))
begin
$display("Error: DRAM at %t rast_l violates min tRASP(ras pulse width)", $stime);
end
if((rast_high_cycle - rast_low_cycle) > (`tRASP_MAX * ticks_per_ns))
begin
$display("Error: DRAM at %t rast_l excedes max tRASP(ras pulse width)", $stime);
end
if((rast_high_cycle - cas_low_cycle) < (`tRSH * ticks_per_ns))
begin
$display("Error: DRAM at %t rast_l violates tRSH(ras hold time)", $stime);
end
end
if(first_time_rast_asserted & (num_of_cas_cyc !== 1'b1) & (type_op != 3'b100))
begin
if((rast_high_cycle - cas_prev_high_cycle) < (`tRHCP * ticks_per_ns))
begin
$display("Error: DRAM at %t tRHCP (RAS hold time from CAS precharge) violated", $stime);
end
end
//********************************************************************************
// For single cycle read/write check tRSH and tRAS
//********************************************************************************
if(first_time_rast_asserted & ((num_of_cas_cyc === 1'b1) | (type_op == 3'b100)))
begin
tRAS = (rast_high_cycle - rast_low_cycle);
if((rast_high_cycle - rast_low_cycle) < (`tRAS_MIN * ticks_per_ns))
begin
$display("Error: DRAM at %t rast_l violates min tRAS(ras pulse width)", $stime);
end
if((rast_high_cycle - rast_low_cycle) > (`tRAS_MAX * ticks_per_ns))
begin
$display("Error: DRAM at %t rast_l exceedes max tRAS(ras pulse width)", $stime);
end
end
if(first_time_rast_asserted & (num_of_cas_cyc === 1'b1)) begin
if((rast_high_cycle - cas_low_cycle) < (`tRSH * ticks_per_ns))
begin
$display("Error: DRAM at %t rast_l violates tRSH(ras hold time)", $stime);
end
end
//********************************************************************************
// For write only check tRWL
//********************************************************************************
if((we_l == 1'bx) & first_time_rast_asserted)
begin
if(((rast_high_cycle - we_low_cycle) < (`tRWL * ticks_per_ns)) && ((rast_high_cycle - we_low_cycle) != 0))
begin
$display("Error: DRAM at %t tRWL(write command to RAS(rast_l) lead time) violated", $stime);
$display("rast_high_cycle %g - we_low_cycle %g = %g ", rast_high_cycle, we_low_cycle, (rast_high_cycle - we_low_cycle));
$display("(`tRWL * ticks_per_ns) = %g ", (`tRWL * ticks_per_ns));
end
end
//********************************************************************************
// For write only check tRAL
//********************************************************************************
if(rast_has_been_asserted & cas_has_been_asserted & first_time_rast_asserted)
begin
if((rast_high_cycle - address_active_cycle) < (`tRAL * ticks_per_ns))
begin
$display("Error: DRAM at %t tRAL(Column address to RAS(rast_l) lead time) violated", $stime);
end
end
end
//********************************************************************************
// For read and write check tRAC max and min, check tCAC, tAA, tCPA
//********************************************************************************
always @(posedge data_valid)
begin
if(we_l & rasb_has_been_asserted & first_time_rasb_asserted & (type_op == 3'b010))
begin
if((data_change_cycle - cas_low_cycle) < (`tCAC * ticks_per_ns))
begin
$display("Error: DRAM at %t tCAC (first_access time from CAS) violated!!", $stime);
end
if((data_change_cycle - address_prev_active_cycle) < (`tAA * ticks_per_ns))
begin
$display("Warning: DRAM at %t tAA (first_access time from column address) violated!!", $stime);
end
if(((data_change_cycle - cas_prev_high_cycle) < (`tCPA * ticks_per_ns)) & ~first_access & tRAC_chkd)
begin
$display("Error: DRAM at %t tCPA (first_access time from CAS precharge) violated!!", $stime);
end
end
if(we_l & rast_has_been_asserted & first_time_rast_asserted & (type_op == 3'b010))
begin
if((data_change_cycle - cas_low_cycle) < (`tCAC * ticks_per_ns))
begin
$display("Error: DRAM at %t tCAC (first_access time from CAS) violated!!", $stime);
end
if((data_change_cycle - address_prev_active_cycle) < (`tAA * ticks_per_ns))
begin
$display("Warning: DRAM at %t tAA (first_access time from column address) violated!!", $stime);
end
if(((data_change_cycle - cas_prev_high_cycle) < (`tCPA * ticks_per_ns)) & ~first_access & tRAC_chkd)
begin
$display("Error: DRAM at %t tCPA (first_access time from CAS precharge) violated!!", $stime);
end
end
if(rasb_has_been_asserted & we_l & first_time_rasb_asserted & (type_op == 3'b010) & ~tRAC_chkd)
begin
// and data[143:0]
tRAC_chkd = 1'b1;
if((data_change_cycle - rasb_low_cycle) < (`tRAC * ticks_per_ns))
begin
$display("Error: DRAM at %t tRAC (first_access time from RAS(rasb_l)) violated!!", $stime);
end
end
if(rast_has_been_asserted & we_l & first_time_rast_asserted & (type_op == 3'b010) & ~tRAC_chkd)
begin
tRAC_chkd = 1'b1;
if((data_change_cycle - rast_low_cycle) < (`tRAC * ticks_per_ns))
begin
$display("Error: DRAM at %t tRAC (first_access time from RAS(rast_l)) violated!!", $stime);
end
end
end
//##################################################################################################################
// record whenever data changes and perform all checks and events related to the data change
//##################################################################################################################
always @(rd_data)
begin
data_change_cycle = $stime; // record time whenever data changes
//********************************************************************************
// For read only check tDOH
//********************************************************************************
if((rd_data === 64'bz) & cas_has_been_asserted & we_l & rasb_has_been_asserted & first_time_rasb_asserted)
begin
if((data_change_cycle - cas_low_cycle) < (`tDOH * ticks_per_ns))
begin
// $display("Error: DRAM at %t tDOH (data output hold after CAS going low) violated!!", $stime);
end
end
if((rd_data === 64'bz) & cas_has_been_asserted & we_l & rast_has_been_asserted & first_time_rast_asserted)
begin
if((data_change_cycle - cas_low_cycle) < (`tDOH * ticks_per_ns))
begin
// $display("Error: DRAM at %t tDOH (data output hold after CAS going low) violated!!", $stime);
end
end
//********************************************************************************
// For write only check tDH(data hold time)
//********************************************************************************
if((rasb_has_been_asserted | rast_has_been_asserted) & (type_op == 3'b001) &
(first_time_rasb_asserted | first_time_rast_asserted) & ~we_l & (data_out !== 64'bz))
begin
if((data_change_cycle - cas_low_cycle) < (`tDH * ticks_per_ns))
begin
$display("Error: DRAM at %t tDH(data-in hold time w.r.t rasb_l) violated", $stime);
end
end
// For the last piece of data on a read
if((rasb_has_been_asserted | rast_has_been_asserted) & (type_op == 3'b001) &
(first_time_rasb_asserted | first_time_rast_asserted) & ~we_l & (data_out === 64'bz))
begin
if((data_change_cycle - cas_low_cycle) < (`tDH * ticks_per_ns))
begin
$display("Error: DRAM at %t tDH(data-in hold time w.r.t rasb_l) violated", $stime);
end
end
//********************************************************************************
// For read check tREZ_max and tREZ_min
// For single reads check tCEZ_min and tCEZ_max
//********************************************************************************
if(type_op === 3'b010) begin
// tCEZ monitors not required,because RAS turns off after CAS tREZ is the
// data turn off parameter.
/*
if(~rasb_has_been_asserted & ~rast_has_been_asserted & first_time_rasb_asserted
& (whichRASprevAsserted == 2'b01) & (num_of_cas_cyc == 1'b1))
begin
if((data_change_cycle - cas_high_cycle) < (`tCEZ_MIN * ticks_per_ns))
begin
$display (" Error: DRAM at %t tCEZ_MIN(output buffer turn off w.r.t cas_l) violated", $stime);
end
end
*/
if(~rast_has_been_asserted & ~rasb_has_been_asserted & first_time_rast_asserted & (whichRASprevAsserted == 2'b10))
begin
if((data_change_cycle - rast_high_cycle) < (`tREZ_MIN * ticks_per_ns))
begin
// $display(" Error: DRAM at %t tREZ_MIN(output buffer turn off delay w.r.t rast_l) violated", $stime);
end
end
if(~rast_has_been_asserted & ~rasb_has_been_asserted & first_time_rasb_asserted & (whichRASprevAsserted == 2'b01))
begin
if((data_change_cycle - rasb_high_cycle) < (`tREZ_MIN * ticks_per_ns))
begin
// $display(" Error: DRAM at %t tREZ_MIN(output buffer turn off delay w.r.t rasb_l) violated", $stime);
end
end
if(~rasb_has_been_asserted & ~rast_has_been_asserted & first_time_rasb_asserted & (whichRASprevAsserted == 2'b01))
begin
if((data_change_cycle - rasb_high_cycle) > (`tREZ_MAX * ticks_per_ns))
begin
$display(" Error: DRAM at %t tREZ_MAX(output buffer turn off delay w.r.t rasb_l) violated", $stime);
end
end
// tCEZ monitors not required,because RAS turns off after CAS tREZ is the
// data turn off parameter.
/*
if(~rasb_has_been_asserted & ~rast_has_been_asserted & first_time_rasb_asserted & (whichRASprevAsserted ==2'b01) &
(num_of_cas_cyc == 1'b1)) begin
if((data_change_cycle - cas_high_cycle) > (`tCEZ_MAX * ticks_per_ns))
begin
$display(" Error: DRAM at %t tCEZ_MAX(output buffer turn off w.r.t cas_l) violated", $stime);
end
end
*/
if(~rast_has_been_asserted & ~rasb_has_been_asserted & first_time_rast_asserted & (whichRASprevAsserted == 2'b10))
begin
if((data_change_cycle - rast_high_cycle) > (`tREZ_MAX * ticks_per_ns))
begin
$display(" Error: DRAM at %t tREZ_MAX(output buffer turn off delay w.r.t rast_l) violated", $stime);
end
end
data_turn_off = 1'b0;
end
end
//##################################################################################################################
// record posedge of we_l and perform all checks and events related to posedge of we_l
//##################################################################################################################
always @(posedge we_l)
begin
we_high_cycle = $stime; // posedge of we_l
//********************************************************************************
// tWCH, tWRH, tRCH
//********************************************************************************
if(rasb_has_been_asserted | rast_has_been_asserted) begin
if((we_high_cycle - cas_low_cycle) < (`tWCH * ticks_per_ns))
begin
$display("Error: DRAM at %t tWCH(write command hold time) violated", $stime);
end
end
if(rasb_has_been_asserted) begin
twrh_chk = 1'b1;
if((we_high_cycle - rasb_low_cycle) < (`tWRH * ticks_per_ns))
begin
$display("Error: DRAM at %t rasb_l violates tWRH (Write Enable hold time)!!", $stime);
end
end
if(rast_has_been_asserted) begin
twrh_chk = 1'b1;
if((we_high_cycle - rast_low_cycle) < (`tWRH * ticks_per_ns))
begin
$display("Error: DRAM at %t rasb_l violates tWRH (Write Enable hold time)!!", $stime);
end
end
if((~rasb_has_been_asserted | ~rast_has_been_asserted) & ~cas_has_been_asserted &
first_time_rasb_asserted & (type_op === 3'b010))
begin
if((we_high_cycle - cas_high_cycle) < (`tRCH * ticks_per_ns)) begin
$display("Error: DRAM at %t tRCH violated", $stime);
$display("we_high_cycle %g - cas_high_cycle %g = %g ", we_high_cycle, cas_high_cycle, (we_high_cycle - cas_high_cycle));
$display("(`tRCH * ticks_per_ns) = %g ", (`tRCH * ticks_per_ns));
end
end
//********************************************************************************
// tWP
//********************************************************************************
if(rasb_has_been_asserted | rast_has_been_asserted) begin
if((we_high_cycle - we_low_cycle) < (`tWP * ticks_per_ns))
begin
$display("Error: DRAM at %t tWP(WE pulse width) violated", $stime);
$display("diff is = %g at %t",(we_high_cycle - we_low_cycle), $stime);
end
end
end
//##################################################################################################################
// record negedge of we_l and perform all checks and events related to negedge of we_l
//##################################################################################################################
always @(negedge we_l)
begin
we_low_cycle = $stime; // negedge of we_l
//********************************************************************************
// tWCH, tWRH, tRCH
//*******************************************************************************
if(rasb_has_been_asserted | rast_has_been_asserted) begin
if((we_low_cycle - cas_low_cycle) < (`tWCH * ticks_per_ns))
begin
$display("Error: DRAM at %t tWCH(write command hold time) violated", $stime);
end
end
if(rasb_has_been_asserted) begin
twrh_chk = 1'b1;
if((we_low_cycle - rasb_low_cycle) < (`tWRH * ticks_per_ns))
begin
$display("Error: DRAM at %t rasb_l violates tWRH (Write Enable hold time)!!", $stime);
end
end
if(rast_has_been_asserted) begin
twrh_chk = 1'b1;
if((we_low_cycle - rast_low_cycle) < (`tWRH * ticks_per_ns))
begin
$display("Error: DRAM at %t rasb_l violates tWRH (Write Enable hold time)!!", $stime);
end
end
if((~rasb_has_been_asserted | ~rast_has_been_asserted) & ~cas_has_been_asserted &
first_time_rasb_asserted & (type_op === 3'b010))
begin
if((we_low_cycle - cas_high_cycle) < (`tRCH * ticks_per_ns)) begin
$display("Error: DRAM at %t tRCH violated", $stime);
$display("we_high_cycle %g - cas_high_cycle %g = %g ", we_high_cycle, cas_high_cycle, (we_high_cycle
- cas_high_cycle));
$display("(`tRCH * ticks_per_ns) = %g ", (`tRCH * ticks_per_ns));
end
end
//********************************************************************************
// For read only check tRRH(read command hold time refrenced to ras
//********************************************************************************
if(~rasb_has_been_asserted & ~cas_has_been_asserted & first_time_rasb_asserted & (type_op == 3'b010))
begin
if((we_low_cycle - rasb_high_cycle) < (`tRRH * ticks_per_ns)) begin
$display("Error: DRAM at %t tRRH(read command hold time w.r.t rasb_l) violated", $stime);
end
end
if(~rast_has_been_asserted & ~cas_has_been_asserted & first_time_rast_asserted & (type_op == 3'b010))
begin
if((we_low_cycle - rast_high_cycle) < (`tRRH * ticks_per_ns)) begin
$display("Error: DRAM at %t tRRH(read command hold time w.r.t rast_l) violated", $stime);
end
end
end
//##################################################################################################################
// READ OPERATION
//##################################################################################################################
always @(negedge cas_l)
begin
if(we_l & (rasb_has_been_asserted || rast_has_been_asserted))
begin
type_op[2:0] = 3'b010;
colm_addrs[10:0] = simm_address[10:0];
if (tAA_done) begin
wait (tRAC_met & tCAC_met & (tOEA_met) & (~first_access || tCPA_met));
// tCPA or first_access to be met.
rd_data = 64'b0;
data_valid = 1'b1; // indicates how long the data should be valid
rd_parity = 64'b0;
start_read = 1'b1;
if(~first_access)
begin
#1 first_access <= 1; // set the first_access flag
end
end // for read after a read-modify-wirte without address change, tAA_met never be set YS
else begin
wait (tRAC_met & tCAC_met & (tAA_met) & (tOEA_met) & (~first_access || tCPA_met)); // wait for tRAC, tCAC, tAA,
//wait (tRAC_met & tCAC_met & (tAA_met) & (~first_access || tCPA_met)); // wait for tRAC, tCAC, tAA,
// tCPA or first_access to be met.
rd_data = 64'b0;
data_valid = 1'b1; // indicates how long the data should be valid
rd_parity = 64'b0;
start_read = 1'b1;
if(~first_access)
begin
#1 first_access <= 1; // set the first_access flag
end
end
end
end
always @(negedge cas_l)
begin
if(we_l & first_cas_low_after_ras_low) // read operation and this is not first cas low
begin
rd_data = #(ticks_per_ns * `tDOH) 64'bx; // drive x's on the data port after tDOH ns
data_valid = 1'b0; // turn off data valid
end
end
always @(negedge cas_l)
begin
if(we_l & first_cas_low_after_ras_low) // read operation and this is not first cas low
begin
rd_parity = #(ticks_per_ns * `tDOH) 64'bx; // drive x's on rd_parity once tDOH has been met
end
end
//################################################################
// For READ operation to add oe_l control by YS 08/27/96
//################################################################
always @(negedge oe_l)
begin
if (we_l & (rasb_has_been_asserted || rast_has_been_asserted))
begin
oe_low_cycle = $stime;
oea_met = 1'b0;
tOEA_met = 1'b0;
oea_met <= #(ticks_per_ns *`tOEA) 1;
if ((oe_low_cycle - cas_high_cycle) < (`tCHO * ticks_per_ns)) begin
$display ("Error: DRAM at %t tCHO (CAS hold time to OE) violated!!", $stime);
end
if ((oe_low_cycle - oe_high_cycle) < (`tOEP * ticks_per_ns)) begin
$display ("Error: DRAM at %t tOEP (OE precharge time) violated!!", $stime);
end
end
end
always @(posedge oe_l)
begin
if (rasb_has_been_asserted || rast_has_been_asserted)
begin
oe_high_cycle = $stime;
oez_min_met = 1'b0;
oez_max_met = 1'b0;
oez_met = 1'b0;
oez_min_met <= #(ticks_per_ns * `tOEZ_MIN) 1;
oez_max_met <= #(ticks_per_ns * `tOEZ_MAX) 1;
rand = {$random} % (`tOEZ_MAX - `tOEZ_MIN);
oez_met <= #(ticks_per_ns * (`tOEZ_MIN + rand)) 1;
end
end
always @(posedge oez_met)
begin
if (type_op == 3'b010)
begin
data_valid = 1'b0;
rd_data = 64'bz;
rd_parity = 64'bz;
if (cas_low_cycle > cas_high_cycle) begin
// $display ("Error: DRAM at %t data still valid after cas goes low (swift turn off data at rising edge of cas)!!", $stime);
end
if (oez_min_met == 1'b0) begin
$display ("Error: DRAM at %t data turn off too early(before tOEZ_MIN met)!!", $stime);
end
if (oez_max_met == 1'b1) begin
$display ("Error: DRAM at %t data turn off too late(after tOEZ_MAX met)!!", $stime);
end
end
end
//##################################################################################################################
// EARLY WRITE CYCLE
//##################################################################################################################
always @(negedge cas_l)
begin
if(~we_l & (rasb_has_been_asserted || rast_has_been_asserted)) // we_l asserted & rasb or rast already asserted
begin
type_op = 3'b001; // indicates write operation
colm_addrs[10:0] = simm_address[10:0];
wr_data = data_in[63:0];
wr_parity = {48'h0, 7'h0, parity_in[1], 7'h0, parity_in[0]};
start_write = 1'b1;
`ifdef DEBUG
$display("At time %t m64 write completed for simm data[63:0]", $stime);
// $display("Stored %g bytes of data = %h at PA = %h", n, wr_data, m_addr);
$display("At time %t m64 write completed for simm parity bits", $stime);
// $display("Stored %g bytes of parity = %h at PA = %h", n, wr_data, m_addr);
$display(" ");
`endif
write_done = 1;
end
end
endmodule
/***************************************************************************
****************************************************************************
****************************************************************************
****************************************************************************/
module RAM
(
FPM_mem_size, cas_stat, ras_stat, FPM_rd_data, FPM_wr_data, FPM_rd_par, FPM_wr_par,
FPM_memaddr, FPM_ras_l, FPM_cas_l, FPM_moe_l, FPM_mwe_l,
FPM_ram_output, simm32_sel
);
output [63:00] FPM_mem_size
; // Return `SIZE to top module as 63-bit.
output [3:0] cas_stat
; // Info on CAS status and cycle type.
output [7:0] ras_stat
; // Info on which RAS and cycle type.
output FPM_ram_output
; // ram output enable signal for tri-state driver check
output [63:00] FPM_rd_data
; // 64-bit bi-dir data bus
output [01:00] FPM_rd_par
; // 2-bit bi-dir parity bus
input [63:00] FPM_wr_data
; // 64-bit bi-dir data bus
input [01:00] FPM_wr_par
; // 2-bit bi-dir parity bus
//inout [63:00] b_memdata; // 64-bit bi-dir data bus
//inout [01:00] b_mempar; // 2-bit bi-dir parity bus
input [10:00] FPM_memaddr
;
input [07:00] FPM_ras_l
;
input [03:00] FPM_cas_l
;
input FPM_moe_l
;
input FPM_mwe_l
;
input simm32_sel
;
wire [03:00] ras_l_page0
; // ras for page0 bank
wire [03:00] ras_l_page1
; // ras for page1 bank
wire [63:00] wr_dat
;
wire [01:00] wr_par
;
reg [63:00] wr_par_reg
; // Needs to be 64 due to sparse memory
reg [63:00] rd_dat
; // This is what we assign to the Swift CPU (delayed by 2 clocks)
reg [63:00] rd_dat_tmp
; // This is what we read from the memory model
reg [63:00] rd_par
; // Needs to be 64 due to sparse memory
reg [63:00] rd_par_tmp
; // This is what we read from the memory model
reg [27:03] Addr
; // used for forming the address.
reg [3:0] cas_stat;
reg [7:0] ras_stat;
reg [3:0] ras_stat_page0
; // status for page0 bank
reg [3:0] ras_stat_page1
; // status for page1 bank
reg [10:0] memaddr_page0
;
reg [10:0] memaddr_page1
;
reg [10:0] memaddr_page01
;
integer CasFlag
, ParUpdateFlag_FPM
;
reg [32:0] Index
; // note: needs to be 33 bits for sparse memory
reg [31:0] mem_mcd
; // file descriptor for mem trace
reg mem_trace
; // enable or disable mem traces
reg FPM_ram_output ;
wire [63:00] FPM_mem_size = 64'h0;
parameter access_time_from_cas_70 = 2 ;
// parameter access_time_from_cas_70 = 1 ; //RDV for IIe
parameter access_time_from_cas_85_100 = 3 ;
parameter access_time_from_cas_125 = 4 ;
parameter access_time_from_cas_150 = 5 ; // should be 5, it works is use 4
parameter access_time_from_cas_175 = 6 ; // should be 6, it works is use 5
parameter access_time_from_cas_200 = 7 ; // should be 7, it works is use 6
parameter access_time_from_cas = 20 ; // we may use 20ns DRAM spec value for all the speed select. YS
parameter RAM_DELAY_FPM = 25 ;
`define NORAS0 4'b1111
`define NORAS1 4'b1111
`define Index_Size 100
/* Size of the index array for DRAM model in dram_index.v file.*/
`define CBR_REF 4'b0000
`define READ 4'b0001
`define WRITE 4'b0010
`define NOCAS 4'b1111
`define NORAS 8'b11111111
`define ASSERTED 1
`define NEGATED 0
`define YES 1
`define NO 0
/*
assign the individual rd_dat & wr_dat buses to the
bidirectional DATA bus.
*/
//assign b_memdata = ( ( (~cas_l[3] | ~cas_l[2] | ~cas_l[1] | ~cas_l[0]) & mwe_l ) ? rd_dat : 64'hzzzzzzzz );
assign FPM_rd_data = rd_dat ;
assign wr_dat = FPM_wr_data ;
/*
assign the individual rd_par & wr_par buses to the
bidirectional PARITY bus.
*/
//assign b_mempar = ( ( (~cas_l[3] | ~cas_l[2] | ~cas_l[1] | ~cas_l[0]) & mwe_l ) ? {rd_par[8],rd_par[0]} : 2'bz );
assign FPM_rd_par = { rd_par[8], rd_par[0]} ;
assign wr_par[1:0] = FPM_wr_par ;
/*
Init memory .... Set top of memory to 0 (none used), zero all of
addr-ram and fill data-ram with pattern.
*/
initial begin
ras_stat = `NORAS ;
cas_stat = `NOCAS ;
ras_stat_page0 = `NORAS0 ;
ras_stat_page1 = `NORAS1 ;
CasFlag = `NEGATED ;
ParUpdateFlag_FPM = `NEGATED ;
FPM_ram_output = 1'b0 ;
$display("Module dram.v - RAM initial block");
mem_trace = 0;
// Wait for working_dir, etc., to be initialized before opening
// the trace file.
#1 ;
mem_mcd = $fopen({Mclocks.working_dir,"/mem_trace.v"});
if (!mem_mcd)
$display( "dram: unable to open 'mem_trace.v'") ;
end
// Group ras for each bank
assign ras_l_page0 = { FPM_ras_l[6], FPM_ras_l[4], FPM_ras_l[2], FPM_ras_l[0] } ;
assign ras_l_page1 = { FPM_ras_l[7], FPM_ras_l[5], FPM_ras_l[3], FPM_ras_l[1] } ;
// initial $monitor(" Monitoring at time = %g ras_l= %b, ras_l_page0= %b, ras_l_page1= %b, cas_l= %b", $stime, ras_l, ras_l_page0, ras_l_page1, cas_l);
/* Monitor group RASes. If a RAS is asserted store the Row-Addr and get
the higher addr-bits from the encode of the RASes.
The row address is created by taking the
buts 24, 22 and 20:12 as specified in the
Table 2.7.2 of Swift CPU Spec. (Physical
address decode for System memory)
*/
always begin
wait ( ras_l_page0 < 4'b1111 ) begin
memaddr_page0 = FPM_memaddr ;
memaddr_page01 = FPM_memaddr;
#5 ras_stat_page0 = ras_l_page0; // let RASes settle
wait ( ras_l_page0 === 4'b1111 ) begin
ras_stat_page0 = `NORAS0 ;
{ras_stat[6], ras_stat[4], ras_stat[2], ras_stat[0]} = `NORAS0 ;
end // of wait.
end // of wait.
end // of always
always begin
wait ( ras_l_page1 < 4'b1111 ) begin
memaddr_page1 = FPM_memaddr ;
memaddr_page01 = FPM_memaddr;
#5 ras_stat_page1 = ras_l_page1; // let RASes settle
wait ( ras_l_page1 === 4'b1111 ) begin
ras_stat_page1 = `NORAS1 ;
{ras_stat[7], ras_stat[5], ras_stat[3], ras_stat[1]} = `NORAS1 ;
end // of wait.
end // of wait.
end // of always
/* Monitor CAS. If CAS is asserted store the Col-address.
The column address is created by taking the
bits 23, 21 and 11:3 as specified in the
Table 2.7.2 of Swift CPU Spec. (Physical
address decode for system memory)
*/
always begin
wait ( FPM_cas_l !== 4'b1111) begin
{Addr[23],Addr[21],Addr[11:03]} = FPM_memaddr ;
if (simm32_sel == 1'b1) begin
case (FPM_cas_l)
// Casl0 is low, or Casl1 is low
// implies bit<25> is zero so the even address bank is selected
4'b1010 , // more significant word
4'b0101 , // less significant word
4'b0000 :begin // double word access
{Addr[24],Addr[22],Addr[20:12]} = memaddr_page01 ;
case (ras_l_page0) // Only one ras is low
4'b1110 : Addr[27:25] = 3'b000 ; //0th 32MB bank
4'b1101 : Addr[27:25] = 3'b010 ; //2nd 32MB bank
4'b1011 : Addr[27:25] = 3'b100 ; //4th 32MB bank
4'b0111 : Addr[27:25] = 3'b110 ; //6th 32MB bank
endcase // for ras_l_page0
case (ras_l_page1) // Only one ras is low
4'b1110 : Addr[27:25] = 3'b001 ; //1st 32MB bank
4'b1101 : Addr[27:25] = 3'b011 ; //3rd 32MB bank
4'b1011 : Addr[27:25] = 3'b101 ; //5th 32MB bank
4'b0111 : Addr[27:25] = 3'b111 ; //7th 32MB bank
endcase // for ras_l_page1
end // for casl0 and casl1
4'b0001 , // illegal conditions for cas_l
4'b0010 , // illegal conditions for cas_l
4'b0011 , // illegal conditions for cas_l
4'b0100 , // illegal conditions for cas_l
4'b0110 , // illegal conditions for cas_l
4'b0111 , // illegal conditions for cas_l
4'b1000 , // illegal conditions for cas_l
4'b1001 , // illegal conditions for cas_l
4'b1011 , // illegal conditions for cas_l
4'b1100 , // illegal conditions for cas_l
4'b1101 , // illegal conditions for cas_l
4'b1110 : // illegal conditions for cas_l
$display("*** ERROR: Illegal condition for cas_l:%b", FPM_cas_l);
endcase //for cas_l
end // if begin
else begin
case (FPM_cas_l)
// Casl0 is low, or Casl1 is low
// implies bit<25> is zero so the even address bank is selected
4'b1110 , // more significant word
4'b1101 , // less significant word
4'b1100 :begin // double word access
{Addr[24],Addr[22],Addr[20:12]} = memaddr_page0 ;
case (ras_l_page0) // Only one ras is low
4'b1110 : Addr[27:25] = 3'b000 ; //0th 32MB bank
4'b1101 : Addr[27:25] = 3'b010 ; //2nd 32MB bank
4'b1011 : Addr[27:25] = 3'b100 ; //4th 32MB bank
4'b0111 : Addr[27:25] = 3'b110 ; //6th 32MB bank
endcase // for ras_l_page0
end // for casl0 and casl1
// Casl2 is low, or Casl3 is low
// implies bit<25> is one so the odd address bank is selected
4'b1011 , // more significant word
4'b0111 , // less significant word
4'b0011 :begin // double word access
{Addr[24],Addr[22],Addr[20:12]} = memaddr_page1 ;
case (ras_l_page1) // Only one ras is low
4'b1110 : Addr[27:25] = 3'b001 ; //1st 32MB bank
4'b1101 : Addr[27:25] = 3'b011 ; //3rd 32MB bank
4'b1011 : Addr[27:25] = 3'b101 ; //5th 32MB bank
4'b0111 : Addr[27:25] = 3'b111 ; //7th 32MB bank
endcase // for ras_l_page1
end // for casl2 and casl3
4'b0001 , // illegal conditions for cas_l
4'b0010 , // illegal conditions for cas_l
4'b0100 , // illegal conditions for cas_l
4'b0101 , // illegal conditions for cas_l
4'b0110 , // illegal conditions for cas_l
4'b1000 , // illegal conditions for cas_l
4'b1001 , // illegal conditions for cas_l
4'b1010 : // illegal conditions for cas_l
$display("*** ERROR: Illegal condition for cas_l:%b", FPM_cas_l);
endcase //for cas_l
end // else begin
CasFlag = `ASSERTED ;
Index = {7'b0,Addr[27:03]};
// $display("Index set = %h ", Index);
wait ( FPM_cas_l == 4'b1111 ) begin
CasFlag = `NEGATED ;
cas_stat = `NOCAS ;
rd_dat = #1 64'hzzzzzzzz ; // assign it to be high impedance
rd_par = #1 64'hzzzzzzzz ; // assign it to be high impedance
end
end // wait
end // of always.
/*
When CasFlag is asserted (see above "always-loop"), CAS has gone
active, so... depending on the state of RASes and MWE, determine
the cycle type and store it in cas_stat. Also, perform the Rd or
Wr if that is the required cycle.
!!! Use "CasFlag" instead of 'cas_l' itself, to avoid race-condition
!!! with the "always-loop" above, which sets up the Addr. This way, we
!!! assure Addr is set, before we start a cycle.
*/
/*********************************************************************
* below, the parity ram is modeled like this:
*
* bit [9] - reference bit for parity on 63:32
* bit [8] - parity on 63:32
* bit [1] - reference bit for parity on 31:0
* bit [0] - parity on 31:0
*
*********************************************************************/
always begin
wait ( CasFlag == `ASSERTED ) begin
//$display("CasFlag asserted");
if ( {ras_stat_page0, ras_stat_page1} == `NORAS ) begin
cas_stat = `CBR_REF ;
end /* of if... */
else if ( FPM_mwe_l == 1'b0 ) begin /* WRITE cycle.*/
cas_stat = `WRITE ;
//$display("write_cycle...1");
wr_par_reg = {48'h0, 7'h0, wr_par[1], 7'h0, wr_par[0]};
if ((FPM_cas_l[0] === 1'b0 ) || (FPM_cas_l[2] === 1'b0)) begin
//$display("write_cycle...2");
$mem_write(Msystem.TheRam.memHandle, Index, 8'b11110000, wr_dat);
mem_dump(Addr,wr_dat[63:32],0);
wr_par_reg[9] = 1'b1; // valid bit for bank 0 (63:32) is 9
$mem_write(Msystem.TheRam.parHandle, Index, 8'b00000010, wr_par_reg);
//$display("par_write0 wr_dat: %h wr_par: %h", wr_dat, wr_par_reg);
end
if ((FPM_cas_l[1] === 1'b0)|| (FPM_cas_l[3] === 1'b0)) begin
//$display("write_cycle...3");
$mem_write(Msystem.TheRam.memHandle, Index, 8'b00001111, wr_dat);
mem_dump(Addr,wr_dat[31:0],1);
wr_par_reg[1] = 1'b1; // valid bit for bank 1 (31:0) is 1
$mem_write(Msystem.TheRam.parHandle, Index, 8'b00000001, wr_par_reg);
//$display("par_write1 wr_dat: %h wr_par: %h", wr_dat, wr_par_reg);
end
end /* of else-if.*/
else begin
//$display("read_cycle...");
cas_stat = `READ ;
$mem_read(Msystem.TheRam.memHandle, Index, 8'b11111111, rd_dat_tmp);
$mem_read(Msystem.TheRam.parHandle, Index, 8'b00000011, rd_par_tmp);
//
// Since we don't load the parity ram with an initial
// image, we keep two parity referenced bits around.
//
// If the reference bit for a bank hasn't been set, then
// we calculate 'even' parity for it, return the parity
// bit and write the newly generated parity into the
// parity ram.
//
// $display("Cycle: %g read_cyc: Index: %h rd_dat_tmp: %h rd_par_tmp: %h", $stime, Index, rd_dat_tmp, rd_par_tmp);
// The delay should be done in parallel for data and parity
case (Msystem.speed_select)
`SPEED70:
fork
rd_dat = # ( access_time_from_cas_70 * `CYCLETIME) rd_dat_tmp ;
rd_par = # ( access_time_from_cas_70 * `CYCLETIME) rd_par_tmp ;
join
`SPEED85, `SPEED100:
| This page: |
Created: | Thu Aug 19 12:01:42 1999 |
| From: |
../../../sparc_v8/system/rtl/dram.v
|