diff --git a/lib/models/memory/flash/serial/S25fl064a/Model_Manual_English.pdf b/lib/models/memory/flash/serial/S25fl064a/Model_Manual_English.pdf new file mode 100644 index 0000000..954c3f6 Binary files /dev/null and b/lib/models/memory/flash/serial/S25fl064a/Model_Manual_English.pdf differ diff --git a/lib/models/memory/flash/serial/S25fl064a/Model_Manual_Japanese.pdf b/lib/models/memory/flash/serial/S25fl064a/Model_Manual_Japanese.pdf new file mode 100644 index 0000000..de2f909 Binary files /dev/null and b/lib/models/memory/flash/serial/S25fl064a/Model_Manual_Japanese.pdf differ diff --git a/lib/models/memory/flash/serial/S25fl064a/model/s25fl064a.v b/lib/models/memory/flash/serial/S25fl064a/model/s25fl064a.v new file mode 100644 index 0000000..3c7aef5 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064a/model/s25fl064a.v @@ -0,0 +1,1217 @@ +////////////////////////////////////////////////////////////////////////////// +// File name : s25fl064a.v +////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2006-2007 Spansion, LLC. +// +// MODIFICATION HISTORY : +// +// version: | author: | mod date: | changes made: +// V1.0 G.Gojanovic 05 May 16 Initial release +// V1.1 D.Randjelovic 06 Apr 11 MSB of latched address is ignored +// V1.2 D.Randjelovic 06 May 04 Page Program Command used with the +// single byte data corrected. +// Release from Deep Power Down when +// Electronic Signature is not read +// fixed +// V1.3 D.Stanojkovic 07 Jul 02 Fixed missing Sec_Prot initialization +// +////////////////////////////////////////////////////////////////////////////// +// PART DESCRIPTION: +// +// Library: FLASH +// Technology: Flash Memory +// Part: S25FL064A +// +// Description: 64 Megabit Serial Flash Memory with 50MHz SPI Bus Interface +// +////////////////////////////////////////////////////////////////////////////// +// Known Bugs: +// +////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// MODULE DECLARATION // +////////////////////////////////////////////////////////////////////////////// +`timescale 1 ns/1 ns +module s25fl064a +( + SCK , + SI , + CSNeg , + HOLDNeg , + WNeg , + SO +); + +//////////////////////////////////////////////////////////////////////// +// Port / Part Pin Declarations +//////////////////////////////////////////////////////////////////////// + input SCK ; + input SI ; + input CSNeg ; + input HOLDNeg ; + input WNeg ; + + output SO ; + +// interconnect path delay signals + wire SCK_ipd ; + wire SI_ipd ; + wire CSNeg_ipd ; + wire HOLDNeg_ipd ; + wire WNeg_ipd ; + +// internal delays + reg PP_in ; + reg PP_out ; + reg PE_in ; + reg PE_out ; + reg BE_in ; + reg BE_out ; + reg SE_in ; + reg SE_out ; + reg WR_in ; + reg WR_out ; + reg DP_in ; + reg DP_out ; + reg RES_in ; + reg RES_out ; + + reg SO_zd = 1'bZ; + reg SO_z = 1'bZ; + + parameter UserPreload = 1; + parameter mem_file_name = "none";//"s25fl064a.mem"; + + parameter TimingModel = "DefaultTimingModel"; + + parameter PartID = "s25fl064a"; + parameter MaxData = 255; + parameter SecSize = 65535; + parameter SecNum = 127; + parameter HiAddrBit = 22; + parameter AddrRANGE = 24'h7FFFFF; + parameter BYTE = 8; + parameter ES = 8'h16; + parameter DeviceID = 24'h010216; + + // powerup + reg PoweredUp; + + reg PDONE ; ////Prog. Done + reg PSTART ; ////Start Programming + + reg EDONE ; ////Era. Done + reg ESTART ; ////Start Erasing + + reg WDONE ; //// Writing Done + reg WSTART ; ////Start writing + + //Command Register + reg write; + reg read_out; + + //Status reg. + reg[7:0] Status_reg = 8'b0; + reg[7:0] Status_reg_in = 8'b0; + + integer SA = 0; // 0 TO SecNum+1 + integer Byte_number = 0; + + //Address + integer Address = 0; // 0 - AddrRANGE + reg change_addr; + reg rd_fast;// = 1'b1; + reg rd_slow; + wire fast_rd; + wire rd; + + //Sector Protection Status + reg [SecNum:0] Sec_Prot; //= SecNum'b0; + + // timing check violation + reg Viol = 1'b0; + + integer Mem[0:AddrRANGE]; + + integer WByte[0:255]; + + integer AddrLo; + integer AddrHi; + + reg[7:0] old_bit, new_bit; + integer old_int, new_int; + integer wr_cnt; + + integer read_cnt = 0; + integer read_addr = 0; + reg[7:0] data_out; + reg[23:0] ident_out; + + reg oe = 1'b0; + event oe_event; + +/////////////////////////////////////////////////////////////////////////////// +//Interconnect Path Delay Section +/////////////////////////////////////////////////////////////////////////////// + + buf (SCK_ipd, SCK); + buf (SI_ipd, SI); + buf (CSNeg_ipd, CSNeg); + buf (HOLDNeg_ipd, HOLDNeg); + buf (WNeg_ipd, WNeg); + +/////////////////////////////////////////////////////////////////////////////// +// Propagation delay Section +/////////////////////////////////////////////////////////////////////////////// + nmos (SO, SO_z, 1); + + specify + // tipd delays: interconnect path delays , mapped to input port delays. + // In Verilog is not necessary to declare any tipd_ delay variables, + // they can be taken from SDF file + // With all the other delays real delays would be taken from SDF file + + // tpd delays + specparam tpd_SCK_SO =1; + specparam tpd_CSNeg_SO =1; + specparam tpd_HOLDNeg_SO =1; + + specparam tsetup_SI_SCK =1; //tsuDAT / + specparam tsetup_CSNeg_SCK =1; // tCSS / + specparam tsetup_HOLDNeg_SCK =1; //tHD / + specparam tsetup_SCK_HOLDNeg =1; //tCH \ + specparam tsetup_WNeg_CSNeg =1; //tWPS \ + + // thold values: hold times + specparam thold_SI_SCK =1; //thdDAT / + specparam thold_CSNeg_SCK =1; //tCSH / + specparam thold_HOLDNeg_SCK =1; //tCD / + specparam thold_SCK_HOLDNeg =1; //tHC \ + specparam thold_WNeg_CSNeg =1; //tWPH \ + + // tpw values: pulse width + specparam tpw_SCK_posedge =1; //tWH + specparam tpw_SCK_negedge =1; //tWL + specparam tpw_CSNeg_posedge =1; //tCS + + // tperiod min (calculated as 1/max freq) + specparam tperiod_SCK_rd =1; // fSCK = 33MHz + specparam tperiod_SCK_fast_rd =1; // fSCK = 50MHz + + // tdevice values: values for internal delays + + // Page Program Operation + specparam tdevice_PP = 3000000; //3 ms; + //Sector Erase Operation + specparam tdevice_SE = 3e9; //3 sec; + //Bulk Erase Operation + specparam tdevice_BE = 384e9; //384 sec; + //Write Status Register Operation + specparam tdevice_WR = 60000000; // 60 ms; + //Software Protect Mode + specparam tdevice_DP = 3000; // 3 us; + //Release from Software Protect Mode + specparam tdevice_RES = 30000; // 30 us; + //VCC (min) to CS# Low + specparam tdevice_PU = 10000000; //10 ms; + +/////////////////////////////////////////////////////////////////////////////// +// Input Port Delays don't require Verilog description +/////////////////////////////////////////////////////////////////////////////// +// Path delays // +/////////////////////////////////////////////////////////////////////////////// + (SCK => SO) = tpd_SCK_SO; + (CSNeg => SO) = tpd_CSNeg_SO; + (HOLDNeg => SO) = tpd_HOLDNeg_SO; + +//////////////////////////////////////////////////////////////////////////////// +// Timing Violation // +//////////////////////////////////////////////////////////////////////////////// + $setup ( WNeg , negedge CSNeg, tsetup_WNeg_CSNeg, Viol); + $setup ( negedge HOLDNeg, posedge SCK, tsetup_HOLDNeg_SCK, Viol); + $setup ( posedge SCK, posedge HOLDNeg, tsetup_SCK_HOLDNeg, Viol); + + $hold ( posedge CSNeg, WNeg, thold_WNeg_CSNeg, Viol); + $hold ( posedge SCK, negedge HOLDNeg, thold_HOLDNeg_SCK, Viol); + $hold ( posedge HOLDNeg, posedge SCK, thold_SCK_HOLDNeg, Viol); + + $setuphold ( posedge SCK, SI, tsetup_SI_SCK, thold_SI_SCK, Viol); + $setuphold ( posedge SCK, CSNeg, tsetup_CSNeg_SCK, + thold_CSNeg_SCK, Viol); + + $width (posedge SCK, tpw_SCK_posedge); + $width (negedge SCK, tpw_SCK_negedge); + + $width (posedge CSNeg, tpw_CSNeg_posedge); + + $period (posedge SCK &&& rd, tperiod_SCK_rd); + $period (posedge SCK &&& fast_rd, tperiod_SCK_fast_rd); + + endspecify + +//////////////////////////////////////////////////////////////////////////////// +// Main Behavior Block // +//////////////////////////////////////////////////////////////////////////////// +// FSM states + parameter IDLE =4'd0; + parameter WRITE_SR =4'd1; + parameter DP_DOWN =4'd2; + parameter SECTOR_ER =4'd3; + parameter BULK_ER =4'd4; + parameter PAGE_PG =4'd5; + + reg [3:0] current_state; + reg [3:0] next_state; + +// Instructions + parameter NONE =5'd0; + parameter WREN =5'd1; + parameter WRDI =5'd2; + parameter WRSR =5'd3; + parameter RDSR =5'd4; + parameter READ =5'd5; + parameter FAST_READ =5'd6; + parameter SE =5'd8; + parameter BE =5'd9; + parameter PP =5'd10; + parameter DP =5'd11; + parameter RDID =5'd12; + parameter RES_READ_ES =5'd13; + + reg [4:0] Instruct; + +//Bus cycle states + parameter STAND_BY =3'd0; + parameter CODE_BYTE =3'd1; + parameter ADDRESS_BYTES =3'd2; + parameter DUMMY_BYTES =3'd3; + parameter DATA_BYTES =3'd4; + + reg [2:0] bus_cycle_state; + + initial + begin : Init + + write = 1'b0; + read_out = 1'b0; + Address = 0; + change_addr = 1'b0; + + PDONE = 1'b1; + PSTART = 1'b0; + + EDONE = 1'b1; + ESTART = 1'b0; + + WDONE = 1'b1; + WSTART = 1'b0; + + DP_in = 1'b0; + DP_out = 1'b0; + RES_in = 1'b0; + RES_out = 1'b0; + Instruct = NONE; + bus_cycle_state = STAND_BY; + current_state = IDLE; + next_state = IDLE; + Sec_Prot = 0; + end + + // initialize memory + initial + begin: InitMemory + integer i; + + for (i=0;i<=AddrRANGE;i=i+1) + begin + Mem[i] = MaxData; + end + + if ((UserPreload) && !(mem_file_name == "none")) + begin + // Memory Preload + //s25fl016a.mem, memory preload file + // @aaaaaa - stands for address + // dd -
is byte to be written at Mem(aaaaaa++) + // (aaaaaa is incremented at every load) + $readmemh(mem_file_name,Mem); + end + end + + //Power Up time; + initial + begin + PoweredUp = 1'b0; + #tdevice_PU PoweredUp = 1'b1; + end + + always @(posedge DP_in) + begin:TDPr + #tdevice_DP DP_out = DP_in; + end + always @(negedge DP_in) + begin:TDPf + #1 DP_out = DP_in; + end + + always @(posedge RES_in) + begin:TRESr + #tdevice_RES RES_out = RES_in; + end + always @(negedge RES_in) + begin:TRESf + #1 RES_out = RES_in; + end + + always @(next_state or PoweredUp) + begin: StateTransition + if (PoweredUp) + begin + current_state = next_state; + end + end + + always @(PoweredUp) + begin:CheckCEOnPowerUP + if ((~PoweredUp) && (~CSNeg_ipd)) + $display ("Device is selected during Power Up"); + end + +// /////////////////////////////////////////////////////////////////////////// +// // Instruction cycle decode +// /////////////////////////////////////////////////////////////////////////// + integer data_cnt = 0; + integer addr_cnt = 0; + integer code_cnt = 0; + integer dummy_cnt = 0; + integer bit_cnt = 0; + reg[2047:0] Data_in = 2048'b0; + reg[7:0] code = 8'b0; + reg[7:0] code_in = 8'b0; + reg[7:0] Byte_slv = 8'b0; + reg[HiAddrBit:0] addr_bytes; + reg[23:0] Address_in = 8'b0; + + always @(negedge CSNeg_ipd) + begin: Buscycle1 + if (bus_cycle_state==STAND_BY) + begin + bus_cycle_state = CODE_BYTE; + Instruct = NONE; + write = 1'b1; + code_cnt = 0; + addr_cnt = 0; + data_cnt = 0; + dummy_cnt = 0; + end + end + + always @(posedge SCK_ipd) + begin: Buscycle2 + integer i; + if ( HOLDNeg_ipd) + begin + case (bus_cycle_state) + CODE_BYTE : + begin + code_in[code_cnt] = SI_ipd; + code_cnt = code_cnt + 1; + if (code_cnt == BYTE) + begin + for (i=0;i<=7;i=i+1) + begin + code[i] = code_in[7-i]; + end + case(code) + 8'b00000110 : + begin + Instruct = WREN; + bus_cycle_state = DATA_BYTES; + end + 8'b00000100 : + begin + Instruct = WRDI; + bus_cycle_state = DATA_BYTES; + end + 8'b00000001 : + begin + Instruct = WRSR; + bus_cycle_state = DATA_BYTES; + end + 8'b00000101 : + begin + Instruct = RDSR; + bus_cycle_state = DATA_BYTES; + end + 8'b00000011 : + begin + Instruct = READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00001011 : + begin + Instruct = FAST_READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10101011 : + begin + Instruct = RES_READ_ES; + bus_cycle_state = DUMMY_BYTES; + end + 8'b11011000 : + begin + Instruct = SE; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11000111 : + begin + Instruct = BE; + bus_cycle_state = DATA_BYTES; + end + 8'b00000010 : + begin + Instruct = PP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10111001 : + begin + Instruct = DP; + bus_cycle_state = DATA_BYTES; + end + 8'b10011111 : + begin + Instruct = RDID; + bus_cycle_state = DATA_BYTES; + end + endcase + end + end + + ADDRESS_BYTES : + begin + Address_in[addr_cnt] = SI_ipd; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE) + begin + for (i=23;i>=23-HiAddrBit;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (Instruct == FAST_READ) + bus_cycle_state = DUMMY_BYTES; + else + bus_cycle_state = DATA_BYTES; + end + end + + DUMMY_BYTES : + begin + dummy_cnt = dummy_cnt + 1; + if ((dummy_cnt == BYTE && Instruct == FAST_READ) || + (dummy_cnt == 3*BYTE && Instruct == RES_READ_ES)) + bus_cycle_state = DATA_BYTES; + end + + DATA_BYTES : + begin + if (data_cnt > 2047) + //In case of PP, if more than 256 bytes are + //sent to the device + begin + if (bit_cnt == 0) + begin + for (i=0;i<=(255*BYTE-1);i=i+1) + begin + Data_in[i] = Data_in[i+8]; + end + end + Data_in[2040 + bit_cnt] = SI_ipd; + bit_cnt = bit_cnt + 1; + if (bit_cnt == 8) + begin + bit_cnt = 0; + end + data_cnt = data_cnt + 1; + end + else + begin + Data_in[data_cnt] = SI_ipd; + data_cnt = data_cnt + 1; + bit_cnt = 0; + end + end + endcase + end + end + + always @(negedge SCK_ipd) + begin: Buscycle3 + if (bus_cycle_state==DATA_BYTES && (~CSNeg_ipd) && (HOLDNeg_ipd)) + if (Instruct == READ || Instruct == RES_READ_ES || + Instruct == FAST_READ || Instruct == RDSR || + Instruct == RDID) + read_out = 1'b1; + #1 read_out = 1'b0; + end + + always @(posedge CSNeg_ipd) + begin: Buscycle4 + integer i; + integer j; + if (bus_cycle_state == DATA_BYTES) + begin + bus_cycle_state = STAND_BY; + if (HOLDNeg_ipd) + begin + case (Instruct) + WREN, + WRDI, + DP, + BE, + SE : + begin + if (data_cnt == 0) + write = 1'b0; + end + + RES_READ_ES, + RDID : + begin + write = 1'b0; + end + + WRSR : + begin + if (data_cnt == BYTE) + write = 1'b0; + Status_reg_in = Data_in[7:0]; + end + + PP : + begin + if ((data_cnt > 0) && ((data_cnt % 8) == 0)) + begin + write = 1'b0; + for (i=0;i<=255;i=i+1) + begin + for (j=7;j>=0;j=j-1) + begin + Byte_slv[j] = Data_in[(i*8) + (7-j)]; + end + WByte[i] = Byte_slv; + end + if (data_cnt > 256*BYTE) + Byte_number = 255; + else + Byte_number = ((data_cnt/8) - 1); + end + end + endcase + end + end + + if (bus_cycle_state == DUMMY_BYTES) + begin + bus_cycle_state = STAND_BY; + if (HOLDNeg_ipd && Instruct == RES_READ_ES) + write = 1'b0; + end + + end + +// ///////////////////////////////////////////////////////////////////////// +// // Timing control for the Program Operations +// // start +// ///////////////////////////////////////////////////////////////////////// + + event pdone_event; + + always @(PSTART) + begin + if (PSTART && PDONE) + begin + PDONE = 1'b0; + ->pdone_event; + end + end + + always @(pdone_event) + begin:pdone_process + PDONE = 1'b0; + #tdevice_PP PDONE = 1'b1; + end + +// ///////////////////////////////////////////////////////////////////////// +// // Timing control for the Write Status Register Operation +// // start +// ///////////////////////////////////////////////////////////////////////// + + event wdone_event; + + always @(WSTART) + begin + if (WSTART && WDONE) + begin + WDONE = 1'b0; + ->wdone_event; + end + end + + always @(wdone_event) + begin:wdone_process + WDONE = 1'b0; + #tdevice_WR WDONE = 1'b1; + end + +// ///////////////////////////////////////////////////////////////////////// +// // Timing control for the Erase Operations +// ///////////////////////////////////////////////////////////////////////// + integer cnt_erase = 0; + time duration_erase; + + event edone_event; + + always @(ESTART) + begin: erase + if (ESTART && EDONE) + begin + + if (Instruct == BE) + begin + duration_erase = tdevice_BE; + end + else //if (Instruct == SE) + begin + duration_erase = tdevice_SE; + end + + EDONE = 1'b0; + ->edone_event; + end + end + + always @(edone_event) + begin : edone_process + EDONE = 1'b0; + #duration_erase EDONE = 1'b1; + end + +// ///////////////////////////////////////////////////////////////////////// +// // Main Behavior Process +// // combinational process for next state generation +// ///////////////////////////////////////////////////////////////////////// + + integer sect; + + always @(negedge write) + begin: StateGen1 + + case (current_state) + IDLE : + begin + if (~write) + begin + if (Instruct == WRSR && Status_reg[1]) + begin + if (~(Status_reg[7] && (~WNeg_ipd))) + next_state = WRITE_SR; + end + else if (Instruct == PP && Status_reg[1]) + begin + sect = Address / 24'h10000; + if (Sec_Prot[sect] == 1'b0) + next_state = PAGE_PG; + end + else if (Instruct == SE && Status_reg[1]) + begin + sect = Address / 24'h10000; + if (Sec_Prot[sect] == 1'b0) + next_state = SECTOR_ER; + end + else if (Instruct == BE && Status_reg[1]) + begin + if (Status_reg[2] == 1'b0 && Status_reg[3] == 1'b0 && + Status_reg[4] == 1'b0) + next_state = BULK_ER; + end + else if (Instruct == DP) + next_state = DP_DOWN; + else + next_state = IDLE; + end + end + + DP_DOWN: + begin + if (~write) + begin + if (Instruct == RES_READ_ES) + next_state = IDLE; + end + end + + endcase + end + + always @(posedge PDONE) + begin: StateGen2 + if (current_state==PAGE_PG) + begin + next_state = IDLE; + end + end + + always @(posedge WDONE) + begin: StateGen3 + if (current_state==WRITE_SR) + begin + next_state = IDLE; + end + end + + always @(posedge EDONE) + begin: StateGen4 + if (current_state==SECTOR_ER || current_state==BULK_ER) + begin + next_state = IDLE; + end + end + + /////////////////////////////////////////////////////////////////////////// + //FSM Output generation and general funcionality + /////////////////////////////////////////////////////////////////////////// + + always @(posedge read_out) + begin + if (PoweredUp == 1'b1) + ->oe_event; + end + + always @(oe_event) + begin + oe = 1'b1; + #1 oe = 1'b0; + end + + always @(Instruct) + begin + read_cnt = 0; + end + + always @(change_addr) + begin + if (change_addr) + read_addr = Address; + end + + always @(Instruct) + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + end + + always @(oe or current_state) + begin + case (current_state) + IDLE : + begin + if (oe && RES_in == 1'b0) + begin + if (Instruct == RDSR) + begin + //Read Status Register + SO_zd = Status_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == READ || Instruct == FAST_READ) + begin + //Read Memory array + if (Instruct == READ) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + end + data_out[7:0] = Mem[read_addr]; + SO_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else if (Instruct == RDID) + begin + // Read ID + ident_out[23:0] = DeviceID; + SO_zd = ident_out[23-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 24) + read_cnt = 0; + end + else if (Instruct == RES_READ_ES) + begin + // Read ID + data_out[7:0] = ES; + SO_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe && RES_in == 1'b1) + begin + $display ("Command results can be corrupted"); + SO_zd = 1'bX; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + + WRITE_SR, + SECTOR_ER, + BULK_ER, + PAGE_PG : + begin + if (oe && Instruct == RDSR) + begin + //Read Status Register + SO_zd = Status_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + + DP_DOWN : + begin + if (~write) + begin + if (Instruct == RES_READ_ES) + RES_in = 1'b1; + end + else if (oe && Instruct == RES_READ_ES) + begin + // Read ES + data_out[7:0] = ES; + SO_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + + endcase + end + + assign fast_rd = rd_fast; + assign rd = rd_slow; + + integer sector; + integer WData [0:255]; + integer Addr; + + always @(negedge write) + begin : Output_generation + integer i; + + case (current_state) + IDLE : + begin + if (~write) + begin + if (RES_in == 1'b1) + begin + $display ("Command results can be corrupted"); + end + if (Instruct == WREN) + Status_reg[1] = 1'b1; + else if (Instruct == WRDI) + Status_reg[1] = 1'b0; + else if (Instruct == WRSR && Status_reg[1] && + (~(Status_reg[7] == 1'b1 && WNeg_ipd == 1'b0))) + begin + WSTART = 1'b1; + WSTART <= #1 1'b0; + Status_reg[0] = 1'b1; + end + else if (Instruct == PP && Status_reg[1] == 1'b1) + begin + sector = Address / 20'h10000; + if (Sec_Prot[sector] == 1'b0) + begin + PSTART = 1'b1; + PSTART <= #1 1'b0; + Status_reg[0] = 1'b1; + Addr = Address; + SA = sector; + wr_cnt = Byte_number; + for (i=0;i<=wr_cnt;i=i+1) + begin + if (Viol!=1'b0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + end + else if (Instruct == SE && Status_reg[1] == 1'b1) + begin + sector = Address / 20'h10000; + if (Sec_Prot[sector] == 1'b0) + begin + ESTART = 1'b1; + ESTART <= #1 1'b0; + Status_reg[0] = 1'b1; + Addr = Address; + end + end + else if (Instruct == BE && Status_reg[1] == 1'b1 && + Status_reg[2] == 1'b0 && Status_reg[3] == 1'b0 && + Status_reg[4] == 1'b0) + begin + ESTART = 1'b1; + ESTART <= #1 1'b0; + Status_reg[0] = 1'b1; + end + else if (Instruct == DP && RES_in == 1'b0) + DP_in = 1'b1; + end + + end + + DP_DOWN : + begin + if (~write) + begin + if (Instruct == RES_READ_ES) + RES_in = 1'b1; + end + end + + endcase + end + + always @(RES_out) + begin : DPDOWN1 + if (RES_out) + begin + RES_in = 1'b0; + end + end + + always @(current_state or EDONE) + begin: ERASE1 + integer i; + case (current_state) + + SECTOR_ER : + begin + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = -1; + end + + if (EDONE) + begin + Status_reg[0] = 1'b0; + Status_reg[1] = 1'b0; + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = MaxData; + end + end + end + + BULK_ER : + begin + for (i=0;i<=AddrRANGE;i=i+1) + begin + Mem[i] = -1; + end + + if (EDONE) + begin + Status_reg[0] = 1'b0; + Status_reg[1] = 1'b0; + for (i=0;i<=AddrRANGE;i=i+1) + begin + Mem[i] = MaxData; + end + end + end + endcase + end + + always @(current_state or WDONE) + begin: WRSR1 + if (current_state == WRITE_SR) + begin + if (WDONE) + begin + Status_reg[0] = 1'b0;//WIP + Status_reg[1] = 1'b0;//WEL + Status_reg[7] = Status_reg_in[0];//MSB first, SRWD + Status_reg[4] = Status_reg_in[3];//MSB first, BP2 + Status_reg[3] = Status_reg_in[4];//MSB first, BP1 + Status_reg[2] = Status_reg_in[5];//MSB first, BP0 + case (Status_reg[4:2]) + + 3'b000 : + begin + Sec_Prot = 128'h00000000000000000000000000000000; + end + + 3'b001 : + begin + Sec_Prot = 128'hC0000000000000000000000000000000; + end + + 3'b010 : + begin + Sec_Prot = 128'hF0000000000000000000000000000000; + end + + 3'b011 : + begin + Sec_Prot = 128'hFF000000000000000000000000000000; + end + + 3'b100 : + begin + Sec_Prot = 128'hFFFF0000000000000000000000000000; + end + + 3'b101 : + begin + Sec_Prot = 128'hFFFFFFFF000000000000000000000000; + end + + 3'b110 : + begin + Sec_Prot = 128'hFFFFFFFFFFFFFFFF0000000000000000; + end + + 3'b111 : + begin + Sec_Prot = 128'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + end + + endcase + end + end + end + + always @(current_state or PDONE) + begin: PPPG1 + integer i, j; + if (current_state == PAGE_PG) + begin + ADDRHILO_PG(AddrLo, AddrHi, Addr); + if ((Addr + wr_cnt) > AddrHi) + wr_cnt = AddrHi - Addr; + for (i=Addr;i<=Addr+wr_cnt;i=i+1) + begin + new_int = WData[i-Addr]; + old_int = Mem[i]; + if (new_int > -1) + begin + new_bit = new_int; + if (old_int > -1) + begin + old_bit = old_int; + for(j=0;j<=7;j=j+1) + if (~old_bit[j]) + new_bit[j]=1'b0; + new_int=new_bit; + end + + WData[i-Addr]= new_int; + end + else + begin + WData[i-Addr] = -1; + end + end + + for (i=Addr;i<=Addr+wr_cnt;i=i+1) + begin + Mem[i] = -1; + end + + if (PDONE) + begin + Status_reg[0] = 1'b0;//wip + Status_reg[1] = 1'b0;// wel + for (i=Addr;i<=Addr+wr_cnt;i=i+1) + begin + Mem[i] = WData[i-Addr]; + end + end + end + end + +// Output Control + always @(CSNeg_ipd or HOLDNeg_ipd or SCK_ipd) + begin + //Output Disable Control + if (CSNeg_ipd ) + SO_zd = 1'bZ; + end + + always @(SO_zd or HOLDNeg_ipd) + begin + if (HOLDNeg_ipd == 1) + SO_z = SO_zd; + else + SO_z = 1'bZ; + end + +// Procedure ADDRHILO_SEC + task ADDRHILO_SEC; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer sector; + begin + + sector = Addr / 20'h10000; + AddrLOW = sector * 20'h10000; + AddrHIGH = sector * 20'h10000 + 16'hFFFF; + + end + endtask + +// Procedure ADDRHILO_PG + task ADDRHILO_PG; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer page; + begin + + page = Addr / 16'h100; + AddrLOW = page * 16'h100; + AddrHIGH = page * 16'h100 + 8'hFF; + + end + endtask + +endmodule diff --git a/lib/models/memory/flash/serial/S25fl064a/model/s25fl064a.vhd b/lib/models/memory/flash/serial/S25fl064a/model/s25fl064a.vhd new file mode 100644 index 0000000..445d593 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064a/model/s25fl064a.vhd @@ -0,0 +1,1256 @@ +------------------------------------------------------------------------------- +-- File Name: s25fl064a.vhd +------------------------------------------------------------------------------- +-- Copyright (C) 2006-2007 Spansion, LLC. +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 G.Gojanovic 05 May 11 Inital Release +-- V1.1 D.Randjelovic 06 Apr 11 MSB of latched address is ignored +-- V1.2 D.Randjelovic 06 May 04 Page Program Command used with the +-- single byte data corrected. +-- Release from Deep Power Down when +-- Electronic Signature is not read +-- fixed +-- V1.3 D.Stanojkovic 07 Jul 02 Correction to enable testing in NCSim +-- +------------------------------------------------------------------------------- +-- PART DESCRIPTION: +-- +-- Library: FLASH +-- Technology: Flash Memory +-- Part: S25FL064A +-- +-- Description: 64 Megabit Serial Flash Memory with 50MHz SPI Bus Interface +-- +------------------------------------------------------------------------------- +-- Comments : +-- When testing with NCSim default value for TimingModel in +-- generic list should be removed, otherwise backannotation of this value +-- will not be done properly +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +-- Known Bugs: +-- +------------------------------------------------------------------------------- +LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; + USE STD.textio.ALL; + USE IEEE.VITAL_timing.ALL; + USE IEEE.VITAL_primitives.ALL; + +LIBRARY FMF; USE FMF.gen_utils.ALL; + USE FMF.conversions.ALL; +------------------------------------------------------------------------------- +-- ENTITY DECLARATION +------------------------------------------------------------------------------- +ENTITY s25fl064a IS + GENERIC ( + -- tipd delays: interconnect path delays + tipd_SCK : VitalDelayType01 := VitalZeroDelay01; + tipd_SI : VitalDelayType01 := VitalZeroDelay01; + tipd_CSNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_HOLDNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WNeg : VitalDelayType01 := VitalZeroDelay01; + + -- tpd delays + tpd_SCK_SO : VitalDelayType01Z := UnitDelay01Z;--tV + tpd_CSNeg_SO : VitalDelayType01Z := UnitDelay01Z;--tDIS + tpd_HOLDNeg_SO : VitalDelayType01Z := UnitDelay01Z;--tLZ,tHZ + + --tsetup values + tsetup_SI_SCK : VitalDelayType := UnitDelay; --tsuDAT / + tsetup_CSNeg_SCK : VitalDelayType := UnitDelay; --tCSS / + tsetup_HOLDNeg_SCK : VitalDelayType := UnitDelay; --tHD / + tsetup_WNeg_CSNeg : VitalDelayType := UnitDelay; --tWPS \ + + --thold values + thold_SI_SCK : VitalDelayType := UnitDelay; --thdDAT / + thold_CSNeg_SCK : VitalDelayType := UnitDelay; --tCSH / + thold_HOLDNeg_SCK : VitalDelayType := UnitDelay; --tCD / + thold_WNeg_CSNeg : VitalDelayType := UnitDelay; --tWPH \ + + --tpw values: pulse width + tpw_SCK_posedge : VitalDelayType := UnitDelay; --tWH + tpw_SCK_negedge : VitalDelayType := UnitDelay; --tWL + tpw_CSNeg_posedge : VitalDelayType := UnitDelay; --tCS + + -- tperiod min (calculated as 1/max freq) + tperiod_SCK_rd : VitalDelayType := UnitDelay; -- fSCK=33MHz + tperiod_SCK_fast_rd : VitalDelayType := UnitDelay; -- fSCK=50MHz + + -- tdevice values: values for internal delays + -- Page Program Operation + tdevice_PP : VitalDelayType := 3 ms; --tPP + --Sector Erase Operation + tdevice_SE : VitalDelayType := 3 sec; --tSE + --Bulk Erase Operation + tdevice_BE : VitalDelayType := 384 sec; --tBE + --Write Status Register Operation + tdevice_WR : VitalDelayType := 60 ms; --tW + --Deep Power Down + tdevice_DP : VitalDelayType := 3 us; --tDP + --Release from Software Protect Mode + tdevice_RES : VitalDelayType := 30 us; --tRES + --VCC (min) to CS# Low + tdevice_PU : VitalDelayType := 10 ms; + -- generic control parameters + InstancePath : STRING := DefaultInstancePath; + TimingChecksOn : BOOLEAN := DefaultTimingChecks; + MsgOn : BOOLEAN := DefaultMsgOn; + XOn : BOOLEAN := DefaultXon; + -- memory file to be loaded + mem_file_name : STRING := "s25fl064a.mem"; + + UserPreload : BOOLEAN := FALSE; --TRUE; + LongTimming : BOOLEAN := TRUE; + + -- For FMF SDF technology file usage + TimingModel : STRING --:= DefaultTimingModel + ); + PORT ( + SCK : IN std_ulogic := 'U'; --serial clock input + SI : IN std_ulogic := 'U'; --serial data input + CSNeg : IN std_ulogic := 'U'; -- chip select input + HOLDNeg : IN std_ulogic := 'U'; -- hold input + WNeg : IN std_ulogic := 'U'; -- write protect input + SO : OUT std_ulogic := 'U' --serial data output + ); + ATTRIBUTE VITAL_LEVEL0 of s25fl064a : ENTITY IS TRUE; +END s25fl064a; + +------------------------------------------------------------------------------- +-- ARCHITECTURE DECLARATION +------------------------------------------------------------------------------- +ARCHITECTURE vhdl_behavioral of s25fl064a IS + ATTRIBUTE VITAL_LEVEL0 OF vhdl_behavioral : ARCHITECTURE IS TRUE; + + CONSTANT PartID : STRING := "s25fl064a"; + CONSTANT MaxData : NATURAL := 16#FF#; --255; + CONSTANT SecSize : NATURAL := 16#FFFF#; --65535 + CONSTANT SecNum : NATURAL := 127; + CONSTANT HiAddrBit : NATURAL := 22; + CONSTANT AddrRANGE : NATURAL := 16#7FFFFF#; + CONSTANT BYTE : NATURAL := 8; + --Electronic Signature + CONSTANT ES : NATURAL := 16#16#; + --Device ID + --Manufacturer Identification && Memory Type && Memory Capacity + CONSTANT DeviceID : NATURAL := 16#010216#; + +-- interconnect path delay signals + SIGNAL SCK_ipd : std_ulogic := 'U'; + SIGNAL SI_ipd : std_ulogic := 'U'; + SIGNAL CSNeg_ipd : std_ulogic := 'U'; + SIGNAL HOLDNeg_ipd : std_ulogic := 'U'; + SIGNAL WNeg_ipd : std_ulogic := 'U'; + + --- internal delays + SIGNAL PP_in : std_ulogic := '0'; + SIGNAL PP_out : std_ulogic := '0'; + SIGNAL PU_in : std_ulogic := '0'; + SIGNAL PU_out : std_ulogic := '0'; + SIGNAL SE_in : std_ulogic := '0'; + SIGNAL SE_out : std_ulogic := '0'; + SIGNAL BE_in : std_ulogic := '0'; + SIGNAL BE_out : std_ulogic := '0'; + SIGNAL WR_in : std_ulogic := '0'; + SIGNAL WR_out : std_ulogic := '0'; + SIGNAL DP_in : std_ulogic := '0'; + SIGNAL DP_out : std_ulogic := '0'; + SIGNAL RES_in : std_ulogic := '0'; + SIGNAL RES_out : std_ulogic := '0'; + +BEGIN + --------------------------------------------------------------------------- + -- Internal Delays + --------------------------------------------------------------------------- + -- Artificial VITAL primitives to incorporate internal delays + PP :VitalBuf(PP_out, PP_in, (tdevice_PP ,UnitDelay)); + PU :VitalBuf(PU_out, PU_in, (tdevice_PU ,UnitDelay)); + SE :VitalBuf(SE_out, SE_in, (tdevice_SE ,UnitDelay)); + BE :VitalBuf(BE_out, BE_in, (tdevice_BE ,UnitDelay)); + WR :VitalBuf(WR_out, WR_in, (tdevice_WR ,UnitDelay)); + DP :VitalBuf(DP_out, DP_in, (tdevice_DP ,UnitDelay)); + RES :VitalBuf(RES_out, RES_in, (tdevice_RES ,UnitDelay)); + + --------------------------------------------------------------------------- + -- Wire Delays + --------------------------------------------------------------------------- + WireDelay : BLOCK + BEGIN + + w_1 : VitalWireDelay (SCK_ipd, SCK, tipd_SCK); + w_2 : VitalWireDelay (SI_ipd, SI, tipd_SI); + w_3 : VitalWireDelay (CSNeg_ipd, CSNeg, tipd_CSNeg); + w_4 : VitalWireDelay (HOLDNeg_ipd, HOLDNeg, tipd_HOLDNeg); + w_5 : VitalWireDelay (WNeg_ipd, WNeg, tipd_WNeg); + + END BLOCK; + + --------------------------------------------------------------------------- + -- Main Behavior Block + --------------------------------------------------------------------------- + Behavior: BLOCK + + -- State Machine : State_Type + TYPE state_type IS (IDLE, + DP_DOWN, + WRITE_SR, + SECTOR_ER, + BULK_ER, + PAGE_PG + ); + + -- Instruction Type + TYPE instruction_type IS (NONE, + WREN, + WRDI, + WRSR, + RDSR, + READ, + RDID, + FAST_READ, + SE, + BE, + PP, + DP, + RES_READ_ES + ); + + TYPE WByteType IS ARRAY (0 TO 255) OF INTEGER RANGE -1 TO MaxData; + --Flash Memory Array + TYPE MemArray IS ARRAY (0 TO AddrRANGE) OF INTEGER RANGE -1 TO MaxData; + + --------------------------------------------------------------------------- + -- memory declaration + --------------------------------------------------------------------------- + SHARED VARIABLE Mem : MemArray := (OTHERS => MaxData); + + -- states + SIGNAL current_state : state_type; + SIGNAL next_state : state_type; + + SIGNAL WByte : WByteType := (others => 0); + SIGNAL Instruct : instruction_type; + --zero delay signal + SIGNAL SO_zd : std_logic :='Z'; + --HOLD delay on output data + SIGNAL SO_z : std_logic :='Z'; + -- powerup + SIGNAL PoweredUp : std_logic := '0'; + + SHARED VARIABLE Status_reg : std_logic_vector(7 downto 0) + := (others => '0'); + + SIGNAL Status_reg_in : std_logic_vector(7 downto 0) + := (others => '0'); + + ALIAS WEL :std_logic IS Status_reg(1); + ALIAS WIP :std_logic IS Status_reg(0); + ALIAS BP0 :std_logic IS Status_reg(2); + ALIAS BP1 :std_logic IS Status_reg(3); + ALIAS BP2 :std_logic IS Status_reg(4); + ALIAS SRWD :std_logic IS Status_reg(7); + --Command Register + SIGNAL write : std_logic := '0'; + SIGNAL read_out : std_logic := '0'; + + SIGNAL fast_rd : boolean := true; + SIGNAL rd : boolean := false; + + SIGNAL change_addr : std_logic := '0'; + + --FSM control signals + SIGNAL PDONE : std_logic := '1'; -- Page Prog. Done + SIGNAL PSTART : std_logic := '0'; --Start Page Programming + + SIGNAL WDONE : std_logic := '1'; -- Write. Done + SIGNAL WSTART : std_logic := '0'; --Start Write + + SIGNAL ESTART : std_logic := '0'; --Start Erase + SIGNAL EDONE : std_logic := '1'; --Erase Done + + SIGNAL SA : NATURAL RANGE 0 TO SecNum := 0; + SIGNAL Byte_number : NATURAL RANGE 0 TO 255 := 0; + + SHARED VARIABLE Sec_Prot : std_logic_vector(SecNum downto 0) := + (OTHERS => '0'); + + SIGNAL Address : NATURAL RANGE 0 TO AddrRANGE := 0; + + -- timing check violation + SIGNAL Viol : X01 := '0'; + + PROCEDURE ADDRHILO_SEC( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE Addr : NATURAL) IS + VARIABLE sector : NATURAL RANGE 0 TO SecNum; + BEGIN + sector := Addr/16#10000#; + AddrLOW := sector*16#10000#; + AddrHIGH := sector*16#10000# + 16#0FFFF#; + END AddrHILO_SEC; + + PROCEDURE ADDRHILO_PG( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE Addr : NATURAL) IS + VARIABLE page : NATURAL RANGE 0 TO 65535; + BEGIN + page := Addr/16#100#; + AddrLOW := Page*16#100#; + AddrHIGH := Page*16#100# + 16#FF#; + END AddrHILO_PG; + + BEGIN + ---------------------------------------------------------------------------- + --Power Up time; + --------------------------------------------------------------------------- + + PoweredUp <= '1' AFTER tdevice_PU; + + --------------------------------------------------------------------------- + -- VITAL Timing Checks Procedures + --------------------------------------------------------------------------- + VITALTimingCheck: PROCESS(SI_ipd, SCK_ipd, CSNeg_ipd, HOLDNeg_ipd, + WNeg_ipd) + -- Timing Check Variables + VARIABLE Tviol_SI_SCK : X01 := '0'; + VARIABLE TD_SI_SCK : VitalTimingDataType; + + VARIABLE Tviol_HOLD_SCK : X01 := '0'; + VARIABLE TD_HOLD_SCK : VitalTimingDataType; + + VARIABLE Tviol_CS_SCK : X01 := '0'; + VARIABLE TD_CS_SCK : VitalTimingDataType; + + VARIABLE Tviol_WS_CS : X01 := '0'; + VARIABLE TD_WS_CS : VitalTimingDataType; + + VARIABLE Tviol_WH_CS : X01 := '0'; + VARIABLE TD_WH_CS : VitalTimingDataType; + + VARIABLE Pviol_CS : X01 := '0'; + VARIABLE PD_CS : VitalPeriodDataType := VitalPeriodDataInit; + + VARIABLE Pviol_SCK : X01 := '0'; + VARIABLE PD_SCK : VitalPeriodDataType := VitalPeriodDataInit; + + VARIABLE Pviol_SCK_rd : X01 := '0'; + VARIABLE PD_SCK_rd : VitalPeriodDataType := VitalPeriodDataInit; + + VARIABLE Pviol_SCK_fast_rd: X01 := '0'; + VARIABLE PD_SCK_fast_rd : VitalPeriodDataType := VitalPeriodDataInit; + + VARIABLE Violation : X01 := '0'; + + BEGIN + --------------------------------------------------------------------------- + -- Timing Check Section + --------------------------------------------------------------------------- + IF (TimingChecksOn) THEN + + -- Setup/Hold Check between SI and SCK + VitalSetupHoldCheck ( + TestSignal => SI_ipd, + TestSignalName => "SI", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK, + SetupLow => tsetup_SI_SCK, + HoldHigh => thold_SI_SCK, + HoldLow => thold_SI_SCK, + CheckEnabled => true, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_SI_SCK, + Violation => Tviol_SI_SCK + ); + + -- Setup/Hold Check between HOLD# and SCK / + VitalSetupHoldCheck ( + TestSignal => HOLDNeg_ipd, + TestSignalName => "HOLD#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupLow => tsetup_HOLDNeg_SCK, + HoldLow => thold_HOLDNeg_SCK, + CheckEnabled => true, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_HOLD_SCK, + Violation => Tviol_HOLD_SCK + ); + + -- Setup/Hold Check between CS# and SCK + VitalSetupHoldCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_CSNeg_SCK, + SetupLow => tsetup_CSNeg_SCK, + HoldHigh => thold_CSNeg_SCK, + HoldLow => thold_CSNeg_SCK, + CheckEnabled => true, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_CS_SCK, + Violation => Tviol_CS_SCK + ); + + -- Setup Check between W# and CS# \ + VitalSetupHoldCheck ( + TestSignal => WNeg_ipd, + TestSignalName => "W#", + RefSignal => CSNeg_ipd, + RefSignalName => "CS#", + SetupHigh => tsetup_WNeg_CSNeg, + CheckEnabled => true, + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WS_CS, + Violation => Tviol_WS_CS + ); + + -- Hold Check between W# and CS# / + VitalSetupHoldCheck ( + TestSignal => WNeg_ipd, + TestSignalName => "W#", + RefSignal => CSNeg_ipd, + RefSignalName => "CS#", + HoldHigh => thold_WNeg_CSNeg, + CheckEnabled => true, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WH_CS, + Violation => Tviol_WH_CS + ); + + -- Period Check CS# m + VitalPeriodPulseCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + PulseWidthHigh => tpw_CSNeg_posedge, + PeriodData => PD_CS, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_CS, + HeaderMsg => InstancePath & PartID, + CheckEnabled => true ); + + -- Period Check SCK for everything but READ + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_negedge, + PulseWidthHigh => tpw_SCK_posedge, + PeriodData => PD_SCK, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK, + HeaderMsg => InstancePath & PartID, + CheckEnabled => true ); + + -- Period Check SCK for READ + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_rd, + PeriodData => PD_SCK_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => rd ); + + -- Period Check SCK for other than READ + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_fast_rd, + PeriodData => PD_SCK_fast_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_fast_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => fast_rd ); + + Violation := Tviol_SI_SCK OR + Tviol_HOLD_SCK OR + Tviol_CS_SCK OR + Tviol_WS_CS OR + Tviol_WH_CS OR + Pviol_SCK OR + Pviol_SCK_rd OR + Pviol_SCK_fast_rd OR + Pviol_CS; + + Viol <= Violation; + + ASSERT Violation = '0' + REPORT InstancePath & partID & ": simulation may be" & + " inaccurate due to timing violations" + SEVERITY WARNING; + + END IF; +END PROCESS VITALTimingCheck; + + ---------------------------------------------------------------------------- + -- sequential process for FSM state transition + ---------------------------------------------------------------------------- + StateTransition : PROCESS(next_state, PoweredUp) + + BEGIN + IF PoweredUp = '1' THEN + current_state <= next_state; + END IF; +END PROCESS StateTransition; + + --------------------------------------------------------------------------- + -- Write cycle decode + --------------------------------------------------------------------------- + BusCycleDecode : PROCESS(SCK_ipd, CSNeg_ipd, HOLDNeg_ipd, SI_ipd, RES_in) + + TYPE bus_cycle_type IS (STAND_BY, + CODE_BYTE, + ADDRESS_BYTES, + DUMMY_BYTES, + DATA_BYTES + ); + + VARIABLE bus_cycle_state : bus_cycle_type; + + VARIABLE data_cnt : NATURAL := 0; + VARIABLE addr_cnt : NATURAL := 0; + VARIABLE code_cnt : NATURAL := 0; + VARIABLE dummy_cnt : NATURAL := 0; + VARIABLE bit_cnt : NATURAL := 0; + VARIABLE Data_in : std_logic_vector(2047 downto 0) + := (others => '0'); + VARIABLE code : std_logic_vector(7 downto 0); + VARIABLE code_in : std_logic_vector(7 downto 0); + VARIABLE Byte_slv : std_logic_vector(7 downto 0); + VARIABLE addr_bytes : std_logic_vector(HiAddrBit downto 0); + VARIABLE Address_in : std_logic_vector(23 downto 0); + BEGIN + + CASE bus_cycle_state IS + WHEN STAND_BY => + IF falling_edge(CSNeg_ipd) THEN + Instruct <= NONE; + write <= '1'; + code_cnt := 0; + addr_cnt := 0; + data_cnt := 0; + dummy_cnt := 0; + bus_cycle_state := CODE_BYTE; + END IF; + + WHEN CODE_BYTE => + IF rising_edge(SCK_ipd) AND HOLDNeg_ipd = '1' THEN + Code_in(code_cnt) := SI_ipd; + code_cnt := code_cnt + 1; + IF code_cnt = BYTE THEN + --MSB first + FOR I IN 7 DOWNTO 0 LOOP + code(i) := code_in(7-i); + END LOOP; + CASE code IS + WHEN "00000110" => + Instruct <= WREN; + bus_cycle_state := DATA_BYTES; + WHEN "00000100" => + Instruct <= WRDI; + bus_cycle_state := DATA_BYTES; + WHEN "00000001" => + Instruct <= WRSR; + bus_cycle_state := DATA_BYTES; + WHEN "00000101" => + Instruct <= RDSR; + bus_cycle_state := DATA_BYTES; + WHEN "00000011" => + Instruct <= READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00001011" => + Instruct <= FAST_READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10011111" => + Instruct <= RDID; + bus_cycle_state := DATA_BYTES; + WHEN "10101011" => + Instruct <= RES_READ_ES; + bus_cycle_state := DUMMY_BYTES; + WHEN "11011000" => + Instruct <= SE; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11000111" => + Instruct <= BE; + bus_cycle_state := DATA_BYTES; + WHEN "00000010" => + Instruct <= PP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10111001" => + Instruct <= DP; + bus_cycle_state := DATA_BYTES; + WHEN others => + null; + END CASE; + END IF; + END IF; + + WHEN ADDRESS_BYTES => + IF rising_edge(SCK_ipd) AND HOLDNeg_ipd = '1' THEN + Address_in(addr_cnt) := SI_ipd; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 3*BYTE THEN + FOR I IN 23 DOWNTO 23-HiAddrBit LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF Instruct = FAST_READ THEN + bus_cycle_state := DUMMY_BYTES; + ELSE + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + END IF; + + WHEN DUMMY_BYTES => + IF rising_edge(SCK_ipd) AND HOLDNeg_ipd = '1' THEN + dummy_cnt := dummy_cnt + 1; + IF dummy_cnt = BYTE THEN + IF Instruct = FAST_READ THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF dummy_cnt = 3*BYTE THEN + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + + IF rising_edge(CSNeg_ipd) THEN + bus_cycle_state := STAND_BY; + IF HOLDNeg_ipd = '1' AND Instruct = RES_READ_ES THEN + write <= '0'; + END IF; + END IF; + + WHEN DATA_BYTES => + IF falling_edge(SCK_ipd) AND CSNeg_ipd = '0' + AND HOLDNeg_ipd = '1' THEN + IF Instruct = READ OR Instruct = RES_READ_ES + OR Instruct = FAST_READ OR Instruct = RDSR + OR Instruct = RDID THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + + IF rising_edge(SCK_ipd) AND HOLDNeg_ipd = '1' THEN + IF data_cnt > 2047 THEN + --In case of PP, if more than 256 bytes are + --sent to the device + IF bit_cnt = 0 THEN + FOR I IN 0 TO (255*BYTE - 1) LOOP + Data_in(i) := Data_in(i+8); + END LOOP; + END IF; + Data_in(2040 + bit_cnt) := SI_ipd; + bit_cnt := bit_cnt + 1; + IF bit_cnt = 8 THEN + bit_cnt := 0; + END IF; + data_cnt := data_cnt + 1; + ELSE + Data_in(data_cnt) := SI_ipd; + data_cnt := data_cnt + 1; + bit_cnt := 0; + END IF; + END IF; + + IF rising_edge(CSNeg_ipd) THEN + bus_cycle_state := STAND_BY; + IF HOLDNeg_ipd = '1' THEN + CASE Instruct IS + WHEN WREN | WRDI | DP | BE | SE => + IF data_cnt = 0 THEN + write <= '0'; + END IF; + WHEN RDID | RES_READ_ES => + write <= '0'; + WHEN WRSR => + IF data_cnt = 8 THEN + write <= '0'; + Status_reg_in <= Data_in(7 downto 0); + --MSB first + END IF; + WHEN PP => + IF ((data_cnt mod 8) = 0 AND + data_cnt > 0) THEN + write <= '0'; + FOR I IN 0 TO 255 LOOP + FOR J IN 7 DOWNTO 0 LOOP + Byte_slv(j) := + Data_in((i*8) + (7-j)); + END LOOP; + WByte(i) <= to_nat(Byte_slv); + END LOOP; + IF data_cnt > 256*BYTE THEN + Byte_number <= 255; + ELSE + Byte_number <= data_cnt/8-1; + END IF; + END IF; + WHEN others => + null; + END CASE; + END IF; + END IF; + + END CASE; + +END PROCESS BusCycleDecode; + --------------------------------------------------------------------------- + -- Timing control for the Page Program + --------------------------------------------------------------------------- + ProgTime : PROCESS(PSTART) + VARIABLE pob : time; + BEGIN + IF LongTimming THEN + pob := tdevice_PP; + ELSE + pob := tdevice_PP / 100; + END IF; + IF rising_edge(PSTART) AND PDONE = '1' THEN + IF NOT Sec_Prot(SA) = '1' THEN + PDONE <= '0', '1' AFTER pob; + END IF; + END IF; +END PROCESS ProgTime; + --------------------------------------------------------------------------- + -- Timing control for the Write Status Register + --------------------------------------------------------------------------- + WriteTime : PROCESS(WSTART) + VARIABLE wob : time; + BEGIN + IF LongTimming THEN + wob := tdevice_WR; + ELSE + wob := tdevice_WR / 100; + END IF; + IF rising_edge(WSTART) AND WDONE = '1' THEN + WDONE <= '0', '1' AFTER wob; + END IF; +END PROCESS WriteTime; + --------------------------------------------------------------------------- + -- Timing control for the Bulk Erase + --------------------------------------------------------------------------- + ErsTime : PROCESS(ESTART) + VARIABLE seo : time; + VARIABLE beo : time; + VARIABLE duration : time; + BEGIN + IF LongTimming THEN + seo := tdevice_SE; + beo := tdevice_BE; + ELSE + seo := tdevice_SE / 100; + beo := tdevice_BE / 100; + END IF; + IF rising_edge(ESTART) AND EDONE = '1' THEN + IF Instruct = BE THEN + duration := beo; + ELSE --Instruct = SE + duration := seo; + END IF; + EDONE <= '0', '1' AFTER duration; + END IF; +END PROCESS ErsTime; + + CheckCEOnPowerUP :PROCESS + BEGIN + IF CSNeg /= '1' THEN + REPORT InstancePath & partID & + ": Device is selected during Power Up" + SEVERITY WARNING; + END IF; + WAIT; + END PROCESS; + + --------------------------------------------------------------------------- + -- Main Behavior Process + -- combinational process for next state generation + --------------------------------------------------------------------------- + StateGen :PROCESS(write, CSNeg, WDONE, PDONE, EDONE) + + VARIABLE sect : NATURAL RANGE 0 TO SecNum; + + BEGIN + ----------------------------------------------------------------------- + -- Functionality Section + ----------------------------------------------------------------------- + + CASE current_state IS + WHEN IDLE => + IF falling_edge(write) THEN + IF Instruct = WRSR AND WEL = '1' + AND not(SRWD = '1' AND WNeg = '0') THEN + -- can not execute if HPM is entered + -- or if WEL bit is zero + next_state <= WRITE_SR; + ELSIF Instruct = PP AND WEL = '1' THEN + sect := Address / 16#10000#; + IF Sec_Prot(sect) = '0' THEN + next_state <= PAGE_PG; + END IF; + ELSIF Instruct = SE AND WEL = '1' THEN + sect := Address / 16#10000#; + IF Sec_Prot(sect) = '0' THEN + next_state <= SECTOR_ER; + END IF; + ELSIF Instruct = BE AND WEL = '1' AND + (BP0 = '0' AND BP1 = '0' AND BP2 = '0') THEN + next_state <= BULK_ER; + ELSIF Instruct = DP THEN + next_state <= DP_DOWN; + ELSE + next_state <= IDLE; + END IF; + END IF; + + WHEN WRITE_SR => + IF rising_edge(WDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PAGE_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN BULK_ER | SECTOR_ER => + IF rising_edge(EDONE) THEN + next_state <= IDLE; + END IF; + + WHEN DP_DOWN => + IF falling_edge(write) AND Instruct = RES_READ_ES THEN + next_state <= IDLE; + END IF; + + END CASE; + +END PROCESS StateGen; + + --------------------------------------------------------------------------- + --FSM Output generation and general funcionality + --------------------------------------------------------------------------- + Functional : PROCESS(write,read_out, WDONE, PDONE, EDONE, current_state, + CSNeg_ipd, HOLDNeg_ipd, Instruct, Address, WByte, + RES_out, change_addr, PoweredUp, WNeg_ipd) + + TYPE WDataType IS ARRAY (0 TO 255) OF INTEGER RANGE -1 TO MaxData; + + VARIABLE WData : WDataType:= (OTHERS => 0); + + VARIABLE oe : boolean := FALSE; + + VARIABLE AddrLo : NATURAL; + VARIABLE AddrHi : NATURAL; + VARIABLE Addr : NATURAL; + + VARIABLE read_cnt : NATURAL; + VARIABLE read_addr : NATURAL RANGE 0 TO AddrRANGE; + VARIABLE data_out : std_logic_vector(7 downto 0); + VARIABLE ident_out : std_logic_vector(23 downto 0); + + VARIABLE old_bit : std_logic_vector(7 downto 0); + VARIABLE new_bit : std_logic_vector(7 downto 0); + VARIABLE old_int : INTEGER RANGE -1 to MaxData; + VARIABLE new_int : INTEGER RANGE -1 to MaxData; + VARIABLE wr_cnt : NATURAL RANGE 0 TO 255; + + VARIABLE sect : NATURAL RANGE 0 TO SecNum; + VARIABLE BP : std_logic_vector(2 downto 0) := "000"; + + BEGIN + ----------------------------------------------------------------------- + -- Functionality Section + ----------------------------------------------------------------------- + + oe := rising_edge(read_out) AND PoweredUp = '1'; + + IF Instruct'EVENT THEN + read_cnt := 0; + fast_rd <= true; + rd <= false; + END IF; + + IF rising_edge(change_addr) THEN + read_addr := Address; + END IF; + + IF RES_out'EVENT AND RES_out = '1' THEN + RES_in <= '0'; + END IF; + + CASE current_state IS + WHEN IDLE => + IF falling_edge(write) THEN + read_cnt := 0; + IF RES_in = '1' THEN + ASSERT false + REPORT InstancePath & partID & "Command results" & + " can be corrupted, a delay of tRES" & + " currently in progress." + SEVERITY WARNING; + END IF; + IF Instruct = WREN THEN + WEL := '1'; + ELSIF Instruct = WRDI THEN + WEL := '0'; + ELSIF Instruct = WRSR AND WEL = '1' + AND not(SRWD = '1' AND WNeg_ipd = '0') THEN + -- can not execute if HPM is entered + -- or if WEL bit is zero + WSTART <= '1', '0' AFTER 1 ns; + WIP := '1'; + ELSIF Instruct = PP AND WEL = '1' THEN + sect := Address / 16#10000#; + IF Sec_Prot(sect) = '0' THEN + PSTART <= '1', '0' AFTER 1 ns; + WIP := '1'; + SA <= sect; + Addr := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' AND Sec_Prot(SA) /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + END IF; + ELSIF Instruct = SE AND WEL = '1' THEN + sect := Address / 16#10000#; + IF Sec_Prot(sect) = '0' THEN + ESTART <= '1', '0' AFTER 1 ns; + WIP := '1'; + Addr := Address; + END IF; + ELSIF Instruct = BE AND WEL = '1' AND + (BP0 = '0' AND BP1 = '0' AND BP2 = '0') THEN + ESTART <= '1', '0' AFTER 1 ns; + WIP := '1'; + END IF; + + ELSIF oe AND RES_in = '0' THEN + IF Instruct = RDSR THEN + --Read Status Register + SO_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = READ OR Instruct = FAST_READ THEN + --Read Memory array + IF Instruct = READ THEN + fast_rd <= false; + rd <= true; + END IF; + data_out := to_slv(Mem(read_addr),8); + SO_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSIF Instruct = RDID THEN + --Read Device ID + --can be terminated by driving CSNeg high + --at any time + ident_out := to_slv(DeviceID,24); + SO_zd <= ident_out(23-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 24 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RES_READ_ES THEN + --Read Electronic Signature + data_out := to_slv(ES,8); + SO_zd <= data_out(7 - read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe AND RES_in = '1' THEN + SO_zd <= 'X'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ASSERT false + REPORT InstancePath & partID & "Command results" & + " can be corrupted, a delay of tRES" & + " currently in progress." + SEVERITY WARNING; + + END IF; + + WHEN WRITE_SR => + + IF oe AND Instruct = RDSR THEN + SO_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + + IF WDONE = '1' THEN + WIP := '0'; + WEL := '0'; + SRWD := Status_reg_in(0);--MSB first + BP2 := Status_reg_in(3); + BP1 := Status_reg_in(4); + BP0 := Status_reg_in(5); + BP := BP2 & BP1 & BP0; + CASE BP IS + WHEN "000" => + Sec_Prot := (others => '0'); + WHEN "001" => + Sec_Prot(127) := '1'; + Sec_Prot(126) := '1'; + Sec_Prot(125 downto 0) := (others => '0'); + WHEN "010" => + Sec_Prot(127 downto 124):= (others => '1'); + Sec_Prot(123 downto 0) := (others => '0'); + WHEN "011" => + Sec_Prot(127 downto 120):= to_slv(16#FF#,8); + Sec_Prot(119 downto 0) := (others => '0'); + WHEN "100" => + Sec_Prot(127 downto 112):= to_slv(16#FFFF#,16); + Sec_Prot(111 downto 0) := (others => '0'); + WHEN "101" => + Sec_Prot(127 downto 112):= to_slv(16#FFFF#,16); + Sec_Prot(111 downto 96):= to_slv(16#FFFF#,16); + Sec_Prot(95 downto 0) := (others => '0'); + WHEN "110" => + Sec_Prot(127 downto 112):= to_slv(16#FFFF#,16); + Sec_Prot(111 downto 96):= to_slv(16#FFFF#,16); + Sec_Prot(95 downto 80):= to_slv(16#FFFF#,16); + Sec_Prot(79 downto 64):= to_slv(16#FFFF#,16); + Sec_Prot(63 downto 0) := (others => '0'); + WHEN others => + Sec_Prot := (others => '1'); + END CASE; + END IF; + + WHEN PAGE_PG => + + IF oe AND Instruct = RDSR THEN + SO_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + + ADDRHILO_PG(AddrLo, AddrHi, Addr); + IF (Addr + wr_cnt) > AddrHi THEN + wr_cnt := AddrHi - Addr; + END IF; + + FOR I IN Addr TO Addr + wr_cnt LOOP + new_int := WData(i-Addr); + old_int := Mem(i); + IF new_int > -1 THEN + new_bit := to_slv(new_int,8); + IF old_int > -1 THEN + old_bit := to_slv(old_int,8); + FOR j IN 0 TO 7 LOOP + IF old_bit(j) = '0' THEN + new_bit(j) := '0'; + END IF; + END LOOP; + new_int := to_nat(new_bit); + END IF; + WData(i-Addr) := new_int; + ELSE + WData(i-Addr) := -1; + END IF; + END LOOP; + + FOR I IN Addr TO Addr + wr_cnt LOOP + Mem (i) := -1; + END LOOP; + + IF PDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN Addr TO Addr + wr_cnt LOOP + Mem(i) := WData(i-Addr); + END LOOP; + END IF; + + WHEN SECTOR_ER => + + IF oe AND Instruct = RDSR THEN + SO_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := -1; + END LOOP; + IF EDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := MaxData; + END LOOP; + END IF; + + WHEN BULK_ER => + + IF oe AND Instruct = RDSR THEN + SO_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + + FOR i IN 0 TO AddrRANGE LOOP + Mem(i) := -1; + END LOOP; + IF EDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO AddrRANGE LOOP + Mem(i) := MaxData; + END LOOP; + END IF; + + WHEN DP_DOWN => + IF falling_edge(write) THEN + IF Instruct = RES_READ_ES THEN + RES_in <= '1'; + END IF; + ELSIF oe AND Instruct = RES_READ_ES THEN + --Read Electronic Signature + data_out := to_slv(ES,8); + SO_zd <= data_out(7 - read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + + END CASE; + + --Output Disable Control + IF (CSNeg_ipd = '1') THEN + SO_zd <= 'Z'; + END IF; + +END PROCESS Functional; + + HOLD_FRAME_ON_SO_ZD : PROCESS( SO_zd, HOLDNeg_ipd) + BEGIN + IF (HOLDNeg_ipd = '0') THEN + SO_z <= 'Z'; + ELSE + SO_z <= SO_zd; + END IF; + END PROCESS HOLD_FRAME_ON_SO_ZD; + + --------------------------------------------------------------------------- + ---- File Read Section - Preload Control + --------------------------------------------------------------------------- + MemPreload : PROCESS + + -- text file input variables + FILE mem_file : text is mem_file_name; + VARIABLE ind : NATURAL := 0; + VARIABLE buf : line; + + BEGIN + --------------------------------------------------------------------------- + --s25fl016a memory preload file format ----------------------------------- + --------------------------------------------------------------------------- + -- / - comment + -- @aaaaaa - stands for address + -- dd -
is byte to be written at Mem(aaaaaa++) + -- (aaaaaa is incremented at every load) + -- only first 1-7 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + --------------------------------------------------------------------------- + + -- memory preload + IF (mem_file_name /= "none" AND UserPreload) THEN + ind := 0; + Mem := (OTHERS => MaxData); + WHILE (not ENDFILE (mem_file)) LOOP + READLINE (mem_file, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 7)); --address + IF ind > AddrRANGE THEN + ASSERT false + REPORT "Given preload address is out of" & + "memory address range" + SEVERITY warning; + END IF; + ELSE + IF ind <= AddrRANGE THEN + Mem(ind) := h(buf(1 to 2)); + END IF; + IF ind < AddrRANGE THEN + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + WAIT; + END PROCESS MemPreload; + + SO_OUT: PROCESS(SO_z) + + VARIABLE SO_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => SO, + OutSignalName => "SO", + OutTemp => SO_z, + GlitchData => SO_GlitchData, + XOn => XOn, + MsgOn => MsgOn, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO), + PathCondition => SO_z /= 'Z'), + 1 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1'), + 2 => (InputChangeTime => HOLDNeg_ipd'LAST_EVENT, + PathDelay => tpd_HOLDNeg_SO, + PathCondition => TRUE) + ) + ); + END PROCESS SO_OUT; + + END BLOCK behavior; +END vhdl_behavioral; diff --git a/lib/models/memory/flash/serial/S25fl064a/model/s25fl064a_verilog.ftm b/lib/models/memory/flash/serial/S25fl064a/model/s25fl064a_verilog.ftm new file mode 100644 index 0000000..d1fe8c7 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064a/model/s25fl064a_verilog.ftm @@ -0,0 +1,52 @@ + +FMF Timing for s25fl064a Parts + + +version: | author: | mod date: | changes made: + V1.0 G.Gojanovic 05 May 13 Initial release + +1ns +s25fl064a + +S25Fl064A0LMAI000 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LMFI000 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LNAI000 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LNFI000 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LMAI001 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LMFI001 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LNAI001 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LNFI001 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LMAI003 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LMFI003 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LNAI003 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LNFI003 s25fl064a_00_a0 April 26, 2005 +The values listed are for VCC=2.7V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius +Comercial Ta=0 to +70 Celsius + + (DELAY (ABSOLUTE + + (IOPATH SCK SO (3:6:9) (3:6:9) () (3:6:9) () (3:6:9)) + (IOPATH HOLDNeg SO () () (4:7:10) (4:7:10) (4:7:10) (4:7:10)) + (IOPATH CSNeg SO () () (4:7:10) () (4:7:10) ()) +)) +(TIMINGCHECK + + (SETUP CSNeg SCK (5)) + (SETUP HOLDNeg SCK (5)) + (SETUP SI SCK (5)) + (SETUP WNeg CSNeg (15)) + + (HOLD CSNeg SCK (5)) + (HOLD HOLDNeg SCK (5)) + (HOLD SI SCK (5)) + (HOLD WNeg CSNeg (15)) + + (WIDTH (negedge SCK) (9)) + (WIDTH (posedge SCK) (9)) + (WIDTH (posedge CSNeg) (100)) + (PERIOD (COND fast_rd SCK) (20.0)) + (PERIOD (COND rd SCK) (40.0)) +) + + diff --git a/lib/models/memory/flash/serial/S25fl064a/model/s25fl064a_vhd.ftm b/lib/models/memory/flash/serial/S25fl064a/model/s25fl064a_vhd.ftm new file mode 100644 index 0000000..0cab2e7 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064a/model/s25fl064a_vhd.ftm @@ -0,0 +1,65 @@ + +FMF Timing for s25fl064a Parts + + +version: | author: | mod date: | changes made: + V1.0 G.Gojanovic 05 May 11 Initial release + +1ns +s25fl064a + +S25Fl064A0LMAI000 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LMFI000 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LNAI000 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LNFI000 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LMAI001 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LMFI001 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LNAI001 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LNFI001 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LMAI003 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LMFI003 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LNAI003 s25fl064a_00_a0 April 26, 2005 +S25Fl064A0LNFI003 s25fl064a_00_a0 April 26, 2005 +The values listed are for VCC=2.7V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius +Comercial Ta=0 to +70 Celsius + + + (DELAY (ABSOLUTE + (IOPATH SCK SO (3:6:9) (3:6:9) () (3:6:9) () (3:6:9)) + (IOPATH HOLDNeg SO () () (4:7:10) (4:7:10) (4:7:10) (4:7:10)) + (IOPATH CSNeg SO () () (4:7:10) () (4:7:10) ()) + )) + (TIMINGCHECK + (SETUP CSNeg SCK (5)) + (SETUP HOLDNeg SCK (5)) + (SETUP SI SCK (5)) + (SETUP WNeg CSNeg (15)) + + (HOLD CSNeg SCK (5)) + (HOLD HOLDNeg SCK (5)) + (HOLD SI SCK (5)) + (HOLD WNeg CSNeg (15)) + + (WIDTH (negedge SCK) (9)) + (WIDTH (posedge SCK) (9)) + (WIDTH (posedge CSNeg) (100)) + (PERIOD (COND fast_rd SCK) (20.0)) + (PERIOD (COND rd SCK) (40.0)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP) (DELAY (ABSOLUTE (DEVICE(1000000:1500000:3000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE) (DELAY (ABSOLUTE (DEVICE(1e9:15e8:3e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(128e9:192e9:384e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WR) (DELAY (ABSOLUTE (DEVICE(60000000:60000000:60000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(10000000:10000000:10000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/DP) (DELAY (ABSOLUTE (DEVICE(3000:3000:3000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/RES) (DELAY (ABSOLUTE (DEVICE(30000:30000:30000) ) ) ) + + diff --git a/lib/models/memory/flash/serial/S25fl064a/utilities/CreateSDF/mk_sdf.cmd b/lib/models/memory/flash/serial/S25fl064a/utilities/CreateSDF/mk_sdf.cmd new file mode 100644 index 0000000..f6d6cc7 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064a/utilities/CreateSDF/mk_sdf.cmd @@ -0,0 +1,10 @@ +SET sdffile_suffix .sdf +SET use_global_timing_dir false +SET timingfile_dir /user/USERNAME/CreateSDF +SET timingfile_suffix .ftm +SET time_scale 1ns +SET local_path . +SET vendor MODELSIM_HOME +SET diagnostics on +SET vhdl_file testbench.vhd +SET lwb false diff --git a/lib/models/memory/flash/serial/S25fl064a/utilities/CreateSDF/mk_sdf_204.pl b/lib/models/memory/flash/serial/S25fl064a/utilities/CreateSDF/mk_sdf_204.pl new file mode 100644 index 0000000..5f2f2b8 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064a/utilities/CreateSDF/mk_sdf_204.pl @@ -0,0 +1,462 @@ +#!/usr/local/bin/perl +# +# mk_sdf : Perl replacement for C mk_sdf +# +# Copyright (C) 2000, 1999 Free Model Foundry; http:/vhdl.org/fmf/ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# Author : R. Munden +# Date : 20001115 +# Version : 2.0.4 +# +# Revision history: +# 2.0: 19990702 +# o Intial release of perl version +# 2.0.1: 19990722 +# o fixed problem with . in path for TimingModels +# 2.0.2: 20000616 +# o changed instance search to work with Mentor +# 2.0.3: 20001115 +# o changed to parse ":" without leading space +# o fixed problem with . in path for TimingModels again +# 2.0.4: 20030405 +# o chaged SDF version to 3.0 +# +################################################################# +# +# command line arguments: + +# ARGV[0] - name of VHDL netlist + +# global variables: + +# %component_list - list of instance names by component name +# %instance_isin - list architectures by instances contained therein +# %instance_comp - list of component names by instance name +# %comp_lib - library each component (by name) is configured to +# @instance_list - array of all instance names in design in order found + +$version = "2.0.4"; +$design_name = ''; +$timing_dir = ''; +$diags = "off"; + +%keywords = (architecture => 1, + component => 1, + timingmodel => 1); + +# INPUT files +$CMD = "mk_sdf.cmd"; +$VHD = ''; # name of VHDL netlist + +# OUTPUT files +$RFV = "/tmp/short.vhd"; # reformatted VHDL +$sdf_file = ''; # name of SDF file + +&read_cmd_file; +&get_names; +&reformat; + +open INPUT, $RFV; +@lines = ; +close INPUT; + +$current_architecture = ""; + +foreach $line (@lines) +{ + @words = split / /, $line; + foreach $word (@words) + { + $keywords{$word} == "1" and do { &$word(@words);}; + if ($component_list{$word}) + { + $line =~ /(.+) : $word/ and do { + if ($1 !~ /for/) { # instantiation found + $component_list{$word} = $component_list{$word} . $1; + push (@instance_list, $1); + $instance_name = $1; + } + }; + $instance_comp{$1} = $word; + $instance_isin{$1} = $current_architecture; + if ( $diags ne off ) { + print "reading instance $instance_name: $word in $current_architecture\n"; + } + $line =~ /for all : $word use entity (.+)/ and do + { + @config = split(/\./, $1); + $comp_lib{$word} = $config[0];}; + } + } +} +if ( $diags ne off ) { + print "finished with netlist\n\n"; +} + +&begin_sdf; +&build_paths; +&close_sdf; +`rm $RFV`; + +print "$time\n"; + +sub architecture +{ + $current_architecture = $_[3]; + push (@architectures, $current_architecture); +} + +sub component +{ + if ($_[0] ne "end") + { + $name = $_[1]; + $arch_list{$current_architecture} = + $arch_list{$current_architecture} . " " . $name; + unless ($component_list{$name}) { $component_list{$name} = " ";} + } +} + +sub timingmodel +{ + $line =~ /timingmodel => \"(.+)\"/ and do { + $model = $1; + $model_name{$instance_name} = $model; + }; +} + +sub begin_sdf +{ + if ( $diags ne off ) { + print "writing SDF boilerplate\n"; + } + $time = localtime; + if (open(SDF, ">$sdf_file") !=1) { die "can't open $sdf_file\n";} + print "Opening $sdf_file\n"; + print SDF "(DELAYFILE\n"; + print SDF " (SDFVERSION \"3.0\")\n"; + print SDF " (DESIGN \"$design_name\")\n"; + print SDF " (DATE \"$time\")\n"; + print SDF " (VENDOR \"Free Model Foundry\")\n"; + print SDF " (PROGRAM \"SDF timing utility(tm)\")\n"; + print SDF " (VERSION \"$version\")\n"; + print SDF " (DIVIDER /)\n"; + print SDF " (VOLTAGE)\n"; + print SDF " (PROCESS)\n"; + print SDF " (TEMPERATURE)\n"; + print SDF " (TIMESCALE 1ns)\n"; +} + +sub build_paths +{ + foreach $instance_list (@instance_list) + { + @instance = $instance_list; + foreach $instance (@instance) + { + if ( $diags ne off ) { + print "working on $instance\n"; + } + if ($gtd =~ /true/i) { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; +# $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}./$timing_dir"; + } else { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; + } + $timing_file = "$path/$instance_comp{$instance}_vhd.ftm"; + $timing_file =~ s/\s//; + if ( $diags ne off ) { + print "$instance should be in $timing_file\n"; + } + if (-e $timing_file) { + if ($model_name{$instance} ne "") { + print SDF " (CELL\n"; + print SDF " (CELLTYPE \"$instance_comp{$instance}\")\n"; + $inst = $instance; + $full_inst = $instance; + while ($component_list{$instance_isin{$inst}}) { + $full_inst = "$component_list{$instance_isin{$inst}}/$full_inst"; + $full_inst =~ s/\s+//; + $inst = $component_list{$instance_isin{$inst}}; + $inst =~ s/\s+//; +# print SDF " (INSTANCE $component_list{$instance_isin{$instance}}/$instance)\n"; + } + print SDF " (INSTANCE $full_inst)\n"; + &add_timing; + } + } else { + if ( $diags ne off ) { + print "$timing_file not found!\n"; + } + } + } + } +} + +sub add_timing +{ + $timing_found = "false"; + $part_found = "false"; +# unless ($lib_path{$comp_lib{$instance_comp{$instance}}}) + unless ($timing_file) + { + print "path to $timing_file not found\n"; + exit; + } + if ($gtd =~ /true/i) { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; +# $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}./$timing_dir"; + } else { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; + } + $timing_file = "$path/$instance_comp{$instance}_vhd.ftm"; + if (open(TF, "<$timing_file") !=1) { warn "can't open $timing_file\n"; } + if ( $diags ne off ) { + print "reading $timing_file\n"; + } + $section_found = "false"; + while () + { + next unless (/$model_name{$instance}/i || ($part_found eq "true")); + $part_found = "true"; + if ( $diags ne off ) { + print "found entry for $model_name{$instance}\n"; + } + next unless (//i || ($timing_found eq "true")); + $timing_found = "true"; + next if (//i); + if (/<\/timing>/i) + { + print SDF " )\n"; + $timing_found = "false"; + $part_found = "false"; + $section_found = "true"; + last; + } else { + if (/%LABEL%/) + { + if ($component_list{$instance_isin{$instance}}) + { + $_ =~ s/%LABEL%/$component_list{$instance_isin{$instance}}\/$instance/; + } else { + $_ =~ s/%LABEL%/$instance/; + } + } + print SDF $_; + } + } + unless ($section_found eq "true") { + print "$model_name not found\n"; + } +} + +sub close_sdf +{ + print SDF ")\n"; + print "closing $sdf_file\n"; + close(SDF); +} + +# read mk_sdf.cmd + +sub read_cmd_file { + + if (open(CMD, $CMD) !=1) { die "can't open $CMD\n"; } + while () { + chop; + @fields = ''; + @fields = split; + unless ($fields[0] =~ /#/) { + if ($fields[0] =~ /SET/) { + if ($fields[1] =~ /vhdl_file/) {$VHD = $fields[2]} + if ($fields[1] =~ /sdffile_suffix/) {$suffix = $fields[2]} + if ($fields[1] =~ /use_global_timing_dir/) {$gtd = $fields[2]} + if ($fields[1] =~ /timingfile_dir/) {$timing_dir = $fields[2]} + if ($fields[1] =~ /vendor/) {$vendor = $fields[2]} + if ($fields[1] =~ /diagnostics/) {$diags = $fields[2]} + } + } + } + if ( $diags ne off ) { + print "\nmk_sdf diagnostics on\n\n"; + print "vhdl_file $VHD\n"; + print "sdffile_suffix $suffix\n"; + print "use_global_timing_dir $gtd\n"; + print "timingfile_dir $timing_dir\n"; + print "vendor $vendor\n\n"; + } +} +# + +# get name of netlist + +sub get_names +{ + + if ($ARGV[0] ne "") { $VHD = "$ARGV[0]"; } + + if ($ARGV[1] eq "") + { + @name = split(/\./,$VHD); + $design_name = $name[0]; + } else { + $design_name = "$ARGV[1]"; + } + $sdf_file = $design_name . $suffix; + if ($gtd =~ /false/i) + { + if ($vendor =~ /modeltech/i) { &read_mti; } + if ($vendor =~ /cadence/i) { &read_cds; } + } + if ( $diags ne off ) { + print "design name is $design_name\n\n"; + } +} +# +################################################################ +# + +# reformat netlist + +sub reformat +{ + $entfound = false; + + if (open(VHD, $VHD) !=1) { die "can't open $VHD\n"; } + if (open(OUT, ">$RFV") !=1) { die "can't open $OUT\n"; } + + while () { + if (/^--|library|package/i) { next } + if (/--/) { # strip embeded comments + @line = split("--"); + $_ = $line[0]; + } + s/:/ : /g; + s/;/ ;/g; + s/\s+/ /g; # reduces spaces and tabs + s/^\s//g; # no leading spaces + if (/entity/i) { + $entfound = "true"; + } + chomp; + if ( $entfound eq true ) { + print OUT lc($_); + if (/;|is|begin/i) { print OUT "\n"; } + } + } + + close OUT; + if ( $diags ne off ) { + print "reformatted netlist written to $RFV\n\n"; + } + +} + +# read ModelTech's modelsim.ini file + +sub read_mti +{ + $lib_found = "false"; + if ($ENV{MODELPATH}) + { + $ini_file = "$ENV{MODELPATH}/../modelsim.ini"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + if ($lib_found eq "true") + { + chomp; + if (/\[.+\]/) { last; } + s/\s+//; + @lib_line = split(/=/); + $lib_line[1] =~ s/\/work//; + $lib_path{$lib_line[0]} = $lib_line[1]; + } elsif (/\[Library\]/i) + { + $lib_found = "true"; + next; + } + } + } else { + print "\$MODELPATH environment variable not found\n"; + } + $lib_found = "false"; + if (-e "modelsim.ini") + { + $ini_file = "modelsim.ini"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + if ($lib_found eq "true") + { + chomp; + if (/\[.+\]/) { last; } + s/\s+//; + @lib_line = split(/=/); + $lib_line[1] =~ s/\/work//; + $lib_path{$lib_line[0]} = $lib_line[1]; + } elsif (/\[Library\]/i) + { + $lib_found = "true"; + next; + } + } + } else { + print "local modelsim.ini file not found, may not be needed\n"; + } +} + +# read Cadence's cds.lib file + +sub read_cds +{ + if ($ENV{CDS_VHDL}) + { + $ini_file = "$ENV{CDS_VHDL}/files/cds.lib"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + chomp; + s/\s+/ /; + if (/define/i) + { + @lib_line = split; + $lib_path{$lib_line[1]} = $lib_line[2]; + } + } + } else { + print "\$CDS_VHDL environment variable not found\n"; + } + if (-e "cds.lib") + { + $ini_file = "cds.lib"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + chomp; + s/\s+/ /; + if (/define/i) + { + @lib_line = split; + $lib_path{$lib_line[1]} = $lib_line[2]; + } + } + } else { + print "local cds.lib file not found, may not be needed\n"; + } +} diff --git a/lib/models/memory/flash/serial/S25fl064a/utilities/CreateSDF/my_mem_vhd.ftm b/lib/models/memory/flash/serial/S25fl064a/utilities/CreateSDF/my_mem_vhd.ftm new file mode 100644 index 0000000..2fc35c2 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064a/utilities/CreateSDF/my_mem_vhd.ftm @@ -0,0 +1,205 @@ + +FMF Timing for testbench Parts + + +version: | author: | mod date: | changes made: + V1.0 VHD2FTM 03 July 11 Initial release + +1ns +am29lv640m + +MY_MEM +AM29LV640MH90R +AM29LV640ML90R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (90:90:90) (90:90:90)) + (IOPATH A0 DQ1 (25:25:25) (25:25:25)) + (IOPATH CENeg DQ0 (85:85:85) (85:85:85) (11:11:11) (85:85:85) (11:11:11) (85:85:85)) + (IOPATH OENeg DQ0 (20:20:20) (20:20:20) (11:11:11) (20:20:20) (11:11:11) (20:20:20)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (90)) + (IOPATH WENeg RY (0) (90)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (90:90:90)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH101 +AM29LV640ML101 +AM29LV640MH101R +AM29LV640ML101R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (100:100:100) (100:100:100)) + (IOPATH A0 DQ1 (30:30:30) (30:30:30)) + (IOPATH CENeg DQ0 (95:95:95) (95:95:95) (11:11:11) (95:95:95) (11:11:11) (95:95:95)) + (IOPATH OENeg DQ0 (25:25:25) (25:25:25) (11:11:11) (25:25:25) (11:11:11) (25:25:25)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (100)) + (IOPATH WENeg RY (0) (100)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (100:100:100)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH112 +AM29LV640ML112 +AM29LV640MH112R +AM29LV640ML112R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (110:110:110) (110:110:110)) + (IOPATH A0 DQ1 (40:40:40) (40:40:40)) + (IOPATH CENeg DQ0 (105:105:105) (105:105:105) (11:11:11) (105:105:105) (11:11:11) (105:105:105)) + (IOPATH OENeg DQ0 (35:35:35) (35:35:35) (11:11:11) (35:35:35) (11:11:11) (35:35:35)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (110)) + (IOPATH WENeg RY (0) (110)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (110:110:110)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH120 +AM29LV640ML120 +AM29LV640MH120R +AM29LV640ML120R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (120:120:120) (120:120:120)) + (IOPATH A0 DQ1 (40:40:40) (40:40:40)) + (IOPATH CENeg DQ0 (115:115:115) (115:115:115) (11:11:11) (115:115:115) (11:11:11) (115:115:115)) + (IOPATH OENeg DQ0 (35:35:35) (35:35:35) (11:11:11) (35:35:35) (11:11:11) (35:35:35)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (120)) + (IOPATH WENeg RY (0) (120)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (120:120:120)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + diff --git a/lib/models/memory/flash/serial/S25fl064a/utilities/CreateSDF/testbench.sdf b/lib/models/memory/flash/serial/S25fl064a/utilities/CreateSDF/testbench.sdf new file mode 100644 index 0000000..02495dd --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064a/utilities/CreateSDF/testbench.sdf @@ -0,0 +1,58 @@ +(DELAYFILE + (SDFVERSION "3.0") + (DESIGN "testbench") + (DATE "Wed Jan 28 15:15:41 2004") + (VENDOR "Free Model Foundry") + (PROGRAM "SDF timing utility(tm)") + (VERSION "2.0.4") + (DIVIDER /) + (VOLTAGE) + (PROCESS) + (TEMPERATURE) + (TIMESCALE 1ns) + (CELL + (CELLTYPE "my_mem") + (INSTANCE dut) + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (90:90:90) (90:90:90)) + (IOPATH A0 DQ1 (25:25:25) (25:25:25)) + (IOPATH CENeg DQ0 (85:85:85) (85:85:85) (11:11:11) (85:85:85) (11:11:11) (85:85:85)) + (IOPATH OENeg DQ0 (20:20:20) (20:20:20) (11:11:11) (20:20:20) (11:11:11) (20:20:20)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (90)) + (IOPATH WENeg RY (0) (90)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (90:90:90)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + ) +) diff --git a/lib/models/memory/flash/serial/S25fl064a/utilities/CreateSDF/testbench.vhd b/lib/models/memory/flash/serial/S25fl064a/utilities/CreateSDF/testbench.vhd new file mode 100644 index 0000000..c7d852a --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064a/utilities/CreateSDF/testbench.vhd @@ -0,0 +1,1606 @@ +------------------------------------------------------------------------------ +-- File name : testbench_640.vhd +------------------------------------------------------------------------------- +-- Copyright (C) 2003 AMD. +-- +-- MODIFICATION HISTORY : +-- +-- version: | author: | mod date: | changes made: +-- V0.1 M.Marinkovic 11 July 03 Initial +-- v0.2 M.Marinkovic 28 Aug 03 Changed protected sector selection +-- +------------------------------------------------------------------------------- +-- PART DESCRIPTION: +-- +-- Description: +-- Generic test enviroment for verification of AMD flash memory +-- VITAL models.my_mem +-- +------------------------------------------------------------------------------- +-- Note: VHDL code formating not done +-- For High/Low sector protection selection change: +-- TimingModel constant and TimingModel generic value +-- +------------------------------------------------------------------------------- +LIBRARY IEEE; + USE IEEE.std_logic_1164.ALL; +--USE IEEE.VITAL_timing.ALL; +--USE IEEE.VITAL_primitives.ALL; + USE STD.textio.ALL; + +LIBRARY VITAL2000; + USE VITAL2000.vital_timing.ALL; + USE VITAL2000.vital_primitives.ALL; + +LIBRARY FMF; + USE FMF.gen_utils.ALL; + USE FMF.conversions.ALL; + + +LIBRARY work; + USE work.amd_tc_pkg.ALL; + +------------------------------------------------------------------------------- +-- ENTITY DECLARATION +------------------------------------------------------------------------------- +ENTITY testbench_640 IS +END testbench_640; + + +------------------------------------------------------------------------------- +-- ARCHITECTURE DECLARATION +------------------------------------------------------------------------------- +ARCHITECTURE vhdl_behavioral of testbench_640 IS + COMPONENT my_mem + GENERIC ( + -- tipd delays: interconnect path delays + tipd_A0 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A1 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A2 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A3 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A4 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A5 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A6 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A7 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A8 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A9 : VitalDelayType01 := VitalZeroDelay01; --address + tipd_A10 : VitalDelayType01 := VitalZeroDelay01; --lines + tipd_A11 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A12 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A13 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A14 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A15 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A16 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A17 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A18 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A19 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A20 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A21 : VitalDelayType01 := VitalZeroDelay01; -- + + tipd_DQ0 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ1 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ2 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ3 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ4 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ5 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ6 : VitalDelayType01 := VitalZeroDelay01; -- data + tipd_DQ7 : VitalDelayType01 := VitalZeroDelay01; -- lines + tipd_DQ8 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ9 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ10 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ11 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ12 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ13 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ14 : VitalDelayType01 := VitalZeroDelay01; -- + + tipd_DQ15 : VitalDelayType01 := VitalZeroDelay01; -- DQ15/A-1 + + tipd_CENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_OENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_RESETNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; --WP#/ACC + tipd_BYTENeg : VitalDelayType01 := VitalZeroDelay01; + + -- tpd delays + tpd_A0_DQ0 : VitalDelayType01 := UnitDelay01;--tACC + tpd_A0_DQ1 : VitalDelayType01 := UnitDelay01;--tPACC + tpd_CENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(tCE,tCE,tDF,-,tDF,-) + tpd_OENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(tOE,tOE,tDF,-,tDF,-) + tpd_RESETNeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(-,-,0,-,0,-) + tpd_CENeg_RY : VitalDelayType01 := UnitDelay01; --tBUSY + tpd_WENeg_RY : VitalDelayType01 := UnitDelay01; --tBUSY + + --tsetup values + tsetup_A0_CENeg : VitalDelayType := UnitDelay; --tAS edge \ + tsetup_A0_OENeg : VitalDelayType := UnitDelay; --tASO edge \ + tsetup_DQ0_CENeg : VitalDelayType := UnitDelay; --tDS edge / + + --thold values + thold_CENeg_RESETNeg: VitalDelayType := UnitDelay; --tRH edge / + thold_OENeg_WENeg : VitalDelayType := UnitDelay; --tOEH edge / + thold_A0_CENeg : VitalDelayType := UnitDelay; --tAH edge \ + thold_A0_OENeg : VitalDelayType := UnitDelay; --tAHT edge \ + thold_DQ0_CENeg : VitalDelayType := UnitDelay; --tDH edge / + thold_WENeg_OENeg : VitalDelayType := UnitDelay; --tGHWL edge / + + --tpw values: pulse width + tpw_RESETNeg_negedge: VitalDelayType := UnitDelay; --tRP + tpw_OENeg_posedge : VitalDelayType := UnitDelay; --tOEPH + tpw_WENeg_negedge : VitalDelayType := UnitDelay; --tWP + tpw_WENeg_posedge : VitalDelayType := UnitDelay; --tWPH + tpw_CENeg_negedge : VitalDelayType := UnitDelay; --tCP + tpw_CENeg_posedge : VitalDelayType := UnitDelay; --tCEPH + tpw_A0_negedge : VitalDelayType := UnitDelay; --tWC tRC + + + -- tdevice values: values for internal delays + --Effective Write Buffer Program Operation tWHWH1 + tdevice_WBPB : VitalDelayType := 11 us; + --Program Operation + tdevice_POB : VitalDelayType := 100 us; + --Sector Erase Operation tWHWH2 + tdevice_SEO : VitalDelayType := 500 ms; + --Timing Limit Exceeded + tdevice_HANG : VitalDelayType := 400 ms; --? + --program/erase suspend timeout + tdevice_START_T1 : VitalDelayType := 5 us; + --sector erase command sequence timeout + tdevice_CTMOUT : VitalDelayType := 50 us; + --device ready after Hardware reset(during embeded algorithm) + tdevice_READY : VitalDelayType := 20 us; --tReady + + -- generic control parameters + InstancePath : STRING := DefaultInstancePath; + TimingChecksOn : BOOLEAN := DefaultTimingChecks; + MsgOn : BOOLEAN := DefaultMsgOn; + XOn : BOOLEAN := DefaultXon; + -- memory file to be loaded + mem_file_name : STRING ;--:= "am29lv640m.mem"; + prot_file_name : STRING ;--:= "am29lv640m_prot.mem"; + secsi_file_name : STRING ;--:= "am29lv_secsi.mem"; + + UserPreload : BOOLEAN ;--:= TRUE; + LongTimming : BOOLEAN ;--:= TRUE; + + -- For FMF SDF technology file usage + TimingModel : STRING --:= "AM29LV640MH90R" + ); + PORT ( + A21 : IN std_logic := 'U'; -- + A20 : IN std_logic := 'U'; -- + A19 : IN std_logic := 'U'; -- + A18 : IN std_logic := 'U'; -- + A17 : IN std_logic := 'U'; -- + A16 : IN std_logic := 'U'; -- + A15 : IN std_logic := 'U'; -- + A14 : IN std_logic := 'U'; -- + A13 : IN std_logic := 'U'; --address + A12 : IN std_logic := 'U'; --lines + A11 : IN std_logic := 'U'; -- + A10 : IN std_logic := 'U'; -- + A9 : IN std_logic := 'U'; -- + A8 : IN std_logic := 'U'; -- + A7 : IN std_logic := 'U'; -- + A6 : IN std_logic := 'U'; -- + A5 : IN std_logic := 'U'; -- + A4 : IN std_logic := 'U'; -- + A3 : IN std_logic := 'U'; -- + A2 : IN std_logic := 'U'; -- + A1 : IN std_logic := 'U'; -- + A0 : IN std_logic := 'U'; -- + + DQ15 : INOUT std_logic := 'U'; -- DQ15/A-1 + DQ14 : INOUT std_logic := 'U'; -- + DQ13 : INOUT std_logic := 'U'; -- + DQ12 : INOUT std_logic := 'U'; -- + DQ11 : INOUT std_logic := 'U'; -- + DQ10 : INOUT std_logic := 'U'; -- + DQ9 : INOUT std_logic := 'U'; -- data + DQ8 : INOUT std_logic := 'U'; -- lines + DQ7 : INOUT std_logic := 'U'; -- + DQ6 : INOUT std_logic := 'U'; -- + DQ5 : INOUT std_logic := 'U'; -- + DQ4 : INOUT std_logic := 'U'; -- + DQ3 : INOUT std_logic := 'U'; -- + DQ2 : INOUT std_logic := 'U'; -- + DQ1 : INOUT std_logic := 'U'; -- + DQ0 : INOUT std_logic := 'U'; -- + + CENeg : IN std_logic := 'U'; + OENeg : IN std_logic := 'U'; + WENeg : IN std_logic := 'U'; + RESETNeg : IN std_logic := 'U'; + WPNeg : IN std_logic := 'U'; --WP#/ACC + BYTENeg : IN std_logic := 'U'; + RY : OUT std_logic := 'U' --RY/BY# + ); + END COMPONENT; + + FOR ALL: my_mem USE ENTITY WORK.my_mem(VHDL_BEHAVIORAL); + + --------------------------------------------------------------------------- + --memory configuration + --------------------------------------------------------------------------- + CONSTANT MaxData : NATURAL := 16#FF#; --255; + CONSTANT SecSize : NATURAL := 16#FFFF#; --65535 + CONSTANT SecSiSize : NATURAL := 255; + CONSTANT SecNum : NATURAL := 127; + CONSTANT HiAddrBit : NATURAL := 21; + --Address of the Protected Sector +-- CONSTANT ProtSecNum : NATURAL := SecNum; + + --------------------------------------------------------------------------- + --model configuration + --------------------------------------------------------------------------- + CONSTANT mem_file : STRING := "am29lv640m.mem"; + CONSTANT prot_file : STRING := "am29lv640m_prot.mem"; + CONSTANT secsi_file : STRING := "am29lv_secsi.mem"; + + CONSTANT UserPreload : boolean := TRUE; + CONSTANT DebugInfo : boolean := FALSE; + CONSTANT LongTimming : boolean := TRUE; + CONSTANT TimingModel : STRING := "MY_MEM"; + -- "AM29LV640MH90R";--High sect prot. + -- "AM29LV128ML93R";--Low sect. prot. + --------------------------------------------------------------------------- + SIGNAL ProtSecNum : NATURAL := SecNum ; + + --Flash Memory Array + TYPE SecType IS ARRAY (0 TO SecSize) OF + INTEGER RANGE -1 TO MaxData; + TYPE MemArray IS ARRAY (0 TO SecNum) OF + SecType; + + --Common Flash Interface Query codes + TYPE CFItype IS ARRAY (16#10# TO 16#50#) OF + NATURAL RANGE 0 TO 16#FF#; + + --SecSi Sector + TYPE SecSiType IS ARRAY ( 0 TO SecSiSize) OF + INTEGER RANGE -1 TO MaxData; + + --------------------------------------------------------------------------- + -- memory declaration + --------------------------------------------------------------------------- + -- -- Mem(SecAddr)(Address).... + SHARED VARIABLE Mem : MemArray := (OTHERS => (OTHERS=> MaxData)); + SHARED VARIABLE CFI_array : CFItype :=(OTHERS=>0); + SHARED VARIABLE SecSi : SecSiType :=(OTHERS=>0); + + --command sequence + SHARED VARIABLE cmd_seq : cmd_seq_type; + + SIGNAL status : status_type := none; + SIGNAL sts_check : std_logic_vector(7 downto 0); + + + SIGNAL check_err : std_logic := '0'; + SIGNAL ErrorInTest : std_logic := '0'; -- + ---------------------------------------------------------------------------- + --Personality module: + -- + -- instanciates the DUT module and adapts generic test signals to it + -- TBD: block port + ---------------------------------------------------------------------------- + --DUT port + SIGNAL T_DQ : std_logic_vector(15 downto 0) := (OTHERS=>'U'); + SIGNAL T_A : std_logic_vector(HiAddrBit downto 0) := (OTHERS=>'U'); + SIGNAL T_RESETNeg : std_logic := 'U'; + SIGNAL T_CENeg : std_logic := 'U'; + SIGNAL T_WENeg : std_logic := 'U'; + SIGNAL T_OENeg : std_logic := 'U'; + SIGNAL T_WPNeg : std_logic := 'U'; + SIGNAL T_BYTENeg : std_logic := 'U'; + SIGNAL T_RY : std_logic := 'U'; + + --------------------------------------------------------------------------- + -- + --------------------------------------------------------------------------- + --SecSi ProtectionStatus + SHARED VARIABLE FactoryProt : std_logic := '1'; + --Sector Protection Status + SHARED VARIABLE Sec_Prot : std_logic_vector (SecNum downto 0) := + (OTHERS => '0'); + SHARED VARIABLE Sect : NATURAL RANGE 0 TO SecNum := 0; + SHARED VARIABLE Addr : NATURAL RANGE 0 TO SecSize := 0; + SHARED VARIABLE WriteData : NATURAL RANGE 0 TO MaxData := 0; + + + --CONSTANT + --timming parameters + CONSTANT RESETNeg_pw : time := 500 ns; --tRP + + SIGNAL pwron : std_logic := '0'; + + SIGNAL Tseries : NATURAL; + SIGNAL Tcase : NATURAL; + + SHARED VARIABLE ts_cnt : NATURAL RANGE 1 TO 30:=1; -- testseries counter + SHARED VARIABLE tc_cnt : NATURAL RANGE 0 TO 10:=0; -- testcase counter + + + BEGIN + DUT : my_mem + GENERIC MAP ( + -- tipd delays: interconnect path delays + tipd_A0 => VitalZeroDelay01, -- + tipd_A1 => VitalZeroDelay01, -- + tipd_A2 => VitalZeroDelay01, -- + tipd_A3 => VitalZeroDelay01, -- + tipd_A4 => VitalZeroDelay01, -- + tipd_A5 => VitalZeroDelay01, -- + tipd_A6 => VitalZeroDelay01, -- + tipd_A7 => VitalZeroDelay01, -- + tipd_A8 => VitalZeroDelay01, -- + tipd_A9 => VitalZeroDelay01, --address + tipd_A10 => VitalZeroDelay01, --lines + tipd_A11 => VitalZeroDelay01, -- + tipd_A12 => VitalZeroDelay01, -- + tipd_A13 => VitalZeroDelay01, -- + tipd_A14 => VitalZeroDelay01, -- + tipd_A15 => VitalZeroDelay01, -- + tipd_A16 => VitalZeroDelay01, -- + tipd_A17 => VitalZeroDelay01, -- + tipd_A18 => VitalZeroDelay01, -- + tipd_A19 => VitalZeroDelay01, -- + tipd_A20 => VitalZeroDelay01, -- + tipd_A21 => VitalZeroDelay01, -- + + tipd_DQ0 => VitalZeroDelay01, -- + tipd_DQ1 => VitalZeroDelay01, -- + tipd_DQ2 => VitalZeroDelay01, -- + tipd_DQ3 => VitalZeroDelay01, -- + tipd_DQ4 => VitalZeroDelay01, -- + tipd_DQ5 => VitalZeroDelay01, -- + tipd_DQ6 => VitalZeroDelay01, -- data + tipd_DQ7 => VitalZeroDelay01, -- lines + tipd_DQ8 => VitalZeroDelay01, -- + tipd_DQ9 => VitalZeroDelay01, -- + tipd_DQ10 => VitalZeroDelay01, -- + tipd_DQ11 => VitalZeroDelay01, -- + tipd_DQ12 => VitalZeroDelay01, -- + tipd_DQ13 => VitalZeroDelay01, -- + tipd_DQ14 => VitalZeroDelay01, -- + + tipd_DQ15 => VitalZeroDelay01, -- DQ15/A-1 + + tipd_CENeg => VitalZeroDelay01, + tipd_OENeg => VitalZeroDelay01, + tipd_WENeg => VitalZeroDelay01, + tipd_RESETNeg => VitalZeroDelay01, + tipd_WPNeg => VitalZeroDelay01,--WP#/ACC + tipd_BYTENeg => VitalZeroDelay01, + + -- tpd delays + tpd_A0_DQ0 => UnitDelay01,--tACC + tpd_A0_DQ1 => UnitDelay01,--tPACC + tpd_CENeg_DQ0 => UnitDelay01Z, + --(tCE,tCE,tDF,-,tDF + tpd_OENeg_DQ0 => UnitDelay01Z, + --(tOE,tOE,tDF,-,tDF + tpd_RESETNeg_DQ0 => UnitDelay01Z, + --(-,-,0,-,0,-) + tpd_CENeg_RY => UnitDelay01, --tBUSY + tpd_WENeg_RY => UnitDelay01, --tBUSY + + --tsetup values + tsetup_A0_CENeg => UnitDelay, --tAS edge \ + tsetup_A0_OENeg => UnitDelay, --tASO edge \ + tsetup_DQ0_CENeg => UnitDelay, --tDS edge / + + --thold values + thold_CENeg_RESETNeg=> UnitDelay, --tRH edge / + thold_OENeg_WENeg => UnitDelay, --tOEH edge / + thold_A0_CENeg => UnitDelay, --tAH edge \ + thold_A0_OENeg => UnitDelay, --tAHT edge \ + thold_DQ0_CENeg => UnitDelay, --tDH edge / + thold_WENeg_OENeg => UnitDelay, --tGHVL edge / + + --tpw values: pulse width + tpw_RESETNeg_negedge=> UnitDelay, --tRP + tpw_OENeg_posedge => UnitDelay, --tOEPH + tpw_WENeg_negedge => UnitDelay, --tWP + tpw_WENeg_posedge => UnitDelay, --tWPH + tpw_CENeg_negedge => UnitDelay, --tCP + tpw_CENeg_posedge => UnitDelay, --tCEPH + tpw_A0_negedge => UnitDelay, --tWC tRC + -- tdevice values: values for internal delays + --Effective Write Buffer Program Operation tWHWH1 + tdevice_WBPB => 11 us, + --Program Operation + tdevice_POB => 100 us, + --Sector Erase Operation tWHWH2 + tdevice_SEO => 500 ms, + --Timing Limit Exceeded + tdevice_HANG => 400 ms, --? + --program/erase suspend timeout + tdevice_START_T1 => 5 us, + --sector erase command sequence timeout + tdevice_CTMOUT => 50 us, + --device ready after Hardware reset(during embeded algorithm) + tdevice_READY => 20 us, --tReady + + -- generic control parameters + InstancePath => DefaultInstancePath, + TimingChecksOn => TRUE,--DefaultTimingChecks, + MsgOn => DefaultMsgOn, + XOn => DefaultXon, + -- memory file to be loaded + mem_file_name => mem_file, + prot_file_name => prot_file , + secsi_file_name => secsi_file, + + UserPreload => UserPreload, + LongTimming => LongTimming, + -- For FMF SDF technology file usage + TimingModel => "AM29LV640MH90R" -- TimingModel + ) + PORT MAP( + A21 => T_A(21), -- + A20 => T_A(20), -- + A19 => T_A(19), -- + A18 => T_A(18), -- + A17 => T_A(17), -- + A16 => T_A(16), -- + A15 => T_A(15), -- + A14 => T_A(14), -- + A13 => T_A(13), --address + A12 => T_A(12), --lines + A11 => T_A(11), -- + A10 => T_A(10), -- + A9 => T_A(9), -- + A8 => T_A(8), -- + A7 => T_A(7), -- + A6 => T_A(6), -- + A5 => T_A(5),-- + A4 => T_A(4),-- + A3 => T_A(3), -- + A2 => T_A(2), -- + A1 => T_A(1), -- + A0 => T_A(0), -- + + DQ15 => T_DQ(15), -- DQ15/A-1 + DQ14 => T_DQ(14), -- + DQ13 => T_DQ(13), -- + DQ12 => T_DQ(12), -- + DQ11 => T_DQ(11), -- + DQ10 => T_DQ(10), -- + DQ9 => T_DQ(9), -- data + DQ8 => T_DQ(8), -- lines + DQ7 => T_DQ(7), -- + DQ6 => T_DQ(6), -- + DQ5 => T_DQ(5), -- + DQ4 => T_DQ(4), -- + DQ3 => T_DQ(3), -- + DQ2 => T_DQ(2), -- + DQ1 => T_DQ(1), -- + DQ0 => T_DQ(0), -- + + CENeg => T_CENeg, + OENeg => T_OENeg, + WENeg => T_WENeg, + RESETNeg => T_RESETNeg, + WPNeg => T_WPNeg, --WP#/ACC + BYTENeg => T_BYTENeg, + RY => T_RY --RY/BY# + ); + + --------------------------------------------------------------------------- + --protected sector + --------------------------------------------------------------------------- + ProtSecNum <= SecNum WHEN TimingModel(11) = 'H' ELSE + 0 ;-- WHEN TimingModel = "AM29LV128ML93R" + + pwron <= '0', '1' after 1 ns; + +--At the end of the simulation, if ErrorInTest='0' there were no errors +err_ctrl : PROCESS ( check_err ) + BEGIN + IF check_err = '1' THEN + ErrorInTest <= '1'; + END IF; + END PROCESS err_ctrl; + +tb :PROCESS + + -------------------------------------------------------------------------- + --= PROCEDURE to select TC + -- can be modified to read TC list from file, or to generate random list + -------------------------------------------------------------------------- + PROCEDURE Pick_TC + (Model : IN STRING := "AM29LV640MH90R" ) + IS + BEGIN + IF TC_cnt < tc(TS_cnt) THEN + TC_cnt := TC_cnt+1; + ELSE + TC_cnt:=1; + IF TS_cnt<30 THEN + TS_cnt := TS_cnt+1; + ELSE + -- end test + IF ErrorInTest='0' THEN + REPORT "Test Ended without errors" + SEVERITY note; + ELSE + REPORT "There were errors in test" + SEVERITY note; + END IF; + WAIT; + END IF; + END IF; + END PROCEDURE Pick_TC; + + --------------------------------------------------------------------------- + --bus commands, device specific implementation + --------------------------------------------------------------------------- + TYPE bus_type IS (bus_idle, + bus_standby, --CE# deasseretd, others are don't care + bus_enable, --CE# asserted, others deasserted + bus_output_disable, + bus_reset, + bus_write, + bus_read); + + --bus drive for specific command sequence cycle + PROCEDURE bus_cycle( + bus_cmd :IN bus_type := bus_idle; + byte :IN boolean ; + data :IN INTEGER RANGE -2 TO MaxData := -2; -- -1 for all Z + dataHi :IN INTEGER RANGE -2 TO MaxData := -2; -- -2 for ignore + sector :IN INTEGER RANGE -1 TO SecNum := -1; -- -1 for ignore addr + address :IN NATURAL RANGE 0 TO SecSize := 0; + disable :IN boolean := false; + violate :IN boolean := false; + tm :IN TIME := 10 ns) + IS + + VARIABLE tmp : std_logic_vector(15 downto 0); + BEGIN + + IF data=-1 THEN -- HiZ + T_DQ(7 downto 0) <= (OTHERS => 'Z'); + END IF; + + IF (NOT byte)THEN --word access + IF dataHi=-1 THEN -- HiZ + T_DQ(15 downto 8) <= (OTHERS => 'Z'); + END IF; + T_BYTENeg <= '1'; + ELSE --byte access + T_BYTENeg <= '0'; + T_DQ(14 downto 8) <= (OTHERS => 'Z'); + END IF; + + IF sector > -1 THEN + T_A(HiAddrBit downto 15) <= to_slv(sector, HiAddrbit-14); + tmp := to_slv(address, 16); + IF byte THEN + T_A(14 downto 0) <= tmp(15 downto 1); + T_DQ(15) <= tmp(0); + ELSE + T_A(14 downto 0) <= tmp(14 downto 0); + END IF; + + END IF; + + wait for 1 ns; + + CASE bus_cmd IS + WHEN bus_output_disable => + T_OENeg <= '1'; + WAIT FOR 20 ns; + + WHEN bus_idle => + T_RESETNeg <= '1'; + T_WENeg <= '1'; + T_CENeg <= '1'; + T_OENeg <= '1'; + IF disable THEN + T_WPNeg <= '0'; + ELSE + T_WPNeg <= '1'; + END IF; + WAIT FOR 30 ns; + + WHEN bus_standby => + T_CENeg <= '1'; + WAIT FOR 30 ns; + + WHEN bus_reset => + T_RESETNeg <= '0', '1' AFTER tm ; + -- WAIT FOR 500 ns should follow this bus cmd for reset to + --complete + WAIT FOR 30 ns; + + WHEN bus_enable => + T_WENeg <= '1' AFTER 50 ns; --- + T_CENeg <= '0' AFTER 50 ns; --- + T_OENeg <= '1' AFTER 30 ns; --- + + WAIT FOR tm ; + + WHEN bus_write => + T_OENeg <= '1' ;-- AFTER 5 ns; + T_CENeg <= '0' AFTER 10 ns ; + T_WENeg <= '0' AFTER 20 ns; + + IF data>-1 THEN + T_DQ(7 downto 0) <= to_slv(data,8); + END IF; + IF NOT byte THEN + IF dataHi>-1 THEN + T_DQ(15 downto 8) <= to_slv(dataHi,8); + END IF; + END IF; + + IF violate THEN + T_WENeg <= '1'; + WAIT FOR 50 ns; + T_WENeg <= '0', '1' AFTER tm; + WAIT FOR 50 ns; + ELSE + WAIT FOR 100 ns; + END IF; + + WHEN bus_read => + + T_CENeg <= '0' ; + T_WENeg <= '1'AFTER 10 ns; + IF NOT disable THEN + T_OENeg <= '0' AFTER 15 ns; + ELSE + T_OENeg <= '1'; + END IF; + + IF NOT byte THEN + T_DQ(15 downto 8) <= (OTHERS => 'Z'); + END IF; + T_DQ(7 downto 0) <= (OTHERS => 'Z'); + + WAIT FOR 100 ns; + + -- T_OENeg <= '1' ; ----------- + + END CASE; + + + END PROCEDURE; + + + --------------------------------------------------------------------------- + --procedure to decode commands into specific bus command sequence + --------------------------------------------------------------------------- + PROCEDURE cmd_dc + ( command : IN cmd_rec ) + IS + VARIABLE D_hi : NATURAL ;--RANGE 0 to MaxData; + VARIABLE D_lo : NATURAL RANGE 0 to MaxData; + VARIABLE Addr : NATURAL RANGE 0 to SecSize :=0; + VARIABLE Addrfix : NATURAL RANGE 0 to SecSize/2:=0; + VARIABLE Sect : INTEGER RANGE -1 to SecNum :=0; + VARIABLE slv_1, slv_2 : std_logic_vector(7 downto 0); + VARIABLE byte : boolean; + VARIABLE i : NATURAL; + BEGIN + CASE command.cmd IS + WHEN idle => + bus_cycle(bus_cmd => bus_idle, + byte => command.byte, + disable => command.aux=disable); + + WHEN h_reset => + bus_cycle(bus_cmd => bus_reset, + byte => command.byte, + tm => command.wtime); + + WHEN rd => + bus_cycle(bus_cmd => bus_enable, + byte => command.byte, + data => -1, + sector => command.sect, + address => command.addr, + tm => 90 ns); + + bus_cycle(bus_cmd => bus_read, + byte => command.byte, + data => -1, + dataHi => -1, + sector => command.sect, + address => command.addr, + disable => command.aux=disable); + + bus_cycle(bus_cmd => bus_output_disable, + byte => command.byte); + + WHEN rd_page => + bus_cycle(bus_cmd => bus_enable, + byte => command.byte, + data => -1, + sector => 0, + address => 0, + tm => 90 ns); + + Addr := command.addr; + Sect := command.sect; + byte := command.byte; + ---- 08July---- + WAIT FOR 10 ns; + -------------- + i := 0; + WHILE i < command.d_hi LOOP + + IF command.wtime > 0 ns THEN + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + --byte toggle mode + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + byte := false; + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + Addrfix := Addr /2; + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + --word read; + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addrfix); + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + byte := true; + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 30 ns); + + --first byte read + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addr); + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + i := i +3; + wait for 10 ns; ------- + ELSE + byte := command.byte; + END IF; + --second byte read in byte toggle mode + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addr); + + + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + i := i +1; + WAIT FOR 10 ns; + END LOOP; + bus_cycle(bus_cmd => bus_output_disable, + byte => command.byte); + + + + WHEN w_cycle => + + D_lo := 16#AA# ; --first command data + Addr := 16#AAA#; --first command byte address + D_hi := 16#55#; --second command data + Addrfix := 16#555#; --second command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + Addrfix := 16#2AA#; --second command byte address + END IF; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_lo, + dataHi => 0, + sector => 0, + address => Addr, + violate => command.aux=violate, + tm => command.wtime); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_hi, + dataHi => 0, + sector => 0, + address => Addrfix); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_reset | w_prog | w_erase | w_unlock | + w_autoselect | w_enter_sec => + Addr := 16#AAA#; + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + + CASE command.cmd IS + WHEN w_reset => + d_lo := 16#F0#; + WHEN w_prog => + d_lo := 16#A0#; + WHEN w_erase => + d_lo := 16#80#; + WHEN w_unlock => + d_lo := 16#20#; + WHEN w_autoselect => + d_lo := 16#90#; + WHEN w_enter_sec => + d_lo := 16#88#; + WHEN OTHERS => + d_lo := 0; + END CASE; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => d_lo, + dataHi => 0, + sector => 0, + address => Addr); + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + + WHEN w_unlock_reset => + Addr := 16#AAA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#90#, + dataHi => 0, + sector => 0, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#F0#, + dataHi => 0, + sector => 0, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + WHEN w_chip_ers => + Addr := 16#AAA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#10#, + dataHi => 0, + sector => 0, + Address => Addr); + FOR i IN 0 TO SecNum LOOP + IF Sec_Prot(i)/='1' THEN + mem(i) := (OTHERS=>16#FF#); + END IF; + END LOOP; + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_cfi => + Addr := 16#AA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#55#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#98#, + dataHi => 0, + sector => 0, + Address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + + WHEN w_suspend => + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#B0#, + dataHi => 0, + sector => -1); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + WHEN w_resume => + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#30#, + dataHi => 0, + sector => -1); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_data => + + D_hi := command.d_hi MOD 16#100#; + D_lo := command.d_lo ; + Addr := command.addr; + Sect := command.sect; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_lo, + dataHi => D_hi, + sector => Sect, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + IF NOT command.byte THEN + Addr := Addr*2; + END IF; + + --write value(s) in default mem + IF status = erase_active AND Sec_Prot(Sect)/='1'THEN + --sector should be erased + mem(Sect) := (OTHERS=>16#FF#); + + ELSIF status = erase_na AND Sec_Prot(Sect)/='1'THEN + --sector erase terminated = data integrity violated + mem(Sect) := (OTHERS=>-1); + + ELSIF status = readX AND Sec_Prot(Sect)/='1' THEN + mem(Sect)(Addr) := -1; + IF NOT command.byte THEN + mem(Sect)(Addr+1) := -1; + END IF; + + -- Write to Secure Silicon Sector Region + ELSIF status = rd_SecSi AND FactoryProt/='1' THEN + slv_1 := to_slv(d_lo,8); + IF SecSi(Addr)>-1 THEN + slv_2 := to_slv(SecSi(Addr),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + SecSi(Addr) := to_nat(slv_1); + IF NOT command.byte THEN + slv_1 := to_slv(d_hi,8); + IF SecSi(Addr+1)>-1 THEN + slv_2 := to_slv(SecSi(Addr+1),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + SecSi(Addr+1) := to_nat(slv_1); + END IF; + + ELSIF status=buff_wr_busy THEN + --Write to Buffer command cycle + null; + + ELSIF status=erase_na THEN + --sector erase command sequence violation + null; + + -- Write to Flash Memory Array + ELSIF status /= err AND Sec_Prot(Sect)/='1'THEN + slv_1 := to_slv(d_lo,8); + IF mem(Sect)(Addr)>-1 THEN + slv_2 := to_slv(mem(Sect)(Addr),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + mem(Sect)(Addr) := to_nat(slv_1); + IF NOT command.byte THEN + slv_1 := to_slv(d_hi,8); + IF mem(Sect)(Addr+1)>-1 THEN + slv_2 := to_slv(mem(Sect)(Addr+1),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + mem(Sect)(Addr+1) := to_nat(slv_1); + END IF; + END IF; + + + WHEN wt => + WAIT FOR command.wtime; + + WHEN wt_rdy => + IF T_RY/='1' THEN + WAIT UNTIL rising_edge(T_RY) FOR command.wtime; + END IF; + + WHEN wt_bsy => + IF T_RY='1' THEN + WAIT UNTIL falling_edge(T_RY) FOR command.wtime; + END IF; + + WHEN OTHERS => null; + END CASE; + END PROCEDURE; + + + VARIABLE cmd_cnt : NATURAL; + VARIABLE command : cmd_rec; -- + +BEGIN + Pick_TC (Model => "AM29LV640MH90R" ); + + Tseries <= ts_cnt ; + Tcase <= tc_cnt ; + + Generate_TC + (Model => "AM29LV640MH90R" , + Series => ts_cnt, + TestCase => tc_cnt, + command_seq => cmd_seq); + + + cmd_cnt := 1; + WHILE cmd_seq(cmd_cnt).cmd/=done LOOP + command:= cmd_seq(cmd_cnt); + IF command.sect = -1 THEN + command.sect := ProtSecNum; + END IF; + status <= command.status; + sts_check<= to_slv(command.d_lo,8); --used only for toggle/status check + cmd_dc(command); + cmd_cnt :=cmd_cnt +1; + + END LOOP; + +END PROCESS tb; + +--process to monitor WP# +PROCESS(T_WPNeg) +VARIABLE reg : std_logic; +BEGIN + IF falling_edge(T_WPNeg) THEN + reg := Sec_Prot(ProtSecNum); + Sec_Prot(ProtSecNum) := '1'; + ELSIF rising_edge(T_WPNeg) THEN + Sec_Prot(ProtSecNum) := reg; + END IF; +END PROCESS; + +-------------------------------------------------------------------------------- +-- Checker process, +-- Bus transition extractor: when bus cycle is read samples addr and data +-- Transition checker : verifies correct read data using default memory +-------------------------------------------------------------------------------- +checker: PROCESS + VARIABLE RAddr : NATURAL; + VARIABLE RSect : NATURAL; + VARIABLE longread : boolean; + VARIABLE shortread : boolean; + VARIABLE toggle : boolean:=false; + VARIABLE toggle_sts : std_logic_vector(7 downto 0); + +BEGIN +-- Transition extractor + IF (T_CENeg='0'AND T_OENeg='0'AND T_WENeg='1') THEN + IF T_BYTENeg='1' THEN + RAddr := to_nat(T_A(14 downto 0)&'0'); + ELSE + RAddr := to_nat(T_A(14 downto 0)&T_DQ(15)); + END IF; + RSect := to_nat(T_A(HiAddrBit downto 15)); + + shortread:= false; + longread := false; + + --DUT specific timing + IF (T_CENeg'EVENT OR T_WENeg'EVENT OR T_A(HiAddrBit downto 2)'EVENT)AND -- + (status=read OR status=rd_cfi OR status=rd_secsi) THEN --OR status=readX) + longread := true; + CASE TimingModel IS + WHEN "AM29LV640MH90R" | + "AM29LV640ML90R" => WAIT FOR 95 ns; +-- WHEN "AM29LV640MH101" | +-- "AM29LV640ML101" => WAIT FOR 105 ns; +-- WHEN "AM29LV640MH101R" | +-- "AM29LV640ML101R" => WAIT FOR 105 ns; +-- WHEN "AM29LV640MH112" | +-- "AM29LV640ML112" => WAIT FOR 115 ns; +-- WHEN "AM29LV640MH112R" | +-- "AM29LV640ML112R" => WAIT FOR 115 ns; +-- WHEN "AM29LV640MH120" | +-- "AM29LV640ML120" => WAIT FOR 125 ns; +-- WHEN "AM29LV640MH120R" | +-- "AM29LV640ML120R" => WAIT FOR 125 ns; + WHEN OTHERS => + REPORT "Timing model NOT supported : "&TimingModel + SEVERITY error; + END CASE; + + ELSIF T_A(1 downto 0)'EVENT OR + (T_DQ(15)'EVENT AND T_BYTENeg='0')OR + (T_BYTENeg'EVENT) OR + T_OENeg'EVENT OR + (status/=read AND status/=rd_cfi AND + status/=rd_secsi) THEN --AND status/=readX) + shortread:=true; + CASE TimingModel IS + WHEN "AM29LV640MH90R" | + "AM29LV640ML90R" => WAIT FOR 30 ns; +-- WHEN "AM29LV640MH101" | +-- "AM29LV640ML101" => WAIT FOR 40 ns; +-- WHEN "AM29LV640MH101R" | +-- "AM29LV640ML101R" => WAIT FOR 40 ns; +-- WHEN "AM29LV640MH112" | +-- "AM29LV640ML112" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH112R" | +-- "AM29LV640ML112R" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH120" | +-- "AM29LV640ML120" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH120R" | +-- "AM29LV640ML120R" => WAIT FOR 45 ns; + WHEN OTHERS => + REPORT "Timing model NOT supported : "&TimingModel + SEVERITY error; + END CASE; + + END IF; + + + + --Checker + IF longread OR shortread THEN + + CASE status IS + WHEN none => + toggle := false; + + -- read memory array data + WHEN read => + toggle := false; + Check_read ( + DQ => T_DQ, + D_lo => mem(RSect)(RAddr), + D_hi => mem(RSect)(RAddr+1), + Byte => T_BYTENeg, + check_err=> check_err); + + -- read secure silicon region + WHEN rd_secsi => + toggle := false; + Check_SecSi ( + DQ => T_DQ, + D_lo => SecSi(RAddr), + D_hi => SecSi(RAddr+1), + Byte => T_BYTENeg, + check_err=>check_err); + + + --read CFI query codes + WHEN rd_cfi => + RAddr := to_nat(T_A(14 downto 0)); --x16 addressing + toggle := false; + Check_CFI ( + DQ => T_DQ, + D_lo => CFI_array(RAddr) , + D_hi => 0 , + Byte => T_BYTENeg, + check_err=>check_err); + + + + -- read Autoselect codes + WHEN rd_AS => + RAddr := to_nat(T_A(14 downto 0)); --x16 addressing + toggle := false; + Check_AS ( + DQ => T_DQ, + addr => RAddr, + ProtSecNum=>ProtSecNum, + secProt => Sec_Prot(RSect), + FactoryProt=>FactoryProt , + Byte => T_BYTENeg, + AS_E => to_slv(16#0C#,8), + AS_F => to_slv(1,8), + + check_err=>check_err); + + + WHEN rd_HiZ => + toggle:=false; + Check_Z ( + DQ => T_DQ, + check_err=>check_err); + + + + WHEN readX => + toggle:=false; + Check_X ( + DQ => T_DQ, + check_err=>check_err); + + + WHEN erase_na | erase_active => + IF toggle THEN + Check_Erase ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN ers_susp_e => + IF toggle THEN + Check_Ers_Susp ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + +-- + + WHEN ers_susp_prog_na | ers_susp_prog => + IF toggle THEN + Check_Ers_Susp_Prog ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + +-- + + WHEN prog_na | prog_active => + IF toggle THEN + Check_Progr ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN buff_wr_busy | buff_wr_N_busy => + IF toggle THEN + Check_Buff_Busy ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN buff_abort => + IF toggle THEN + Check_Abort ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + WHEN OTHERS => null; + END CASE; + + -- get firs data for toggle check + CASE status IS + WHEN prog_active | prog_na | + erase_active | erase_na | + ers_susp_e | + ers_susp_prog | ers_susp_prog_na | + buff_wr_busy | buff_wr_N_busy | + buff_abort | get_toggle => + + IF (NOT toggle) OR (status=get_toggle) THEN + toggle:=true; + toggle_sts := T_DQ(7 downto 0); + END IF; + + WHEN OTHERS => null; + END CASE; + + + END IF; + + END IF; + + WAIT ON T_A, T_CENeg, T_OENeg, T_WENeg, T_DQ(15), T_BYTENeg; + +END PROCESS checker; + + +default: PROCESS + -- text file input variables + FILE mem_f : text is mem_file; + FILE prot_f : text is prot_file; + FILE secsi_f : text is secsi_file; + + VARIABLE S_ind : NATURAL RANGE 0 TO SecNum:= 0; + VARIABLE ind : NATURAL RANGE 0 TO SecSize:= 0; + VARIABLE buf : line; + +BEGIN + --Preload Control + ----------------------------------------------------------------------- + -- File Read Section + ----------------------------------------------------------------------- + IF UserPreload THEN + --- Sector protection preload + IF (prot_file /= "none" ) THEN + ind := 0; + FactoryProt := '0'; + Sec_Prot := (OTHERS => '0'); + WHILE (not ENDFILE (prot_f)) LOOP + READLINE (prot_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 3)); --address + ELSE + IF ind > SecNum THEN + --SecSi Factory protect preload + IF buf(1)='1' THEN + FactoryProt := '1'; + END IF; + ELSE + -- Standard Sector prload + IF buf(1)='1' THEN + Sec_Prot(ind):= '1'; + END IF; + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + -- Secure Silicon Sector Region preload + IF (SecSi_file /= "none" ) THEN + SecSi := (OTHERS => MaxData); + ind := 0; + WHILE (not ENDFILE (SecSi_f)) LOOP + READLINE (SecSi_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 3)); --address + ELSE + IF ind <= SecSiSize THEN + SecSi(ind) := h(buf(1 TO 2)); + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + --- Memory Preload + IF (mem_file /= "none" ) THEN + ind := 0; + Mem := (OTHERS => (OTHERS => MaxData)); + -- load sector 0 + WHILE (not ENDFILE (mem_f)) LOOP + READLINE (mem_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 5)); --address + ELSE + IF ind <= SecSize THEN + Mem(0)(ind) := h(buf(1 to 2)); + ind := ind + 1; + END IF; + END IF; + END LOOP; + -- load other sectors + FOR i IN 1 TO SecNum LOOP + Mem(i) := Mem(0); + END LOOP; + END IF; + + END IF; + ----------------------------------------------------------------------- + --CFI array data / AM29LV640MH90R !!! DEVICE SPECIFIC + ----------------------------------------------------------------------- + --CFI query identification string + -- !!!!!! WORD ADDRESSES (x16) - for x8 addressing double addr + --CFI query identification string + CFI_array(16#10#) := 16#51#; + CFI_array(16#11#) := 16#52#; + CFI_array(16#12#) := 16#59#; + CFI_array(16#13#) := 16#02#; + CFI_array(16#14#) := 16#00#; + CFI_array(16#15#) := 16#40#; + CFI_array(16#16#) := 16#00#; + CFI_array(16#17#) := 16#00#; + CFI_array(16#18#) := 16#00#; + CFI_array(16#19#) := 16#00#; + CFI_array(16#1A#) := 16#00#; + --system interface string + CFI_array(16#1B#) := 16#27#; + CFI_array(16#1C#) := 16#36#; + CFI_array(16#1D#) := 16#00#; + CFI_array(16#1E#) := 16#00#; + CFI_array(16#1F#) := 16#07#; + CFI_array(16#20#) := 16#07#; + CFI_array(16#21#) := 16#0A#; + CFI_array(16#22#) := 16#00#; + CFI_array(16#23#) := 16#01#; + CFI_array(16#24#) := 16#05#; + CFI_array(16#25#) := 16#04#; + CFI_array(16#26#) := 16#00#; + --device geometry definition + CFI_array(16#27#) := 16#17#; + CFI_array(16#28#) := 16#02#; + CFI_array(16#29#) := 16#00#; + CFI_array(16#2A#) := 16#05#; + CFI_array(16#2B#) := 16#00#; + CFI_array(16#2C#) := 16#01#; + CFI_array(16#2D#) := 16#7F#; + CFI_array(16#2E#) := 16#00#; + CFI_array(16#2F#) := 16#00#; + CFI_array(16#30#) := 16#01#; + CFI_array(16#31#) := 16#00#; + CFI_array(16#32#) := 16#00#; + CFI_array(16#33#) := 16#00#; + CFI_array(16#34#) := 16#00#; + CFI_array(16#35#) := 16#00#; + CFI_array(16#36#) := 16#00#; + CFI_array(16#37#) := 16#00#; + CFI_array(16#38#) := 16#00#; + CFI_array(16#39#) := 16#00#; + CFI_array(16#3A#) := 16#00#; + CFI_array(16#3B#) := 16#00#; + CFI_array(16#3C#) := 16#00#; + --primary vendor-specific extended query + CFI_array(16#40#) := 16#50#; + CFI_array(16#41#) := 16#52#; + CFI_array(16#42#) := 16#49#; + CFI_array(16#43#) := 16#31#; + CFI_array(16#44#) := 16#33#; + CFI_array(16#45#) := 16#08#; + CFI_array(16#46#) := 16#02#; + CFI_array(16#47#) := 16#01#; + CFI_array(16#48#) := 16#01#; + CFI_array(16#49#) := 16#04#; + CFI_array(16#4A#) := 16#00#; + CFI_array(16#4B#) := 16#00#; + CFI_array(16#4C#) := 16#01#; + CFI_array(16#4D#) := 16#B5#; + CFI_array(16#4E#) := 16#C5#; + IF TimingModel(11) = 'L' THEN + CFI_array(16#4F#) := 16#04#; + ELSE + CFI_array(16#4F#) := 16#05#; --uniform sectors top protect + END IF; + CFI_array(16#50#) := 16#01#; + + WAIT; + +END PROCESS default; + + + +END vhdl_behavioral; + diff --git a/lib/models/memory/flash/serial/S25fl064a/utilities/conversions.vhd b/lib/models/memory/flash/serial/S25fl064a/utilities/conversions.vhd new file mode 100644 index 0000000..e5fc0d6 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064a/utilities/conversions.vhd @@ -0,0 +1,1035 @@ +-------------------------------------------------------------------------------- +-- File Name: conversions_p.vhd +-------------------------------------------------------------------------------- +-- Copyright (C) 1997, 1998, 2001 Free Model Foundry; http://eda.org/fmf/ +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License version 2 as +-- published by the Free Software Foundation. +-- +-- This package was written by SEVA Technologies, Inc. and donated to the FMF. +-- www.seva.com +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 R. Steele 97 DEC 05 Added header and formatting to SEVA file +-- V1.1 R. Munden 98 NOV 28 Corrected some comments +-- Corrected function b +-- V1.2 R. Munden 01 MAY 27 Corrected function to_nat for weak values +-- and combined into a single file +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; + +-------------------------------------------------------------------------------- +-- CONVERSION FUNCTION SELECTION TABLES +-------------------------------------------------------------------------------- +-- +-- FROM TO: std_logic_vector std_logic natural time string +-- -----------------|---------------|---------|---------|---------|----------- +-- std_logic_vector | N/A | N/A | to_nat | combine | see below +-- std_logic | N/A | N/A | to_nat | combine | see below +-- natural | to_slv | to_sl | N/A | to_time | see below +-- time | N/A | N/A | to_nat | N/A | to_time_str +-- hex string | h | N/A | h | combine | N/A +-- decimal string | d | N/A | d | combine | N/A +-- octal string | o | N/A | o | combine | N/A +-- binary string | b | N/A | b | combine | N/A +-- -----------------|---------------|---------|---------|---------|----------- +-- +-- FROM TO: hex string decimal string octal string binary string +-- -----------------|------------|-------------|------------|---------------- +-- std_logic_vector | to_hex_str | to_int_str | to_oct_str | to_bin_str +-- std_logic | N/A | N/A | N/A | to_bin_str +-- natural | to_hex_str | to_int_str | to_oct_str | to_bin_str +-- -----------------|------------|-------------|------------|---------------- +-- +-------------------------------------------------------------------------------- + +PACKAGE conversions IS + + ---------------------------------------------------------------------------- + -- the conversions in this package are not guaranteed to be synthesizable. + -- + -- others functions available + -- fill creates a variable length string of the fill character + -- + -- + -- + -- input parameters of type natural or integer can be in the form: + -- normal -> 8, 99, 4_237 + -- base#value# -> 2#0101#, 16#fa4C#, 8#6_734# + -- with exponents(x10) -> 8e4, 16#2e#E4 + -- + -- input parameters of type string can be in the form: + -- "99", "4_237", "0101", "1010_1010" + -- + -- for bit/bit_vector <-> std_logic/std_logic_vector conversions use + -- package std_logic_1164 + -- to_bit(std_logic) + -- to_bitvector(std_logic_vector) + -- to_stdlogic(bit) + -- to_stdlogicvector(bit_vector) + -- + -- for "synthesizable" signed/unsigned/std_logic_vector/integer + -- conversions use + -- package std_logic_arith + -- conv_integer(signed/unsigned) + -- conv_unsigned(integer/signed,size) + -- conv_signed(integer/unsigned,size) + -- conv_std_logic_vector(integer/signed/unsigned,size) + -- + -- for "synthesizable" std_logic_vector -> integer conversions use + -- package std_logic_unsigned/std_logic_signed + -- + -- conv_integer(std_logic_vector) + -- + -- type1'(expression of type2) + -- + -- most conversions have 4 parmeters: + -- x : value to be converted + -- rtn_len : size of the return value + -- justify : justify value 'left' or 'right', default is right + -- basespec : print the base of the value - 'yes'/'no', default is yes + -- + -- Typical ways to call these functions: + -- simple, all defaults used + -- to_bin_str(x) + -- x will be converted to a string of minimum size with a + -- base specification appended for clarity + -- if x is 10101 then return is b"10101" + -- + -- to control size of return string + -- to_hex_str(x, + -- 6) + -- length of string returned will be 6 characters + -- value will be right justified in the field + -- if x is 10101 then return is ....h"15" + -- where '.' represents a blank + -- if 'rtn_len' parm defaults or is set to 0 then + -- return string will always be minimum size + -- + -- to left justify and suppress base specification + -- to_int_str(x, + -- 6, + -- justify => left, + -- basespec => yes) + -- length of return string will be 6 characters + -- the base specification will be suppressed + -- if x is 10101 then return is 21.... + -- where '.' represents a blank + -- + -- other usage notes + -- + -- if rtn_len less than or equal to x'length then ignore + -- rtn_len and return string of x'length + -- the 'justify' parm is effectively ignored in this case + -- + -- if rtn_len greater than x'length then return string + -- of rtn_len with blanks based on 'justify' parm + -- + -- these routines do not handle negative numbers + ---------------------------------------------------------------------------- + + type justify_side is (left, right); + type b_spec is (no , yes); + + -- std_logic_vector to binary string + function to_bin_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- std_logic to binary string + function to_bin_str(x : std_logic; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to binary string + function to_bin_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to hex string + function to_hex_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to hex string + function to_hex_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to octal string + function to_oct_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to octal string + function to_oct_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- natural to integer string + function to_int_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to integer string + function to_int_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- time to string + function to_time_str (x : time) + return string; + + -- add characters to a string + function fill (fill_char : character := '*'; + rtn_len : integer := 1) + return string; + -- usage: + -- fill + -- returns * + -- fill(' ',10) + -- returns .......... when '.' represents a blank + -- fill(lf) or fill(ht) + -- returns line feed character or tab character respectively + + -- std_logic_vector to natural + function to_nat (x : std_logic_vector) + return natural; + + -- std_logic to natural + function to_nat (x : std_logic) + return natural; + + -- time to natural + function to_nat (x : time) + return natural; + + -- hex string to std_logic_vector + function h (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or a,A to f,F + -- or x,X,z,Z,u,U,-,w,W, result will be 0 + + -- decimal string to std_logic_vector + function d (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- octal string to std_logic_vector + function o (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 7 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- binary string to std_logic_vector + function b (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 1 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- hex string to natural + function h (x : string) + return natural; + -- if x is other than characters 0 to 9 or a,A to f,F, result will be 0 + + -- decimal string to natural + function d (x : string) + return natural; + -- if x is other than characters 0 to 9, result will be 0 + + -- octal string to natural + function o (x : string) + return natural; + -- if x is other than characters 0 to 7, result will be 0 + + -- binary string to natural + function b (x : string) + return natural; + -- if x is other than characters 0 to 1, result will be 0 + + -- natural to std_logic_vector + function to_slv (x : natural; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than sizeof(x), result will be truncated on the left + -- see note above regarding possible formats for x + + -- natural to std_logic + function to_sl (x : natural) + return std_logic; + + -- natural to time + function to_time (x : natural) + return time; + -- see note above regarding possible formats for x + +END conversions; +-- +-------------------------------------------------------------------------------- +-- + +PACKAGE BODY conversions IS + + -- private declarations for this package + type basetype is (binary, octal, decimal, hex); + + function max(x,y: integer) return integer is + begin + if x > y then return x; else return y; end if; + end max; + + function min(x,y: integer) return integer is + begin + if x < y then return x; else return y; end if; + end min; + + -- consider function sizeof for string/slv/???, return natural + + -- function size(len: natural) return natural is + -- begin + -- if len=0 then + -- return 31; + -- else return len; + -- end if; + -- end size; + + function nextmultof (x : positive; + size : positive) return positive is + begin + case x mod size is + when 0 => return size * x/size; + when others => return size * (x/size + 1); + end case; + end nextmultof; + + function rtn_base (base : basetype) return character is + begin + case base is + when binary => return 'b'; + when octal => return 'o'; + when decimal => return 'd'; + when hex => return 'h'; + end case; + end rtn_base; + + function format (r : string; + base : basetype; + rtn_len : natural ; + justify : justify_side; + basespec : b_spec) return string is + variable int_rtn_len : integer; + begin + if basespec=yes then + int_rtn_len := rtn_len - 3; + else + int_rtn_len := rtn_len; + end if; + if int_rtn_len <= r'length then + case basespec is + when no => return r ; + when yes => return rtn_base(base) & '"' & r & '"'; + end case; + else + case justify is + when left => + case basespec is + when no => + return r & fill(' ',int_rtn_len - r'length); + when yes => + return rtn_base(base) & '"' & r & '"' & + fill(' ',int_rtn_len - r'length); + end case; + when right => + case basespec is + when no => + return fill(' ',int_rtn_len - r'length) & r ; + when yes => + return fill(' ',int_rtn_len - r'length) & + rtn_base(base) & '"' & r & '"'; + end case; + end case; + end if; + end format; + + -- convert numeric string of any base to natural + function cnvt_base (x : string; + inbase : natural range 2 to 16) return natural is + -- assumes x is an unsigned number string of base 'inbase' + -- values larger than natural'high are not supported + variable r,t : natural := 0; + variable place : positive := 1; + begin + for i in x'reverse_range loop + case x(i) is + when '0' => t := 0; + when '1' => t := 1; + when '2' => t := 2; + when '3' => t := 3; + when '4' => t := 4; + when '5' => t := 5; + when '6' => t := 6; + when '7' => t := 7; + when '8' => t := 8; + when '9' => t := 9; + when 'a'|'A' => t := 10; + when 'b'|'B' => t := 11; + when 'c'|'C' => t := 12; + when 'd'|'D' => t := 13; + when 'e'|'E' => t := 14; + when 'f'|'F' => t := 15; + when '_' => t := 0; -- ignore these characters + place := place / inbase; + when others => + assert false + report lf & + "CNVT_BASE found input value larger than base: " & lf & + "Input value: " & x(i) & + " Base: " & to_int_str(inbase) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + if t / inbase > 1 then -- invalid value for base + assert false + report lf & + "CNVT_BASE found input value larger than base: " & lf & + "Input value: " & x(i) & + " Base: " & to_int_str(inbase) & lf & + "converting input to integer 0" + severity warning; + return 0; + else + r := r + (t * place); + place := place * inbase; + end if; + end loop; + return r; + end cnvt_base; + + function extend (x : std_logic; + len : positive) return std_logic_vector is + variable v : std_logic_vector(1 to len) := (others => x); + begin + return v; + end extend; + + + -- implementation of public declarations + + function to_bin_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + + variable int : std_logic_vector(1 to x'length):=x; + variable r : string(1 to x'length):=(others=>'$'); + begin + for i in int'range loop + r(i to i) := to_bin_str(int(i),basespec=>no); + end loop; + return format (r,binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_bin_str(x : std_logic; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable r : string(1 to 1); + begin + case x is + when '0' => r(1) := '0'; + when '1' => r(1) := '1'; + when 'U' => r(1) := 'U'; + when 'X' => r(1) := 'X'; + when 'Z' => r(1) := 'Z'; + when 'W' => r(1) := 'W'; + when 'H' => r(1) := 'H'; + when 'L' => r(1) := 'L'; + when '-' => r(1) := '-'; + end case; + return format (r,binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_bin_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 2 to 32 := 32; + variable r : string(2 to 32):=(others=>'$'); + begin + if int = 0 then + return format ("0",binary,rtn_len,justify,basespec); + end if; + + while int > 0 loop + case int rem 2 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when others => + assert false report lf & "TO_BIN_STR, shouldn't happen" + severity failure; + return "$"; + null; + end case; + int := int / 2; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 32),binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_hex_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + -- will return x'length/4 + variable nxt : positive := nextmultof(x'length,4); + variable int : std_logic_vector(1 to nxt):= (others => '0'); + variable ptr : positive range 1 to (nxt/4)+1 := 1; + variable r : string(1 to nxt/4):=(others=>'$'); + subtype slv4 is std_logic_vector(1 to 4); + begin + int(nxt-x'length+1 to nxt) := x; + if nxt-x'length > 0 and x(x'left) /= '1' then + int(1 to nxt-x'length) := extend(x(x'left),nxt-x'length); + end if; + for i in int'range loop + next when i rem 4 /= 1; + case slv4'(int(i to i+3)) is + when "0000" => r(ptr) := '0'; + when "0001" => r(ptr) := '1'; + when "0010" => r(ptr) := '2'; + when "0011" => r(ptr) := '3'; + when "0100" => r(ptr) := '4'; + when "0101" => r(ptr) := '5'; + when "0110" => r(ptr) := '6'; + when "0111" => r(ptr) := '7'; + when "1000" => r(ptr) := '8'; + when "1001" => r(ptr) := '9'; + when "1010" => r(ptr) := 'A'; + when "1011" => r(ptr) := 'B'; + when "1100" => r(ptr) := 'C'; + when "1101" => r(ptr) := 'D'; + when "1110" => r(ptr) := 'E'; + when "1111" => r(ptr) := 'F'; + when "ZZZZ" => r(ptr) := 'Z'; + when "WWWW" => r(ptr) := 'W'; + when "LLLL" => r(ptr) := 'L'; + when "HHHH" => r(ptr) := 'H'; + when "UUUU" => r(ptr) := 'U'; + when "XXXX" => r(ptr) := 'X'; + when "----" => r(ptr) := '-'; + when others => + assert false + report lf & + "TO_HEX_STR found illegal value: " & + to_bin_str(int(i to i+3)) & lf & + "converting input to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr + 1; + end loop; + return format (r,hex,rtn_len,justify,basespec); + end to_hex_str; + + function to_hex_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 20 := 20; + variable r : string(1 to 20):=(others=>'$'); + begin + if x=0 then return format ("0",hex,rtn_len,justify,basespec); end if; + while int > 0 loop + case int rem 16 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when 8 => r(ptr) := '8'; + when 9 => r(ptr) := '9'; + when 10 => r(ptr) := 'A'; + when 11 => r(ptr) := 'B'; + when 12 => r(ptr) := 'C'; + when 13 => r(ptr) := 'D'; + when 14 => r(ptr) := 'E'; + when 15 => r(ptr) := 'F'; + when others => + assert false report lf & "TO_HEX_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 16; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 20),hex,rtn_len,justify,basespec); + end to_hex_str; + + function to_oct_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + -- will return x'length/3 + variable nxt : positive := nextmultof(x'length,3); + variable int : std_logic_vector(1 to nxt):= (others => '0'); + variable ptr : positive range 1 to (nxt/3)+1 := 1; + variable r : string(1 to nxt/3):=(others=>'$'); + subtype slv3 is std_logic_vector(1 to 3); + begin + int(nxt-x'length+1 to nxt) := x; + if nxt-x'length > 0 and x(x'left) /= '1' then + int(1 to nxt-x'length) := extend(x(x'left),nxt-x'length); + end if; + for i in int'range loop + next when i rem 3 /= 1; + case slv3'(int(i to i+2)) is + when "000" => r(ptr) := '0'; + when "001" => r(ptr) := '1'; + when "010" => r(ptr) := '2'; + when "011" => r(ptr) := '3'; + when "100" => r(ptr) := '4'; + when "101" => r(ptr) := '5'; + when "110" => r(ptr) := '6'; + when "111" => r(ptr) := '7'; + when "ZZZ" => r(ptr) := 'Z'; + when "WWW" => r(ptr) := 'W'; + when "LLL" => r(ptr) := 'L'; + when "HHH" => r(ptr) := 'H'; + when "UUU" => r(ptr) := 'U'; + when "XXX" => r(ptr) := 'X'; + when "---" => r(ptr) := '-'; + when others => + assert false + report lf & + "TO_OCT_STR found illegal value: " & + to_bin_str(int(i to i+2)) & lf & + "converting input to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr + 1; + end loop; + return format (r,octal,rtn_len,justify,basespec); + end to_oct_str; + + function to_oct_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 20 := 20; + variable r : string(1 to 20):=(others=>'$'); + begin + if x=0 then return format ("0",octal,rtn_len,justify,basespec); end if; + while int > 0 loop + case int rem 8 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when others => + assert false report lf & "TO_OCT_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 8; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 20),octal,rtn_len,justify,basespec); + end to_oct_str; + + function to_int_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 32 := 32; + variable r : string(1 to 32):=(others=>'$'); + begin + if x=0 then return format ("0",hex,rtn_len,justify,basespec); + else + while int > 0 loop + case int rem 10 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when 8 => r(ptr) := '8'; + when 9 => r(ptr) := '9'; + when others => + assert false report lf & "TO_INT_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 10; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 32),decimal,rtn_len,justify,basespec); + end if; + end to_int_str; + + function to_int_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string is + begin + return to_int_str(to_nat(x),rtn_len,justify,basespec); + end to_int_str; + + + function to_time_str (x : time) + return string is + begin + return to_int_str(to_nat(x),basespec=>no) & " ns"; + end to_time_str; + + function fill (fill_char : character := '*'; + rtn_len : integer := 1) + return string is + variable r : string(1 to max(rtn_len,1)) := (others => fill_char); + variable len : integer; + begin + if rtn_len < 2 then -- always returns at least 1 fill char + len := 1; + else + len := rtn_len; + end if; + return r(1 to len); + end fill; + + function to_nat(x : std_logic_vector) return natural is + -- assumes x is an unsigned number, lsb on right, + -- more than 31 bits are truncated on left + variable t : std_logic_vector(1 to x'length) := x; + variable int : std_logic_vector(1 to 31) := (others => '0'); + variable r : natural := 0; + variable place : positive := 1; + begin + if x'length < 32 then + int(max(32-x'length,1) to 31) := t(1 to x'length); + else -- x'length >= 32 + int(1 to 31) := t(x'length-30 to x'length); + end if; + for i in int'reverse_range loop + case int(i) is + when '1' | 'H' => r := r + place; + when '0' | 'L' => null; + when others => + assert false + report lf & + "TO_NAT found illegal value: " & to_bin_str(int(i)) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + exit when i=1; + place := place * 2; + end loop; + return r; + end to_nat; + + function to_nat (x : std_logic) + return natural is + begin + case x is + when '0' => return 0 ; + when '1' => return 1 ; + when others => + assert false + report lf & + "TO_NAT found illegal value: " & to_bin_str(x) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + end to_nat; + + function to_nat (x : time) + return natural is + begin + return x / 1 ns; + end to_nat; + + function h(x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or a,A to f,F or + -- x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length*4,rtn_len); + variable ptr : integer range -3 to size := size; + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr-3 to ptr) := "0000"; + when '1' => r(ptr-3 to ptr) := "0001"; + when '2' => r(ptr-3 to ptr) := "0010"; + when '3' => r(ptr-3 to ptr) := "0011"; + when '4' => r(ptr-3 to ptr) := "0100"; + when '5' => r(ptr-3 to ptr) := "0101"; + when '6' => r(ptr-3 to ptr) := "0110"; + when '7' => r(ptr-3 to ptr) := "0111"; + when '8' => r(ptr-3 to ptr) := "1000"; + when '9' => r(ptr-3 to ptr) := "1001"; + when 'a'|'A' => r(ptr-3 to ptr) := "1010"; + when 'b'|'B' => r(ptr-3 to ptr) := "1011"; + when 'c'|'C' => r(ptr-3 to ptr) := "1100"; + when 'd'|'D' => r(ptr-3 to ptr) := "1101"; + when 'e'|'E' => r(ptr-3 to ptr) := "1110"; + when 'f'|'F' => r(ptr-3 to ptr) := "1111"; + when 'U' => r(ptr-3 to ptr) := "UUUU"; + when 'X' => r(ptr-3 to ptr) := "XXXX"; + when 'Z' => r(ptr-3 to ptr) := "ZZZZ"; + when 'W' => r(ptr-3 to ptr) := "WWWW"; + when 'H' => r(ptr-3 to ptr) := "HHHH"; + when 'L' => r(ptr-3 to ptr) := "LLLL"; + when '-' => r(ptr-3 to ptr) := "----"; + when '_' => ptr := ptr + 4; + when others => + assert false + report lf & + "O conversion found illegal input character: " & + int(i) & lf & "converting character to '----'" + severity warning; + r(ptr-3 to ptr) := "----"; + end case; + ptr := ptr - 4; + end loop; + return r(size-rtn_len+1 to size); + end h; + + function d (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than binary length of x, result will be truncated on + -- the left + -- if x is other than characters 0 to 9, result will be 0 + begin + return to_slv(cnvt_base(x,10),rtn_len); + end d; + + function o (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length*3, result will be truncated on the left + -- if x is other than characters 0 to 7 or or x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length*3,rtn_len); + variable ptr : integer range -2 to size := size; + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr-2 to ptr) := "000"; + when '1' => r(ptr-2 to ptr) := "001"; + when '2' => r(ptr-2 to ptr) := "010"; + when '3' => r(ptr-2 to ptr) := "011"; + when '4' => r(ptr-2 to ptr) := "100"; + when '5' => r(ptr-2 to ptr) := "101"; + when '6' => r(ptr-2 to ptr) := "110"; + when '7' => r(ptr-2 to ptr) := "111"; + when 'U' => r(ptr-2 to ptr) := "UUU"; + when 'X' => r(ptr-2 to ptr) := "XXX"; + when 'Z' => r(ptr-2 to ptr) := "ZZZ"; + when 'W' => r(ptr-2 to ptr) := "WWW"; + when 'H' => r(ptr-2 to ptr) := "HHH"; + when 'L' => r(ptr-2 to ptr) := "LLL"; + when '-' => r(ptr-2 to ptr) := "---"; + when '_' => ptr := ptr + 3; + when others => + assert false + report lf & + "O conversion found illegal input character: " & + int(i) & lf & "converting character to '---'" + severity warning; + r(ptr-2 to ptr) := "---"; + end case; + ptr := ptr - 3; + end loop; + return r(size-rtn_len+1 to size); + end o; + + function b (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length, result will be truncated on the left + -- if x is other than characters 0 to 1 or x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length,rtn_len); + variable ptr : integer range 0 to size+1 := size; -- csa + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr) := '0'; + when '1' => r(ptr) := '1'; + when 'U' => r(ptr) := 'U'; + when 'X' => r(ptr) := 'X'; + when 'Z' => r(ptr) := 'Z'; + when 'W' => r(ptr) := 'W'; + when 'H' => r(ptr) := 'H'; + when 'L' => r(ptr) := 'L'; + when '-' => r(ptr) := '-'; + when '_' => ptr := ptr + 1; + when others => + assert false + report lf & + "B conversion found illegal input character: " & + int(i) & lf & "converting character to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr - 1; + end loop; + return r(size-rtn_len+1 to size); + end b; + + function h (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 9 + -- a,A to f,F + -- blanks, underscore + begin + return cnvt_base(x,16); + end h; + + function d (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 9 + -- blanks, underscore + begin + return cnvt_base(x,10); + end d; + + function o (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 7 + -- blanks, underscore + begin + return cnvt_base(x,8); + end o; + + function b (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 1 + -- blanks, underscore + begin + return cnvt_base(x,2); + end b; + + function to_slv(x : natural; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than sizeof(x), result will be truncated on the left + variable int : natural := x; + variable ptr : positive := 32; + variable r : std_logic_vector(1 to 32) := (others=>'0'); + begin + while int > 0 loop + case int rem 2 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when others => + assert false report lf & "TO_SLV, shouldn't happen" + severity failure; + return "0"; + end case; + int := int / 2; + ptr := ptr - 1; + end loop; + return r(33-rtn_len to 32); + end to_slv; + + function to_sl(x : natural) + return std_logic is + variable r : std_logic := '0'; + begin + case x is + when 0 => null; + when 1 => r := '1'; + when others => + assert false + report lf & + "TO_SL found illegal input character: " & + to_int_str(x) & lf & "converting character to '-'" + severity warning; + return '-'; + end case; + return r; + end to_sl; + + function to_time (x: natural) return time is + begin + return x * 1 ns; + end to_time; + +END conversions; diff --git a/lib/models/memory/flash/serial/S25fl064a/utilities/gen_utils.vhd b/lib/models/memory/flash/serial/S25fl064a/utilities/gen_utils.vhd new file mode 100644 index 0000000..65c0e77 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064a/utilities/gen_utils.vhd @@ -0,0 +1,144 @@ +-------------------------------------------------------------------------------- +-- File name: gen_utils.vhd +-------------------------------------------------------------------------------- +-- Copyright (C) 1996, 1998, 2001 Free Model Foundry; http://eda.org/fmf/ +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License version 2 as +-- published by the Free Software Foundation. +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 R. Steele 96 SEP 26 Initial release +-- V1.1 REV3 97 Feb 27 Added Xon and MsgOn generics +-- V1.2 R. Steele 97 APR 16 Changed wired-or to wired-and +-- V1.3 R. Steele 97 APR 16 Added diff. receiver table +-- V1.4 R. Munden 98 APR 13 Added GenParity and CheckParity +-- V1.5 R. Munden 01 NOV 24 Added UnitDelay01ZX +-- +-------------------------------------------------------------------------------- +LIBRARY IEEE; USE IEEE.std_Logic_1164.ALL; + USE IEEE.VITAL_primitives.ALL; + USE IEEE.VITAL_timing.ALL; + +PACKAGE gen_utils IS + + ---------------------------------------------------------------------------- + -- Result map for Wired-and output values (open collector) + ---------------------------------------------------------------------------- + CONSTANT STD_wired_and_rmap : VitalResultMapType := ('U','X','0','Z'); + + ---------------------------------------------------------------------------- + -- Table for computing a single signal from a differential receiver input + -- pair. + ---------------------------------------------------------------------------- + CONSTANT diff_rec_tab : VitalStateTableType := ( + + ------INPUTS--|-PREV-|-OUTPUT---- + -- A ANeg | Aint | Aint' -- + --------------|------|----------- + ( 'X', '-', '-', 'X'), -- A unknown + ( '-', 'X', '-', 'X'), -- A unknown + ( '1', '-', 'X', '1'), -- Recover from 'X' + ( '0', '-', 'X', '0'), -- Recover from 'X' + ( '/', '0', '0', '1'), -- valid diff. rising edge + ( '1', '\', '0', '1'), -- valid diff. rising edge + ( '\', '1', '1', '0'), -- valid diff. falling edge + ( '0', '/', '1', '0'), -- valid diff. falling edge + ( '-', '-', '-', 'S') -- default + ); -- end of VitalStateTableType definition + + + ---------------------------------------------------------------------------- + -- Default Constants + ---------------------------------------------------------------------------- + CONSTANT UnitDelay : VitalDelayType := 1 ns; + CONSTANT UnitDelay01 : VitalDelayType01 := (1 ns, 1 ns); + CONSTANT UnitDelay01Z : VitalDelayType01Z := (others => 1 ns); + CONSTANT UnitDelay01ZX : VitalDelayType01ZX := (others => 1 ns); + + CONSTANT DefaultInstancePath : STRING := "*"; + CONSTANT DefaultTimingChecks : BOOLEAN := FALSE; + CONSTANT DefaultTimingModel : STRING := "UNIT"; + CONSTANT DefaultXon : BOOLEAN := TRUE; + CONSTANT DefaultMsgOn : BOOLEAN := TRUE; + + -- Older VITAL generic being phased out + CONSTANT DefaultXGeneration : BOOLEAN := TRUE; + + ------------------------------------------------------------------- + -- Generate Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION GenParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic_vector; + + ------------------------------------------------------------------- + -- Check Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION CheckParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic; -- '0' - Parity Error + +END gen_utils; + +PACKAGE BODY gen_utils IS + + function XOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 403 + variable result: STD_LOGIC; + begin + result := '0'; + for i in ARG'range loop + result := result xor ARG(i); + end loop; + return result; + end; + ------------------------------------------------------------------- + -- Generate Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION GenParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic_vector + IS + VARIABLE I: NATURAL; + VARIABLE Result: std_logic_vector (Data'Length - 1 DOWNTO 0); + BEGIN + I := 0; + WHILE (I < SIZE) LOOP + Result(I+7 DOWNTO I) := Data(I+7 downto I); + Result(I+8) := XOR_REDUCE( Data(I+7 downto I) ) XOR ODDEVEN; + I := I + 9; + END LOOP; + RETURN Result; + END GenParity; + + ------------------------------------------------------------------- + -- Check Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION CheckParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic -- '0' - Parity Error + IS + VARIABLE I: NATURAL; + VARIABLE Result: std_logic; + BEGIN + I := 0; Result := '1'; + WHILE (I < SIZE) LOOP + Result := Result AND + NOT (XOR_REDUCE( Data(I+8 downto I) ) XOR ODDEVEN); + I := I + 9; + END LOOP; + RETURN Result; + END CheckParity; + +END gen_utils; diff --git a/lib/models/memory/flash/serial/S25fl064k/Model_Manual_English.pdf b/lib/models/memory/flash/serial/S25fl064k/Model_Manual_English.pdf new file mode 100644 index 0000000..954c3f6 Binary files /dev/null and b/lib/models/memory/flash/serial/S25fl064k/Model_Manual_English.pdf differ diff --git a/lib/models/memory/flash/serial/S25fl064k/Model_Manual_Japanese.pdf b/lib/models/memory/flash/serial/S25fl064k/Model_Manual_Japanese.pdf new file mode 100644 index 0000000..de2f909 Binary files /dev/null and b/lib/models/memory/flash/serial/S25fl064k/Model_Manual_Japanese.pdf differ diff --git a/lib/models/memory/flash/serial/S25fl064k/model/model_release_history.txt b/lib/models/memory/flash/serial/S25fl064k/model/model_release_history.txt new file mode 100644 index 0000000..b919e1e --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064k/model/model_release_history.txt @@ -0,0 +1,89 @@ +########################################## +Date (DD/MM/YYYY) - 07.09.2010 + +Model name - S25FL064K + +Vendor - SPANSION (www.spansion.com) + +Publication ID - Document No. P/N: S25FL064K_00 Rev. 0.01, June 29. 2010, + Spansion Inc. + +VITAL model author - Ranko Prokopovic + r-prokopovic@hdl-dh.com +########################################## +########################################## +INITIAL RELEASE + +# Release Label => vital-amd-serial-s25fl-REL-s25fl064k-2010-09-07-1.tar.gz +# Release Date (DD/MM/YYYY) => 07/09/2010 +# Release Version => 1.0 + +########################################## +VITAL model author - Ranko Prokopovic + r-prokopovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl064k-2010-09-08-2.tar.gz +# Release Date (DD/MM/YYYY) => 08/09/2010 +# Release Version => 1.1 + +# Corrections: +# Documentation added. +# Write Enable for Volatile Status register Instruction implemented. +# Test for Write Enable for Volatile Status register instruction. + +# Files modified +-s25fl064.v +-testbench_s25fl064k_verilog.vhd +-spansion_tc_pkg.vhd +########################################## +VITAL model author - Ranko Prokopovic + r-prokopovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl064k-2010-09-15-1.tar.gz +# Release Date (DD/MM/YYYY) => 15/09/2010 +# Release Version => 1.2 + +# Corrections: +# VHDL model added +# Read ID instruciton (ABh) also can be issued when device is not in deep power down mode +# bus_cycle section for WRR command is changed +# path delay conditions modified + +# Files modified +-s25fl064.v +-testbench_s25fl064k_verilog.vhd +-spansion_tc_pkg.vhd +-s25fl064k.ftmv +-s25fl064k_verilog.sdf +########################################## +VITAL model author - Ranko Prokopovic + r-prokopovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl064k-2010-09-17-1.tar.gz +# Release Date (DD/MM/YYYY) => 17/09/2010 +# Release Version => 1.3 + +# Corrections: +# Line "define SPEEDSIM" in Verilog model was left commented, and testbench had parameter +# 'LongTimming' set on FALSE +# some unnecessary lines were removed + +# Files modified +-s25fl064.v +-testbench_s25fl064k_verilog.vhd +-s25fl064k.vhd +-testbench_s25fl064k_vhdl.vhd +########################################## +VITAL model author - Snezana Petrovic + s-petrovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl064k-2012-06-15-1.tar.gz +# Release Date (DD/MM/YYYY) => 15/06/2012 +# Release Version => 1.4 + +# Corrections: +# Corrected functionality for sector and block erase and page program operation + +# Files modified +-s25fl064k.vhd +########################################## \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl064k/model/s25fl064k.v b/lib/models/memory/flash/serial/S25fl064k/model/s25fl064k.v new file mode 100644 index 0000000..4d54f4c --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064k/model/s25fl064k.v @@ -0,0 +1,4219 @@ +/////////////////////////////////////////////////////////////////////////////// +// File name : s25fl064k.v +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2010 Spansion, LLC. +// +// MODIFICATION HISTORY : +// +// version: | author: | mod date: | changes made: +// V1.0 R.Prokopovic 03 Aug 10 Initial +// +/////////////////////////////////////////////////////////////////////////////// +// PART DESCRIPTION: +// +// Library: FLASH +// Technology: FLASH MEMORY +// Part: S25FL064K +// +// Description: 64 Megabit Serial Flash Memory +// +/////////////////////////////////////////////////////////////////////////////// +// Comments : +// +////////////////////////////////////////////////////////////////////////////// +// Known Bugs: +// +////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// MODULE DECLARATION // +////////////////////////////////////////////////////////////////////////////// +`timescale 1 ps/1 ps + +module s25fl064k + ( + // Data Inputs/Outputs + SI , + SO , + // Controls + SCK , + CSNeg , + HOLDNeg, + WPNeg + +); + +/////////////////////////////////////////////////////////////////////////////// +// Port / Part Pin Declarations +/////////////////////////////////////////////////////////////////////////////// + inout SI ; + inout SO ; + input SCK ; + input CSNeg ; + inout HOLDNeg ; + inout WPNeg ; + + // interconnect path delay signals + wire SCK_ipd ; + wire SI_ipd ; + wire SO_ipd ; + + wire SI_in ; + assign SI_in = SI_ipd ; + + wire SI_out ; + assign SI_out = SI ; + + wire SO_in ; + assign SO_in = SO_ipd ; + + wire SO_out ; + assign SO_out = SO ; + + wire CSNeg_ipd ; + wire HOLDNeg_ipd ; + wire WPNeg_ipd ; + + wire HOLDNeg_in ; + //Internal pull-up + assign HOLDNeg_in = (HOLDNeg_ipd === 1'bx) ? 1'b1 : HOLDNeg_ipd; + + wire HOLDNeg_out ; + assign HOLDNeg_out = HOLDNeg ; + + wire WPNeg_in ; + //Internal pull-up + assign WPNeg_in = (WPNeg_ipd === 1'bx) ? 1'b1 : WPNeg_ipd; + + wire WPNeg_out ; + assign WPNeg_out = WPNeg ; + + // ***** internal delays ********************* + reg PP_in ; + reg PP_out ; + reg BP_in ; + reg BP_out ; + reg SE_in ; + reg SE_out ; + reg BE_in ; + reg BE_out ; + reg PRGSUSP_in ; + reg PRGSUSP_out ; + reg ERSSUSP_in ; + reg ERSSUSP_out ; + reg PRGRES_out ; + reg ERSRES_out ; + reg PRGRES_in ; + reg ERSRES_in ; + reg WRR_in ; + reg WRR_out ; + reg DP_in ; + reg DP_out ; + reg RES_in ; + reg RES_out ; + // ******* event control registers ************ + reg PRGSUSP_out_event; + reg PRGRES_out_event; + reg ERSSUSP_out_event; + reg ERSRES_out_event; + reg PGSUSP_event; + reg PGRES_event; + reg ESUSP_event; + reg ERES_event; + reg next_state_event; + + reg rising_edge_PoweredUp; + reg rising_edge_RES_out; + reg rising_edge_PRGRES_out; + reg rising_edge_PSTART; + reg rising_edge_WSTART; + reg rising_edge_VLTSTART; + reg rising_edge_ESTART; + reg rising_edge_prot_bits; + reg rising_edge_CSNeg_ipd = 1'b0; + reg falling_edge_CSNeg_ipd = 1'b0; + reg rising_edge_SCK_ipd = 1'b0; + reg falling_edge_SCK_ipd = 1'b0; + + reg SOut_zd = 1'bZ ; + reg SOut_z = 1'bZ ; + + wire SI_z ; + wire SO_z ; + + reg SIOut_zd = 1'bZ ; + reg SIOut_z = 1'bZ ; + + reg WPNegOut_zd = 1'bZ ; + reg HOLDNegOut_zd = 1'bZ ; + + assign SI_z = SIOut_z; + assign SO_z = SOut_z; + + parameter UserPreload = 1; + parameter mem_file_name = "none";//"s25fl064k.mem"; + parameter screg_file_name = "s25fl064kscreg.mem";//"none"; + parameter TimingModel = "DefaultTimingModel"; + + parameter PartID = "s25fl064k"; + parameter MaxData = 255; + parameter AddrRANGE = 24'h7FFFFF; + parameter PageNum = 16'h7FFF; + parameter SecSize_4 = 12'hFFF; + parameter SecSize_32 = 16'h7FFF; + parameter SecSize_64 = 16'hFFFF; + parameter Blk_4_Num = 2047; + parameter Blk_64_Num = 127; + parameter Blk_32_Num = 255; + parameter SFDP_HiAddr = 8'hFF; + parameter SFDP_LoAddr = 8'h00; + parameter SecReg_HiAddr = 8'hFF; + parameter SecReg_LoAddr = 8'h00; + parameter SCREG_LoAddr = 12'h000; + parameter SCREG_HiAddr = 12'h2FF; + parameter BYTE = 8; + + // Manufacturer Identification and Device Identification + parameter Manuf_ID = 8'hEF; + parameter Device_ID1 = 8'h16; + parameter Device_ID2 = 8'h40; + parameter Device_ID3 = 8'h17; + parameter unique_id = 64'h000000000000ABAB; + + // If speedsimulation is needed uncomment following line + + `define SPEEDSIM; + + // powerup + reg PoweredUp; + + // FSM control signals + reg PDONE ; + reg PSTART ; + reg PGSUSP ; + reg PGRES ; +// reg ERSRES ; + + reg WDONE ; + reg WSTART ; + reg VLTSTART ; + reg VLTDONE ; + + reg EDONE ; + reg ESTART ; + reg ESUSP ; + reg ERES ; + + // Programming buffer + integer WByte[0:255]; + + // Flash Memory Array + integer Mem[0:AddrRANGE]; + + // Registers + // Status Register 1 + reg[7:0] Status_reg1 = 8'h00; + reg[7:0] Status_reg1_in = 8'h00; + + wire SRP0; + wire SEC; + wire TB; + wire BP2; + wire BP1; + wire BP0; + wire WEL; + wire BUSY; + assign SRP0 = Status_reg1[7]; + assign SEC = Status_reg1[6]; + assign TB = Status_reg1[5]; + assign BP2 = Status_reg1[4]; + assign BP1 = Status_reg1[3]; + assign BP0 = Status_reg1[2]; + assign WEL = Status_reg1[1]; + assign BUSY = Status_reg1[0]; + + // Status Register 2 + reg[7:0] Status_reg2 = 8'h00; + reg[7:0] Status_reg2_in = 8'h00; + + wire SUS; + wire CMP; +// wire LB3; +// wire LB2; +// wire LB1; + wire [2:0]LB; + wire QE; + wire SRP1; + assign SUS = Status_reg2[7]; + assign CMP = Status_reg2[6]; + assign LB = Status_reg2[5:3]; +// assign LB2 = Status_reg2[4]; +// assign LB1 = Status_reg2[3]; + assign QE = Status_reg2[1]; + assign SRP1 = Status_reg2[0]; + + reg[15:0] Status_reg; // Status_reg2 & Status_reg1 + reg[15:0] Status_reg_in; // Status_reg2 & Status_reg1 + + // Sector is protect if Sec_Prot(SecNum) = '1' + reg [Blk_4_Num:0] Sec_Prot = {2048{1'b0}}; + + // Security registers array + integer Security_Reg[SCREG_LoAddr:SCREG_HiAddr]; + integer Security_Reg1[SecReg_LoAddr:SecReg_HiAddr]; + integer Security_Reg2[SecReg_LoAddr:SecReg_HiAddr]; + integer Security_Reg3[SecReg_LoAddr:SecReg_HiAddr]; + + // SFDP register array + integer SFDP_array[SFDP_LoAddr:SFDP_HiAddr]; + + /////////////////////////////////////////////////////////////////////////// + // Command Register + reg write; + reg read_out; + reg slow_read; + reg dual_read; + reg fast_read; + reg quad_read; + reg pp_quad; + reg oe = 1'b0; + event oe_event; + + reg[7:0] old_bit, new_bit; + integer old_int, new_int; + integer wr_cnt; + integer cnt; + integer Byte_number = 0; + integer read_cnt = 0; + integer read_addr = 0; + reg[7:0] data_out; + reg[23:0] ident_out; + reg[15:0] ident_out2; + integer AddrLo; + integer AddrHi; + integer AddrLo_ers; + integer AddrHi_ers; + integer AddrLo_wrap; + integer AddrHi_wrap; + + reg change_prot_bits = 0; + + //Address + integer Address = 0; // 0 - AddrRANGE + reg change_addr; + + //Sector and subsector addresses + integer SA = 0; + integer sect; + integer sect_tmp_pg; + integer sect_tmp_ers; + integer sfdp_addr; + integer w_size; +// integer w_size; + + reg hold_mode = 1'b0; + + // Flag for release from deep power down, read ID or not + reg res_flag; + reg pg_screg_flag = 1'b0; + reg ers_screg_flag = 1'b0; + reg wren_vlt_flag = 1'b0; + reg susp_flag = 1'b0; + // timing check violation + reg Viol = 1'b0; + reg sr_read = 1'b0; + reg read_id = 1'b0; +/////////////////////////////////////////////////////////////////////////////// +//Interconnect Path Delay Section +/////////////////////////////////////////////////////////////////////////////// + buf (SCK_ipd, SCK); + buf (SI_ipd, SI); + + buf (SO_ipd, SO); + buf (CSNeg_ipd, CSNeg); + buf (HOLDNeg_ipd, HOLDNeg); + buf (WPNeg_ipd, WPNeg); + +/////////////////////////////////////////////////////////////////////////////// +// Propagation delay Section +/////////////////////////////////////////////////////////////////////////////// + nmos (SI, SI_z , 1); + + nmos (SO, SO_z , 1); + nmos (HOLDNeg, HOLDNegOut_zd , 1); + nmos (WPNeg, WPNegOut_zd , 1); + + wire deg_pin; + wire deg_sin; + wire deg_holdin; + + reg deq_holdin; + always @(HOLDNeg_ipd, HOLDNegOut_zd) + begin + if (HOLDNeg_ipd==HOLDNegOut_zd) + deq_holdin=1'b0; + else + deq_holdin=1'b1; + end + //VHDL VITAL CheckEnable equivalents + wire rd_slow; + assign rd_slow = slow_read; + wire rd_fast; + assign rd_fast = fast_read; + wire quad_rd; + assign quad_rd = deg_holdin && QE && ~dual_read && (SIOut_z != 1'bz); + wire quad_pg; + assign quad_pg = QE && WEL && pp_quad; + wire wr_prot; + assign wr_prot = SRP0 && WEL; + wire dual_rd; + assign dual_rd = dual_read ; + wire power; + assign power = PoweredUp; + wire hold_cond; + assign hold_cond = PoweredUp && ~QE; + wire any_read; + assign any_read = (dual_read || quad_read || slow_read || fast_read) + && ~WEL && ~sr_read; + // check when data is generated from model to avoid setuphold check in + // this occasion + assign deg_holdin=deq_holdin; + + reg deq_sin; + always @(SI_in, SIOut_z) + begin + if (SIOut_z !== 1'bZ) + deq_sin=1'b0; + else + deq_sin=1'b1; + end + assign deg_sin = deq_sin; /*&& (~any_read);*/ + + wire pg_ers; + assign pg_ers = PSTART || ESTART || sr_read; + +specify + // tipd delays: interconnect path delays , mapped to input port delays. + // In Verilog is not necessary to declare any tipd_ delay variables, + // they can be taken from SDF file + // With all the other delays real delays would be taken from SDF file + + // tpd delays + specparam tpd_SCK_SO_1 =1; // tCLQV1 + specparam tpd_SCK_SO_2 =1; // tCLQV2 -for read ID instructions + specparam tpd_CSNeg_SO =1; // tSHQZ (tDIS) + specparam tpd_HOLDNeg_SO =1; // tHLQZ, tHHQX + + //tsetup values: setup times + specparam tsetup_CSNeg_SCK =1; // tSLCH, tSHCH + specparam tsetup_SI_SCK =1; // tDVCH + specparam tsetup_HOLDNeg_SCK =1; // tHLCH, tHHCH + specparam tsetup_WPNeg_CSNeg =1; // tWHSL + + //thold values: hold times + specparam thold_CSNeg_SCK =1; // tCHSL, tCHSH + specparam thold_SI_SCK =1; // tCHDX + specparam thold_HOLDNeg_SCK =1; // tCHHL, tCHHH + specparam thold_WPNeg_CSNeg =1; // tSHWL + + // tpw values: pulse width + specparam tpw_SCK_slow_posedge =1; // tCH + specparam tpw_SCK_slow_negedge =1; // tCL + specparam tpw_SCK_fast_posedge =1; // tCH + specparam tpw_SCK_fast_negedge =1; // tCL + specparam tpw_CSNeg_read_posedge =1; // tSHSL1 + specparam tpw_CSNeg_pger_posedge =1; // tSHSL2 + + // tperiod min (calculated as 1/max freq) + specparam tperiod_SCK_slow =1; + specparam tperiod_SCK_fast =1; + + // tdevice values: values for internal delays + + // VCC (min) to CS# Low + specparam tdevice_PU = 1e7; // 10 us + // CS# High to Power Down Mode -- tDP + specparam tdevice_DP = 3e6; // 3 us + // CS# High to StandBy mode without Electronic Signature read + specparam tdevice_RES1 = 3e6; // 3 us + // CS# High to StandBy mode with Electronic Signature read + specparam tdevice_RES2 = 18e5; // 1.8 us + // CS# High to next Instruction after Suspend + specparam tdevice_SUS = 2e7; // 20 us + // Resume Suspend to Program/Erase time + specparam tdevice_PRGSUSP = 2e5; // 200 ns + + `ifdef SPEEDSIM + // Page Program Time + specparam tdevice_PP = 3e8; // 30 us + // Byte Program Time (First Byte) + specparam tdevice_BP1 = 5e5; // 0.5 us + // Additional Byte Program Time (After First Byte) + specparam tdevice_BP2 = 12e4; // 120 ns + // Sector Erase Time (4KB) + specparam tdevice_SE = 4e9; // 4 ms + // Block Erase Time (32KB) + specparam tdevice_BE1 = 8e9; // 8 ms + // Block Erase Time (64KB) + specparam tdevice_BE2 = 1e10; // 10 ms + // Chip Erase Time + specparam tdevice_CE = 3e11; // 300 ms + // Write Status Register Time + specparam tdevice_WRR = 15e7; // 150 us + // Write Volatile Status Register Time + specparam tdevice_VRR = 5e4; // 50 ns + `else + // Page Program Time + specparam tdevice_PP = 3e9; // 3 ms + // Byte Program Time (First Byte) + specparam tdevice_BP1 = 5e7; // 50 us + // Additional Byte Program Time (After First Byte) + specparam tdevice_BP2 = 12e6; // 12 us + // Sector Erase Time (4KB) + specparam tdevice_SE = 4e11; // 400 ms + // Block Erase Time (32KB) + specparam tdevice_BE1 = 8e11; // 800 ms + // Block Erase Time (64KB) + specparam tdevice_BE2 = 1e12; // 1000 ms + // Chip Erase Time + specparam tdevice_CE = 3e13; // 30 s + // Write Status Register Time + specparam tdevice_WRR = 15e9; // 15 ms + // Write Volatile Status Register Time + specparam tdevice_VRR = 5e4; // 50 ns + `endif // SPEEDSIM + +/////////////////////////////////////////////////////////////////////////////// +// Input Port Delays don't require Verilog description +/////////////////////////////////////////////////////////////////////////////// +// Path delays // +/////////////////////////////////////////////////////////////////////////////// + if (~read_id) (SCK => SO) = tpd_SCK_SO_1; + if (read_id) (SCK => SO) = tpd_SCK_SO_2; + if (CSNeg) (CSNeg => SO) = tpd_CSNeg_SO; + if (~quad_read) (HOLDNeg => SO) = tpd_HOLDNeg_SO; + if (dual_read || quad_read) (SCK => SI) = tpd_SCK_SO_1; + if (CSNeg && ~deg_sin) (CSNeg => SI) = tpd_CSNeg_SO; + if (~quad_read && dual_read) (HOLDNeg => SI) = tpd_HOLDNeg_SO; +// if (QE) (SCK => SI) = tpd_SCK_SO_1; + if (quad_read) (SCK => WPNeg) = tpd_SCK_SO_1; + if (quad_read) (SCK => HOLDNeg) = tpd_SCK_SO_1; + if (CSNeg && QE) (CSNeg => SI) = tpd_CSNeg_SO; + if (CSNeg && QE) (CSNeg => WPNeg) = tpd_CSNeg_SO; + if (CSNeg && QE) (CSNeg => HOLDNeg) = tpd_CSNeg_SO; +/////////////////////////////////////////////////////////////////////////////// +// Timing Violation // +/////////////////////////////////////////////////////////////////////////////// + $setup ( CSNeg , posedge SCK &&& power, + tsetup_CSNeg_SCK , Viol); + $setup ( SI , posedge SCK &&& deg_sin, + tsetup_SI_SCK , Viol); + $setup ( SO , posedge SCK &&& quad_pg, + tsetup_SI_SCK , Viol); + $setup ( WPNeg , posedge SCK &&& quad_pg, + tsetup_SI_SCK , Viol); + $setup ( HOLDNeg , posedge SCK &&& quad_pg, + tsetup_SI_SCK , Viol); + $setup ( HOLDNeg , posedge SCK &&& hold_cond, + tsetup_HOLDNeg_SCK , Viol); + $setup ( WPNeg , negedge CSNeg &&& WPNeg, + tsetup_WPNeg_CSNeg , Viol); + + $hold ( posedge SCK &&& power, CSNeg, + thold_CSNeg_SCK , Viol); + $hold ( posedge SCK &&& deg_sin, SI , + thold_SI_SCK , Viol); + $hold ( posedge SCK &&& quad_pg, SO , + thold_SI_SCK , Viol); + $hold ( posedge SCK &&& quad_pg, WPNeg, + thold_SI_SCK , Viol); + $hold ( posedge SCK &&& quad_pg, HOLDNeg, + thold_SI_SCK , Viol); + $hold ( posedge SCK &&& hold_cond, HOLDNeg, + thold_HOLDNeg_SCK, Viol); + $hold ( posedge CSNeg &&& wr_prot, WPNeg, + thold_WPNeg_CSNeg, Viol); + + $width ( posedge SCK &&& rd_slow , tpw_SCK_slow_posedge); + $width ( negedge SCK &&& rd_slow , tpw_SCK_slow_negedge); + $width ( posedge SCK &&& rd_fast , tpw_SCK_fast_posedge); + $width ( negedge SCK &&& rd_fast , tpw_SCK_fast_negedge); + $width ( posedge CSNeg &&& any_read , tpw_CSNeg_read_posedge); + $width ( posedge CSNeg &&& pg_ers , tpw_CSNeg_pger_posedge); + + $period ( posedge SCK &&& rd_slow , tperiod_SCK_slow); + $period ( posedge SCK &&& rd_fast , tperiod_SCK_fast); + +endspecify + +/////////////////////////////////////////////////////////////////////////////// +// Main Behavior Block // +/////////////////////////////////////////////////////////////////////////////// +// FSM states + parameter IDLE = 4'd0; + parameter WRITE_SR = 4'd1; + parameter PAGE_PG = 4'd2; + parameter PG_SUSP = 4'd3; + parameter SECTOR_ERS = 4'd4; + parameter BULK_ERS = 4'd5; + parameter ERS_SUSP = 4'd6; + parameter ERS_SUSP_PG = 4'd7; + parameter PG_SUSP_ERS = 4'd8; + parameter DP_DOWN = 4'd9; + parameter WRITE_SR_V = 4'd10; + + reg [3:0] current_state; + reg [3:0] next_state; + +// Instruction type + parameter NONE = 6'd0; + parameter WREN = 6'd1; // 06h + parameter WRENV = 6'd2; // 50h + parameter WRDI = 6'd3; // 04h + parameter RDSR = 6'd4; // 05h + parameter RDSR2 = 6'd5; // 35h + parameter WRR = 6'd6; // 01h + parameter READ = 6'd7; // 03h + parameter FAST_READ = 6'd8; // 0Bh + parameter FAST_DREAD = 6'd9; // 3Bh + parameter FAST_QREAD = 6'd10; // 6Bh + parameter FAST_DREAD_2 = 6'd11; // BBh + parameter FAST_QREAD_4 = 6'd12; // EBh + parameter W_QREAD = 6'd13; // E7h + parameter WOCT_QREAD = 6'd14; // E3h + parameter SET_BURST_WRAP = 6'd15; // 77h + parameter CONT_RD_RST = 6'd16; // FFh or FFFFH + parameter PP = 6'd17; // 02h + parameter QPP = 6'd18; // 32h + parameter SE = 6'd19; // 20h + parameter BE_32 = 6'd20; // 52h + parameter BE_64 = 6'd21; // D8h + parameter CE = 6'd22; // C7h or 60h + parameter ERS_PG_SUSP = 6'd23; // 75h + parameter ERS_PG_RES = 6'd24; // 7Ah + parameter DP = 6'd25; // B9h + parameter RES_RD_ID = 6'd26; // ABh + parameter RDID = 6'd27; // 90h + parameter RDID_DUAL = 6'd28; // 92h + parameter RDID_QUAD = 6'd29; // 94h + parameter RD_UNIQ_ID = 6'd30; // 4Bh + parameter RDIDJ = 6'd31; // 9Fh + parameter RD_SFDP = 6'd32; // 5Ah + parameter ERS_SCREG = 6'd33; // 44h + parameter PG_SCREG = 6'd34; // 42h + parameter RD_SCREG = 6'd35; // 48h + + reg [5:0] Instruct; + +//Bus cycle state + parameter STAND_BY = 3'd0; + parameter OPCODE_BYTE = 3'd1; + parameter ADDRESS_BYTES = 3'd2; + parameter DUMMY_BYTES = 3'd3; + parameter MODE_BYTE = 3'd4; + parameter DATA_BYTES = 3'd5; + + reg [2:0] bus_cycle_state; + + + //Power Up time; + initial + begin + PoweredUp = 1'b0; + #tdevice_PU PoweredUp = 1'b1; + end + + always @(PoweredUp or falling_edge_CSNeg_ipd) + begin:CheckCEOnPowerUP + if ((~PoweredUp) && falling_edge_CSNeg_ipd) + $display ("Device is selected during Power Up"); + end + + initial + begin : Init + write = 1'b0; + read_out = 1'b0; + Address = 0; + change_addr = 1'b0; +// cnt = 0; + PGSUSP = 1'b0; + PGRES = 1'b0; + ESUSP = 1'b0; + ERES = 1'b0; + PDONE = 1'b1; + PSTART = 1'b0; + EDONE = 1'b1; + ESTART = 1'b0; + WDONE = 1'b1; + WSTART = 1'b0; + VLTDONE = 1'b1; + VLTSTART = 1'b0; + + DP_in = 1'b0; + DP_out = 1'b0; + RES_in = 1'b0; + RES_out = 1'b0; + PRGRES_in = 1'b0; + ERSRES_in = 1'b0; + Instruct = NONE; + bus_cycle_state = STAND_BY; + current_state = IDLE; + next_state = IDLE; + + end + + // initialize memory and load preload files if any + initial + begin: InitMemory + integer i; + + for (i=0;i<=AddrRANGE;i=i+1) + begin + Mem[i] = MaxData; + end + + if ((UserPreload) && !(mem_file_name == "none")) + begin + // Memory Preload + //s25fl064k.mem, memory preload file + // @aaaaaa - stands for address + // dd -
is byte to be written at Mem(aaaaaa++) + // (aaaaaa is incremented at every load) + $readmemh(mem_file_name,Mem); + end + + for (i=SCREG_LoAddr;i<=SCREG_HiAddr;i=i+1) + begin + Security_Reg[i] = MaxData; + end + + if (UserPreload && !(screg_file_name == "none")) + begin + //s25fl064kSCREG memory file + // / - comment + // @aaa - stands for address of specific Security register + // dd -
is byte to be written at SCREG(aaa++) + // (aa is incremented at every load) + // only first 1-4 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + $readmemh(screg_file_name,Security_Reg); + end + for (i=0;i<=255;i=i+1) + begin + Security_Reg1[i] = Security_Reg[i]; + Security_Reg2[i] = Security_Reg[256+i]; + Security_Reg3[i] = Security_Reg[512+i]; + end + end + + /////////////////////////////////////////////////////////////////////////// + // SFDP - Serial Flash Discoverable Parameter register + initial + begin: InitSFDP + integer i; + integer j; + SFDP_array[8'h00] = 8'h53; + SFDP_array[8'h01] = 8'h46; + SFDP_array[8'h02] = 8'h44; + SFDP_array[8'h03] = 8'h50; + SFDP_array[8'h04] = 8'h01; + SFDP_array[8'h05] = 8'h01; + SFDP_array[8'h06] = 8'h00; + SFDP_array[8'h07] = 8'hFF; + SFDP_array[8'h08] = 8'hEF; + SFDP_array[8'h09] = 8'h00; + SFDP_array[8'h0A] = 8'h01; + SFDP_array[8'h0B] = 8'h04; + SFDP_array[8'h0C] = 8'h80; + SFDP_array[8'h0D] = 8'h00; + SFDP_array[8'h0E] = 8'h00; + SFDP_array[8'h0F] = 8'hFF; + SFDP_array[8'h10] = 8'hEF; + SFDP_array[8'h11] = 8'h00; + SFDP_array[8'h12] = 8'h01; + SFDP_array[8'h13] = 8'h00; + SFDP_array[8'h14] = 8'h90; + SFDP_array[8'h15] = 8'h00; + SFDP_array[8'h16] = 8'h00; + SFDP_array[8'h17] = 8'hFF; + + for (i=24;i<=127;i=i+1) + begin + SFDP_array[i] = MaxData; + end + + SFDP_array[8'h80] = 8'hE5; + SFDP_array[8'h81] = 8'h20; + SFDP_array[8'h82] = 8'hF1; + SFDP_array[8'h83] = 8'hFF; + SFDP_array[8'h84] = 8'hFF; + SFDP_array[8'h85] = 8'hFF; + SFDP_array[8'h86] = 8'hFF; + SFDP_array[8'h87] = 8'h03; + SFDP_array[8'h88] = 8'h44; + SFDP_array[8'h89] = 8'hEB; + SFDP_array[8'h8A] = 8'h08; + SFDP_array[8'h8B] = 8'h6B; + SFDP_array[8'h8C] = 8'h08; + SFDP_array[8'h8D] = 8'h3B; + SFDP_array[8'h8E] = 8'h80; + SFDP_array[8'h8F] = 8'hBB; + + for (i=144;i<=255;i=i+1) + begin + SFDP_array[i] = MaxData; + end +// SFDP_array[8'h90:8'hFF] = {112{8'hFF}}; + + end + /////////////////////////////////////////////////////////////////////////// + //// Internal Delays + /////////////////////////////////////////////////////////////////////////// + always @(posedge DP_in) + begin:TDPr + #tdevice_DP DP_out = DP_in; + end + always @(negedge DP_in) + begin:TDPf + #1 DP_out = DP_in; + end + + always @(posedge RES_in) + begin:TRESr + if (res_flag) // res_flag is '1' when read ID after resume DP + // res_flag will be set to '1' in DUMMY_BYTES if read ID + #tdevice_RES2 RES_out = RES_in; + else + #tdevice_RES1 RES_out = RES_in; + end + always @(negedge RES_in) + begin:TRESf + #1 RES_out = RES_in; + end + + always @(posedge PRGSUSP_in) + begin:PRGSuspend + PRGSUSP_out = 1'b0; + #tdevice_SUS PRGSUSP_out = 1'b1; + end + + always @(posedge PRGRES_in) + begin:ProgSuspend + PRGRES_out = 1'b0; + #tdevice_PRGSUSP PRGRES_out = 1'b1; + end + + always @(posedge ERSSUSP_in) + begin:ERSSuspend + ERSSUSP_out = 1'b0; + #tdevice_SUS ERSSUSP_out = 1'b1; + end + + always @(posedge ERSRES_in) + begin:ERSresume + ERSRES_out = 1'b0; + #tdevice_PRGSUSP ERSRES_out = 1'b1; + end + + always @(posedge ERSRES_in or posedge PRGRES_in) + begin + susp_flag = 1'b1; + #tdevice_SUS susp_flag = 1'b0; + end + + always @(next_state or PoweredUp) + begin: StateTransition + if (PoweredUp) + begin + current_state = next_state; + end + end + +/////////////////////////////////////////////////////////////////////////////// +// write cycle decode +/////////////////////////////////////////////////////////////////////////////// + integer opcode_cnt = 0; + integer addr_cnt = 0; + integer mode_cnt = 0; + integer wrap_cnt = 0; + integer dummy_cnt = 0; + integer data_cnt = 0; + integer bit_cnt = 0; + + reg [4095:0] Data_in = 4096'b0; + reg [7:0] opcode; + reg [15:0] opcode_double; + reg [7:0] opcode_in; + reg [15:0] opcode_double_in; + reg [23:0] addr_bytes; + reg [23:0] Address_in; + reg [7:0] mode_byte; + reg [7:0] mode_in; + reg [7:0] wrap_in; + reg [7:0] wrap_byte; + + integer quad_data_in [0:511]; + reg [3:0] quad_nybble = 4'b0; + reg [3:0] Quad_slv; + reg [7:0] Byte_slv; + + always @(rising_edge_CSNeg_ipd or falling_edge_CSNeg_ipd or + rising_edge_SCK_ipd or falling_edge_SCK_ipd) + begin: Buscycle + integer i; + integer j; + integer k; + if (falling_edge_CSNeg_ipd) + begin + if (bus_cycle_state==STAND_BY) + begin + bus_cycle_state = OPCODE_BYTE; + Instruct = NONE; + write = 1'b1; + opcode_cnt = 0; + addr_cnt = 0; + data_cnt = 0; + mode_cnt = 0; + wrap_cnt = 0; + dummy_cnt = 0; + end + else if (bus_cycle_state==DATA_BYTES && (mode_byte[5:4]==2'b10)) + begin + bus_cycle_state = ADDRESS_BYTES; + dummy_cnt = 0; + opcode_cnt = 0; + end + end + if (rising_edge_SCK_ipd && PoweredUp) + begin + if (~CSNeg_ipd) + begin + case (bus_cycle_state) + OPCODE_BYTE : + begin + if ((HOLDNeg_in && ~QE) || QE) + begin + opcode_in[opcode_cnt] = SI_in; +// opcode_double_in[opcode_cnt] = SI_in; + opcode_cnt = opcode_cnt + 1; + if (opcode_cnt == BYTE) + begin + for (i=0;i<=7;i=i+1) + begin + opcode[i] = opcode_in[7-i]; + end + case(opcode) + 8'b00000110 : // 06h + begin + Instruct = WREN; + bus_cycle_state = DATA_BYTES; + end + 8'b01010000 : // 50h + begin + Instruct = WRENV; + bus_cycle_state = DATA_BYTES; + end + 8'b00000100 : // 04h + begin + Instruct = WRDI; + bus_cycle_state = DATA_BYTES; + end + 8'b00000101 : // 05h + begin + Instruct = RDSR; + bus_cycle_state = DATA_BYTES; + end + 8'b00110101 : // 05h + begin + Instruct = RDSR2; + bus_cycle_state = DATA_BYTES; + end + 8'b00000001 : // 01h + begin + Instruct = WRR; + bus_cycle_state = DATA_BYTES; + end + 8'b00000011 : // 03h + begin + Instruct = READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00001011 : // 0Bh + begin + Instruct = FAST_READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00111011 : // 3Bh + begin + Instruct = FAST_DREAD; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01101011 : // 6Bh + begin + Instruct = FAST_QREAD; + if (QE) + bus_cycle_state = ADDRESS_BYTES; + else + bus_cycle_state = STAND_BY; + end + 8'b10111011 : // BBh + begin + Instruct = FAST_DREAD_2; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11101011 : // EBh + begin + Instruct = FAST_QREAD_4; + if (QE) + bus_cycle_state = ADDRESS_BYTES; + else + bus_cycle_state = STAND_BY; + end + 8'b11100111 : // E7h + begin + Instruct = W_QREAD; + if (QE) + bus_cycle_state = ADDRESS_BYTES; + else + bus_cycle_state = STAND_BY; + end + 8'b11100011 : // E3h + begin + Instruct = WOCT_QREAD; + if (QE) + bus_cycle_state = ADDRESS_BYTES; + else + bus_cycle_state = STAND_BY; + end + 8'b01110111 : // 77h + begin + Instruct = SET_BURST_WRAP; + if (QE) + bus_cycle_state = DUMMY_BYTES; + else + bus_cycle_state = STAND_BY; + end + 8'b11111111 : // FFh + begin + Instruct = CONT_RD_RST; + bus_cycle_state = MODE_BYTE; + end + 8'b00000010 : // 02h + begin + Instruct = PP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00110010 : // 32h + begin + Instruct = QPP; + if (QE) + bus_cycle_state = ADDRESS_BYTES; + else + bus_cycle_state = STAND_BY; + end + 8'b00100000 : // 20h + begin + Instruct = SE; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01010010 : // 52h + begin + Instruct = BE_32; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11011000 : // D8h + begin + Instruct = BE_64; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11000111, 8'b01100000 : // C7h or 60h + begin + Instruct = CE; + bus_cycle_state = DATA_BYTES; + end + 8'b01110101 : // 75h + begin + Instruct = ERS_PG_SUSP; + bus_cycle_state = DATA_BYTES; + end + 8'b01111010 : // 7Ah + begin + Instruct = ERS_PG_RES; + bus_cycle_state = DATA_BYTES; + end + 8'b10111001 : // B9h + begin + Instruct = DP; + bus_cycle_state = DATA_BYTES; + end + 8'b10101011: // ABh + begin + Instruct = RES_RD_ID; + bus_cycle_state = DUMMY_BYTES; + end + 8'b10010000: // 90h + begin + Instruct = RDID; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10010010: // 92h + begin + Instruct = RDID_DUAL; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10010100: // 94h + begin + Instruct = RDID_QUAD; + if (QE) + bus_cycle_state = ADDRESS_BYTES; + else + bus_cycle_state = STAND_BY; + end + 8'b01001011: // 4Bh + begin + Instruct = RD_UNIQ_ID; + bus_cycle_state = DUMMY_BYTES; + end + 8'b10011111: // 9Fh + begin + Instruct = RDIDJ; + bus_cycle_state = DATA_BYTES; + end + 8'b01011010: // 5Ah + begin + Instruct = RD_SFDP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01000100: // 44h + begin + Instruct = ERS_SCREG; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01000010: // 42h + begin + Instruct = PG_SCREG; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01001000: // 48h + begin + Instruct = RD_SCREG; + bus_cycle_state = ADDRESS_BYTES; + end + endcase + end + end + else + $display("Device is in HOLD mode, opcode"); + end // end of OPCODE_BYTE + + ADDRESS_BYTES : + begin + if ((HOLDNeg_in && ~QE) || QE) + begin + if (Instruct == READ || Instruct == FAST_READ || + Instruct == FAST_DREAD || Instruct == RDID || + Instruct == SE || Instruct == PP || + Instruct == RD_SCREG || Instruct == PG_SCREG || + Instruct == RD_SFDP || Instruct == BE_32 || + Instruct == BE_64 || Instruct == ERS_SCREG || + ((Instruct == QPP || Instruct == FAST_QREAD) + && QE)) + begin + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE) + begin + for (i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + Address = addr_bytes ; + change_addr = 1'b1; + #1000 change_addr = 1'b0; + if (Instruct == PP || Instruct == QPP + || Instruct == READ || Instruct == SE + || Instruct == BE_32 || Instruct == BE_64 + || Instruct == RDID || Instruct == PG_SCREG + || Instruct == ERS_SCREG) + bus_cycle_state = DATA_BYTES; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if (Instruct == RDID_DUAL || + Instruct == FAST_DREAD_2) + begin + if (SO_in !== 1'bX) + begin + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt + 1] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE/2) + begin + addr_cnt = 0; + for (i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + Address = addr_bytes ; + change_addr = 1'b1; + #1000 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + else + begin + if (mode_byte[5:4] == 2'b10) + begin + opcode_double_in[opcode_cnt] = SI_in; + opcode_cnt = opcode_cnt + 1; + + if (opcode_cnt == 2*BYTE) + begin + for (i=0;i<=15;i=i+1) + begin + opcode_double[i] = + opcode_double_in[15-i]; + end + if (opcode_double == 16'hFFFF) + begin + Instruct = CONT_RD_RST; + bus_cycle_state = MODE_BYTE; + end + end + end + end + end + else if (QE && (Instruct == FAST_QREAD_4 || + Instruct == W_QREAD || + Instruct == WOCT_QREAD || + Instruct == RDID_QUAD)) + begin + if (SO_in !== 1'bX) + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE/4) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + Address = addr_bytes ; + change_addr = 1'b1; + #1000 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + else + begin + if (mode_byte[5:4] == 2'b10) + begin + opcode_in[opcode_cnt] = SI_in; + opcode_cnt = opcode_cnt + 1; + if (opcode_cnt == BYTE) + begin + for (i=0;i<=7;i=i+1) + begin + opcode[i] = opcode_in[7-i]; + end + if (opcode == 8'hFF) + begin + Instruct = CONT_RD_RST; + bus_cycle_state = MODE_BYTE; + end + end + end + end + end + end + else + $display("Device is in HOLD mode, addr"); + end // end of ADDRESS_BYTES + + MODE_BYTE: + begin + if (QE || (HOLDNeg_in && ~QE)) + begin + if (Instruct == SET_BURST_WRAP && QE) + begin + wrap_in[4*wrap_cnt] = HOLDNeg_in; + wrap_in[4*wrap_cnt+1] = WPNeg_in; + wrap_in[4*wrap_cnt+2] = SO_in; + wrap_in[4*wrap_cnt+3] = SI_in; + wrap_cnt = wrap_cnt + 1; + if (wrap_cnt == BYTE/4) + begin + wrap_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + wrap_byte[i] = wrap_in[7-i]; + end + bus_cycle_state = DATA_BYTES; + end + case (wrap_byte[6:5]) + 2'b00: + w_size = 8; + 2'b01: + w_size = 16; + 2'b10: + w_size = 32; + 2'b11: + w_size = 64; + endcase + end + else if ((Instruct == FAST_QREAD_4 || + Instruct == WOCT_QREAD || + Instruct == W_QREAD || + Instruct == RDID_QUAD ) && QE) + // FAST_QREAD_4,WOCT_QREAD,W_QREAD,RDID_QUAD + begin + mode_in[4*mode_cnt] = HOLDNeg_in; + mode_in[4*mode_cnt+1] = WPNeg_in; + mode_in[4*mode_cnt+2] = SO_in; + mode_in[4*mode_cnt+3] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/4) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_byte[i] = mode_in[7-i]; + end + if (Instruct == WOCT_QREAD) + bus_cycle_state = DATA_BYTES; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if (Instruct == RDID_DUAL || + Instruct == FAST_DREAD_2) + begin + mode_in[2*mode_cnt] = SO_in; + mode_in[2*mode_cnt+1] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/2) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_byte[i] = mode_in[7-i]; + end + bus_cycle_state = DATA_BYTES; + end + end + end + else + $display("Device is in HOLD mode, mode"); + + end // end of MODE_BYTE + + DUMMY_BYTES: + begin + if (QE || (HOLDNeg_in && ~QE)) + begin + if ((Instruct == FAST_QREAD_4 || + Instruct == RDID_QUAD) && QE) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == BYTE/2) + bus_cycle_state = DATA_BYTES; + end + else if (Instruct == W_QREAD && QE) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == BYTE/4) + bus_cycle_state = DATA_BYTES; + end + else if (Instruct == SET_BURST_WRAP && QE) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == 3*BYTE/4) + bus_cycle_state = MODE_BYTE; + end + else if (Instruct == FAST_QREAD && QE) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == BYTE) + bus_cycle_state = DATA_BYTES; + end + else if (Instruct==FAST_READ || Instruct==RD_SFDP + || Instruct == FAST_DREAD || Instruct == RD_SCREG) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == BYTE) + bus_cycle_state = DATA_BYTES; + end + else if (Instruct == RD_UNIQ_ID) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == 4*BYTE) + bus_cycle_state = DATA_BYTES; + end + else // for RES_RD_ID + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == 3*BYTE) + bus_cycle_state = DATA_BYTES; + end + end + else + $display("Device is in HOLD mode, dummy"); + end // end of DUMMY_BYTES + + DATA_BYTES: + begin + if (Instruct == PP || Instruct == WRR || + Instruct == PG_SCREG) + begin + if ((HOLDNeg_in && ~QE) || QE) + begin + if (data_cnt > 2047) + //In case of serial mode and PP,if more than + //256 bytes are sent to the device + begin + if (bit_cnt == 0) + begin + for (i=0;i<=(255*BYTE-1);i=i+1) + begin + Data_in[i] = Data_in[i+8]; + end + end + Data_in[2040 + bit_cnt] = SI_in; + bit_cnt = bit_cnt + 1; + if (bit_cnt == 8) + begin + bit_cnt = 0; + end + data_cnt = data_cnt + 1; + end + else + begin + Data_in[data_cnt] = SI_in; + data_cnt = data_cnt + 1; + bit_cnt = 0; + end + end + else + $display("Device is in HOLD mode, data"); + end + else if (Instruct == QPP && QE) + begin + pp_quad = 1'b1; + quad_nybble = {HOLDNeg_in, WPNeg_in, + SO_in, SI_in}; + if (data_cnt > 511) + begin + //In case of quad mode and QPP,if more than + // 256 bytes are sent to the device + for(i=0;i<=510;i=i+1) + begin + quad_data_in[i] = quad_data_in[i+1]; + end + quad_data_in[511] = quad_nybble; + data_cnt = data_cnt +1; + end + else + begin + if (quad_nybble !== 4'bZZZZ) + begin + quad_data_in[data_cnt] = quad_nybble; + end + data_cnt = data_cnt +1; + end + end + end // end of DATA_BYTES + endcase // end of case bus_cycle_state + end // end of ~CSNeg + end // end of rising_edge_SCK + + if (falling_edge_SCK_ipd) + begin + if ((bus_cycle_state == DATA_BYTES) && (~CSNeg_ipd)) + begin + if (((Instruct == RDSR || Instruct == RDSR2 || + Instruct == FAST_READ || Instruct == FAST_DREAD || + Instruct == FAST_DREAD_2 || Instruct == RES_RD_ID || + Instruct == RDID || Instruct == RDID_DUAL || + Instruct == RD_UNIQ_ID || Instruct == RDIDJ || + Instruct == RD_SFDP || Instruct == RD_SCREG || + Instruct == READ) && ((HOLDNeg_in && ~QE) || QE)) || + ((Instruct == FAST_QREAD || Instruct == FAST_QREAD_4 || + Instruct == W_QREAD || Instruct == RDID_QUAD || + Instruct == WOCT_QREAD) && QE)) + begin + read_out = 1'b1; + #1 read_out = 1'b0; + end + end // end of ~CSNeg_ipd + end // end of falling_edge_SCK_ipd + + if (rising_edge_CSNeg_ipd) + begin + if (bus_cycle_state==MODE_BYTE && Instruct == CONT_RD_RST) + begin + mode_byte[5:4] = 2'b11; + mode_byte[7:6] = 2'b00; + mode_byte[3:0] = 4'b0000; + bus_cycle_state = STAND_BY; + end + else if (bus_cycle_state==DATA_BYTES && ~(mode_byte[5:4]==2'b10)) + begin + bus_cycle_state = STAND_BY; + case (Instruct) + WREN, +// WRENV, + WRDI, + SET_BURST_WRAP, + SE, + BE_32, + BE_64, + CE, + ERS_PG_RES, + DP, + ERS_SCREG: + begin + if (data_cnt == 0) + write = 1'b0; + end + + WRENV: + begin + write = 1'b0; + wren_vlt_flag = 1'b1; + end + + RES_RD_ID: + begin + write = 1'b0; + res_flag = 1'b1; + end + + WRR: + begin + if (data_cnt == 8) + //If CS# is driven high after eight + //cycle,only the Status Register is + //written to. + begin + write = 1'b0; + for(i=0;i<=7;i=i+1) + begin + Status_reg1_in[i]= + Data_in[7-i]; + end + end + else if (data_cnt == 16) + //After the 16th cycle both the + //Status and Configuration Registers + //are written to. + begin + write = 1'b0; + for(i=0;i<=7;i=i+1) + begin + Status_reg1_in[i]= + Data_in[7-i]; + Status_reg2_in[i]= + Data_in[15-i]; + end + end + end + + PP, + PG_SCREG: + begin + if (data_cnt > 0) + begin + if ((data_cnt % 8) == 0) + begin + write = 1'b0; + for (i=0;i<=255;i=i+1) + begin + for (j=7;j>=0;j=j-1) + begin + Byte_slv[j] = + Data_in[(i*8) + (7-j)]; + end + WByte[i] = Byte_slv; + end + if (data_cnt > 256*BYTE) + Byte_number = 255; + else + Byte_number = ((data_cnt/8) - 1); + end + end + end + + QPP: + begin + if (data_cnt >0) + begin + if ((data_cnt % 2) == 0) + begin + write = 1'b0; + for (i=0;i<=255;i=i+1) + begin + for(j=1;j>=0;j=j-1) + begin + Quad_slv = + quad_data_in[(i*2)+(1-j)]; + if (j==1) + Byte_slv[7:4] = Quad_slv; + else // if (j==0) + Byte_slv[3:0] = Quad_slv; + end + WByte[i] = Byte_slv; + end + if (data_cnt > 256*BYTE/4) + Byte_number = 255; + else + Byte_number = ((data_cnt/2) - 1); + end + end + end + + endcase + end + else if (bus_cycle_state==DATA_BYTES && (mode_byte[5:4]==2'b10)) + begin + bus_cycle_state = DATA_BYTES; + end + else + begin + bus_cycle_state = STAND_BY; + if (HOLDNeg_in && (Instruct == RES_RD_ID) && + (dummy_cnt == 0)) + begin + write = 1'b0; + res_flag = 1'b0; + end + end + end // end of rising_edge_CSNeg_ipd + + end // end of Buscycle + + /////////////////////////////////////////////////////////////////////////// + // Timing control for the Page Program + /////////////////////////////////////////////////////////////////////////// + time pob; + time elapsed; + time start; + time duration; + event pdone_event; + + always @(rising_edge_PSTART) + begin + if ((Instruct == PP) || (Instruct == QPP) || (Instruct == PG_SCREG)) + pob = tdevice_PP; + else + pob = tdevice_BP1; + if ((rising_edge_PSTART) && PDONE) + begin + elapsed = 0; + PDONE = 1'b0; + ->pdone_event; + start = $time; + end + end + + always @(PGSUSP_event) + begin + if ((PGSUSP_event) && PGSUSP && (~PDONE)) + begin + disable pdone_process; + elapsed = $time - start; + duration = pob - elapsed; + PDONE = 1'b0; + end + end + + always @(PGRES_event) + begin + if ((PGRES_event) && PGRES && (~PDONE)) + begin + start = $time; + ->pdone_event; + end + end + + always @(pdone_event) + begin:pdone_process + PDONE = 1'b0; + #pob PDONE = 1'b1; + end + + /////////////////////////////////////////////////////////////////////////// + // Timing control for the Write Status Register Operation + // start + /////////////////////////////////////////////////////////////////////////// + time wob; + always @(WSTART) + begin + wob = tdevice_WRR; + if ((rising_edge_WSTART) && WDONE) + begin + WDONE = 1'b0; + #wob WDONE = 1'b1; + end + end + /////////////////////////////////////////////////////////////////////////// + // Timing control for the Volatile Write Status Register Operation + // start + /////////////////////////////////////////////////////////////////////////// + time vob; + always @(VLTSTART) + begin + vob = tdevice_VRR; + if (rising_edge_VLTSTART && VLTDONE) + begin + VLTDONE = 1'b0; + #vob VLTDONE = 1'b1; + end + end + + /////////////////////////////////////////////////////////////////////////// + // Timing control for the Erase Operations + /////////////////////////////////////////////////////////////////////////// + time seo; + time beo32; + time beo64; + time ceo; + event edone_event; + + always @(rising_edge_ESTART) + begin + seo = tdevice_SE; + beo32 = tdevice_BE1; + beo64 = tdevice_BE2; + ceo = tdevice_CE; + if ((rising_edge_ESTART) && EDONE) + begin + if (Instruct == CE) + begin + duration = ceo; + end + else if (Instruct == BE_64) + begin + duration = beo64; + end + else if (Instruct == BE_32) + begin + duration = beo32; + end + else + begin + duration = seo; + end + elapsed = 0; + EDONE = 1'b0; + ->edone_event; + start = $time; + end + end + + always @(ESUSP_event) + begin + if ((ESUSP_event) && ESUSP && (~EDONE)) + begin + disable edone_process; + elapsed = $time - start; + duration = duration - elapsed; + EDONE = 1'b0; + end + end + + always @(ERES_event) + begin + if ((ERES_event) && ERES && (~EDONE)) + begin + start = $time; + ->edone_event; + end + end + + always @(edone_event) + begin : edone_process + EDONE = 1'b0; + #duration EDONE = 1'b1; + end + + /////////////////////////////////////////////////////////////////////////// + // Main Behavior Process + // combinational process for next state generation + /////////////////////////////////////////////////////////////////////////// + reg rising_edge_PDONE = 1'b0; + reg rising_edge_EDONE = 1'b0; + reg rising_edge_WDONE = 1'b0; + reg rising_edge_VLTDONE = 1'b0; + reg falling_edge_write = 1'b0; + reg rising_edge_DP_out = 1'b0; + + integer i; + integer j; + + always @(rising_edge_PoweredUp or falling_edge_write or rising_edge_DP_out + or rising_edge_PDONE or rising_edge_WDONE or rising_edge_EDONE or + ERSSUSP_out_event or ERSRES_out_event or RES_out or + PRGSUSP_out_event or PRGRES_out_event or rising_edge_VLTDONE) + begin: StateGen1 + + if (rising_edge_PoweredUp) + next_state = IDLE; + else + begin + case (current_state) + IDLE : + begin + if (falling_edge_write) + begin + if (Instruct == WRR && (~SRP1 && + (~SRP0 || (SRP0 && WPNeg)))) + begin + if (WEL && ~wren_vlt_flag) + next_state = WRITE_SR; + else if (~WEL && wren_vlt_flag) + next_state = WRITE_SR_V; + end + else if (Instruct == PP && WEL) + begin + sect = Address / 16'h1000; + sect_tmp_pg = sect; + if (Sec_Prot[sect] == 0) + next_state = PAGE_PG; + end + else if (Instruct == QPP && WEL && QE) + begin + sect = Address / 16'h1000; + sect_tmp_pg = sect; + if (Sec_Prot[sect] == 0) + next_state = PAGE_PG; + end + else if (Instruct == PG_SCREG && WEL) + begin + sect = Address / 16'h1000; + if ((sect < 4 && sect > 0) && LB[sect-1]==0) + next_state = PAGE_PG; + end + else if (Instruct == ERS_SCREG && WEL) + begin + sect = Address / 16'h1000; + if ((sect <= 3) && LB[sect-1]==0) + next_state = SECTOR_ERS; + end + else if ((Instruct == SE || Instruct == BE_32 || + Instruct == BE_64) && WEL) + begin + sect = Address / 16'h1000; + sect_tmp_ers = sect; + if (Sec_Prot[sect] == 0) + next_state = SECTOR_ERS; + end + else if (Instruct == CE && WEL && + ((~CMP && ~BP2 && ~BP1 && ~BP0) || + (CMP && BP2 && BP1 && BP0))) + next_state = BULK_ERS; + else + next_state = IDLE; + end + else if (rising_edge_DP_out) + next_state = DP_DOWN; + end // end of IDLE + + WRITE_SR: + begin + if (rising_edge_WDONE) + next_state = IDLE; + end // end of WRITE_SR + + WRITE_SR_V: + begin + if (rising_edge_VLTDONE) + next_state = IDLE; + end + + PAGE_PG: + begin + if (PRGSUSP_out_event && PRGSUSP_out == 1) + next_state = PG_SUSP; + else if (rising_edge_PDONE) + next_state = IDLE; + end // end of PAGE_PG + + PG_SUSP: + begin + if (PRGRES_out_event && PRGRES_out == 1) + next_state = PAGE_PG; + else if (falling_edge_write) + begin + if (Instruct == SE || Instruct == BE_32 || + Instruct == BE_64) + begin + sect = Address / 16'h1000; + if ((Sec_Prot[sect] == 0) && (sect != sect_tmp_pg)) + next_state = PG_SUSP_ERS; + end + end + end // end of PG_SUSP + + PG_SUSP_ERS: + begin + if (rising_edge_EDONE) + next_state = PG_SUSP; + else + next_state = PG_SUSP_ERS; + end + + BULK_ERS: + begin + if (rising_edge_EDONE) + next_state = IDLE; + end + + SECTOR_ERS: + begin + if (ERSSUSP_out_event && ERSSUSP_out == 1) + next_state = ERS_SUSP; + else if (rising_edge_EDONE) + next_state = IDLE; + end + + ERS_SUSP: + begin + if (ERSRES_out_event && ERSRES_out == 1) + next_state = SECTOR_ERS; + else if (falling_edge_write) + begin + if (Instruct == PP || (Instruct == QPP && QE)) + begin + sect = Address / 16'h1000; + if ((Sec_Prot[sect] == 0)&&(sect != sect_tmp_ers)) + next_state = ERS_SUSP_PG; + end + else if (Instruct == PG_SCREG) + begin + sect = Address / 16'h1000; + if ((sect < 4 && sect > 0) && LB[sect-1]==0) + next_state = ERS_SUSP_PG; + end + end + end + + ERS_SUSP_PG: + begin + if (rising_edge_PDONE) + next_state = ERS_SUSP; + else + next_state = ERS_SUSP_PG; + end + + DP_DOWN: + begin + if (rising_edge_RES_out) + next_state = IDLE; + end + + endcase // end case of current_state + end // + end // end of StateGen1 + + /////////////////////////////////////////////////////////////////////////// + //FSM Output generation and general functionality + /////////////////////////////////////////////////////////////////////////// + reg rising_edge_read_out = 1'b0; + reg Instruct_event = 1'b0; + reg change_addr_event = 1'b0; + reg current_state_event = 1'b0; + + integer WData [0:255]; + integer Addr; + integer Addr_ers; + integer Addr_tmp; + integer Addr_tmp_2; + integer Addr_tmp_3; + integer Addr_screg; + + always @(oe_event) + begin + oe = 1'b1; + #1000 oe = 1'b0; + end + + always @(rising_edge_read_out or Instruct or rising_edge_SCK_ipd or + change_addr_event or oe or current_state_event or Address or + falling_edge_write or PDONE or rising_edge_WDONE or Instruct_event + or rising_edge_EDONE or ERSSUSP_out or rising_edge_PoweredUp or + rising_edge_CSNeg_ipd or rising_edge_RES_out or ERSRES_out or + PRGSUSP_out or PRGRES_out_event or rising_edge_VLTDONE or + rising_edge_DP_out) + + begin: Functionality + integer i,j; + + if (rising_edge_read_out) + begin + if (PoweredUp == 1'b1) + ->oe_event; + end + + if (Instruct_event) + begin + read_cnt = 0; + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + read_id = 1'b0; + pp_quad = 1'b0; + if (current_state == IDLE) + begin + if (DP_in == 1'b1) + begin + $display ("Command results can be corrupted "); + end + end + end + + if (rising_edge_PoweredUp) + begin + Status_reg1[1] = 1'b0; // WEL bit + Status_reg1[0] = 1'b0; // BUSY bit + + Status_reg2[7] = 1'b0; // SUS bit + end + + if (change_addr_event) + begin + read_addr = Address; + end + + if (rising_edge_RES_out) + begin + if(RES_out) + begin + RES_in = 1'b0; + end + end + + case (current_state) + IDLE : + begin + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + res_flag = 1'b0; + pg_screg_flag = 1'b0; + ers_screg_flag = 1'b0; + if (falling_edge_write && ~DP_in) + begin + read_cnt = 0; + if (Instruct == WREN) + Status_reg1[1] = 1'b1; + else if (Instruct == WRDI) + Status_reg1[1] = 1'b0; + else if (Instruct == WRR) + begin + if(~SRP1 && (~SRP0 || (SRP0 && WPNeg))) + begin + if (WEL && ~wren_vlt_flag) + begin + WSTART = 1'b1; + WSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (~WEL && wren_vlt_flag) + begin + VLTSTART = 1'b1; + VLTSTART <= #5 1'b0; + end + end + else + Status_reg1[1] = 1'b0; + end + else if ((Instruct == PP || (Instruct == QPP && QE)) + && WEL && PDONE) + begin + sect = Address / 16'h1000; + if (Sec_Prot[sect] == 0) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 1'b0; + PGRES = 1'b0; + Status_reg1[0] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + Status_reg1[1] = 1'b0; + end + else if (Instruct == PG_SCREG && WEL) + begin + sect = Address / 16'h1000; + if ((sect <= 3) && LB[sect-1]==0) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 1'b0; + PGRES = 1'b0; + Status_reg1[0] = 1'b1; + SA = sect; + wr_cnt = Byte_number; + Addr_screg = Address % 16'h1000; + pg_screg_flag = 1'b1; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + Status_reg1[1] = 1'b0; + end + end + else if ((Instruct == SE || Instruct == BE_32 || + Instruct == BE_64) && WEL) + begin + sect = Address / 16'h1000; + if (Sec_Prot[sect] == 0) + begin + ESTART = 1'b1; + ESTART <= #5 1'b0; + ESUSP = 1'b0; + ERES = 1'b0; + Status_reg1[0] = 1'b1; + Addr_ers = Address; + end + else + Status_reg1[1] = 1'b0; + end + else if (Instruct == CE && WEL) + begin +// if ((~CMP && ~BP2 && ~BP1 && ~BP0) || +// (CMP && BP2 && BP1 && BP0)) + if (Sec_Prot == 0) + begin + ESTART = 1'b1; + ESTART <= #5 1'b0; + ESUSP = 1'b0; + ERES = 1'b0; + Status_reg1[0] = 1'b1; + end + else + Status_reg1[1] = 1'b0; + end + else if (Instruct == ERS_SCREG && WEL) + begin + sect = Address / 16'h1000; + if ((sect <= 3) && LB[sect-1]==0) + begin + ESTART = 1'b1; + ESTART <= #5 1'b0; + ESUSP = 1'b0; + ERES = 1'b0; + Status_reg1[0] = 1'b1; + SA = sect; + ers_screg_flag = 1'b1; + end + else + Status_reg1[1] = 1'b0; + end + else if (Instruct == DP) + begin + RES_in <= 1'b0; + DP_in <= 1'b1; + end + end // end of falling_edge_write + else if (oe && ~DP_in) + begin + if (Instruct == RDSR) + begin //Read Status Register + sr_read = 1'b1; + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + sr_read = 1'b1; + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == READ || Instruct == FAST_READ) + begin + if (Instruct == READ) + begin + fast_read = 1'b0; + dual_read = 1'b0; + slow_read = 1'b1; + quad_read = 1'b0; + sr_read = 1'b0; + end + else + begin + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + end + if (Mem[read_addr] !== -1) + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + end + else + begin + SOut_zd = 8'bx; + end + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else if (Instruct==FAST_DREAD || Instruct==FAST_DREAD_2) + begin + fast_read = 1'b0; + dual_read = 1'b1; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else if ((Instruct==FAST_QREAD || Instruct==FAST_QREAD_4 || + Instruct==W_QREAD || Instruct==WOCT_QREAD) + && QE) + begin + if ((Instruct==W_QREAD && Address[0]) || + (Instruct==WOCT_QREAD && ~(Address[3:0] == 4'h0))) + begin + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + $display("Word Read could not execute"); + $display("Wrong Read Address"); + end + end + else + begin + fast_read = 1'b0; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b1; + sr_read = 1'b0; + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (wrap_byte[4]==1'b0 && + (Instruct==FAST_QREAD_4 || Instruct==W_QREAD)) + begin + ADDRHILO_WRAP(AddrLo_wrap,AddrHi_wrap, + Address,w_size); + if (read_addr == AddrHi_wrap) + read_addr = AddrLo_wrap; + else + read_addr = read_addr + 1; + end + else + begin + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + end + else if (Instruct==RDID || Instruct==RDID_DUAL || + Instruct==RDID_QUAD) + begin + if (read_addr % 2 == 0) + begin + ident_out2 = {Manuf_ID,Device_ID1}; + end + else + begin + ident_out2 = {Device_ID1,Manuf_ID}; + end + read_id = 1'b1; + if (Instruct == RDID) + begin + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + SOut_zd = ident_out2[15-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 16) + read_cnt = 0; + end + else if (Instruct == RDID_DUAL) + begin + fast_read = 1'b0; + dual_read = 1'b1; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + SOut_zd = ident_out2[15-2*read_cnt]; + SIOut_zd = ident_out2[14-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else // (Instruct == RDID_QUAD) + begin + fast_read = 1'b0; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b1; + sr_read = 1'b0; + HOLDNegOut_zd = ident_out2[15-4*read_cnt]; + WPNegOut_zd = ident_out2[14-4*read_cnt]; + SOut_zd = ident_out2[13-4*read_cnt]; + SIOut_zd = ident_out2[12-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + read_cnt = 0; + end + end + else if (Instruct == RD_UNIQ_ID) + begin + // unique ID number is not in data sheet + read_id = 1'b1; + SOut_zd = unique_id[63-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 64) + read_cnt = 0; + end + else if (Instruct == RDIDJ) + begin + read_id = 1'b1; + ident_out = {Manuf_ID,Device_ID2,Device_ID3}; + SOut_zd = ident_out[23-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 24) + read_cnt = 0; + end + else if (Instruct == RD_SFDP) + begin + sfdp_addr = read_addr / 12'h100; + if (sfdp_addr == 0) + begin + Addr_tmp_2 = (read_addr % 12'h100); + data_out[7:0] = SFDP_array[Addr_tmp_2]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == SFDP_HiAddr) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + $display("Given SFDP address is out of range"); + end + end + end + else if (Instruct == RD_SCREG) + begin + Addr_tmp_2 = read_addr / 12'h100; + Addr_tmp_3 = read_addr % 12'h100; + if (Addr_tmp_2 == 16) + begin + // Security Register No.1 + data_out[7:0] = Security_Reg1[Addr_tmp_3]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + end + else if (Addr_tmp_2 == 32) + begin + // Security Register No.2 + data_out[7:0] = Security_Reg2[Addr_tmp_3]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + end + else if (Addr_tmp_2 == 48) + // Security Register No.2 + begin + data_out[7:0] = Security_Reg3[Addr_tmp_3]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + $display("Given Security Register Read "); + $display("address is out of range "); + end + end + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr % 256 == SecReg_HiAddr) + read_addr = (read_addr/256)*(SecReg_HiAddr+1); + else + read_addr = read_addr + 1; + end + end + else if (Instruct == RES_RD_ID) + begin + read_id = 1'b1; + data_out[7:0] = Device_ID1; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end // end of oe + else if (rising_edge_DP_out) + DP_in = 1'b0; + end // end of IDLE state + + WRITE_SR: + begin + if (WDONE) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + + Status_reg1[7:2] = Status_reg1_in[7:2]; + Status_reg2[6] = Status_reg2_in[6]; + Status_reg2[1] = Status_reg2_in[1]; + // SRP1 bit will only change value from '0' to '1' + // if SRP1 is '1' than Status Register is protected + //and is not possible to write it + Status_reg2[0] = Status_reg2_in[0]; + for(i=5;i>=3;i=i-1) + begin + if (Status_reg2[i] == 1'b0) + Status_reg2[i] = Status_reg2_in[i]; + else + begin + $display("LB bit is set to '1'"); + $display("No change allowed"); + end + end + change_prot_bits = 1'b1; + #1000 change_prot_bits = 1'b0; + end // end of WDONE + + if (oe) + begin + if (Instruct == RDSR) + begin + //Read Status Register 1 + sr_read = 1'b1; + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end // end of oe + end // end of WRITE_SR + + WRITE_SR_V: + begin + if (VLTDONE) + begin + Status_reg1[7:2] = Status_reg1_in[7:2]; + Status_reg2[6] = Status_reg2_in[6]; + Status_reg2[1] = Status_reg2_in[1]; + // SRP1 bit will only change value from '0' to '1' + // if SRP1 is '1' than Status Register is protected + //and is not possible to write it + Status_reg2[0] = Status_reg2_in[0]; + for(i=5;i>=3;i=i-1) + begin + if (Status_reg2[i] == 1'b0) + Status_reg2[i] = Status_reg2_in[i]; + else + begin + $display("LB bit is set to '1'"); + $display("No change allowed"); + end + end + change_prot_bits = 1'b1; + #1000 change_prot_bits = 1'b0; + wren_vlt_flag = 1'b0; + end + end + + PAGE_PG, + ERS_SUSP_PG: + begin + if (current_state_event && ~PDONE) + begin + if (Instruct !== PG_SCREG) + begin + ADDRHILO_PG(AddrLo, AddrHi, Addr); + end + cnt = 0; + + for (i=0;i<=wr_cnt;i=i+1) + begin + new_int = WData[i]; + if (Instruct == PG_SCREG) + begin + if (sect == 1) + old_int = Security_Reg1[Addr_screg + i - cnt]; + else if (sect == 2) + old_int = Security_Reg2[Addr_screg + i - cnt]; + else + old_int = Security_Reg3[Addr_screg + i - cnt]; + end + else + begin + old_int = Mem[Addr + i - cnt]; + end + if (new_int > -1) + begin + new_bit = new_int; + if (old_int > -1) + begin + old_bit = old_int; + for(j=0;j<=7;j=j+1) + begin + if (~old_bit[j]) + new_bit[j]=1'b0; + end + new_int=new_bit; + end + WData[i]= new_int; + end + else + begin + WData[i] = -1; + end + if (Instruct == PG_SCREG) + begin + if (sect == 1) + Security_Reg1[Addr_screg + i - cnt] = - 1; + else if (sect == 2) + Security_Reg2[Addr_screg + i - cnt] = - 1; + else + Security_Reg3[Addr_screg + i - cnt] = - 1; + end + else + Mem[Addr + i - cnt] = - 1; + if ((Addr + i) == AddrHi) + begin + + Addr = AddrLo; + cnt = i + 1; + end + end + cnt = 0; + end // end of current_state_event + + if (PDONE) + begin + if (current_state !== ERS_SUSP_PG) + begin + Status_reg1[0] = 1'b0; + end + Status_reg1[1] = 1'b0; + for (i=0;i<=wr_cnt;i=i+1) + begin + if (pg_screg_flag ) + begin + if (sect == 1) + Security_Reg1[Addr_screg + i - cnt] = WData[i]; + else if (sect == 2) + Security_Reg2[Addr_screg + i - cnt] = WData[i]; + else + Security_Reg3[Addr_screg + i - cnt] = WData[i]; + + if ((Addr_screg + i) == SecReg_HiAddr) + begin + Addr_screg = SecReg_LoAddr; + cnt = i + 1; + end + end + else + begin + Mem[Addr_tmp + i - cnt] = WData[i]; + if ((Addr_tmp + i) == AddrHi) + begin + Addr_tmp = AddrLo; + cnt = i + 1; + end + end + end + end // end of PDONE + + if (Instruct == ERS_PG_SUSP && current_state == PAGE_PG && ~susp_flag) + begin + PGSUSP = 1'b1; + PGSUSP <= #1000 1'b0; + PRGSUSP_in = 1'b1; + end + + if (oe) + begin + if (Instruct == RDSR) + begin + //Read Status Register 1 + sr_read = 1'b1; + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + end // end of PAGE_PG + + PG_SUSP: + begin + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + if (PRGSUSP_out == 1 && ~(Instruct == ERS_PG_RES)) + begin + PRGSUSP_in = 1'b0; + //The BUSY bit in the Status Register will indicate that + //the device is ready for another operation. + Status_reg1[0] = 1'b0; + //The Suspend (SUS) bit in the Status Register2 will + //be set to the logical “1” state to indicate that the + //program operation has been suspended. + Status_reg2[7] = 1'b1; + end + if (PRGRES_out_event && PRGRES_out == 1) + begin + PRGRES_in = 1'b0; + Status_reg1[0] = 1'b1; + end + if (SUS) + begin + if (falling_edge_write) + begin + if (Instruct == ERS_PG_RES) + begin + Status_reg2[7] = 1'b0; + PRGRES_in = 1'b1; + PGRES = 1'b1; + PGRES <= #1000 1'b0; + end + else if ((Instruct == SE || Instruct == BE_32 || + Instruct == BE_64) && WEL) + begin + sect = Address / 16'h1000; + if (sect !== sect_tmp_pg && Sec_Prot[sect] == 0) + begin + ESTART = 1'b1; + ESTART <= #5 1'b0; + ESUSP = 1'b0; + ERES = 1'b0; + Status_reg1[0] = 1'b1; + Addr_ers = Address; + end + else + begin + Status_reg1[0] = 1'b0; + $display("Can't erase sector/block"); + $display("Block is protected or suspended"); + end + end + end + else if (oe) + begin + if (Instruct == RDSR) + begin + //Read Status Register 1 + sr_read = 1'b1; + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + sr_read = 1'b1; + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == READ || Instruct == FAST_READ) + begin + if (sect_tmp_pg !== read_addr / 16'h1000) + begin + if (Instruct == READ) + begin + fast_read = 1'b0; + dual_read = 1'b0; + slow_read = 1'b1; + quad_read = 1'b0; + sr_read = 1'b0; + end + else + begin + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + end + if (Mem[read_addr] !== -1) + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + end + else + begin + SOut_zd = 8'bx; + end + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + $display("Can't read suspended sector"); + read_cnt = 0; + end + end + end + else if (Instruct==FAST_DREAD || + Instruct==FAST_DREAD_2) + begin + if (sect_tmp_pg !== read_addr / 16'h1000) + begin + fast_read = 1'b0; + dual_read = 1'b1; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + if (Mem[read_addr] !== -1) + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + end + else + begin + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + end + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + $display("Can't read suspended sector"); + read_cnt = 0; + end + end + end + else if ((Instruct==FAST_QREAD || Instruct==W_QREAD + || Instruct==FAST_QREAD_4 || Instruct==WOCT_QREAD) + && QE) + begin + if (sect_tmp_pg !== read_addr / 16'h1000) + begin + if ((Instruct==W_QREAD && Address[0]) || + (Instruct==WOCT_QREAD && + ~(Address[3:0] == 4'h0))) + begin + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + $display("Word Read can't execute"); + $display("Wrong Read Address"); + end + end + else + begin + fast_read = 1'b0; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b1; + sr_read = 1'b0; + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (wrap_byte[4]==0 && + (Instruct==FAST_QREAD_4 || + Instruct==W_QREAD)) + begin + ADDRHILO_WRAP(AddrLo_wrap, + AddrHi_wrap, Address,w_size); + if (read_addr == AddrHi_wrap) + read_addr = AddrLo_wrap; + else + read_addr = read_addr + 1; + end + else + begin + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + $display("Can't read suspended sector"); + read_cnt = 0; + end + end + end + else if (Instruct==RDID || Instruct==RDID_DUAL || + Instruct==RDID_QUAD) + begin + if (read_addr % 2 == 0) + begin + ident_out2 = {Manuf_ID,Device_ID1}; + end + else + begin + ident_out2 = {Device_ID1,Manuf_ID}; + end + read_id = 1'b1; + if (Instruct == RDID) + begin + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + SOut_zd = ident_out2[15-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 16) + read_cnt = 0; + end + else if (Instruct == RDID_DUAL) + begin + fast_read = 1'b0; + dual_read = 1'b1; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + SOut_zd = ident_out2[15-2*read_cnt]; + SIOut_zd = ident_out2[14-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else // (Instruct == RDID_QUAD) + begin + fast_read = 1'b0; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b1; + sr_read = 1'b0; + HOLDNegOut_zd = ident_out2[15-4*read_cnt]; + WPNegOut_zd = ident_out2[14-4*read_cnt]; + SOut_zd = ident_out2[13-4*read_cnt]; + SIOut_zd = ident_out2[12-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + read_cnt = 0; + end + end + else if (Instruct == RD_UNIQ_ID) + begin + // unique ID number is not in data sheet + read_id = 1'b1; + SOut_zd = unique_id[63-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 64) + read_cnt = 0; + end + else if (Instruct == RDIDJ) + begin + read_id = 1'b1; + ident_out = {Manuf_ID,Device_ID2,Device_ID3}; + SOut_zd = ident_out[23-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 24) + read_cnt = 0; + end + else if (Instruct == RD_SFDP) + begin + sfdp_addr = read_addr / 12'h100; + if (sfdp_addr == 0) + begin + Addr_tmp_2 = (read_addr % 12'h100); + data_out[7:0] = SFDP_array[Addr_tmp_2]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == SFDP_HiAddr) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + $display("SFDP address is out of range"); + end + end + end + else if (Instruct == RD_SCREG) + begin + Addr_tmp_2 = read_addr / 12'h100; + Addr_tmp_3 = read_addr % 12'h100; + if (Addr_tmp_2 == 16) + begin + // Security Register No.1 + data_out[7:0] = Security_Reg1[Addr_tmp_3]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + end + else if (Addr_tmp_2 == 32) + begin + // Security Register No.2 + data_out[7:0] = Security_Reg2[Addr_tmp_3]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + end + else if (Addr_tmp_2 == 48) + // Security Register No.2 + begin + data_out[7:0] = Security_Reg3[Addr_tmp_3]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + $display("Given Security Register Read "); + $display("address is out of range "); + end + end +// SOut_zd = data_out[7-read_cnt]; +// read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr % 256 == SecReg_HiAddr) + read_addr=(read_addr/256)* + (SecReg_HiAddr+1); + else + read_addr = read_addr + 1; + end + end + end // end of 'oe' + end + end // end of PG_SUSP + + SECTOR_ERS, + PG_SUSP_ERS: + begin + if (current_state_event && ~EDONE) + begin + if (Instruct == SE) + ADDRHILO_SEC4(AddrLo_ers, AddrHi_ers, Addr_ers); + else if (Instruct == BE_32) + ADDRHILO_SEC32(AddrLo_ers, AddrHi_ers, Addr_ers); + else if (Instruct == BE_64) + begin + ADDRHILO_SEC64(AddrLo_ers, AddrHi_ers, Addr_ers); + end + if (Instruct !== ERS_SCREG) + begin + for (i=AddrLo_ers;i<=AddrHi_ers;i=i+1) + begin + Mem[i] = -1; + end + end + else + begin + if (sect == 1) + begin + for(i=SecReg_LoAddr;i<=SecReg_HiAddr;i=i+1) + begin + Security_Reg1[i] = -1; + end + end + else if (sect == 2) + begin + for(i=SecReg_LoAddr;i<=SecReg_HiAddr;i=i+1) + begin + Security_Reg2[i] = -1; + end + end + else + begin + for(i=SecReg_LoAddr;i<=SecReg_HiAddr;i=i+1) + begin + Security_Reg3[i] = -1; + end + end + end + end + + if (EDONE == 1) + begin + if (current_state !== PG_SUSP_ERS) + begin + Status_reg1[0] = 1'b0; + end + Status_reg1[1] = 1'b0; + if (ers_screg_flag ) + begin + if (sect == 1) + begin + for(i=SecReg_LoAddr;i<=SecReg_HiAddr;i=i+1) + begin + Security_Reg1[i] = MaxData; + end + end + else if (sect == 2) + for(i=SecReg_LoAddr;i<=SecReg_HiAddr;i=i+1) + begin + Security_Reg2[i] = MaxData; + end + else + for(i=SecReg_LoAddr;i<=SecReg_HiAddr;i=i+1) + begin + Security_Reg3[i] = MaxData; + end + + end + else + begin + for (i=AddrLo_ers;i<=AddrHi_ers;i=i+1) + begin + Mem[i] = MaxData; + end + end + end + + if (Instruct == ERS_PG_SUSP && current_state == SECTOR_ERS) + begin + ESUSP = 1'b1; + ESUSP <= #1000 1'b0; + ERSSUSP_in = 1'b1; + end + if (oe) + begin + if (Instruct == RDSR) + begin + //Read Status Register 1 + sr_read = 1'b1; + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + end // end of SECTOR_ERS + + BULK_ERS: + begin + if (current_state_event && ~EDONE) + begin + for (i=0;i<=AddrRANGE;i=i+1) + begin + Mem[i] = -1; + end + end + if (EDONE == 1) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + for (i=0;i<=AddrRANGE;i=i+1) + begin + Mem[i] = MaxData; + end + end + if (oe) + begin + if (Instruct == RDSR) + begin + //Read Status Register 1 + sr_read = 1'b1; + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + end // end of BULK_ERS + + ERS_SUSP: + begin + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + if (ERSSUSP_out == 1 && ~(Instruct == ERS_PG_RES)) + begin + ERSSUSP_in = 1'b0; + //The BUSY bit in the Status Register will indicate that + //the device is ready for another operation. + Status_reg1[0] = 1'b0; + //The Suspend (SUS) bit in the Status Register2 will + //be set to the logical “1” state to indicate that the + //program operation has been suspended. + Status_reg2[7] = 1'b1; + end + if (ERSRES_out_event && ERSRES_out == 1) + begin + ERSRES_in = 1'b0; + Status_reg1[0] = 1'b1; + end + if (SUS) + begin + if (falling_edge_write) + begin + if (Instruct == ERS_PG_RES) + begin + Status_reg2[7] = 1'b0; + ERSRES_in = 1'b1; + ERES = 1'b1; + ERES <= #1000 1'b0; + end + else if ((Instruct == PP || (Instruct==QPP && QE)) + && WEL) + begin + sect = Address / 16'h1000; + if (sect !== sect_tmp_ers && Sec_Prot[sect]==0) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 1'b0; + PGRES = 1'b0; + Status_reg1[0] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + Status_reg1[0] = 1'b0; + $display("Can't program sector/block"); + $display("Block is protected or suspended"); + end + end + else if (Instruct == PG_SCREG) + begin + sect = Address / 16'h1000; + if ((sect <= 3 && sect >=1) && LB[sect-1]==0) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 1'b0; + PGRES = 1'b0; + Status_reg1[0] = 1'b1; + SA = sect; + wr_cnt = Byte_number; + Addr_screg = Address % 16'h1000; + pg_screg_flag = 1'b1; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + Status_reg1[1] = 1'b0; + end + end + else if (oe) + begin + if (Instruct == RDSR) + begin + //Read Status Register 1 + sr_read = 1'b1; + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + sr_read = 1'b1; + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == READ || Instruct == FAST_READ) + begin + if (sect !== read_addr / 16'h1000) + begin + if (Instruct == READ) + begin + fast_read = 1'b0; + dual_read = 1'b0; + slow_read = 1'b1; + quad_read = 1'b0; + sr_read = 1'b0; + end + else + begin + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + end + if (Mem[read_addr] !== -1) + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + end + else + begin + SOut_zd = 8'bx; + end + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + $display("Can't read suspended sector"); + read_cnt = 0; + end + end + end + else if (Instruct==FAST_DREAD || Instruct==FAST_DREAD_2) + begin + if (sect !== read_addr / 16'h1000) + begin + fast_read = 1'b0; + dual_read = 1'b1; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + if (Mem[read_addr] !== -1) + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + end + else + begin + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + end + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + $display("Can't read suspended sector"); + read_cnt = 0; + end + end + end + else if ((Instruct==FAST_QREAD || Instruct==W_QREAD + || Instruct==FAST_QREAD_4 || Instruct==WOCT_QREAD) + && QE) + begin + if (sect_tmp_ers !== read_addr / 16'h1000) + begin + if ((Instruct==W_QREAD && Address[0]) || + (Instruct==WOCT_QREAD && + ~(Address[3:0]==4'h0))) + begin + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + $display("Word Read can't execute"); + $display("Wrong Read Address"); + end + end + else + begin + fast_read = 1'b0; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b1; + sr_read = 1'b0; + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (wrap_byte[4]==0 && + (Instruct==FAST_QREAD_4 + || Instruct==W_QREAD)) + begin + ADDRHILO_WRAP(AddrLo_wrap, + AddrHi_wrap,Address,w_size); + if (read_addr == AddrHi_wrap) + read_addr = AddrLo_wrap; + else + read_addr = read_addr + 1; + end + else + begin + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + $display("Can't read suspended sector"); + read_cnt = 0; + end + end + end + else if (Instruct==RDID || Instruct==RDID_DUAL || + Instruct==RDID_QUAD) + begin + if (read_addr % 2 == 0) + begin + ident_out2 = {Manuf_ID,Device_ID1}; + end + else + begin + ident_out2 = {Device_ID1,Manuf_ID}; + end + read_id = 1'b1; + if (Instruct == RDID) + begin + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + SOut_zd = ident_out2[15-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 16) + read_cnt = 0; + end + else if (Instruct == RDID_DUAL) + begin + fast_read = 1'b0; + dual_read = 1'b1; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + SOut_zd = ident_out2[15-2*read_cnt]; + SIOut_zd = ident_out2[14-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else // (Instruct == RDID_QUAD) + begin + fast_read = 1'b0; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b1; + sr_read = 1'b0; + HOLDNegOut_zd = ident_out2[15-4*read_cnt]; + WPNegOut_zd = ident_out2[14-4*read_cnt]; + SOut_zd = ident_out2[13-4*read_cnt]; + SIOut_zd = ident_out2[12-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + read_cnt = 0; + end + end + else if (Instruct == RD_UNIQ_ID) + begin + // unique ID number is not in data sheet + read_id = 1'b1; + SOut_zd = unique_id[63-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 64) + read_cnt = 0; + end + else if (Instruct == RDIDJ) + begin + read_id = 1'b1; + ident_out = {Manuf_ID,Device_ID2,Device_ID3}; + SOut_zd = ident_out[23-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 24) + read_cnt = 0; + end + else if (Instruct == RD_SFDP) + begin + sfdp_addr = read_addr / 12'h100; + if (sfdp_addr == 0) + begin + Addr_tmp_2 = (read_addr % 12'h100); + data_out[7:0] = SFDP_array[Addr_tmp_2]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == SFDP_HiAddr) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + $display("SFDP address is out of range"); + end + end + end + else if (Instruct == RD_SCREG) + begin + Addr_tmp_2 = read_addr / 12'h100; + Addr_tmp_3 = read_addr % 12'h100; + if (Addr_tmp_2 == 16) + begin + // Security Register No.1 + data_out[7:0] = Security_Reg1[Addr_tmp_3]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + end + else if (Addr_tmp_2 == 32) + begin + // Security Register No.2 + data_out[7:0] = Security_Reg2[Addr_tmp_3]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + end + else if (Addr_tmp_2 == 48) + // Security Register No.2 + begin + data_out[7:0] = Security_Reg3[Addr_tmp_3]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + $display("Given Security Register Read "); + $display("address is out of range "); + end + end + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr % 256 == SecReg_HiAddr) + read_addr = (read_addr/256)* + (SecReg_HiAddr+1); + else + read_addr = read_addr + 1; + end + end + end // end of 'oe' + end // end of SUS + end // end of ERS_SUSP + + DP_DOWN: + begin + if (oe) + begin + if (Instruct == RES_RD_ID) + begin + read_id = 1'b1; + data_out[7:0] = Device_ID1; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + if (falling_edge_write) + begin + if (Instruct == RES_RD_ID) + begin + RES_in = 1'b1; + end + else + begin + $display("Device is in Deep Power Down Mode"); + $display("No instructions allowed"); + end + end + end + + endcase + //Output Disable Control + if (CSNeg_ipd ) + begin + SIOut_zd = 1'bZ; + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + end + end // end of Functionality + + /////////////////////////////////////////////////////////////////////////// + always @(posedge change_prot_bits) + begin +// if (rising_edge_prot_bits) +// begin + case (Status_reg1[4:2]) + 3'b000: + begin + if (Status_reg2[6] == 1'b0) + Sec_Prot[2047:0] = {2048{1'b0}}; + else + Sec_Prot[2047:0] = {2048{1'b1}}; + end + + 3'b001: + begin + if (Status_reg2[6] ==1'b0) + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[2047:2016] = {32{1'b1}}; + Sec_Prot[2015:0] = {2016{1'b0}}; + end + 2'b01: + begin + Sec_Prot[2047:32] = {2016{1'b0}}; + Sec_Prot[31:0] = {32{1'b1}}; + end + 2'b10: + begin + Sec_Prot[2047] = 1'b1; + Sec_Prot[2046:0] = {2047{1'b0}}; + end + 2'b11: + begin + Sec_Prot[2047:1] = {2047{1'b0}}; + Sec_Prot[0] = 1'b1; + end + endcase + end + else + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[2047:2016] = {32{1'b0}}; + Sec_Prot[2015:0] = {2016{1'b1}}; + end + 2'b01: + begin + Sec_Prot[2047:32] = {2016{1'b1}}; + Sec_Prot[31:0] = {32{1'b0}}; + end + 2'b10: + begin + Sec_Prot[2047] = 1'b0; + Sec_Prot[2046:0] = {2047{1'b1}}; + end + 2'b11: + begin + Sec_Prot[2047:1] = {2047{1'b1}}; + Sec_Prot[0] = 1'b0; + end + endcase + end + end + + 3'b010: + begin + if (Status_reg2[6] == 1'b0) + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[2047:1984] = {64{1'b1}} ; + Sec_Prot[1983:0] = {1984{1'b0}} ; + end + 2'b01: + begin + Sec_Prot[2047:64] = {1984{1'b0}} ; + Sec_Prot[63:0] = {64{1'b1}} ; + end + 2'b10: + begin + Sec_Prot[2047:2046] = 2'b11; + Sec_Prot[2045:0] = {2046{1'b0}}; + end + 2'b11: + begin + Sec_Prot[2047:2] = {2046{1'b0}}; + Sec_Prot[1:0] = 2'b11; + end + endcase + end + else + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[2047:1984] = {64{1'b0}} ; + Sec_Prot[1983:0] = {1984{1'b1}} ; + end + 2'b01: + begin + Sec_Prot[2047:64] = {1984{1'b1}} ; + Sec_Prot[63:0] = {64{1'b0}} ; + end + 2'b10: + begin + Sec_Prot[2047:2046] = 2'b00; + Sec_Prot[2045:0] = {2046{1'b1}}; + end + 2'b11: + begin + Sec_Prot[2047:2] = {2046{1'b1}}; + Sec_Prot[1:0] = 2'b00; + end + endcase + end + end + + 3'b011: + begin + if (Status_reg2[6] == 1'b0) + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[2047:1920] = {128{1'b1}} ; + Sec_Prot[1919:0] = {1920{1'b0}} ; + end + 2'b01: + begin + Sec_Prot[2047:128] = {1920{1'b0}} ; + Sec_Prot[127:0] = {128{1'b1}} ; + end + 2'b10: + begin + Sec_Prot[2047:2044] = 4'b1111; + Sec_Prot[2043:0] = {2044{1'b0}}; + end + 2'b11: + begin + Sec_Prot[2047:4] = {2044{1'b0}}; + Sec_Prot[3:0] = 4'b1111; + end + endcase + end + else + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[2047:1920] = {128{1'b0}} ; + Sec_Prot[1919:0] = {1920{1'b1}} ; + end + 2'b01: + begin + Sec_Prot[2047:128] = {1920{1'b1}} ; + Sec_Prot[127:0] = {128{1'b0}} ; + end + 2'b10: + begin + Sec_Prot[2047:2044] = {4{1'b0}}; + Sec_Prot[2043:0] = {2044{1'b1}}; + end + 2'b11: + begin + Sec_Prot[2047:4] = {2044{1'b1}}; + Sec_Prot[3:0] = {4{1'b0}}; + end + endcase + end + end + + 3'b100: + begin + if (Status_reg2[6] == 1'b0) + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[2047:1792] = {256{1'b1}} ; + Sec_Prot[1791:0] = {1792{1'b0}} ; + end + 2'b01: + begin + Sec_Prot[2047:256] = {1792{1'b0}} ; + Sec_Prot[255:0] = {256{1'b1}} ; + end + 2'b10: + begin + Sec_Prot[2047:2040] = 8'hFF; + Sec_Prot[2039:0] = {2040{1'b0}}; + end + 2'b11: + begin + Sec_Prot[2047:8] = {2040{1'b0}}; + Sec_Prot[7:0] = 8'hFF; + end + endcase + end + else + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[2047:1792] = {256{1'b0}}; + Sec_Prot[1791:0] = {1792{1'b1}}; + end + 2'b01: + begin + Sec_Prot[2047:256] = {1792{1'b1}}; + Sec_Prot[255:0] = {256{1'b0}}; + end + 2'b10: + begin + Sec_Prot[2047:2040] = {8{1'b0}}; + Sec_Prot[2039:0] = {2040{1'b1}}; + end + 2'b11: + begin + Sec_Prot[2047:8] = {2040{1'b1}}; + Sec_Prot[7:0] = {8{1'b0}}; + end + endcase + end + end + + 3'b101: + begin + if (Status_reg2[6] == 1'b0) + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[2047:1536] = {512{1'b1}} ; + Sec_Prot[1535:0] = {1536{1'b0}} ; + end + 2'b01: + begin + Sec_Prot[2047:512] = {1536{1'b0}} ; + Sec_Prot[511:0] = {512{1'b1}} ; + end + 2'b10: + begin + Sec_Prot[2047:2040] = 8'hFF; + Sec_Prot[2039:0] = {2040{1'b0}} ; + end + 2'b11: + begin + Sec_Prot[2047:8] = {2040{1'b0}} ; + Sec_Prot[7:0] = 8'hFF; + end + endcase + end + else + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[2047:1536] = {512{1'b0}} ; + Sec_Prot[1535:0] = {1536{1'b1}} ; + end + 2'b01: + begin + Sec_Prot[2047:512] = {1536{1'b1}} ; + Sec_Prot[511:0] = {512{1'b0}} ; + end + 2'b10: + begin + Sec_Prot[2047:2040] = {8{1'b0}}; + Sec_Prot[2039:0] = {2040{1'b1}}; + end + 2'b11: + begin + Sec_Prot[2047:8] = {2040{1'b1}}; + Sec_Prot[7:0] = {8{1'b0}}; + end + endcase + end + end + + 3'b110: + begin + if (Status_reg2[6] == 1'b0) + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[2047:1024] = {1024{1'b1}} ; + Sec_Prot[1023:0] = {1024{1'b0}} ; + end + 2'b01: + begin + Sec_Prot[2047:1024] = {1024{1'b0}} ; + Sec_Prot[1023:0] = {1024{1'b1}} ; + end + 2'b10, 2'b11: + begin + $display("This combination of bits "); + $display("is not deffined"); + end + endcase + end + else + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[2047:1024] = {1024{1'b0}} ; + Sec_Prot[1023:0] = {1024{1'b1}} ; + end + 2'b01: + begin + Sec_Prot[2047:1024] = {1024{1'b1}} ; + Sec_Prot[1023:0] = {1024{1'b0}} ; + end + 2'b10, 2'b11: + begin + $display("This combination of bits "); + $display("is not deffined"); + end + endcase + end + end + + 3'b111: + begin + if (Status_reg2[6]== 1'b0) + Sec_Prot[2047:0] = {2048{1'b1}}; + else + Sec_Prot[2047:0] = {2048{1'b0}}; + end + endcase +// end + end // end of rising_edge_prot_bits + //////////////////////////////////////////////////////////////////////// + always @(SOut_zd or HOLDNeg_in or SIOut_zd) + begin + if (HOLDNeg_in == 0 && ~QE) + begin + hold_mode = 1'b1; + SIOut_z = 1'bZ; + SOut_z = 1'bZ; + end + else + begin + if (hold_mode == 1) + begin + SIOut_z <= #(tpd_HOLDNeg_SO) SIOut_zd; + SOut_z <= #(tpd_HOLDNeg_SO) SOut_zd; + hold_mode = #(tpd_HOLDNeg_SO) 1'b0; + end + else + begin + SIOut_z = SIOut_zd; + SOut_z = SOut_zd; + hold_mode = 1'b0; + end + end + end + + //////////////////////////////////////////////////////////////////////// + // functions & tasks + //////////////////////////////////////////////////////////////////////// + // Procedure ADDRHILO_SEC 4KB, 32KB, 64KB + task ADDRHILO_SEC64; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer sector; + begin + sector = Addr / 20'h10000; + AddrLOW = sector * 20'h10000; + AddrHIGH = sector * 20'h10000 + 20'h0FFFF; + end + endtask + + task ADDRHILO_SEC32; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer sector; + begin + sector = Addr / 16'h8000; + AddrLOW = sector * 16'h8000; + AddrHIGH = sector * 16'h8000 + 16'h7FFF; + end + endtask + + task ADDRHILO_SEC4; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer sector; + begin + sector = Addr / 16'h1000; + AddrLOW = sector * 16'h1000; + AddrHIGH = sector * 16'h1000 + 16'h0FFF; + end + endtask + + // Procedure ADDRHILO_PG + task ADDRHILO_PG; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer page; + begin + page = Addr / 16'h0100; + AddrLOW = page * 16'h0100; + AddrHIGH = page * 16'h0100 + 16'h00FF; + end + endtask + + // Procedure ADDRHILO_WRAP + task ADDRHILO_WRAP; + inout Addr_low_wrap; + inout Addr_hi_wrap; + input Address; + input w_size; + integer Addr_low_wrap; + integer Addr_hi_wrap; + integer Address; + integer w_size; + integer sect_wrap; + begin + sect_wrap = Address / w_size; + Addr_low_wrap = sect_wrap * w_size; + Addr_hi_wrap = sect_wrap * w_size + w_size - 1; + end + endtask + + /////////////////////////////////////////////////////////////////////////// + // edge controll processes + /////////////////////////////////////////////////////////////////////////// + always @(posedge PoweredUp) + begin + rising_edge_PoweredUp = 1; + #1000 rising_edge_PoweredUp = 0; + end + + always @(posedge SCK_ipd) + begin + rising_edge_SCK_ipd = 1'b1; + #1000 rising_edge_SCK_ipd = 1'b0; + end + + always @(negedge SCK_ipd) + begin + falling_edge_SCK_ipd = 1'b1; + #1000 falling_edge_SCK_ipd = 1'b0; + end + + always @(posedge read_out) + begin + rising_edge_read_out = 1'b1; + #1000 rising_edge_read_out = 1'b0; + end + + always @(negedge write) + begin + falling_edge_write = 1'b1; + #1000 falling_edge_write = 1'b0; + end + + always @(posedge CSNeg_ipd) + begin + rising_edge_CSNeg_ipd = 1'b1; + #1000 rising_edge_CSNeg_ipd = 1'b0; + end + + always @(negedge CSNeg_ipd) + begin + falling_edge_CSNeg_ipd = 1'b1; + #1000 falling_edge_CSNeg_ipd = 1'b0; + end + + always @(posedge PDONE) + begin + rising_edge_PDONE = 1'b1; + #1000 rising_edge_PDONE = 1'b0; + end + + always @(posedge WDONE) + begin + rising_edge_WDONE = 1'b1; + #1000 rising_edge_WDONE = 1'b0; + end + + always @(posedge VLTDONE) + begin + rising_edge_VLTDONE = 1'b1; + #1000 rising_edge_VLTDONE = 1'b0; + end + + always @(posedge WSTART) + begin + rising_edge_WSTART = 1'b1; + #1000 rising_edge_WSTART = 1'b0; + end + + always @(posedge VLTSTART) + begin + rising_edge_VLTSTART = 1'b1; + #1000 rising_edge_VLTSTART = 1'b0; + end + + always @(posedge EDONE) + begin + rising_edge_EDONE = 1'b1; + #1000 rising_edge_EDONE = 1'b0; + end + + always @(posedge ESTART) + begin + rising_edge_ESTART = 1'b1; + #1000 rising_edge_ESTART = 1'b0; + end + + always @(posedge PSTART) + begin + rising_edge_PSTART = 1'b1; + #1000 rising_edge_PSTART = 1'b0; + end + + always @(posedge DP_out) + begin + rising_edge_DP_out = 1'b1; + #1 rising_edge_DP_out = 1'b0; + end + + always @(posedge RES_out) + begin + rising_edge_RES_out = 1'b1; + #1000 rising_edge_RES_out = 1'b0; + end + + always @(Instruct) + begin + Instruct_event = 1'b1; + #1000 Instruct_event = 1'b0; + end + + always @(change_addr) + begin + change_addr_event = 1'b1; + #1000 change_addr_event = 1'b0; + end + + always @(next_state) + begin + next_state_event = 1'b1; + #1000 next_state_event = 1'b0; + end + + always @(current_state) + begin + current_state_event = 1'b1; + #1000 current_state_event = 1'b0; + end + + always @(posedge PRGSUSP_out) + begin + PRGSUSP_out_event = 1; + #1000 PRGSUSP_out_event = 0; + end + + always @(posedge PRGRES_out) + begin + PRGRES_out_event = 1; + #1000 PRGRES_out_event = 0; + end + + always @(posedge ESUSP) + begin + ESUSP_event = 1'b1; + #1000 ESUSP_event = 1'b0; + end + + always @(posedge ERSSUSP_out) + begin + ERSSUSP_out_event = 1; + #1000 ERSSUSP_out_event = 0; + end + + always @(posedge ERSRES_out) + begin + ERSRES_out_event = 1; + #1000 ERSRES_out_event = 0; + end + + always @(posedge PGSUSP) + begin + PGSUSP_event = 1'b1; + #1000 PGSUSP_event = 1'b0; + end + + always @(posedge PGRES) + begin + PGRES_event = 1'b1; + #1000 PGRES_event = 1'b0; + end + + always @(posedge ERES) + begin + ERES_event = 1'b1; + #1000 ERES_event = 1'b0; + end + + always @(posedge change_prot_bits) + begin + rising_edge_prot_bits = 1'b1; + #1000 rising_edge_prot_bits = 1'b0; + end + +endmodule \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl064k/model/s25fl064k.vhd b/lib/models/memory/flash/serial/S25fl064k/model/s25fl064k.vhd new file mode 100644 index 0000000..f767cd6 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064k/model/s25fl064k.vhd @@ -0,0 +1,3768 @@ +------------------------------------------------------------------------------- +-- File Name: s25fl064k.vhd +------------------------------------------------------------------------------- +-- Copyright (C) 2012 Spansion, LLC. +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 R. Prokopovic 10 Sep 08 Inital Release +-- V1.0 S. Petrovic 12 Sep 12 Corrected functionality for sector +-- and block erase and page program +-- operation +------------------------------------------------------------------------------- +-- PART DESCRIPTION: +-- +-- Library: FLASH +-- Technology: FLASH MEMORY +-- Part: S25FL064K +-- +-- Description: 64 Megabit Serial Flash Memory +-- +------------------------------------------------------------------------------- +-- Known Bugs: +-- +------------------------------------------------------------------------------- +LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; + USE STD.textio.ALL; + USE IEEE.VITAL_timing.ALL; + USE IEEE.VITAL_primitives.ALL; + +LIBRARY FMF; USE FMF.gen_utils.ALL; + USE FMF.conversions.ALL; +------------------------------------------------------------------------------- +-- ENTITY DECLARATION +------------------------------------------------------------------------------- +ENTITY s25fl064k IS + GENERIC ( + --------------------------------------------------------------------------- + -- TIMING GENERICS: + --------------------------------------------------------------------------- + -- tipd delays: interconnect path delays (delay between components) + -- There should be one for each IN or INOUT pin in the port list + -- They are given default values of zero delay. + tipd_SCK : VitalDelayType01 := VitalZeroDelay01; + tipd_SI : VitalDelayType01 := VitalZeroDelay01; + tipd_SO : VitalDelayType01 := VitalZeroDelay01; + + tipd_CSNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_HOLDNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; + + -- tpd delays: propagation delays (pin-to-pin delay within a component) + tpd_SCK_SO_RDID_EQ_0 : VitalDelayType01Z := UnitDelay01Z;--tCLQV1 + tpd_SCK_SO_RDID_EQ_1 : VitalDelayType01Z := UnitDelay01Z;--tCLQV2 + tpd_CSNeg_SO : VitalDelayType01Z := UnitDelay01Z;--tSHQZ + tpd_HOLDNeg_SO : VitalDelayType01Z := UnitDelay01Z;--tHLQZ + + -- tsetup values: setup times + tsetup_CSNeg_SCK : VitalDelayType := UnitDelay;--tSLCH,tSHCH + tsetup_SI_SCK_normal_noedge_posedge : VitalDelayType + := UnitDelay;--tDVCH + tsetup_HOLDNeg_SCK : VitalDelayType := UnitDelay;--tHLCH,tHHCH + tsetup_WPNeg_CSNeg : VitalDelayType := UnitDelay;--tWHSL + + -- thold values: hold times + thold_CSNeg_SCK : VitalDelayType := UnitDelay;--tSLCH,tSHCH + thold_SI_SCK_normal_noedge_posedge : VitalDelayType + := UnitDelay;--tCHDX + thold_HOLDNeg_SCK : VitalDelayType := UnitDelay;--tCHHL,tCHHH + thold_WPNeg_CSNeg : VitalDelayType := UnitDelay;--tSHWL + + --tpw values: pulse width + tpw_SCK_slow_posedge : VitalDelayType := UnitDelay; -- tCH + tpw_SCK_slow_negedge : VitalDelayType := UnitDelay; -- tCL + tpw_SCK_fast_posedge : VitalDelayType := UnitDelay; -- tCH + tpw_SCK_fast_negedge : VitalDelayType := UnitDelay; -- tCL + tpw_CSNeg_read_posedge : VitalDelayType := UnitDelay; -- tSHSL1 + tpw_CSNeg_pger_posedge : VitalDelayType := UnitDelay; -- tSHSL2 + + -- tperiod min (calculated as 1/max freq) + tperiod_SCK_slow : VitalDelayType := UnitDelay;-- + tperiod_SCK_fast : VitalDelayType := UnitDelay;-- + + -- tdevice values: values for internal delays + -- VCC (min) to CS# Low + tdevice_PU : VitalDelayType := 10 us; + -- CS# High to Power Down Mode -- tDP + tdevice_DP : VitalDelayType := 3 us; + -- CS# High to StandBy mode without Electronic Signature read + tdevice_RES1 : VitalDelayType := 3 us; + -- CS# High to StandBy mode with Electronic Signature read + tdevice_RES2 : VitalDelayType := 1.8 us; + -- CS# High to next Instruction after Suspend + tdevice_PRGSUSP : VitalDelayType := 20 us; + -- CS# High to next Instruction after Suspend + tdevice_ERSSUSP : VitalDelayType := 20 us; + -- CS# High to next Instruction after Suspend + tdevice_SUSP_DLY : VitalDelayType := 20 us; + -- Resume Suspend to Program/Erase time + tdevice_PRGRES : VitalDelayType := 200 ns; + -- Resume Suspend to Program/Erase time + tdevice_ERSRES : VitalDelayType := 200 ns; + -- Page Program Time + tdevice_PP : VitalDelayType := 3 ms; + -- Byte Program Time (First Byte) + tdevice_BP1 : VitalDelayType := 50 us; + -- Additional Byte Program Time (After First Byte) + tdevice_BP2 : VitalDelayType := 12 us; + -- Sector Erase Time (4KB) + tdevice_SE : VitalDelayType := 400 ms; + -- Block Erase Time (32KB) + tdevice_BE1 : VitalDelayType := 800 ms; + -- Block Erase Time (64KB) + tdevice_BE2 : VitalDelayType := 1000 ms; + -- Chip Erase Time + tdevice_CE : VitalDelayType := 30 sec; + -- Write Status Register Time + tdevice_WRR : VitalDelayType := 15 ms; + -- Write Volatile Status Register Time + tdevice_VRR : VitalDelayType := 50 ns; + + --------------------------------------------------------------------------- + -- CONTROL GENERICS: + --------------------------------------------------------------------------- + + -- generic control parameters + InstancePath : STRING := DefaultInstancePath; + TimingChecksOn : BOOLEAN := DefaultTimingChecks; + MsgOn : BOOLEAN := DefaultMsgOn; + XOn : BOOLEAN := DefaultXon; + + -- memory file to be loaded + mem_file_name : STRING := "s25fl064k.mem"; + screg_file_name : STRING := "s25fl064kscreg.mem"; + + UserPreload : BOOLEAN := FALSE; --TRUE; + LongTimming : BOOLEAN := FALSE; + + -- For FMF SDF technology file usage + TimingModel : STRING := DefaultTimingModel + ); + PORT ( + -- Data Inputs/Outputs + SI : INOUT std_ulogic := 'U'; -- serial data input/IO0 + SO : INOUT std_ulogic := 'U'; -- serial data output/IO1 + -- Controls + SCK : IN std_ulogic := 'U'; -- serial clock input + CSNeg : IN std_ulogic := 'U'; -- chip select input + WPNeg : INOUT std_ulogic := 'U'; -- write protect input/IO2 + HOLDNeg : INOUT std_ulogic := 'U' -- hold input/IO3 + ); + + ATTRIBUTE VITAL_LEVEL0 of s25fl064k : ENTITY IS TRUE; +END s25fl064k; + +------------------------------------------------------------------------------- +-- ARCHITECTURE DECLARATION +------------------------------------------------------------------------------- +ARCHITECTURE vhdl_behavioral of s25fl064k IS + ATTRIBUTE VITAL_LEVEL0 OF vhdl_behavioral : ARCHITECTURE IS TRUE; + + --------------------------------------------------------------------------- + -- CONSTANT AND SIGNAL DECLARATION + --------------------------------------------------------------------------- + --Declaration of constants - memory characteristics + -- The constant declared here are used to enable the creation of models + -- of memories within a family with a minimum amount of editing + + CONSTANT PartID : STRING := "s25fl064k"; + CONSTANT MaxData : NATURAL := 16#FF#; + CONSTANT AddrRANGE : NATURAL := 16#7FFFFF#; + CONSTANT PageNum : NATURAL := 16#7FFF#; + CONSTANT SecSize_4 : NATURAL := 16#FFF#; + CONSTANT SecSize_32 : NATURAL := 16#7FFF#; + CONSTANT SecSize_64 : NATURAL := 16#FFFF#; + CONSTANT Blk_4_Num : NATURAL := 2047; + CONSTANT Blk_64_Num : NATURAL := 127; + CONSTANT Blk_32_Num : NATURAL := 255; + CONSTANT SFDP_HiAddr : NATURAL := 16#FF#; + CONSTANT SFDP_LoAddr : NATURAL := 16#00#; + CONSTANT SecReg_HiAddr : NATURAL := 16#FF#; + CONSTANT SecReg_LoAddr : NATURAL := 16#00#; + CONSTANT SCREG_LoAddr : NATURAL := 16#000#; + CONSTANT SCREG_HiAddr : NATURAL := 16#2FF#; + CONSTANT BYTE : NATURAL := 8; + + -- Manufacturer Identification and Device Identification + CONSTANT Manuf_ID : NATURAL := 16#EF#; + CONSTANT Device_ID1 : NATURAL := 16#16#; + CONSTANT Device_ID2 : NATURAL := 16#40#; + CONSTANT Device_ID3 : NATURAL := 16#17#; + CONSTANT Unique_id_1 : NATURAL := 16#ABAB#;--this is 64bit ID number + CONSTANT Unique_id_2 : NATURAL := 16#00#;--this is 64bit ID number + + -- Declaration of signals that will hold the delayed values of ports + SIGNAL SI_ipd : std_ulogic := 'U'; + SIGNAL SO_ipd : std_ulogic := 'U'; + SIGNAL SCK_ipd : std_ulogic := 'U'; + SIGNAL CSNeg_ipd : std_ulogic := 'U'; + SIGNAL WPNeg_ipd : std_ulogic := 'U'; + SIGNAL HOLDNeg_ipd : std_ulogic := 'U'; + SIGNAL HOLDNeg_pullup : std_ulogic := 'U'; + SIGNAL WPNeg_pullup : std_ulogic := 'U'; + + -- internal delays + SIGNAL PP_in : std_ulogic := '0'; + SIGNAL PP_out : std_ulogic := '0'; + SIGNAL BP1_in : std_ulogic := '0'; + SIGNAL BP1_out : std_ulogic := '0'; + SIGNAL BP2_in : std_ulogic := '0'; + SIGNAL BP2_out : std_ulogic := '0'; + SIGNAL SE_in : std_ulogic := '0'; + SIGNAL SE_out : std_ulogic := '0'; + SIGNAL BE1_in : std_ulogic := '0'; + SIGNAL BE1_out : std_ulogic := '0'; + SIGNAL BE2_in : std_ulogic := '0'; + SIGNAL BE2_out : std_ulogic := '0'; + SIGNAL CE_in : std_ulogic := '0'; + SIGNAL CE_out : std_ulogic := '0'; + SIGNAL WRR_in : std_ulogic := '0'; + SIGNAL WRR_out : std_ulogic := '0'; + SIGNAL ERSSUSP_in : std_ulogic := '0'; + SIGNAL ERSSUSP_out : std_ulogic := '0'; + SIGNAL ERSRES_in : std_ulogic := '0'; + SIGNAL ERSRES_out : std_ulogic := '0'; + SIGNAL PRGSUSP_in : std_ulogic := '0'; + SIGNAL PRGSUSP_out : std_ulogic := '0'; + SIGNAL PRGRES_in : std_ulogic := '0'; + SIGNAL PRGRES_out : std_ulogic := '0'; + SIGNAL PU_in : std_ulogic := '0'; + SIGNAL PU_out : std_ulogic := '0'; + SIGNAL RES1_in : std_ulogic := '0'; + SIGNAL RES1_out : std_ulogic := '0'; + SIGNAL RES2_in : std_ulogic := '0'; + SIGNAL RES2_out : std_ulogic := '0'; + SIGNAL DP_in : std_ulogic := '0'; + SIGNAL DP_out : std_ulogic := '0'; + SIGNAL SUSP_FL_IN : std_ulogic := '0'; + SIGNAL SUSP_FL_OUT : std_ulogic := '0'; + +BEGIN + + --------------------------------------------------------------------------- + -- Internal Delays + --------------------------------------------------------------------------- + -- Artificial VITAL primitives to incorporate internal delays + -- Because a tdevice generics is used, there must be a VITAL_primitives + -- assotiated with them + PP :VitalBuf(PP_out, PP_in, (tdevice_PP ,UnitDelay)); + BP1 :VitalBuf(BP1_out, BP1_in, (tdevice_BP1 ,UnitDelay)); + BP2 :VitalBuf(BP2_out, BP2_in, (tdevice_BP2 ,UnitDelay)); + SE :VitalBuf(SE_out, SE_in, (tdevice_SE ,UnitDelay)); + BE1 :VitalBuf(BE1_out, BE1_in, (tdevice_BE1 ,UnitDelay)); + BE2 :VitalBuf(BE2_out, BE2_in, (tdevice_BE2 ,UnitDelay)); + WRR :VitalBuf(WRR_out, WRR_in, (tdevice_WRR ,UnitDelay)); + ERSSUSP :VitalBuf(ERSSUSP_out, ERSSUSP_in, (tdevice_ERSSUSP ,UnitDelay)); + ERSRES :VitalBuf(ERSRES_out, ERSRES_in, (tdevice_ERSRES ,UnitDelay)); + PRGSUSP :VitalBuf(PRGSUSP_out, PRGSUSP_in, (tdevice_PRGSUSP ,UnitDelay)); + PRGRES :VitalBuf(PRGRES_out, PRGRES_in, (tdevice_PRGRES ,UnitDelay)); + PU :VitalBuf(PU_out, PU_in, (tdevice_PU ,UnitDelay)); + RES1 :VitalBuf(RES1_out, RES1_in, (tdevice_RES1 ,UnitDelay)); + CE :VitalBuf(CE_out, CE_in, (tdevice_CE ,UnitDelay)); + DP :VitalBuf(DP_out, DP_in, (tdevice_DP ,UnitDelay)); + RES2 :VitalBuf(RES2_out, RES2_in, (tdevice_RES2 ,UnitDelay)); + SUSP_DLY :VitalBuf(SUSP_FL_OUT, SUSP_FL_IN, (tdevice_SUSP_DLY,UnitDelay)); + + --------------------------------------------------------------------------- + -- Wire Delays + --------------------------------------------------------------------------- + WireDelay : BLOCK + BEGIN + + w_1 : VitalWireDelay (SI_ipd, SI, tipd_SI); + w_2 : VitalWireDelay (SO_ipd, SO, tipd_SO); + w_3 : VitalWireDelay (SCK_ipd, SCK, tipd_SCK); + w_4 : VitalWireDelay (CSNeg_ipd, CSNeg, tipd_CSNeg); + w_6 : VitalWireDelay (WPNeg_ipd, WPNeg, tipd_WPNeg); + w_7 : VitalWireDelay (HOLDNeg_ipd, HOLDNeg, tipd_HOLDNeg); + + END BLOCK; + + --------------------------------------------------------------------------- + -- Main Behavior Block + --------------------------------------------------------------------------- + Behavior: BLOCK + + PORT ( + SIIn : IN std_ulogic := 'U'; + SIOut : OUT std_ulogic := 'U'; + SOIn : IN std_logic := 'U'; + SOut : OUT std_logic := 'U'; + SCK : IN std_ulogic := 'U'; + CSNeg : IN std_ulogic := 'U'; + HOLDNegIn : IN std_ulogic := 'U'; + HOLDNegOut : OUT std_ulogic := 'U'; + WPNegIn : IN std_ulogic := 'U'; + WPNegOut : OUT std_ulogic := 'U' + ); + + PORT MAP ( + SIIn => SI_ipd, + SIOut => SI, + SOIn => SO_ipd, + SOut => SO, + SCK => SCK_ipd, + CSNeg => CSNeg_ipd, + HOLDNegIn => HOLDNeg_ipd, + HOLDNegOut => HOLDNeg, + WPNegIn => WPNeg_ipd, + WPNegOut => WPNeg + ); + + -- State Machine : State_Type + TYPE state_type IS (IDLE, + WRITE_SR, + PAGE_PG, + PG_SUSP, + SECTOR_ERS, + BULK_ERS, + ERS_SUSP, + ERS_SUSP_PG, + PG_SUSP_ERS, + DP_DOWN, + WRITE_SR_V + ); + + -- Instruction Type + TYPE instruction_type IS ( NONE, + WREN , -- 06h + WRENV , -- 50h + WRDI , -- 04h + RDSR , -- 05h + RDSR2 , -- 35h + WRR , -- 01h + READ , -- 03h + FAST_READ , -- 0Bh + FAST_DREAD , -- 3Bh + FAST_QREAD , -- 6Bh + FAST_DREAD_2 , -- BBh + FAST_QREAD_4 , -- EBh + W_QREAD , -- E7h + WOCT_QREAD , -- E3h + SET_BURST_WRAP , -- 77h + CONT_RD_RST , -- FFh or FFFFH + PP , -- 02h + QPP , -- 32h + SE , -- 20h + BE_32 , -- 52h + BE_64 , -- D8h + CE , -- C7h or 60h + ERS_PG_SUSP , -- 75h + ERS_PG_RES , -- 7Ah + DP , -- B9h + RES_RD_ID , -- ABh + RDID , -- 90h + RDID_DUAL , -- 92h + RDID_QUAD , -- 94h + RD_UNIQ_ID , -- 4Bh + RDIDJ , -- 9Fh + RD_SFDP , -- 5Ah + ERS_SCREG , -- 44h + PG_SCREG , -- 42h + RD_SCREG -- 48h + ); + + TYPE WByteType IS ARRAY (0 TO 255) OF INTEGER RANGE -1 TO MaxData; + -- Flash Memory Array + TYPE MemArray IS ARRAY (0 TO AddrRANGE) OF INTEGER RANGE -1 TO MaxData; + -- SFDP Memory Array + TYPE SFDPArray IS ARRAY (SFDP_LoAddr TO SFDP_HiAddr) OF INTEGER + RANGE -1 TO MaxData; + -- Security Register Array + TYPE SCREGArray IS ARRAY (SecReg_LoAddr TO SecReg_HiAddr) OF INTEGER + RANGE -1 TO MaxData; + ----------------------------------------------------------------------- + -- memory declaration + ----------------------------------------------------------------------- + -- Memory + SHARED VARIABLE Mem : MemArray := (OTHERS => MaxData); + -- Security Register 1 + SHARED VARIABLE Security_Reg1 : SCREGArray := (OTHERS => MaxData); + -- Security Register 2 + SHARED VARIABLE Security_Reg2 : SCREGArray := (OTHERS => MaxData); + -- Security Register 3 + SHARED VARIABLE Security_Reg3 : SCREGArray := (OTHERS => MaxData); + --SFDP Array + SHARED VARIABLE SFDP_array : SFDPArray := (OTHERS => 0); + -- Programming Buffer + SIGNAL WByte : WByteType := (OTHERS => MaxData); + + -- states + SIGNAL current_state : state_type; + SIGNAL next_state : state_type; + + SIGNAL Instruct : instruction_type; + + --zero delay signal + SIGNAL SOut_zd : std_logic := 'Z'; + SIGNAL SIOut_zd : std_logic := 'Z'; + SIGNAL HOLDNegOut_zd : std_logic := 'Z'; + SIGNAL WPNegOut_zd : std_logic := 'Z'; + --HOLD delay on output data + SIGNAL SOut_z : std_logic := 'Z'; + SIGNAL SIOut_z : std_logic := 'Z'; + -- powerup + SIGNAL PoweredUp : std_logic := '0'; + + ----------------------------------------------------------------------- + -- Registers + ----------------------------------------------------------------------- + -- Status register 1 + SHARED VARIABLE Status_reg1 : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Status_reg1_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Status Register Protect Bit 0 + ALIAS SRP0 :std_logic IS Status_reg1(7); + -- Sector/Block protect bit + ALIAS SEC :std_logic IS Status_reg1(6); + -- Top Bottom Bit + ALIAS TB :std_logic IS Status_reg1(5); + -- Status Register Block Protection Bits + ALIAS BP2 :std_logic IS Status_reg1(4); + ALIAS BP1 :std_logic IS Status_reg1(3); + ALIAS BP0 :std_logic IS Status_reg1(2); + -- Status Register Write Enable Latch Bit + ALIAS WEL :std_logic IS Status_reg1(1); + -- Status Register Busy Bit + ALIAS BUSY :std_logic IS Status_reg1(0); + + -- Status register 2 + SHARED VARIABLE Status_reg2 : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Status_reg2_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Suspend status bit + ALIAS SUS :std_logic IS Status_reg2(7); + -- Complement protect bit + ALIAS CMP :std_logic IS Status_reg2(6); + -- Security Register Lock bits + ALIAS LB3 :std_logic IS Status_reg2(5); + ALIAS LB2 :std_logic IS Status_reg2(4); + ALIAS LB1 :std_logic IS Status_reg2(3); + -- Quad enable bit + ALIAS QE :std_logic IS Status_reg2(1); + -- Status register protect bit + ALIAS SRP1 :std_logic IS Status_reg2(0); + + -- Sector is protect if Sec_Prot(Blk_4_Num) = '1' + SHARED VARIABLE Sec_Prot : std_logic_vector(Blk_4_Num downto 0) := + (OTHERS => '0'); + + --Command Register + SIGNAL write : std_logic := '0'; + SIGNAL read_out : std_logic := '0'; + + SIGNAL pg_screg_flag : boolean := false; + SIGNAL ers_screg_flag : boolean := false; + SIGNAL slow_read : boolean := false; + SIGNAL dual_read : boolean := false; + SIGNAL fast_rd : boolean := true; + SIGNAL quad_read : boolean := false; + SIGNAL read_id : boolean := false; + SIGNAL sr_read : boolean := false; + + SHARED VARIABLE pp_quad : boolean := false; + SHARED VARIABLE hold_mode : boolean := false; + SHARED VARIABLE res_flag : boolean := false; + SHARED VARIABLE wren_vlt_flag : boolean := false; + + --FSM control signals + SIGNAL PDONE : std_logic := '1'; + SIGNAL PSTART : std_logic := '0'; + SIGNAL PGSUSP : std_logic := '0'; + SIGNAL PGRES : std_logic := '0'; + + SIGNAL WDONE : std_logic := '1'; + SIGNAL WSTART : std_logic := '0'; + SIGNAL VLTSTART : std_logic := '0'; + SIGNAL VLTDONE : std_logic := '1'; + + SIGNAL EDONE : std_logic := '1'; + SIGNAL ESTART : std_logic := '0'; + SIGNAL ESUSP : std_logic := '0'; + SIGNAL ERES : std_logic := '0'; + + SHARED VARIABLE read_cnt : NATURAL := 0; + SHARED VARIABLE read_addr : NATURAL RANGE 0 TO AddrRANGE ; + SHARED VARIABLE wrap_byte : std_logic_vector(7 downto 0); + SIGNAL change_addr : std_logic := '0'; + SIGNAL Address : NATURAL RANGE 0 TO AddrRANGE := 0; + + SIGNAL change_prot_bits : std_logic := '0'; + SHARED VARIABLE BP_bits : std_logic_vector(2 downto 0) := "000"; + SHARED VARIABLE LB_bits : std_logic_vector(2 downto 0) := "000"; + + SIGNAL Byte_number : NATURAL RANGE 0 TO 255 := 0; + + -- Sector and subsector addresses + SIGNAL SA : NATURAL RANGE 0 TO Blk_4_Num := 0; + SHARED VARIABLE sect : NATURAL RANGE 0 TO Blk_4_Num; + SHARED VARIABLE sect_tmp_pg : NATURAL RANGE 0 TO Blk_4_Num; + SHARED VARIABLE sect_tmp_ers: NATURAL RANGE 0 TO Blk_4_Num; + + SHARED VARIABLE w_size : NATURAL RANGE 0 TO 64; + + -- timing check violation + SIGNAL Viol : X01 := '0'; + + PROCEDURE ADDRHILO_SEC64 ( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to AddrRANGE; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to AddrRANGE; + VARIABLE Addr : NATURAL) IS + VARIABLE sector : NATURAL RANGE 0 TO Blk_64_Num; + BEGIN + sector := Addr/16#10000#; + AddrLOW := sector*16#10000#; + AddrHIGH := sector*16#10000# + 16#0FFFF#; + END ADDRHILO_SEC64; + + PROCEDURE ADDRHILO_SEC32 ( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to AddrRANGE; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to AddrRANGE; + VARIABLE Addr : NATURAL) IS + VARIABLE sector : NATURAL RANGE 0 TO Blk_32_Num; + BEGIN + sector := Addr/16#8000#; + AddrLOW := sector*16#8000#; + AddrHIGH := sector*16#8000# + 16#7FFF#; + END ADDRHILO_SEC32; + + PROCEDURE ADDRHILO_SEC4 ( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to AddrRANGE; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to AddrRANGE; + VARIABLE Addr : NATURAL) IS + VARIABLE sector : NATURAL RANGE 0 TO Blk_4_Num; + BEGIN + sector := Addr/16#1000#; + AddrLOW := sector*16#1000#; + AddrHIGH := sector*16#1000# + 16#0FFF#; + END ADDRHILO_SEC4; + + PROCEDURE ADDRHILO_PG( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to AddrRANGE; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to AddrRANGE; + VARIABLE Addr : NATURAL) IS + VARIABLE page : NATURAL RANGE 0 TO PageNum; + BEGIN + page := Addr/16#100#; + AddrLOW := Page*16#100#; + AddrHIGH := Page*16#100# + 16#FF#; + END AddrHILO_PG; + +-- PROCEDURE ADDRHILO_WRAP( +-- VARIABLE AddrLOW_w : INOUT NATURAL RANGE 0 to AddrRANGE; +-- VARIABLE AddrHIGH_w : INOUT NATURAL RANGE 0 to AddrRANGE; +-- VARIABLE Addr : NATURAL; +-- VARIABLE w_size : NATURAL) IS +-- VARIABLE sect_wrap : NATURAL ; +-- BEGIN +-- sect_wrap := Addr/w_size; +-- AddrLOW_w := sect_wrap*w_size; +-- AddrHIGH_w := sect_wrap*w_size + (w_size - 1); +-- END ADDRHILO_WRAP; + + PROCEDURE ADDRHILO_WRAP( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE Address : NATURAL; + VARIABLE Wrap_size: NATURAL) IS + VARIABLE Addr_tmp : NATURAL; + VARIABLE Sect_wrap: NATURAL; + BEGIN + Addr_tmp := Address; + Sect_wrap := Addr_tmp/Wrap_size; + + AddrLOW := Sect_wrap*Wrap_size; + AddrHIGH := Sect_wrap*Wrap_size + (Wrap_size - 1); + END ADDRHILO_WRAP; + + BEGIN + --------------------------------------------------------------------------- + --Power Up time + --------------------------------------------------------------------------- + PoweredUp <= '1' AFTER tdevice_PU; + + --------------------------------------------------------------------------- + -- VITAL Timing Checks Procedures + --------------------------------------------------------------------------- + VITALTimingCheck: PROCESS(SIIn,SOIn,SCK_ipd,CSNeg_ipd,HOLDNegIn,WPNegIn) + + -- Timing Check Variables + -- Setup/Hold Checks variables + VARIABLE Tviol_CSNeg_SCK : X01 := '0'; + VARIABLE TD_CSNeg_SCK : VitalTimingDataType; + + VARIABLE Tviol_SI_SCK : X01 := '0'; + VARIABLE TD_SI_SCK : VitalTimingDataType; + + VARIABLE Tviol_SOIn_SCK : X01 := '0'; + VARIABLE TD_SOIn_SCK : VitalTimingDataType; + + VARIABLE Tviol_HOLDNeg_SCK : X01 := '0'; + VARIABLE TD_HOLDNeg_SCK : VitalTimingDataType; + + VARIABLE Tviol_HOLDNegIn_SCK : X01 := '0'; + VARIABLE TD_HOLDNegIn_SCK : VitalTimingDataType; + + VARIABLE Tviol_WPNegIn_SCK : X01 := '0'; + VARIABLE TD_WPNegIn_SCK : VitalTimingDataType; + + VARIABLE Tviol_WPNeg_CSNeg_setup : X01 := '0'; + VARIABLE TD_WPNeg_CSNeg_setup : VitalTimingDataType; + + VARIABLE Tviol_WPNeg_CSNeg_hold : X01 := '0'; + VARIABLE TD_WPNeg_CSNeg_hold : VitalTimingDataType; + + --Pulse Width and Period Check Variables + VARIABLE Pviol_SCK_slow : X01 := '0'; + VARIABLE PD_SCK_slow : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_fast : X01 := '0'; + VARIABLE PD_SCK_fast : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_CSNeg_read : X01 := '0'; + VARIABLE PD_CSNeg_read : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_CSNeg_pgers : X01 := '0'; + VARIABLE PD_CSNeg_pgers : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_slow_p : X01 := '0'; + VARIABLE PD_SCK_slow_p : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_fast_p : X01 := '0'; + VARIABLE PD_SCK_fast_p : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Violation : X01 := '0'; + + BEGIN + --------------------------------------------------------------------------- + -- Timing Check Section + --------------------------------------------------------------------------- + IF (TimingChecksOn) THEN + + -- Setup/Hold Check between CS# and SCK + VitalSetupHoldCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_CSNeg_SCK, + SetupLow => tsetup_CSNeg_SCK, + HoldHigh => thold_CSNeg_SCK, + HoldLow => thold_CSNeg_SCK, + CheckEnabled => true, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_CSNeg_SCK, + Violation => Tviol_CSNeg_SCK + ); + -- Setup/Hold Check between SI and SCK / + VitalSetupHoldCheck ( + TestSignal => SIIn, + TestSignalName => "SI", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_normal_noedge_posedge, + SetupLow => tsetup_SI_SCK_normal_noedge_posedge, + HoldHigh => thold_SI_SCK_normal_noedge_posedge, + HoldLow => thold_SI_SCK_normal_noedge_posedge, + CheckEnabled => SIOut_z /= SIIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_SI_SCK, + Violation => Tviol_SI_SCK + ); + + VitalSetupHoldCheck ( + TestSignal => SOIn, + TestSignalName => "SO", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_normal_noedge_posedge, + SetupLow => tsetup_SI_SCK_normal_noedge_posedge, + HoldHigh => thold_SI_SCK_normal_noedge_posedge, + HoldLow => thold_SI_SCK_normal_noedge_posedge, + CheckEnabled => SOut_z /= SOIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_SOIn_SCK, + Violation => Tviol_SOIn_SCK + ); + + VitalSetupHoldCheck ( + TestSignal => HOLDNegIn, + TestSignalName => "HOLD#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_normal_noedge_posedge, + SetupLow => tsetup_SI_SCK_normal_noedge_posedge, + HoldHigh => thold_SI_SCK_normal_noedge_posedge, + HoldLow => thold_SI_SCK_normal_noedge_posedge, + CheckEnabled => HOLDNegOut_zd /= HOLDNegIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_HOLDNegIn_SCK, + Violation => Tviol_HOLDNegIn_SCK + ); + + VitalSetupHoldCheck ( + TestSignal => WPNegIn, + TestSignalName => "WP#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_normal_noedge_posedge, + SetupLow => tsetup_SI_SCK_normal_noedge_posedge, + HoldHigh => thold_SI_SCK_normal_noedge_posedge, + HoldLow => thold_SI_SCK_normal_noedge_posedge, + CheckEnabled => WPNegOut_zd /= WPNegIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WPNegIn_SCK, + Violation => Tviol_WPNegIn_SCK + ); + + -- Setup/Hold Check between HOLD# and SCK / + VitalSetupHoldCheck ( + TestSignal => HOLDNegIn, + TestSignalName => "HOLD#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_HOLDNeg_SCK, + SetupLow => tsetup_HOLDNeg_SCK, + HoldHigh => thold_HOLDNeg_SCK, + HoldLow => thold_HOLDNeg_SCK, + CheckEnabled => QE = '0', + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_HOLDNeg_SCK, + Violation => Tviol_HOLDNeg_SCK + ); + + -- Setup Check between WP# and CS# \ + VitalSetupHoldCheck ( + TestSignal => WPNegIn, + TestSignalName => "WP#", + RefSignal => CSNeg_ipd, + RefSignalName => "CS#", + SetupHigh => tsetup_WPNeg_CSNeg, + CheckEnabled => QE = '0', + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WPNeg_CSNeg_setup, + Violation => Tviol_WPNeg_CSNeg_setup + ); + + -- Hold Check between WP# and CS# / + VitalSetupHoldCheck ( + TestSignal => WPNegIn, + TestSignalName => "WP#", + RefSignal => CSNeg_ipd, + RefSignalName => "CS#", + HoldHigh => thold_WPNeg_CSNeg, + CheckEnabled => QE = '0', + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WPNeg_CSNeg_hold, + Violation => Tviol_WPNeg_CSNeg_hold + ); + + --Pulse Width and Period Check Variables + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_slow_negedge, + PulseWidthHigh => tpw_SCK_slow_posedge, + PeriodData => PD_SCK_slow, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_slow, + HeaderMsg => InstancePath & PartID, + CheckEnabled => slow_read + ); + + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_fast_negedge, + PulseWidthHigh => tpw_SCK_fast_posedge, + PeriodData => PD_SCK_fast, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_fast, + HeaderMsg => InstancePath & PartID, + CheckEnabled => fast_rd + ); + + -- Pulse Width Check CS# for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + PulseWidthHigh => tpw_CSNeg_read_posedge, + PeriodData => PD_CSNeg_read, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_CSNeg_read, + HeaderMsg => InstancePath & PartID, + CheckEnabled => slow_read OR fast_rd OR dual_read OR + quad_read + ); + + -- Pulse Width Check CS# for Program/Erase, serial mode + VitalPeriodPulseCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + PulseWidthHigh => tpw_CSNeg_pger_posedge, + PeriodData => PD_CSNeg_pgers, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_CSNeg_pgers, + HeaderMsg => InstancePath & PartID, + CheckEnabled => true); + + -- Period Check SCK for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_slow, + PeriodData => PD_SCK_slow_p, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_slow_p, + HeaderMsg => InstancePath & PartID, + CheckEnabled => slow_read + ); + + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_fast, + PeriodData => PD_SCK_fast_p, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_fast_p, + HeaderMsg => InstancePath & PartID, + CheckEnabled => fast_rd OR dual_read OR quad_read + ); + + Violation := Tviol_CSNeg_SCK OR + Tviol_SI_SCK OR + Tviol_HOLDNeg_SCK OR + Tviol_WPNeg_CSNeg_setup OR + Tviol_WPNeg_CSNeg_hold OR + Tviol_HOLDNegIn_SCK OR + Tviol_WPNegIn_SCK OR + Tviol_SOIn_SCK OR + Pviol_SCK_slow OR + Pviol_SCK_fast OR + Pviol_CSNeg_read OR + Pviol_CSNeg_pgers OR + Pviol_SCK_slow_p OR + Pviol_SCK_fast_p; + + Viol <= Violation; + + ASSERT Violation = '0' + REPORT InstancePath & partID & ": simulation may be" & + " inaccurate due to timing violations" + SEVERITY WARNING; + + END IF; + END PROCESS VITALTimingCheck; + + --------------------------------------------------------------------------- + -- sequential process for FSM state transition + --------------------------------------------------------------------------- + StateTransition : PROCESS(next_state,PoweredUp) + + BEGIN + IF PoweredUp = '1' THEN + IF next_state'EVENT THEN + current_state <= next_state; + END IF; + END IF; + END PROCESS StateTransition; + + --------------------------------------------------------------------------- + -- Write cycle decode + --------------------------------------------------------------------------- + BusCycleDecode : PROCESS(SCK_ipd, CSNeg_ipd) + + TYPE bus_cycle_type IS (STAND_BY, + OPCODE_BYTE, + ADDRESS_BYTES, + DUMMY_BYTES, + MODE_BYTE, + DATA_BYTES + ); + + TYPE quad_data_type IS ARRAY (0 TO 511) OF INTEGER RANGE 0 TO 15; + + VARIABLE bus_cycle_state : bus_cycle_type; + + VARIABLE opcode_cnt : NATURAL := 0; + VARIABLE addr_cnt : NATURAL := 0; + VARIABLE mode_cnt : NATURAL := 0; + VARIABLE wrap_cnt : NATURAL := 0; + VARIABLE dummy_cnt : NATURAL := 0; + VARIABLE data_cnt : NATURAL := 0; + VARIABLE bit_cnt : NATURAL := 0; + + VARIABLE Data_in : std_logic_vector(2047 downto 0) + := (others => '0'); + VARIABLE opcode : std_logic_vector(7 downto 0); + VARIABLE opcode_in : std_logic_vector(7 downto 0); + VARIABLE opcode_double : std_logic_vector(15 downto 0); + VARIABLE opcode_double_in : std_logic_vector(15 downto 0); + VARIABLE addr_bytes : std_logic_vector(23 downto 0); + VARIABLE Address_in : std_logic_vector(23 downto 0); + VARIABLE mode_bits : std_logic_vector(7 downto 0); + VARIABLE mode_in : std_logic_vector(7 downto 0); +-- VARIABLE wrap_byte : std_logic_vector(7 downto 0); + VARIABLE wrap_in : std_logic_vector(7 downto 0); + VARIABLE quad_data_in : quad_data_type; + VARIABLE quad_nybble : std_logic_vector(3 downto 0); + VARIABLE Quad_slv : std_logic_vector(3 downto 0); + VARIABLE Byte_slv : std_logic_vector(7 downto 0); + + BEGIN + + IF falling_edge(CSNeg_ipd) THEN + IF (bus_cycle_state = STAND_BY) THEN + bus_cycle_state := OPCODE_BYTE; + Instruct <= NONE; + write <= '1'; + opcode_cnt := 0; + addr_cnt := 0; + data_cnt := 0; + mode_cnt := 0; + wrap_cnt := 0; + dummy_cnt := 0; + ELSIF (bus_cycle_state = DATA_BYTES AND + mode_bits(5 DOWNTO 4) = "10") THEN + bus_cycle_state := ADDRESS_BYTES; + dummy_cnt := 0; + opcode_cnt := 0; + END IF; + END IF; + + IF rising_edge(SCK_ipd) AND (PoweredUp = '1') THEN + IF (CSNeg_ipd = '0') THEN + CASE (bus_cycle_state) IS + WHEN OPCODE_BYTE => + IF (HOLDNeg_pullup = '1' AND QE='0') OR QE='1' THEN + opcode_in(opcode_cnt) := SIIn; + opcode_cnt := opcode_cnt + 1; + IF opcode_cnt = BYTE THEN + FOR I IN 7 DOWNTO 0 LOOP + opcode(i) := opcode_in(7-i); + END LOOP; + + CASE opcode IS + WHEN "00000110" => -- 06H + Instruct <= WREN; + bus_cycle_state := DATA_BYTES; + WHEN "01010000" => + Instruct <= WRENV; + bus_cycle_state := DATA_BYTES; + WHEN "00000100" => --04h + Instruct <= WRDI; + bus_cycle_state := DATA_BYTES; + WHEN "00000101" => -- 05h + Instruct <= RDSR; + bus_cycle_state := DATA_BYTES; + WHEN "00110101" => -- 35h + Instruct <= RDSR2; + bus_cycle_state := DATA_BYTES; + WHEN "00000001" => -- 01h + Instruct <= WRR; + bus_cycle_state := DATA_BYTES; + WHEN "00000011" => -- 03h + Instruct <= READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00001011" => -- 0Bh + Instruct <= FAST_READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00111011" => -- 3Bh + Instruct <= FAST_DREAD; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01101011" => -- 6Bh + Instruct <= FAST_QREAD; + IF (QE = '1') THEN + bus_cycle_state := ADDRESS_BYTES; + ELSE + bus_cycle_state := STAND_BY; + END IF; + WHEN "10111011" => -- BBh + Instruct <= FAST_DREAD_2; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11101011" => -- EBh + Instruct <= FAST_QREAD_4; + IF (QE = '1') THEN + bus_cycle_state := ADDRESS_BYTES; + ELSE + bus_cycle_state := STAND_BY; + END IF; + WHEN "11100111" => --E7h + Instruct <= W_QREAD; + IF (QE = '1') THEN + bus_cycle_state := ADDRESS_BYTES; + ELSE + bus_cycle_state := STAND_BY; + END IF; + WHEN "11100011" => -- E3h + Instruct <= WOCT_QREAD; + IF (QE = '1') THEN + bus_cycle_state := ADDRESS_BYTES; + ELSE + bus_cycle_state := STAND_BY; + END IF; + WHEN "01110111" => -- 77h + Instruct <= SET_BURST_WRAP; + IF (QE = '1') THEN + bus_cycle_state := DUMMY_BYTES; + ELSE + bus_cycle_state := STAND_BY; + END IF; + WHEN "11111111" => -- FFh + Instruct <= CONT_RD_RST; + bus_cycle_state := MODE_BYTE; + WHEN "00000010" => -- 02H + Instruct <= PP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00110010" => -- 32h + Instruct <= QPP; + IF (QE = '1') THEN + bus_cycle_state := ADDRESS_BYTES; + ELSE + bus_cycle_state := STAND_BY; + END IF; + WHEN "00100000" => -- 20h + Instruct <= SE; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01010010" => -- 52h + Instruct <= BE_32; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11011000" => -- D8h + Instruct <= BE_64; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11000111" | "01100000" => -- C7 or 60h + Instruct <= CE; + bus_cycle_state := DATA_BYTES; + WHEN "01110101" => -- 75h + Instruct <= ERS_PG_SUSP; + bus_cycle_state := DATA_BYTES; + WHEN "01111010" => -- 7Ah + Instruct <= ERS_PG_RES; + bus_cycle_state := DATA_BYTES; + WHEN "10111001" => -- B9h + Instruct <= DP; + bus_cycle_state := DATA_BYTES; + WHEN "10101011" => -- ABh + Instruct <= RES_RD_ID; + bus_cycle_state := DUMMY_BYTES; + WHEN "10010000" => -- 90h + Instruct <= RDID; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10010010" => -- 92h + Instruct <= RDID_DUAL; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10010100" => -- 94h + Instruct <= RDID_QUAD; + IF (QE = '1') THEN + bus_cycle_state := ADDRESS_BYTES; + ELSE + bus_cycle_state := STAND_BY; + END IF; + WHEN "01001011" => -- 4Bh + Instruct <= RD_UNIQ_ID; + bus_cycle_state := DUMMY_BYTES; + WHEN "10011111" => -- 9Fh + Instruct <= RDIDJ; + bus_cycle_state := DATA_BYTES; + WHEN "01011010" => -- 5Ah + Instruct <= RD_SFDP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01000100" => -- 44h + Instruct <= ERS_SCREG; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01000010" => -- 42h + Instruct <= PG_SCREG; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01001000" => -- 48h + Instruct <= RD_SCREG; + bus_cycle_state := ADDRESS_BYTES; + + WHEN OTHERS => + NULL; + + END CASE; + END IF; + ELSE + REPORT "Device is in HOLD mode, opcode" + SEVERITY NOTE; + END IF; + + WHEN ADDRESS_BYTES => + IF (HOLDNeg_pullup = '1' AND QE='0') OR QE='1' THEN + IF (Instruct = READ OR Instruct = FAST_READ OR + Instruct = FAST_DREAD OR Instruct = RDID OR + Instruct = SE OR Instruct = PP OR + Instruct = RD_SCREG OR Instruct = PG_SCREG OR + Instruct = RD_SFDP OR Instruct = BE_32 OR + Instruct = BE_64 OR Instruct = ERS_SCREG OR + ((Instruct = QPP OR Instruct = FAST_QREAD) + AND QE = '1')) THEN + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 3*BYTE THEN + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + + IF (Instruct = PP OR Instruct = QPP + OR Instruct = READ OR Instruct = SE + OR Instruct = BE_32 OR Instruct = BE_64 + OR Instruct = RDID OR Instruct = PG_SCREG + OR Instruct = ERS_SCREG) THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF (Instruct = RDID_DUAL OR + Instruct = FAST_DREAD_2) THEN + IF (SOIn /= 'Z') THEN + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt + 1):= SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF (addr_cnt = (3*BYTE)/2) THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + ELSIF (mode_bits(5 downto 4) = "10") THEN + opcode_double_in(opcode_cnt) := SIIn; + opcode_cnt := opcode_cnt + 1; + IF (opcode_cnt = 2*BYTE) THEN + FOR I IN 15 DOWNTO 0 LOOP + opcode_double(i) := + opcode_double_in(15-i); + END LOOP; + IF (opcode_double="1111111111111111") THEN + Instruct <= CONT_RD_RST; + bus_cycle_state := MODE_BYTE; + END IF; + END IF; + END IF; + ELSIF (QE = '1' AND (Instruct = FAST_QREAD_4 OR + Instruct = W_QREAD OR Instruct = WOCT_QREAD OR + Instruct = RDID_QUAD)) THEN + IF (SOIn /= 'Z') THEN + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF (addr_cnt = (3*BYTE)/4) THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + ELSIF (mode_bits(5 downto 4) = "10") THEN + opcode_in(opcode_cnt) := SIIn; + opcode_cnt := opcode_cnt + 1; + IF (opcode_cnt = BYTE) THEN + FOR I IN 7 DOWNTO 0 LOOP + opcode(i) := + opcode_in(7-i); + END LOOP; + IF (opcode = "11111111") THEN + Instruct <= CONT_RD_RST; + bus_cycle_state := MODE_BYTE; + END IF; + END IF; + END IF; + END IF; + ELSE + REPORT "Device is in HOLD mode, addr" + SEVERITY NOTE; + END IF; + + WHEN MODE_BYTE => + IF (QE = '1' OR (HOLDNeg_pullup = '1' AND QE = '0')) THEN + IF (Instruct = SET_BURST_WRAP AND QE = '1') THEN + wrap_in(4*wrap_cnt) := HOLDNegIn; + wrap_in(4*wrap_cnt+1) := WPNegIn; + wrap_in(4*wrap_cnt+2) := SOIn; + wrap_in(4*wrap_cnt+3) := SIIn; + wrap_cnt := wrap_cnt + 1; + IF (wrap_cnt = BYTE/4) THEN + wrap_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + wrap_byte(i) := wrap_in(7-i); + END LOOP; + bus_cycle_state := DATA_BYTES; + END IF; + CASE (wrap_byte(6 DOWNTO 5)) IS + WHEN "00" => + w_size := 8; + WHEN "01" => + w_size := 16; + WHEN "10" => + w_size := 32; + WHEN "11" => + w_size := 64; + WHEN OTHERS => + NULL; + END CASE; + ELSIF ((Instruct = FAST_QREAD_4 OR + Instruct = WOCT_QREAD OR Instruct = W_QREAD OR + Instruct = RDID_QUAD ) AND QE = '1') THEN + mode_in(4*mode_cnt) := HOLDNegIn; + mode_in(4*mode_cnt+1) := WPNegIn; + mode_in(4*mode_cnt+2) := SOIn; + mode_in(4*mode_cnt+3) := SIIn; + mode_cnt := mode_cnt + 1; + IF (mode_cnt = BYTE/4) THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bits(i) := mode_in(7-i); + END LOOP; + IF (Instruct = WOCT_QREAD) THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF (Instruct = RDID_DUAL OR + Instruct = FAST_DREAD_2) THEN + mode_in(2*mode_cnt) := SOIn; + mode_in(2*mode_cnt+1) := SIIn; + mode_cnt := mode_cnt + 1; + IF (mode_cnt = BYTE/2) THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bits(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSE + REPORT "Device is in HOLD mode, mode" + SEVERITY NOTE; + END IF; + + WHEN DUMMY_BYTES => + IF (QE = '1' OR (HOLDNeg_pullup = '1' AND QE = '0')) THEN + IF ((Instruct = FAST_QREAD_4 OR + Instruct = RDID_QUAD) AND QE = '1') THEN + dummy_cnt := dummy_cnt + 1; + IF (dummy_cnt = BYTE/2) THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct = W_QREAD AND QE = '1') THEN + dummy_cnt := dummy_cnt + 1; + IF (dummy_cnt = BYTE/4) THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct = SET_BURST_WRAP AND QE = '1') THEN + dummy_cnt := dummy_cnt + 1; + IF (dummy_cnt = 3*BYTE/4) THEN + bus_cycle_state := MODE_BYTE; + END IF; + ELSIF (Instruct = FAST_QREAD AND QE = '1') THEN + dummy_cnt := dummy_cnt + 1; + IF (dummy_cnt = BYTE) THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct=FAST_READ OR Instruct=RD_SFDP + OR Instruct = FAST_DREAD OR Instruct=RD_SCREG) THEN + dummy_cnt := dummy_cnt + 1; + IF (dummy_cnt = BYTE) THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct = RD_UNIQ_ID) THEN + dummy_cnt := dummy_cnt + 1; + IF (dummy_cnt = 4*BYTE) THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSE -- for RES_RD_ID + dummy_cnt := dummy_cnt + 1; + IF (dummy_cnt = 3*BYTE) THEN + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSE + REPORT "Device is in HOLD mode, dummy" + SEVERITY NOTE; + END IF; -- end of DUMMY_BYTES + + WHEN DATA_BYTES => + IF (Instruct = PP OR Instruct = WRR OR + Instruct = PG_SCREG) THEN + IF ((HOLDNeg_pullup = '1' AND QE='0') OR QE='1') THEN + IF (data_cnt > 2047) THEN + --In case of serial mode and PP,IF more than + --256 bytes are sent to the device + IF (bit_cnt = 0) THEN + FOR I IN 0 TO (255*BYTE-1) LOOP + Data_in(i) := Data_in(i+8); + END LOOP; + END IF; + Data_in(2040 + bit_cnt) := SIIn; + bit_cnt := bit_cnt + 1; + IF (bit_cnt = 8) THEN + bit_cnt := 0; + END IF; + data_cnt := data_cnt + 1; + ELSE + Data_in(data_cnt) := SIIn; + data_cnt := data_cnt + 1; + bit_cnt := 0; + END IF; + ELSE + REPORT "Device is in HOLD mode, data" + SEVERITY NOTE; + END IF; + ELSIF (Instruct = QPP AND QE ='1') THEN + pp_quad := TRUE; + quad_nybble := HOLDNegIn & WPNegIn & SOIn & SIIn; + IF (data_cnt > 511) THEN + --In case of quad mode and QPP,IF more than + -- 256 bytes are sent to the device + FOR I IN 0 TO 510 LOOP + quad_data_in(i) := quad_data_in(i+1); + END LOOP; + quad_data_in(511) := to_nat(quad_nybble); + data_cnt := data_cnt +1; + ELSE + IF (quad_nybble /= "ZZZZ") THEN + quad_data_in(data_cnt) := + to_nat(quad_nybble); + END IF; + data_cnt := data_cnt +1; + END IF; + END IF; + + WHEN OTHERS => NULL; + END CASE; + END IF; + END IF; + + IF falling_edge(SCK_ipd) AND (bus_cycle_state = DATA_BYTES AND + CSNeg_ipd ='0') THEN + IF (((Instruct = RDSR OR Instruct = RDSR2 OR + Instruct = FAST_READ OR Instruct = FAST_DREAD OR + Instruct = FAST_DREAD_2 OR Instruct = RES_RD_ID OR + Instruct = RDID OR Instruct = RDID_DUAL OR + Instruct = RD_UNIQ_ID OR Instruct = RDIDJ OR + Instruct = RD_SFDP OR Instruct = RD_SCREG OR + Instruct = READ) AND ((HOLDNeg_pullup ='1' AND QE='0') OR QE='1')) + OR ((Instruct = FAST_QREAD OR Instruct = FAST_QREAD_4 OR + Instruct = W_QREAD OR Instruct = RDID_QUAD OR + Instruct = WOCT_QREAD) AND QE='1')) THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + + IF rising_edge(CSNeg_ipd) THEN + IF (bus_cycle_state=MODE_BYTE AND Instruct = CONT_RD_RST) THEN + mode_bits(5 downto 4) := "11"; + mode_bits(7 downto 6) := "00"; + mode_bits(3 downto 0) := "0000"; + bus_cycle_state := STAND_BY; + ELSIF (bus_cycle_state=DATA_BYTES AND + NOT (mode_bits(5 downto 4)="10")) THEN + bus_cycle_state := STAND_BY; + CASE (Instruct) IS + WHEN WREN | WRDI | SET_BURST_WRAP | SE | BE_32 | BE_64 | + CE | ERS_PG_RES | DP | ERS_SCREG => + + IF (data_cnt = 0) THEN + write <= '0'; + END IF; + WHEN WRENV => + write <= '0'; + wren_vlt_flag := TRUE; + + WHEN RES_RD_ID => + write <= '0'; + res_flag := TRUE; + + WHEN WRR => + IF (data_cnt = 8) THEN + --If CS# is driven high after eight + --cycle,only the Status Register is + --written to. + write <= '0'; + FOR i IN 0 TO 7 LOOP + Status_reg1_in(i) <= Data_in(7-i); + END LOOP; + ELSIF (data_cnt = 16) THEN + --After the 16th cycle both the + --Status and Configuration Registers + --are written to. + write <= '0'; + FOR i IN 0 TO 7 LOOP + Status_reg1_in(i) <= Data_in(7-i); + END LOOP; + + FOR j IN 0 TO 7 LOOP + Status_reg2_in(j) <= Data_in(15-j); + END LOOP; +-- FOR I IN 0 TO 15 LOOP +-- Status_reg1_in(i) <= Data_in(7-i); +-- Status_reg2_in(i) <= Data_in(15-i); +-- END LOOP; + END IF; + + WHEN PP | PG_SCREG => + IF (data_cnt > 0) THEN + IF ((data_cnt mod 8) = 0) THEN + write <= '0'; + FOR I IN 0 TO 255 LOOP + FOR J IN 7 DOWNTO 0 LOOP + Byte_slv(j) := + Data_in((i*8) + (7-j)); + END LOOP; + WByte(i) <= + to_nat(Byte_slv); + END LOOP; + + IF (data_cnt > 256*BYTE) THEN + Byte_number <= 255; + ELSE + Byte_number <= ((data_cnt/8) - 1); + END IF; + END IF; + END IF; + + WHEN QPP => + IF (data_cnt >0) THEN + IF ((data_cnt mod 2) = 0) THEN + write <= '0'; + FOR I IN 0 TO 255 LOOP + FOR J IN 1 DOWNTO 0 LOOP + Quad_slv := + to_slv(quad_data_in((i*2) + + (1-j)),4); + + Byte_slv(4*j+3 DOWNTO 4*j) := + Quad_slv; + END LOOP; + WByte(i) <= to_nat(Byte_slv); + END LOOP; + + IF (data_cnt > 256*BYTE/4) THEN + Byte_number <= 255; + ELSE + Byte_number <= ((data_cnt/2) - 1); + END IF; + END IF; + END IF; + + WHEN others => + null; + + END CASE; + + ELSIF (bus_cycle_state=DATA_BYTES AND + (mode_bits(5 DOWNTO 4)="10")) THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := STAND_BY; + IF (HOLDNeg_pullup ='1' AND (Instruct = RES_RD_ID) AND + (dummy_cnt = 0)) THEN + write <= '0'; + res_flag := FALSE; + END IF; + END IF; + END IF; -- end of rising_edge_CSNeg_ipd + + END PROCESS BusCycleDecode; + + --------------------------------------------------------------------------- + -- Timing control for the Page Program + --------------------------------------------------------------------------- + ProgTime : PROCESS(PSTART, PGSUSP, PGRES) + VARIABLE pob : time; + VARIABLE elapsed : time; + VARIABLE start : time; + VARIABLE duration : time; + BEGIN + IF Instruct = PP OR Instruct = QPP OR Instruct = PG_SCREG THEN + IF LongTimming THEN + pob := tdevice_PP; + ELSE + pob := tdevice_PP / 10; + END IF; + END IF; + IF rising_edge(PSTART) AND PDONE = '1' THEN + elapsed := 0 ns; + PDONE <= '0', '1' AFTER pob; + start := NOW; + ELSIF PGSUSP'EVENT AND PGSUSP = '1' AND PDONE /= '1' THEN + elapsed := NOW - start; + duration := pob - elapsed; + PDONE <= '0'; + ELSIF PGRES'EVENT AND PGRES = '1' AND PDONE /= '1'THEN + start := NOW; + PDONE <= '0', '1' AFTER duration; + END IF; + + END PROCESS ProgTime; + + --------------------------------------------------------------------------- + -- Timing control for the Write Status Register + --------------------------------------------------------------------------- + WriteTime : PROCESS(WSTART) + VARIABLE wob : time; + BEGIN + IF LongTimming THEN + wob := tdevice_WRR; + ELSE + wob := tdevice_WRR / 100; + END IF; + IF rising_edge(WSTART) AND WDONE = '1' THEN + WDONE <= '0', '1' AFTER wob; + END IF; + + END PROCESS WriteTime; + + --------------------------------------------------------------------------- + -- Timing control for the Write Status Register when Write Enable for + -- Volatile Status Register was issued + --------------------------------------------------------------------------- + + WriteTimeVlt : PROCESS(VLTSTART) + VARIABLE wvob : time; + BEGIN + wvob := tdevice_VRR; + IF rising_edge(VLTSTART) AND VLTDONE = '1' THEN + VLTDONE <= '0' , '1' AFTER wvob; + END IF; + END PROCESS WriteTimeVlt; + + --------------------------------------------------------------------------- + -- Timing control for the Erase Operation + --------------------------------------------------------------------------- + ErsTime : PROCESS(ESTART, ESUSP, ERES) + VARIABLE seo : time; + VARIABLE beo32 : time; + VARIABLE beo64 : time; + VARIABLE ceo : time; + VARIABLE elapsed : time; + VARIABLE start : time; + VARIABLE duration : time; + BEGIN + IF LongTimming THEN + seo := tdevice_SE; + beo32 := tdevice_BE1; + beo64 := tdevice_BE2; + ceo := tdevice_CE; + ELSE + seo := tdevice_SE / 100; + beo32 := tdevice_BE1 / 100; + beo64 := tdevice_BE2 / 100; + ceo := tdevice_CE / 100; + END IF; + IF rising_edge(ESTART) AND EDONE = '1' THEN + IF Instruct = CE THEN + duration := ceo; + ELSIF Instruct = BE_64 THEN + duration := beo64; + ELSIF Instruct = BE_32 THEN + duration := beo32; + ELSE -- sector erase 4KB, instruct SE + duration := seo; + END IF; + elapsed := 0 ns; + EDONE <= '0', '1' AFTER duration; + start := NOW; + ELSIF ESUSP'EVENT AND ESUSP = '1' AND EDONE /= '1' THEN + elapsed := NOW - start; + duration := duration - elapsed; + EDONE <= '0'; + ELSIF ERES'EVENT AND ERES = '1' AND EDONE /= '1' THEN + start := NOW; + EDONE <= '0', '1' AFTER duration; + END IF; + + END PROCESS ErsTime; + + CheckCEOnPowerUP :PROCESS(CSNeg_ipd) + BEGIN + IF (PoweredUp = '0' AND falling_edge(CSNeg_ipd)) THEN + REPORT InstancePath & partID & + ": Device is selected during Power Up" + SEVERITY WARNING; + END IF; + END PROCESS; + + --------------------------------------------------------------------------- + -- Main Behavior Process + -- combinational process for next state generation + --------------------------------------------------------------------------- + StateGen :PROCESS(PoweredUp, write, CSNeg_ipd, WDONE, ERSSUSP_out, RES1_out, + ERSRES_out, PRGSUSP_out, EDONE,PRGRES_out, DP_out, PDONE, + VLTDONE,RES2_out) + + BEGIN + + IF rising_edge(PoweredUp) THEN + next_state <= IDLE; + ELSE + CASE current_state IS + WHEN IDLE => + IF falling_edge(write) THEN + IF (Instruct = WRR AND (SRP1='0' AND + (SRP0='0' OR (SRP0='1' AND WPNeg ='1')))) THEN + IF (WEL='1' AND NOT (wren_vlt_flag)) THEN + next_state <= WRITE_SR; + ELSIF (WEL='0' AND wren_vlt_flag) THEN + next_state <= WRITE_SR_V; + END IF; + ELSIF (Instruct = PP AND WEL='1') THEN + sect := Address / 16#1000#; + sect_tmp_pg := sect; + IF (Sec_Prot(sect) = '0') THEN + next_state <= PAGE_PG; + END IF; + ELSIF (Instruct = QPP AND WEL='1' AND QE='1') THEN + sect := Address / 16#1000#; + sect_tmp_pg := sect; + IF (Sec_Prot(sect) = '0') THEN + next_state <= PAGE_PG; + END IF; + ELSIF (Instruct = PG_SCREG AND WEL='1') THEN + sect := Address / 16#1000#; + IF ((sect < 4 AND sect > 0) AND + LB_bits(sect-1)='0') THEN + next_state <= PAGE_PG; + END IF; + ELSIF (Instruct = ERS_SCREG AND WEL='1') THEN + sect := Address / 16#1000#; + IF ((sect <= 3) AND LB_bits(sect-1)='0') THEN + next_state <= SECTOR_ERS; + END IF; + ELSIF ((Instruct = SE OR Instruct = BE_32 OR + Instruct = BE_64) AND WEL='1') THEN + sect := Address / 16#1000#; + sect_tmp_ers := sect; + IF (Sec_Prot(sect) = '0') THEN + next_state <= SECTOR_ERS; + END IF; + ELSIF (Instruct = CE AND WEL='1' AND + ((CMP='0' AND BP2='0' AND BP1='0' AND BP0='0') OR + (CMP='1' AND BP2='1' AND BP1='1' AND BP0='1'))) THEN + next_state <= BULK_ERS; + ELSE + next_state <= IDLE; + END IF; + ELSIF rising_edge(DP_out) THEN + next_state <= DP_DOWN; + END IF; + + WHEN WRITE_SR => + IF rising_edge(WDONE) THEN + next_state <= IDLE; + END IF; -- end of WRITE_SR + + WHEN WRITE_SR_V => + IF rising_edge(VLTDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PAGE_PG => + IF (PRGSUSP_out'event AND PRGSUSP_out = '1') THEN + next_state <= PG_SUSP; + ELSIF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; -- end of PAGE_PG + + WHEN PG_SUSP => + IF (PRGRES_out'event AND PRGRES_out = '1') THEN + next_state <= PAGE_PG; + ELSIF falling_edge(write) THEN + IF (Instruct = SE OR Instruct = BE_32 OR + Instruct = BE_64) THEN + sect := Address / 16#1000#; + IF ((Sec_Prot(sect) = '0') AND + (sect /= sect_tmp_pg)) THEN + next_state <= PG_SUSP_ERS; + END IF; + END IF; + END IF; -- end of PG_SUSP + + WHEN PG_SUSP_ERS => + IF rising_edge(EDONE) THEN + next_state <= PG_SUSP; + ELSE + next_state <= PG_SUSP_ERS; + END IF; + + WHEN BULK_ERS => + IF rising_edge(EDONE) THEN + next_state <= IDLE; + END IF; + + WHEN SECTOR_ERS => + IF (ERSSUSP_out'event AND ERSSUSP_out = '1') THEN + next_state <= ERS_SUSP; + ELSIF rising_edge(EDONE) THEN + next_state <= IDLE; + END IF; + + WHEN ERS_SUSP => + IF (ERSRES_out'event AND ERSRES_out = '1') THEN + next_state <= SECTOR_ERS; + ELSIF falling_edge(write) THEN + IF (Instruct = PP OR (Instruct = QPP AND QE='1')) THEN + sect := Address / 16#1000#; + IF ((Sec_Prot(sect) = '0') AND + (sect /= sect_tmp_ers)) THEN + next_state <= ERS_SUSP_PG; + END IF; + ELSIF (Instruct = PG_SCREG) THEN + sect := Address / 16#1000#; + IF ((sect < 4 AND sect > 0) AND + LB_bits(sect-1)='0') THEN + next_state <= ERS_SUSP_PG; + END IF; + END IF; + END IF; + + WHEN ERS_SUSP_PG => + IF rising_edge(PDONE) THEN + next_state <= ERS_SUSP; + ELSE + next_state <= ERS_SUSP_PG; + END IF; + + WHEN DP_DOWN => + IF rising_edge(RES1_out) OR rising_edge(RES2_out) THEN + next_state <= IDLE; + END IF; + + END CASE; + END IF; + END PROCESS StateGen; + --------------------------------------------------------------------------- + --FSM Output generation and general funcionality + --------------------------------------------------------------------------- + Functional : PROCESS(read_out, Instruct, SCK_ipd, change_addr, write, + Address, PDONE, WDONE, EDONE, ERSSUSP_out, PoweredUp, + CSNeg_ipd, RES1_out, ERSRES_out, PRGSUSP_out,PRGRES_out, + VLTDONE, current_state, DP_out, RES2_out,SUSP_FL_OUT) + + VARIABLE WData : WByteType:= (OTHERS => MaxData); + + VARIABLE oe : boolean := FALSE; + + VARIABLE AddrLo : NATURAL; + VARIABLE AddrHi : NATURAL; + + VARIABLE AddrLo_ers : NATURAL; + VARIABLE AddrHi_ers : NATURAL; + VARIABLE AddrLo_wrap : NATURAL; + VARIABLE AddrHi_wrap : NATURAL; + + VARIABLE Addr : NATURAL; + VARIABLE Addr_w : NATURAL; + VARIABLE Addr_ers : NATURAL; + VARIABLE Addr_tmp : NATURAL; + VARIABLE Addr_tmp_2 : NATURAL; + VARIABLE Addr_tmp_3 : NATURAL; + VARIABLE Addr_screg : NATURAL; + VARIABLE Addr_screg_tmp : NATURAL; + + VARIABLE data_out : std_logic_vector(7 downto 0); + VARIABLE ident_out : std_logic_vector(23 downto 0); + VARIABLE ident_out2 : std_logic_vector(15 downto 0); + VARIABLE uniq_id : std_logic_vector(63 downto 0); + + VARIABLE old_bit : std_logic_vector(7 downto 0); + VARIABLE new_bit : std_logic_vector(7 downto 0); + VARIABLE old_int : INTEGER RANGE -1 to MaxData; + VARIABLE new_int : INTEGER RANGE -1 to MaxData; + + VARIABLE wr_cnt : NATURAL RANGE 0 TO 255; +-- VARIABLE sect : NATURAL RANGE 0 TO Blk_4_Num; + VARIABLE cnt : NATURAL RANGE 0 TO 256 := 0; + + BEGIN + + oe := rising_edge(read_out) AND PoweredUp = '1'; + + IF Instruct'EVENT THEN + read_cnt := 0; + + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + sr_read <= false; + read_id <= false; + pp_quad := FALSE; + + IF (current_state = IDLE AND DP_in = '1') THEN + REPORT "Command results can be corrupted " + SEVERITY WARNING; + END IF; + END IF; + + IF rising_edge(PoweredUp) THEN + WEL := '0'; + BUSY := '0'; + SUS := '0'; + change_prot_bits <= '1', '0' AFTER 1 ns; + END IF; + + IF change_addr'EVENT THEN + read_addr := Address; + END IF; + + IF RES1_out'EVENT AND RES1_out = '1' THEN + RES1_in <= '0'; + END IF; + + IF RES2_out'EVENT AND RES2_out = '1' THEN + RES2_in <= '0'; + END IF; + + IF SUSP_FL_OUT'EVENT AND SUSP_FL_OUT = '1' THEN + SUSP_FL_IN <= '0'; + END IF; + + CASE current_state IS + + WHEN IDLE => + + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + read_id <= false; + sr_read <= false; + res_flag := FALSE; + pg_screg_flag <= false; + ers_screg_flag <= false; + + IF falling_edge(write) AND DP_in ='0' THEN + read_cnt := 0; + IF (Instruct = WREN) THEN + WEL := '1'; + ELSIF (Instruct = WRDI) THEN + WEL := '0'; + ELSIF (Instruct = WRR) THEN + IF(SRP1='0' AND (SRP0='0' OR + (SRP0='1' AND WPNeg='1'))) THEN + IF WEL='1' AND NOT (wren_vlt_flag) THEN + WSTART <= '1', '0' AFTER 5 ns; + BUSY := '1'; + ELSIF (WEL='0' AND wren_vlt_flag) THEN + VLTSTART <= '1', '0' AFTER 5 ns; + END IF; + ELSE + WEL := '0'; + END IF; + ELSIF ((Instruct = PP OR (Instruct = QPP AND QE='1')) + AND WEL='1' AND PDONE='1') THEN + sect := Address / 16#1000#; + IF (Sec_Prot(sect) = '0') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + BUSY := '1'; + SA <= sect; + Addr := Address; + Addr_tmp:= Address; + wr_cnt := Byte_number; + + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + WEL := '0'; + END IF; + ELSIF (Instruct = PG_SCREG AND WEL='1') THEN + sect := Address / 16#1000#; + IF ((sect <= 3) AND LB_bits(sect-1)='0') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + BUSY := '1'; + SA <= sect; + wr_cnt := Byte_number; + Addr_screg := Address mod 16#1000#; + Addr_screg_tmp := Address mod 16#1000#; + pg_screg_flag <= true; + + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + + ELSE + WEL := '0'; + END IF; + ELSIF ((Instruct = SE OR Instruct = BE_32 OR + Instruct = BE_64) AND WEL='1') THEN + sect := Address / 16#1000#; + IF (Sec_Prot(sect) = '0') THEN + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + BUSY := '1'; + Addr_ers := Address; + ELSE + WEL := '0'; + END IF; + ELSIF (Instruct = CE AND WEL='1') THEN + IF ((CMP='0' AND BP2='0' AND BP1='0' AND BP0='0') OR + (CMP='1' AND BP2='1' AND BP1='1' AND BP0='1')) THEN +-- IF (Sec_Prot = 0) + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + BUSY := '1'; + ELSE + WEL := '0'; + END IF; + ELSIF (Instruct = ERS_SCREG AND WEL='1') THEN + sect := Address / 16#1000#; + IF ((sect <= 3) AND LB_bits(sect-1)='0') THEN + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + BUSY := '1'; + SA <= sect; + ers_screg_flag <= true; + ELSE + WEL := '0'; + END IF; + ELSIF (Instruct = DP) THEN + RES2_in <= '0'; + RES1_in <= '0'; + DP_in <= '1'; + END IF; + -- end of falling_edge_write + ELSIF (oe AND DP_in='0') THEN + IF (Instruct = RDSR) THEN + --Read Status Register + sr_read <= true; + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RDSR2) THEN + sr_read <= true; + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = READ OR Instruct = FAST_READ) THEN + IF (Instruct = READ) THEN + fast_rd <= false; + dual_read <= false; + slow_read <= true; + quad_read <= false; + sr_read <= false; + ELSE + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + sr_read <= false; + END IF; + IF (Mem(read_addr) /= -1) THEN + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + ELSE + SOut_zd <= 'U'; + END IF; + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + IF (read_addr = AddrRANGE) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSIF (Instruct=FAST_DREAD OR Instruct=FAST_DREAD_2) THEN + fast_rd <= false; + dual_read <= true; + slow_read <= false; + quad_read <= false; + sr_read <= false; + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 4) THEN + read_cnt := 0; + IF (read_addr = AddrRANGE) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSIF ((Instruct=FAST_QREAD OR Instruct=FAST_QREAD_4 OR + Instruct=W_QREAD OR Instruct=WOCT_QREAD) + AND QE='1') THEN + IF ((Instruct=W_QREAD AND (Address mod 2 /= 0) ) OR + (Instruct=WOCT_QREAD AND + (Address mod 16 /= 0))) THEN + read_cnt := read_cnt + 1; + IF (read_cnt = 2) THEN + read_cnt := 0; + REPORT "Word Read can't execute Wrong Address" + SEVERITY NOTE; + END IF; + ELSE + fast_rd <= false; + dual_read <= false; + slow_read <= false; + quad_read <= true; + sr_read <= false; + Addr_w := Address; + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 2) THEN + read_cnt := 0; + IF (wrap_byte(4)='0' AND (Instruct=FAST_QREAD_4 + OR Instruct=W_QREAD)) THEN + ADDRHILO_WRAP(AddrLo_wrap,AddrHi_wrap, + Addr_w,w_size); + IF (read_addr = AddrHi_wrap) THEN + read_addr := AddrLo_wrap; + ELSE + read_addr := read_addr + 1; + END IF; + ELSE + IF (read_addr = AddrRANGE) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + END IF; + ELSIF (Instruct=RDID OR Instruct=RDID_DUAL OR + Instruct=RDID_QUAD) THEN + IF (read_addr mod 2 = 0) THEN + ident_out2 := to_slv(Manuf_ID,8) & + to_slv(Device_ID1,8); + ELSE + ident_out2 := to_slv(Device_ID1,8) & + to_slv(Manuf_ID,8); + END IF; + read_id <= true; + IF (Instruct = RDID) THEN + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + sr_read <= false; + SOut_zd <= ident_out2(15-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 16) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RDID_DUAL) THEN + fast_rd <= false; + dual_read <= true; + slow_read <= false; + quad_read <= false; + sr_read <= false; + SOut_zd <= ident_out2(15-2*read_cnt); + SIOut_zd <= ident_out2(14-2*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + ELSE -- (Instruct = RDID_QUAD) + fast_rd <= false; + dual_read <= false; + slow_read <= false; + quad_read <= true; + sr_read <= false; + HOLDNegOut_zd <= ident_out2(15-4*read_cnt); + WPNegOut_zd <= ident_out2(14-4*read_cnt); + SOut_zd <= ident_out2(13-4*read_cnt); + SIOut_zd <= ident_out2(12-4*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 4) THEN + read_cnt := 0; + END IF; + END IF; + ELSIF (Instruct = RD_UNIQ_ID) THEN + -- unique ID number is not in data sheet + read_id <= true; + uniq_id := to_slv(Unique_id_2,32)& + to_slv(Unique_id_1,32); + SOut_zd <= uniq_id(63-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 64) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RDIDJ) THEN + read_id <= true; + ident_out := to_slv(Manuf_ID,8) & + to_slv(Device_ID2,8) & to_slv(Device_ID3,8); + SOut_zd <= ident_out(23-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 24) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RD_SFDP) THEN +-- sfdp_addr := read_addr / 16#100#; + IF (read_addr / 16#100# = 0) THEN + Addr_tmp_2 := (read_addr mod 16#100#); + data_out := to_slv(SFDP_array(Addr_tmp_2),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + IF (read_addr = SFDP_HiAddr) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + REPORT "Given SFDP address is out of range" + SEVERITY NOTE; + END IF; + END IF; + ELSIF (Instruct = RD_SCREG) THEN + Addr_tmp_2 := read_addr / 16#100#; + Addr_tmp_3 := read_addr mod 16#100#; + IF (Addr_tmp_2 = 16) THEN + -- Security Register No.1 + data_out := to_slv(Security_Reg1(Addr_tmp_3),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + ELSIF (Addr_tmp_2 = 32) THEN + -- Security Register No.2 + data_out := to_slv(Security_Reg2(Addr_tmp_3),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + ELSIF (Addr_tmp_2 = 48) THEN + -- Security Register No.2 + data_out := to_slv(Security_Reg3(Addr_tmp_3),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + REPORT "Security Reg address is out of range " + SEVERITY NOTE; + END IF; + END IF; + IF (read_cnt = 8) THEN + read_cnt := 0; + IF (read_addr mod 256 = SecReg_HiAddr) THEN + read_addr := (read_addr/256)*(SecReg_HiAddr+1); + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSIF Instruct = RES_RD_ID THEN + read_id <= true; + data_out := to_slv(Device_ID1,8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + END IF; -- end of oe + ELSIF rising_edge(DP_out) THEN + DP_in <= '0'; + END IF; -- end of IDLE state + + WHEN WRITE_SR => + + IF (WDONE ='1') THEN + BUSY := '0'; + WEL := '0'; + + SRP0 := Status_reg1_in(7); + SEC := Status_reg1_in(6); + TB := Status_reg1_in(5); + BP2 := Status_reg1_in(4); + BP1 := Status_reg1_in(3); + BP0 := Status_reg1_in(2); + BP_bits := BP2 & BP1 & BP0; + CMP := Status_reg2_in(6); + QE := Status_reg2_in(1); + -- SRP1 bit will only change value from '0' to '1' + -- if SRP1 is '1' than Status Register is protected + --and is not possible to write it + SRP1 := Status_reg2_in(0); + + IF LB3 = '0' THEN + LB3 := Status_reg2_in(5); + ELSE + REPORT "LB bit is set to '1', no change allowed" + SEVERITY NOTE; + END IF; + + IF LB2 = '0' THEN + LB2 := Status_reg2_in(4); + ELSE + REPORT "LB bit is set to '1', no change allowed" + SEVERITY NOTE; + END IF; + IF LB1 = '0' THEN + LB1 := Status_reg2_in(3); + ELSE + REPORT "LB bit is set to '1', no change allowed" + SEVERITY NOTE; + END IF; + LB_bits := LB3 & LB2 & LB1; + change_prot_bits <= '1' , '0' AFTER 2 ns; + END IF; -- end of WDONE + + IF (oe AND Instruct = RDSR) THEN + --Read Status Register 1 + sr_read <= true; + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + END IF; -- end of WRITE_SR + + WHEN WRITE_SR_V => + + IF (VLTDONE = '1') THEN + SRP0 := Status_reg1_in(7); + SEC := Status_reg1_in(6); + TB := Status_reg1_in(5); + BP2 := Status_reg1_in(4); + BP1 := Status_reg1_in(3); + BP0 := Status_reg1_in(2); + BP_bits := BP2 & BP1 & BP0; + CMP := Status_reg2_in(6); + QE := Status_reg2_in(1); + -- SRP1 bit will only change value from '0' to '1' + -- if SRP1 is '1' than Status Register is protected + --and is not possible to write it + SRP1 := Status_reg2_in(0); + IF LB3 = '0' THEN + LB3 := Status_reg2_in(5); + ELSIF LB2 = '0' THEN + LB2 := Status_reg2_in(4); + ELSIF LB1 = '0' THEN + LB1 := Status_reg2_in(3); + ELSE + REPORT "LB bit is set to '1', no change allowed" + SEVERITY NOTE; + END IF; + + change_prot_bits <= '1' , '0' AFTER 2 ns; + + wren_vlt_flag := FALSE; + END IF; + + WHEN PAGE_PG | ERS_SUSP_PG => + + IF falling_edge(PDONE) THEN + + IF (Instruct /= PG_SCREG) THEN + ADDRHILO_PG(AddrLo, AddrHi, Addr); + END IF; + cnt := 0; + + FOR i IN 0 TO wr_cnt LOOP + new_int := WData(i); + IF (Instruct = PG_SCREG) THEN + IF (sect = 1) THEN + old_int := Security_Reg1(Addr_screg + i - cnt); + ELSIF (sect = 2) THEN + old_int := Security_Reg2(Addr_screg + i - cnt); + ELSE + old_int := Security_Reg3(Addr_screg + i - cnt); + END IF; + ELSE + old_int := Mem(Addr + i - cnt); + END IF; + IF (new_int > -1) THEN + new_bit := to_slv(new_int,8); + IF (old_int > -1) THEN + old_bit := to_slv(old_int,8); + FOR j IN 0 TO 7 LOOP + IF old_bit(j) = '0' THEN + new_bit(j) := '0'; + END IF; + END LOOP; + new_int := to_nat(new_bit); + END IF; + WData(i) := new_int; + ELSE + WData(i) := -1; + END IF; + IF (Instruct = PG_SCREG) THEN + IF (sect = 1) THEN + Security_Reg1(Addr_screg + i - cnt) := - 1; + ELSIF (sect = 2) THEN + Security_Reg2(Addr_screg + i - cnt) := - 1; + ELSE + Security_Reg3(Addr_screg + i - cnt) := - 1; + END IF; + ELSE + Mem(Addr + i - cnt) := - 1; + END IF; + IF (Instruct /= PG_SCREG) THEN + IF ((Addr + i) = AddrHi) THEN + Addr := AddrLo; + cnt := i + 1; + END IF; + ELSE + IF Addr_screg + i = SecReg_HiAddr THEN + Addr_screg := SecReg_LoAddr; + cnt := i + 1; + END IF; + END IF; + END LOOP; + cnt := 0; + + END IF; + + IF (PDONE = '1') THEN + IF (current_state /= ERS_SUSP_PG) THEN + BUSY := '0'; + END IF; + WEL := '0'; + + FOR I IN 0 TO wr_cnt LOOP + IF pg_screg_flag THEN + IF (sect = 1) THEN + Security_Reg1(Addr_screg_tmp + i - cnt) :=WData(i); + ELSIF (sect = 2) THEN + Security_Reg2(Addr_screg_tmp + i - cnt) :=WData(i); + ELSE + Security_Reg3(Addr_screg_tmp + i - cnt) :=WData(i); + END IF; + IF ((Addr_screg_tmp + i) = SecReg_HiAddr) THEN + Addr_screg_tmp := SecReg_LoAddr; + cnt := i + 1; + END IF; + ELSE + Mem(Addr_tmp + i - cnt) := WData(i); + IF ((Addr_tmp + i) = AddrHi) THEN + Addr_tmp := AddrLo; + cnt := i + 1; + END IF; + END IF; + END LOOP; + END IF; -- end of PDONE + + IF (Instruct = ERS_PG_SUSP AND current_state = PAGE_PG AND + SUSP_FL_IN = '0') THEN + PGSUSP <= '1', '0' AFTER 1 ns; + PRGSUSP_in <= '1'; + END IF; + + IF (oe AND Instruct = RDSR) THEN + --Read Status Register 1 + sr_read <= true; + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + END IF; + + WHEN PG_SUSP => + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + sr_read <= false; + BUSY := '0'; + IF (PRGSUSP_out = '1' AND (Instruct /= ERS_PG_RES)) THEN + PRGSUSP_in <= '0'; + --The BUSY bit in the Status Register will indicate that + --the device is ready for another operation. +-- BUSY := '0'; + --The SuspEND (SUS) bit in the Status Register2 will + --be set to the logical “1” state to indicate that the + --program operation has been suspENDed. + SUS := '1'; + END IF; + IF (PRGRES_out'event AND PRGRES_out = '1') THEN + PRGRES_in <= '0'; + BUSY := '1'; + END IF; + IF (SUS = '1') THEN + IF falling_edge(write) THEN + IF (Instruct = ERS_PG_RES) THEN + SUS := '0'; + PRGRES_in <= '1'; + SUSP_FL_IN <= '1'; + PGRES <= '1', '0' AFTER 5 ns; + ELSIF ((Instruct = SE OR Instruct = BE_32 OR + Instruct = BE_64) AND WEL='1') THEN + sect := Address / 16#1000#; + IF (sect /= sect_tmp_pg AND + Sec_Prot(sect) = '0') THEN + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + BUSY := '1'; + Addr_ers := Address; + ELSE + BUSY := '0'; + REPORT "Can't erase sector,protected or susp." + SEVERITY NOTE; + END IF; + END IF; + ELSIF (oe) THEN + IF (Instruct = RDSR) THEN + --Read Status Register 1 + sr_read <= true; + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RDSR2) THEN + --Read Status Register 2 + sr_read <= true; + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = READ OR Instruct = FAST_READ) THEN + IF (sect_tmp_pg /= read_addr / 16#1000#) THEN + IF (Instruct = READ) THEN + fast_rd <= false; + dual_read <= false; + slow_read <= true; + quad_read <= false; + sr_read <= false; + ELSE + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + sr_read <= false; + END IF; + IF (Mem(read_addr) /= -1) THEN + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + ELSE + SOut_zd <= 'U'; + END IF; + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + IF (read_addr = AddrRANGE) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + REPORT "Can't read suspended sector" + SEVERITY NOTE; + read_cnt := 0; + END IF; + END IF; + ELSIF (Instruct=FAST_DREAD OR + Instruct=FAST_DREAD_2) THEN + IF sect_tmp_pg /= (read_addr / 16#1000#) THEN + fast_rd <= false; + dual_read <= true; + slow_read <= false; + quad_read <= false; + sr_read <= false; + IF (Mem(read_addr) /= -1) THEN + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + ELSE + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + END if; + read_cnt := read_cnt + 1; + IF (read_cnt = 4) THEN + read_cnt := 0; + IF (read_addr = AddrRANGE) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 4) THEN + REPORT "Can't read suspended sector" + SEVERITY NOTE; + read_cnt := 0; + END IF; + END IF; + ELSIF ((Instruct=FAST_QREAD OR Instruct=W_QREAD + OR Instruct=FAST_QREAD_4 OR Instruct=WOCT_QREAD) + AND QE = '1') THEN + IF sect_tmp_pg /= (read_addr / 16#1000#) THEN + IF ((Instruct=W_QREAD AND + Address mod 2 /= 0) OR + (Instruct=WOCT_QREAD AND + Address mod 16 /= 0)) THEN + read_cnt := read_cnt + 1; + IF (read_cnt = 2) THEN + read_cnt := 0; + REPORT "Word Read - Wrong Read Address" + SEVERITY NOTE; + END IF; + ELSE + fast_rd <= false; + dual_read <= false; + slow_read <= false; + quad_read <= true; + sr_read <= false; + Addr_w := Address; + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 2) THEN + read_cnt := 0; + IF (wrap_byte(4)= '0' AND + (Instruct=FAST_QREAD_4 OR + Instruct=W_QREAD)) THEN + ADDRHILO_WRAP(AddrLo_wrap, + AddrHi_wrap, Addr_w,w_size); + IF (read_addr = AddrHi_wrap) THEN + read_addr := AddrLo_wrap; + ELSE + read_addr := read_addr + 1; + END IF; + ELSE + IF (read_addr = AddrRANGE) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 2) THEN + REPORT "Can't read suspended sector" + SEVERITY NOTE; + read_cnt := 0; + END IF; + END IF; + ELSIF (Instruct=RDID OR Instruct=RDID_DUAL OR + Instruct=RDID_QUAD) THEN + IF (read_addr mod 2 = 0) THEN + ident_out2 := to_slv(Manuf_ID,8) & + to_slv(Device_ID1,8); + ELSE + ident_out2 := to_slv(Device_ID1,8)& + to_slv(Manuf_ID,8); + END IF; + read_id <= true; + IF (Instruct = RDID) THEN + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + sr_read <= false; + SOut_zd <= ident_out2(15-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 16) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RDID_DUAL) THEN + fast_rd <= false; + dual_read <= true; + slow_read <= false; + quad_read <= false; + sr_read <= false; + SOut_zd <= ident_out2(15-2*read_cnt); + SIOut_zd <= ident_out2(14-2*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + ELSE -- (Instruct = RDID_QUAD) + fast_rd <= false; + dual_read <= false; + slow_read <= false; + quad_read <= true; + sr_read <= false; + HOLDNegOut_zd <= ident_out2(15-4*read_cnt); + WPNegOut_zd <= ident_out2(14-4*read_cnt); + SOut_zd <= ident_out2(13-4*read_cnt); + SIOut_zd <= ident_out2(12-4*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 4) THEN + read_cnt := 0; + END IF; + END IF; + ELSIF (Instruct = RD_UNIQ_ID) THEN + -- unique ID number is not in data sheet + read_id <= true; + uniq_id := to_slv(Unique_id_2,32)& + to_slv(Unique_id_1,32); + SOut_zd <= uniq_id(63-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 64) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RDIDJ) THEN + read_id <= true; + ident_out := to_slv(Manuf_ID,8) & + to_slv(Device_ID2,8) & to_slv(Device_ID3,8); + SOut_zd <= ident_out(23-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 24) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RD_SFDP) THEN + IF (read_addr / 16#100# = 0) THEN + Addr_tmp_2 := (read_addr mod 16#100#); + data_out := to_slv(SFDP_array(Addr_tmp_2),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + IF (read_addr = SFDP_HiAddr) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + REPORT "SFDP address is out of range" + SEVERITY NOTE; + END IF; + END IF; + ELSIF (Instruct = RD_SCREG) THEN + Addr_tmp_2 := read_addr / 16#100#; + Addr_tmp_3 := read_addr mod 16#100#; + IF (Addr_tmp_2 = 16) THEN + -- Security Register No.1 + data_out := to_slv(Security_Reg1(Addr_tmp_3),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + ELSIF (Addr_tmp_2 = 32) THEN + -- Security Register No.2 + data_out := to_slv(Security_Reg2(Addr_tmp_3),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + ELSIF (Addr_tmp_2 = 48) THEN + -- Security Register No.2 + data_out := to_slv(Security_Reg3(Addr_tmp_3),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + REPORT "Security Reg addr is out of range " + SEVERITY NOTE; + END if; + END IF; + + IF (read_cnt = 8) THEN + read_cnt := 0; + IF (read_addr mod 256) = SecReg_HiAddr THEN + read_addr:=(read_addr/256)* + (SecReg_HiAddr+1); + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + END IF; + END IF; + + WHEN SECTOR_ERS | PG_SUSP_ERS => + IF falling_edge(EDONE) THEN + IF (Instruct = SE) THEN + ADDRHILO_SEC4(AddrLo_ers, AddrHi_ers, Addr_ers); + ELSIF (Instruct = BE_32) THEN + ADDRHILO_SEC32(AddrLo_ers, AddrHi_ers, Addr_ers); + ELSIF (Instruct = BE_64) THEN + ADDRHILO_SEC64(AddrLo_ers, AddrHi_ers, Addr_ers); + END IF; + IF (Instruct /= ERS_SCREG) THEN + + FOR I IN AddrLo_ers TO AddrHi_ers LOOP + Mem(i) := -1; + END LOOP; + ELSE + IF (sect = 1) THEN + FOR I IN SecReg_LoAddr TO SecReg_HiAddr LOOP + Security_Reg1(i) := -1; + END LOOP; + ELSIF (sect = 2) THEN + FOR I IN SecReg_LoAddr TO SecReg_HiAddr LOOP + Security_Reg2(i) := -1; + END LOOP; + ELSE + FOR I IN SecReg_LoAddr TO SecReg_HiAddr LOOP + Security_Reg3(i) := -1; + END LOOP; + END IF; + END IF; + END IF; + IF (EDONE = '1') THEN + IF (current_state /= PG_SUSP_ERS) THEN + BUSY := '0'; + END IF; + WEL := '0'; + IF (ers_screg_flag) THEN + IF (sect = 1) THEN + FOR I IN SecReg_LoAddr TO SecReg_HiAddr LOOP + Security_Reg1(i) := MaxData; + END LOOP; + ELSIF (sect = 2) THEN + FOR I IN SecReg_LoAddr TO SecReg_HiAddr LOOP + Security_Reg2(i) := MaxData; + END LOOP; + ELSE + FOR I IN SecReg_LoAddr TO SecReg_HiAddr LOOP + Security_Reg3(i) := MaxData; + END LOOP; + END IF; + ELSE + FOR I IN AddrLo_ers TO AddrHi_ers LOOP + Mem(i) := MaxData; + END LOOP; + END IF; + END IF; + + IF (Instruct = ERS_PG_SUSP AND current_state = SECTOR_ERS AND + SUSP_FL_IN = '0') THEN + ESUSP <= '1', '0' AFTER 1 ns; + ERSSUSP_in <= '1'; + END IF; + IF (oe AND Instruct = RDSR) THEN + --Read Status Register 1 + sr_read <= true; + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + END IF; + + WHEN BULK_ERS => + IF (current_state'event AND EDONE = '0') THEN + FOR I IN 0 TO AddrRANGE LOOP + Mem(i) := -1; + END LOOP; + END IF; + IF (EDONE = '1') THEN + BUSY := '0'; + WEL := '0'; + FOR I IN 0 TO AddrRANGE LOOP + Mem(i) := MaxData; + END LOOP; + + END IF; + IF (oe AND Instruct = RDSR) THEN + --Read Status Register 1 + sr_read <= true; + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + END IF; + + WHEN ERS_SUSP => + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + sr_read <= false; + pg_screg_flag <= false; + BUSY := '0'; + IF (ERSSUSP_out = '1' AND (Instruct /= ERS_PG_RES)) THEN + ERSSUSP_in <= '0'; + --The BUSY bit in the Status Register will indicate that + --the device is ready for another operation. +-- BUSY := '0'; + --The SuspEND (SUS) bit in the Status Register2 will + --be set to the logical “1” state to indicate that the + --program operation has been suspENDed. + SUS := '1'; + END IF; + IF (ERSRES_out'event AND ERSRES_out = '1') THEN + ERSRES_in <= '0'; + BUSY := '1'; + END IF; + IF (SUS = '1') THEN + IF falling_edge(write) THEN + IF (Instruct = ERS_PG_RES) THEN + SUS := '0'; + ERSRES_in <= '1'; + SUSP_FL_IN <= '1'; + ERES <= '1', '0' AFTER 5 ns; + ELSIF ((Instruct = PP OR (Instruct=QPP AND QE='1')) + AND WEL ='1') THEN + sect := Address / 16#1000#; + IF (sect /= sect_tmp_ers AND + Sec_Prot(sect)='0') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + BUSY := '1'; + SA <= sect; + Addr := Address; + Addr_tmp:= Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + BUSY := '0'; + REPORT "Can't program sector,protected or susp" + SEVERITY NOTE; + END IF; + ELSIF (Instruct = PG_SCREG) THEN + sect := Address / 16#1000#; + IF ((sect <= 3 AND sect >=1) AND + LB_bits(sect-1)='0') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + BUSY := '1'; + SA <= sect; + wr_cnt := Byte_number; + Addr_screg := Address mod 16#1000#; + Addr_screg_tmp := Address mod 16#1000#; + pg_screg_flag <= true; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + WEL := '0'; + END IF; + END IF; + ELSIF (oe) THEN + IF (Instruct = RDSR) THEN + --Read Status Register 1 + sr_read <= true; + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RDSR2) THEN + --Read Status Register 2 + sr_read <= true; + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = READ OR Instruct = FAST_READ) THEN + IF sect /= (read_addr / 16#1000#) THEN + IF (Instruct = READ) THEN + fast_rd <= false; + dual_read <= false; + slow_read <= true; + quad_read <= false; + sr_read <= true; + ELSE + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + sr_read <= false; + END IF; + IF (Mem(read_addr) /= -1) THEN + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + ELSE + SOut_zd <= 'U'; + END IF; + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + IF (read_addr = AddrRANGE) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + REPORT "Can't read suspended sector" + SEVERITY NOTE; + read_cnt := 0; + END IF; + END IF; + ELSIF (Instruct = FAST_DREAD OR + Instruct = FAST_DREAD_2) THEN + IF sect_tmp_ers /= (read_addr / 16#1000#) THEN + fast_rd <= false; + dual_read <= true; + slow_read <= false; + quad_read <= false; + sr_read <= false; + IF (Mem(read_addr) /= -1) THEN + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + ELSE + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + END IF; + read_cnt := read_cnt + 1; + IF (read_cnt = 4) THEN + read_cnt := 0; + IF (read_addr = AddrRANGE) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 4) THEN + REPORT "Can't read suspended sector" + SEVERITY NOTE; + read_cnt := 0; + END IF; + END IF; + ELSIF ((Instruct=FAST_QREAD OR Instruct=W_QREAD + OR Instruct=FAST_QREAD_4 OR Instruct=WOCT_QREAD) + AND QE = '1') THEN + IF sect_tmp_ers /= (read_addr / 16#1000#) THEN + IF ((Instruct=W_QREAD AND + Address mod 2 /= 0) OR + (Instruct=WOCT_QREAD AND + Address mod 16 /=0)) THEN + read_cnt := read_cnt + 1; + IF (read_cnt = 2) THEN + read_cnt := 0; + REPORT "Bad Word Read- Wrong Address" + SEVERITY NOTE; + END IF; + ELSE + fast_rd <= false; + dual_read <= false; + slow_read <= false; + quad_read <= true; + sr_read <= false; + data_out := to_slv(Mem(read_addr),8); + Addr_w := Address; + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 2) THEN + read_cnt := 0; + IF (wrap_byte(4)='0' AND + (Instruct=FAST_QREAD_4 + OR Instruct=W_QREAD)) THEN + ADDRHILO_WRAP(AddrLo_wrap, + AddrHi_wrap,Addr_w,w_size); + IF (read_addr = AddrHi_wrap) THEN + read_addr := AddrLo_wrap; + ELSE + read_addr := read_addr + 1; + END IF; + ELSE + IF (read_addr = AddrRANGE) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 2) THEN + REPORT "Can't read suspended sector" + SEVERITY NOTE; + read_cnt := 0; + END IF; + END IF; + ELSIF (Instruct=RDID OR Instruct=RDID_DUAL OR + Instruct=RDID_QUAD) THEN + IF (read_addr mod 2 = 0) THEN + ident_out2 := to_slv(Manuf_ID,8) & + to_slv(Device_ID1,8); + ELSE + ident_out2 := to_slv(Device_ID1,8) & + to_slv(Manuf_ID,8); + END IF; + read_id <= true; + IF (Instruct = RDID) THEN + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + sr_read <= false; + SOut_zd <= ident_out2(15-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 16) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RDID_DUAL) THEN + fast_rd <= false; + dual_read <= true; + slow_read <= false; + quad_read <= false; + sr_read <= false; + SOut_zd <= ident_out2(15-2*read_cnt); + SIOut_zd <= ident_out2(14-2*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + ELSE -- (Instruct = RDID_QUAD) + fast_rd <= false; + dual_read <= false; + slow_read <= false; + quad_read <= true; + sr_read <= false; + HOLDNegOut_zd <= ident_out2(15-4*read_cnt); + WPNegOut_zd <= ident_out2(14-4*read_cnt); + SOut_zd <= ident_out2(13-4*read_cnt); + SIOut_zd <= ident_out2(12-4*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 4) THEN + read_cnt := 0; + END IF; + END IF; + ELSIF (Instruct = RD_UNIQ_ID) THEN + -- unique ID number is not in data sheet + read_id <= true; + uniq_id := to_slv(Unique_id_2,32)& + to_slv(Unique_id_1,32); + SOut_zd <= uniq_id(63-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 64) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RDIDJ) THEN + read_id <= true; + ident_out := to_slv(Manuf_ID,8) & + to_slv(Device_ID2,8) & to_slv(Device_ID3,8); + SOut_zd <= ident_out(23-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 24) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RD_SFDP) THEN +-- sfdp_addr := read_addr / 16#100#; + IF (read_addr / 16#100# = 0) THEN + Addr_tmp_2 := (read_addr mod 16#100#); + data_out := to_slv(SFDP_array(Addr_tmp_2),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + IF (read_addr = SFDP_HiAddr) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + REPORT "Given SFDP address is out of range" + SEVERITY NOTE; + END IF; + END IF; + ELSIF (Instruct = RD_SCREG) THEN + Addr_tmp_2 := read_addr / 16#100#; + Addr_tmp_3 := read_addr mod 16#100#; + IF (Addr_tmp_2 = 16) THEN + -- Security Register No.1 + data_out :=to_slv(Security_Reg1(Addr_tmp_3),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + ELSIF (Addr_tmp_2 = 32) THEN + -- Security Register No.2 + data_out :=to_slv(Security_Reg2(Addr_tmp_3),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + ELSIF (Addr_tmp_2 = 48) THEN + -- Security Register No.2 + data_out :=to_slv(Security_Reg3(Addr_tmp_3),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; +-- END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + REPORT "Security Reg addr is out of range" + SEVERITY NOTE; + END IF; + END IF; + IF (read_cnt = 8) THEN + read_cnt := 0; + IF (read_addr mod 256 = SecReg_HiAddr) THEN + read_addr := (read_addr/256)* + (SecReg_HiAddr+1); + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + END IF; + END IF; + + WHEN DP_DOWN => + IF (oe AND Instruct = RES_RD_ID) THEN + read_id <= true; + data_out := to_slv(Device_ID1,8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + END IF; + IF falling_edge(write) THEN + IF (Instruct = RES_RD_ID) THEN + IF res_flag = true THEN + RES2_in <= '1'; + ELSE + RES1_in <= '1'; + END IF; + ELSE + REPORT "Device is in DPD Mode No instructions allowed" + SEVERITY NOTE; + END IF; + END IF; + + END CASE; + + --Output Disable Control + IF (CSNeg_ipd = '1') THEN + SIOut_zd <= 'Z'; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + END IF; + + END PROCESS Functional; + + --------------------------------------------------------------------------- + -- SFDP Process + --------------------------------------------------------------------------- + SFDPPreload: PROCESS + + BEGIN + ----------------------------------------------------------------------- + --SFDP array data + ----------------------------------------------------------------------- + + SFDP_array(16#00#) := 16#53#; + SFDP_array(16#01#) := 16#46#; + SFDP_array(16#02#) := 16#44#; + SFDP_array(16#03#) := 16#50#; + SFDP_array(16#04#) := 16#01#; + SFDP_array(16#05#) := 16#01#; + SFDP_array(16#06#) := 16#00#; + SFDP_array(16#07#) := 16#FF#; + SFDP_array(16#08#) := 16#EF#; + SFDP_array(16#09#) := 16#00#; + SFDP_array(16#0A#) := 16#01#; + SFDP_array(16#0B#) := 16#04#; + SFDP_array(16#0C#) := 16#80#; + SFDP_array(16#0D#) := 16#00#; + SFDP_array(16#0E#) := 16#00#; + SFDP_array(16#0F#) := 16#FF#; + SFDP_array(16#10#) := 16#EF#; + SFDP_array(16#11#) := 16#00#; + SFDP_array(16#12#) := 16#01#; + SFDP_array(16#13#) := 16#00#; + SFDP_array(16#14#) := 16#90#; + SFDP_array(16#15#) := 16#00#; + SFDP_array(16#16#) := 16#00#; + SFDP_array(16#17#) := 16#FF#; + + FOR I IN 24 TO 127 LOOP + SFDP_array(i) := MaxData; + END LOOP; + + SFDP_array(16#80#) := 16#E5#; + SFDP_array(16#81#) := 16#20#; + SFDP_array(16#82#) := 16#F1#; + SFDP_array(16#83#) := 16#FF#; + SFDP_array(16#84#) := 16#FF#; + SFDP_array(16#85#) := 16#FF#; + SFDP_array(16#86#) := 16#FF#; + SFDP_array(16#87#) := 16#03#; + SFDP_array(16#88#) := 16#44#; + SFDP_array(16#89#) := 16#EB#; + SFDP_array(16#8A#) := 16#08#; + SFDP_array(16#8B#) := 16#6B#; + SFDP_array(16#8C#) := 16#08#; + SFDP_array(16#8D#) := 16#3B#; + SFDP_array(16#8E#) := 16#80#; + SFDP_array(16#8F#) := 16#BB#; + + FOR I IN 144 TO 255 LOOP + SFDP_array(i) := MaxData; + END LOOP; + + WAIT; + + END PROCESS SFDPPreload; + + --------------------------------------------------------------------------- + -- Sector Protection Bits + --------------------------------------------------------------------------- + Protect : PROCESS(change_prot_bits) + BEGIN + IF rising_edge(change_prot_bits) THEN + + CASE BP_bits IS + WHEN "000" => + IF (CMP = '0') THEN + Sec_Prot := (others => '0'); + ELSE + Sec_Prot := (others => '1'); + END IF; + WHEN "001" => + IF (CMP = '0') THEN + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(2047 downto 2016) := + (others => '1'); + Sec_Prot(2015 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(31 downto 0) := + (others => '1'); + Sec_Prot(2047 downto 32) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(2047) := '1'; + Sec_Prot(2046 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(0) := '1'; + Sec_Prot(2047 downto 1) := + (others => '0'); + END IF; + ELSE + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(2015 downto 0) := + (others => '1'); + Sec_Prot(2047 downto 2016) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(2047 downto 32) := + (others => '1'); + Sec_Prot(31 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(2046 downto 0) := + (others => '1'); + Sec_Prot(2047) := '0'; + + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(2047 downto 1) := + (others => '1'); + Sec_Prot(0) := '0'; + END IF; + END IF; + WHEN "010" => + IF (CMP = '0') THEN + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(2047 downto 1984) := + (others => '1'); + Sec_Prot(1983 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(63 downto 0) := + (others => '1'); + Sec_Prot(2047 downto 64) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(2047 downto 2046) := + (others => '1'); + Sec_Prot(2045 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(1 downto 0) := + (others => '1'); + Sec_Prot(2047 downto 2) := + (others => '0'); + END IF; + ELSE + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(1983 downto 0) := + (others => '1'); + Sec_Prot(2047 downto 1984) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(2047 downto 64) := + (others => '1'); + Sec_Prot(63 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(2045 downto 0) := + (others => '1'); + Sec_Prot(2047 downto 2046) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(2047 downto 2) := + (others => '1'); + Sec_Prot(1 downto 0) := + (others => '0'); + END IF; + END IF; + + WHEN "011" => + IF (CMP = '0') THEN + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(2047 downto 1920) := + (others => '1'); + Sec_Prot(1919 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(127 downto 0) := + (others => '1'); + Sec_Prot(2047 downto 128) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(2047 downto 2044) := + (others => '1'); + Sec_Prot(2043 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(3 downto 0) := + (others => '1'); + Sec_Prot(2047 downto 4) := + (others => '0'); + END IF; + ELSE + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(1919 downto 0) := + (others => '1'); + Sec_Prot(2047 downto 1920) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(2047 downto 128) := + (others => '1'); + Sec_Prot(127 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(2043 downto 0) := + (others => '1'); + Sec_Prot(2047 downto 2044) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(2047 downto 4) := + (others => '1'); + Sec_Prot(3 downto 0) := + (others => '0'); + END IF; + END IF; + + WHEN "100" => + IF (CMP = '0') THEN + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(2047 downto 1792) := + (others => '1'); + Sec_Prot(1791 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(255 downto 0) := + (others => '1'); + Sec_Prot(2047 downto 256) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(2047 downto 2040) := + (others => '1'); + Sec_Prot(2041 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(7 downto 0) := + (others => '1'); + Sec_Prot(2047 downto 8) := + (others => '0'); + END IF; + ELSE + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(1791 downto 0) := + (others => '1'); + Sec_Prot(2047 downto 1792) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(2047 downto 256) := + (others => '1'); + Sec_Prot(255 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(2039 downto 0) := + (others => '1'); + Sec_Prot(2047 downto 2040) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(2047 downto 8) := + (others => '1'); + Sec_Prot(7 downto 0) := + (others => '0'); + END IF; + END IF; + + WHEN "101" => + IF (CMP = '0') THEN + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(2047 downto 1536) := + (others => '1'); + Sec_Prot(1535 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(511 downto 0) := + (others => '1'); + Sec_Prot(2047 downto 512) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(2047 downto 2040) := + (others => '1'); + Sec_Prot(2039 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(7 downto 0) := + (others => '1'); + Sec_Prot(2047 downto 8) := + (others => '0'); + END IF; + ELSE + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(1535 downto 0) := + (others => '1'); + Sec_Prot(2047 downto 1536) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(2047 downto 512) := + (others => '1'); + Sec_Prot(511 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(2039 downto 0) := + (others => '1'); + Sec_Prot(2047 downto 2040) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(2047 downto 8) := + (others => '1'); + Sec_Prot(7 downto 0) := + (others => '0'); + END IF; + END IF; + + WHEN "110" => + IF (CMP = '0') THEN + IF (SEC = '0' AND TB = '0') THEN + Sec_Prot(2047 downto 1024) := (others => '1'); + Sec_Prot(1023 downto 0) := (others => '0'); + ELSIF (SEC = '0' AND TB = '1') THEN + Sec_Prot(1023 downto 0) := (others => '1'); + Sec_Prot(2047 downto 1024) := (others => '0'); + END IF; + ELSE + IF (SEC = '0' AND TB = '0') THEN + Sec_Prot(2047 downto 1024) := (others => '0'); + Sec_Prot(1023 downto 0) := (others => '1'); + ELSIF (SEC = '0' AND TB = '1') THEN + Sec_Prot(2047 downto 1024) := (others => '1'); + Sec_Prot(1023 downto 0) := (others => '0'); + END IF; + END IF; + + WHEN "111" => + IF (CMP = '0') THEN + Sec_Prot(2047 downto 0) := (others => '1'); + ELSE + Sec_Prot(2047 downto 0) := (others => '0'); + END IF; + WHEN OTHERS => + Sec_Prot := (OTHERS => '1'); + END CASE; -- end of CASE BP_bits + END IF; + END PROCESS Protect; + + HOLD_FRAME_ON_PO_ZD : PROCESS(SOut_zd, SIOut_zd, HOLDNegIn) + BEGIN + IF (HOLDNegIn = '0' AND QE /= '1') THEN + hold_mode := TRUE; + SIOut_z <= 'Z'; + SOut_z <= 'Z'; + ELSE + IF hold_mode THEN + SIOut_z <= SIOut_zd AFTER tpd_HOLDNeg_SO(trz0); + SOut_z <= SOut_zd AFTER tpd_HOLDNeg_SO(trz0); + hold_mode := FALSE; + ELSE + SIOut_z <= SIOut_zd; + SOut_z <= SOut_zd; + hold_mode := FALSE; + END IF; + END IF; + END PROCESS HOLD_FRAME_ON_PO_ZD; + + HOLD_PULL_UP : PROCESS(HOLDNegIn) + BEGIN + IF (QE = '0') THEN + IF (HOLDNegIn = 'Z') THEN + HOLDNeg_pullup <= '1'; + ELSE + HOLDNeg_pullup <= HOLDNegIn; + END IF; + END IF; + END PROCESS HOLD_PULL_UP; + + WP_PULL_UP : PROCESS(WPNegIn) + BEGIN + IF (QE = '0') THEN + IF (WPNegIn = 'Z') THEN + WPNeg_pullup <= '1'; + ELSE + WPNeg_pullup <= WPNegIn; + END IF; + END IF; + END PROCESS WP_PULL_UP; + + --------------------------------------------------------------------------- + ---- File Read Section - Preload Control + --------------------------------------------------------------------------- + + MemPreload: PROCESS + -- text file input variables + FILE mem_file : text is mem_file_name; + FILE screg_file : text is screg_file_name; + VARIABLE ind : NATURAL RANGE 0 TO AddrRANGE:= 0; + VARIABLE screg_ind: NATURAL RANGE 16#00# TO 16#2FF#:= 16#00#; + VARIABLE buf : line; + + BEGIN + -- memory preload + IF (mem_file_name (1 to 4)/= "none" AND UserPreload) THEN + ind := 0; + Mem := (OTHERS => MaxData); + WHILE (not ENDFILE (mem_file)) LOOP + READLINE (mem_file, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 7)); --address + ELSE + IF ind <= AddrRANGE THEN + Mem(ind) := h(buf(1 to 2)); + END IF; + IF ind < AddrRANGE THEN + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + ----------------------------------------------------------------------- + -- Security Register Preload + ----------------------------------------------------------------------- + + IF (screg_file_name(1 to 4) /= "none" AND UserPreload) THEN + ind := 0; + Security_Reg1 := (OTHERS => MaxData); + Security_Reg2 := (OTHERS => MaxData); + Security_Reg3 := (OTHERS => MaxData); + WHILE (not ENDFILE (screg_file)) LOOP + READLINE (screg_file, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + screg_ind := h(buf(2 to 4)); --address + ELSE + IF screg_ind <= 16#0FF# THEN + Security_Reg1(screg_ind) := h(buf(1 to 2)); + ELSIF screg_ind>=16#100# AND screg_ind<=16#1FF# THEN + Security_Reg2(screg_ind-16#100#) := h(buf(1 to 2)); + ELSIF screg_ind>=16#200# AND screg_ind<=16#2FF# THEN + Security_Reg3(screg_ind-16#200#) := h(buf(1 to 2)); + END IF; + IF (screg_ind mod 16#100#) < 16#FF# THEN + screg_ind := screg_ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + WAIT; + END PROCESS MemPreload; + + --------------------------------------------------------------------------- + -- Path Delay Section + --------------------------------------------------------------------------- + + S_Out_PathDelay_Gen : PROCESS(SOut_z) + + VARIABLE SO_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => SOut, + OutSignalName => "SO", + OutTemp => SOut_z, + GlitchData => SO_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_0), + PathCondition => SOut_z /= 'Z' AND NOT(read_id)), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_1), + PathCondition => SOut_z /= 'Z' AND read_id), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1'), + 3 => (InputChangeTime => HOLDNegIn'LAST_EVENT, + PathDelay => tpd_HOLDNeg_SO, + PathCondition => QE = '0') + ) + ); + END PROCESS; + + SI_Out_PathDelay : PROCESS(SIOut_z) + + VARIABLE SI_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => SIOut, + OutSignalName => "SI", + OutTemp => SIOut_z, + GlitchData => SI_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_0), + PathCondition => SIOut_z /= 'Z' AND NOT(read_id)), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_1), + PathCondition => SIOut_z /= 'Z' AND read_id), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND SIOut_zd = 'Z'), + 3 => (InputChangeTime => HOLDNegIn'LAST_EVENT, + PathDelay => tpd_HOLDNeg_SO, + PathCondition => SIOut_z /= 'Z' AND QE = '0') + ) + ); + END PROCESS; + + HOLD_Out_PathDelay : PROCESS(HOLDNegOut_zd) + + VARIABLE HOLD_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => HOLDNegOut, + OutSignalName => "HOLDNeg", + OutTemp => HOLDNegOut_zd, + GlitchData => HOLD_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_0), + PathCondition => HOLDNegOut_zd /= 'Z' --AND quad_read + AND QE = '1' AND NOT(read_id)), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_1), + PathCondition => HOLDNegOut_zd /= 'Z' --AND quad_read + AND QE = '1' AND read_id), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND --quad_read AND + HOLDNegOut_zd = 'Z' AND QE = '1') + ) + ); + END PROCESS; + + WP_Out_PathDelay : PROCESS(WPNegOut_zd) + + VARIABLE WP_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => WPNegOut, + OutSignalName => "WPNeg", + OutTemp => WPNegOut_zd, + GlitchData => WP_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_0), + PathCondition => WPNegOut_zd /= 'Z' --AND quad_read + AND QE = '1' AND NOT(read_id)), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_1), + PathCondition => WPNegOut_zd /= 'Z' -- AND quad_read + AND QE = '1' AND read_id), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND --quad_read AND + WPNegOut_zd = 'Z' AND QE = '1') + ) + ); + END PROCESS; + + END BLOCK behavior; +END vhdl_behavioral; \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl064k/model/s25fl064k_ver.ftm b/lib/models/memory/flash/serial/S25fl064k/model/s25fl064k_ver.ftm new file mode 100644 index 0000000..8f3facd --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064k/model/s25fl064k_ver.ftm @@ -0,0 +1,61 @@ + +FMF Timing for s25fl064k Parts + + +version: | author: | mod date: | changes made: + V1.0 R. Prokopovic 10 Aug 25 Initial release + +1ns +s25fl064k + +S25FL064KOSMFI000 Spansion, S25FL064K, Rev. 01,JUN.29,2010 +S25FL064KOSMFI001 Spansion, S25FL064K, Rev. 01,JUN.29,2010 +S25FL064KOSMFI003 Spansion, S25FL064K, Rev. 01,JUN.29,2010 +S25FL064KOSMFI010 Spansion, S25FL064K, Rev. 01,JUN.29,2010 +S25FL064KOSMFI011 Spansion, S25FL064K, Rev. 01,JUN.29,2010 +S25FL064KOSMFI013 Spansion, S25FL064K, Rev. 01,JUN.29,2010 +The values listed are for VCC=2.7V to 3.6V, +Industrial Ta=-40 to +85 Celsius + +(DELAY(ABSOLUTE + (COND ~read_id (IOPATH SCK SO (5:6:7) (5:6:7) () (5:6:7) () (5:6:7))) + (COND read_id (IOPATH SCK SO (5.5:7:8.5) (5.5:7:8.5) () (5.5:7:8.5) () (5.5:7:8.5))) + (COND CSNeg (IOPATH CSNeg SO () () (5:6:7) () (5:6:7) ())) + (COND ~quad_read (IOPATH HOLDNeg SO () () (8:10:12) (5:6:7) (8:10:12) (5:6:7))) + (COND dual_read || quad_read (IOPATH SCK SI (5:6:7) (5:6:7) () (5:6:7) () (5:6:7))) + (COND CSNeg && ~deg_sin (IOPATH CSNeg SI () () (5:6:7) () (5:6:7) ())) + (COND ~quad_read && dual_read (IOPATH HOLDNeg SI () () (8:10:12) (5:6:7) (8:10:12) (5:6:7))) + (COND quad_read (IOPATH SCK WPNeg (5:6:7) (5:6:7) () (5:6:7) () (5:6:7))) + (COND quad_read (IOPATH SCK HOLDNeg (5:6:7) (5:6:7) () (5:6:7) () (5:6:7))) + (COND CSNeg && QE (IOPATH CSNeg SI () () (5:6:7) () (5:6:7) ())) + (COND CSNeg && QE (IOPATH CSNeg WPNeg () () (5:6:7) () (5:6:7) ())) + (COND CSNeg && QE (IOPATH CSNeg HOLDNeg () () (5:6:7) () (5:6:7) ())) +)) +(TIMINGCHECK + (SETUP CSNeg (posedge SCK) (5)) + (SETUP SI (COND deg_sin(posedge SCK)) (2)) + (SETUP SO (COND quad_pg(posedge SCK)) (2)) + (SETUP WPNeg (COND quad_pg(posedge SCK)) (2)) + (SETUP HOLDNeg (COND quad_pg(posedge SCK)) (2)) + (SETUP HOLDNeg (COND hold_cond(posedge SCK)) (5)) + (SETUP WPNeg CSNeg (20)) + + (HOLD CSNeg SCK (5)) + (HOLD SI (COND deg_sin (posedge SCK)) (5)) + (HOLD SO (COND quad_pg (posedge SCK)) (5)) + (HOLD WPNeg (COND quad_pg (posedge SCK)) (5)) + (HOLD HOLDNeg (COND quad_pg (posedge SCK)) (5)) + (HOLD HOLDNeg (COND hold_cond(posedge SCK)) (5)) + (HOLD WPNeg (COND wr_prot (posedge CSNeg)) (100)) + + (WIDTH (COND rd_slow (posedge SCK)) (15.2)) + (WIDTH (COND rd_slow (negedge SCK)) (15.2)) + (WIDTH (COND rd_fast (posedge SCK)) (6.25)) + (WIDTH (COND rd_fast (negedge SCK)) (6.25)) + (WIDTH (COND any_read (posedge CSNeg)) (10)) + (WIDTH (COND pg_ers (posedge CSNeg)) (50)) + (PERIOD (COND rd_slow SCK) (30.4)) + (PERIOD (COND rd_fast SCK) (12.5)) +) + + \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl064k/model/s25fl064k_vhd.ftm b/lib/models/memory/flash/serial/S25fl064k/model/s25fl064k_vhd.ftm new file mode 100644 index 0000000..e6be6b6 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064k/model/s25fl064k_vhd.ftm @@ -0,0 +1,81 @@ + +FMF Timing for s25fl064k Parts + + +version: | author: | mod date: | changes made: + V1.0 R. Prokopovic 10 Sep 11 Initial release + +1ns +s25fl064k + +S25FL064KOSMFI000 Spansion, S25FL064K, Rev. 01,JUN.29,2010 +S25FL064KOSMFI001 Spansion, S25FL064K, Rev. 01,JUN.29,2010 +S25FL064KOSMFI003 Spansion, S25FL064K, Rev. 01,JUN.29,2010 +S25FL064KOSMFI010 Spansion, S25FL064K, Rev. 01,JUN.29,2010 +S25FL064KOSMFI011 Spansion, S25FL064K, Rev. 01,JUN.29,2010 +S25FL064KOSMFI013 Spansion, S25FL064K, Rev. 01,JUN.29,2010 +The values listed are for VCC=2.7V to 3.6V, +Industrial Ta=-40 to +85 Celsius + +(DELAY(ABSOLUTE + (COND RDID == 0 (IOPATH SCK SO (5:6:7) (5:6:7) () (5:6:7) () (5:6:7))) + (COND RDID == 1 (IOPATH SCK SO (5.5:7:8.5) (5.5:7:8.5) () (5.5:7:8.5) () (5.5:7:8.5))) + (IOPATH CSNeg SO () () (5:6:7) () (5:6:7) ()) + (IOPATH HOLDNeg SO () () (8:10:12) (5:6:7) (8:10:12) (5:6:7)) + )) + (TIMINGCHECK + (SETUP CSNeg SCK (5)) + (SETUP (COND normal SI) (posedge SCK) (2)) + (SETUP HOLDNeg SCK (5)) + (SETUP WPNeg CSNeg (20)) + + (HOLD CSNeg SCK (5)) + (HOLD (COND normal SI) (posedge SCK) (5)) + (HOLD HOLDNeg SCK (5)) + (HOLD WPNeg CSNeg (100)) + + (WIDTH (COND slow (posedge SCK)) (15.2)) + (WIDTH (COND slow (negedge SCK)) (15.2)) + (WIDTH (COND fast (posedge SCK)) (6.25)) + (WIDTH (COND fast (negedge SCK)) (6.25)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pger (posedge CSNeg)) (50)) + (PERIOD (COND slow SCK) (30.4)) + (PERIOD (COND fast SCK) (12.5)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP) (DELAY (ABSOLUTE (DEVICE(400000:700000:3000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BP1) (DELAY (ABSOLUTE (DEVICE(15000:30000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BP2) (DELAY (ABSOLUTE (DEVICE(1000:2500:12000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE) (DELAY (ABSOLUTE (DEVICE(10000000:30000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE1) (DELAY (ABSOLUTE (DEVICE(5e7:12e7:8e8) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE2) (DELAY (ABSOLUTE (DEVICE(5e7:15e7:1e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/CE) (DELAY (ABSOLUTE (DEVICE(5e9:15e9:30e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(10000:10000:10000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/DP) (DELAY (ABSOLUTE (DEVICE(3000:3000:3000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/RES1) (DELAY (ABSOLUTE (DEVICE(3000:3000:3000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/RES2) (DELAY (ABSOLUTE (DEVICE(1800:1800:1800) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/ERSSUSP) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PRGSUSP) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PRGRES) (DELAY (ABSOLUTE (DEVICE(200:200:200) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/ERSRES) (DELAY (ABSOLUTE (DEVICE(200:200:200) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WRR) (DELAY (ABSOLUTE(DEVICE(15000000:15000000:15000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SUSP_DLY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl064k/utilities/CreateSDF/mk_sdf.cmd b/lib/models/memory/flash/serial/S25fl064k/utilities/CreateSDF/mk_sdf.cmd new file mode 100644 index 0000000..f6d6cc7 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064k/utilities/CreateSDF/mk_sdf.cmd @@ -0,0 +1,10 @@ +SET sdffile_suffix .sdf +SET use_global_timing_dir false +SET timingfile_dir /user/USERNAME/CreateSDF +SET timingfile_suffix .ftm +SET time_scale 1ns +SET local_path . +SET vendor MODELSIM_HOME +SET diagnostics on +SET vhdl_file testbench.vhd +SET lwb false diff --git a/lib/models/memory/flash/serial/S25fl064k/utilities/CreateSDF/mk_sdf_204.pl b/lib/models/memory/flash/serial/S25fl064k/utilities/CreateSDF/mk_sdf_204.pl new file mode 100644 index 0000000..5f2f2b8 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064k/utilities/CreateSDF/mk_sdf_204.pl @@ -0,0 +1,462 @@ +#!/usr/local/bin/perl +# +# mk_sdf : Perl replacement for C mk_sdf +# +# Copyright (C) 2000, 1999 Free Model Foundry; http:/vhdl.org/fmf/ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# Author : R. Munden +# Date : 20001115 +# Version : 2.0.4 +# +# Revision history: +# 2.0: 19990702 +# o Intial release of perl version +# 2.0.1: 19990722 +# o fixed problem with . in path for TimingModels +# 2.0.2: 20000616 +# o changed instance search to work with Mentor +# 2.0.3: 20001115 +# o changed to parse ":" without leading space +# o fixed problem with . in path for TimingModels again +# 2.0.4: 20030405 +# o chaged SDF version to 3.0 +# +################################################################# +# +# command line arguments: + +# ARGV[0] - name of VHDL netlist + +# global variables: + +# %component_list - list of instance names by component name +# %instance_isin - list architectures by instances contained therein +# %instance_comp - list of component names by instance name +# %comp_lib - library each component (by name) is configured to +# @instance_list - array of all instance names in design in order found + +$version = "2.0.4"; +$design_name = ''; +$timing_dir = ''; +$diags = "off"; + +%keywords = (architecture => 1, + component => 1, + timingmodel => 1); + +# INPUT files +$CMD = "mk_sdf.cmd"; +$VHD = ''; # name of VHDL netlist + +# OUTPUT files +$RFV = "/tmp/short.vhd"; # reformatted VHDL +$sdf_file = ''; # name of SDF file + +&read_cmd_file; +&get_names; +&reformat; + +open INPUT, $RFV; +@lines = ; +close INPUT; + +$current_architecture = ""; + +foreach $line (@lines) +{ + @words = split / /, $line; + foreach $word (@words) + { + $keywords{$word} == "1" and do { &$word(@words);}; + if ($component_list{$word}) + { + $line =~ /(.+) : $word/ and do { + if ($1 !~ /for/) { # instantiation found + $component_list{$word} = $component_list{$word} . $1; + push (@instance_list, $1); + $instance_name = $1; + } + }; + $instance_comp{$1} = $word; + $instance_isin{$1} = $current_architecture; + if ( $diags ne off ) { + print "reading instance $instance_name: $word in $current_architecture\n"; + } + $line =~ /for all : $word use entity (.+)/ and do + { + @config = split(/\./, $1); + $comp_lib{$word} = $config[0];}; + } + } +} +if ( $diags ne off ) { + print "finished with netlist\n\n"; +} + +&begin_sdf; +&build_paths; +&close_sdf; +`rm $RFV`; + +print "$time\n"; + +sub architecture +{ + $current_architecture = $_[3]; + push (@architectures, $current_architecture); +} + +sub component +{ + if ($_[0] ne "end") + { + $name = $_[1]; + $arch_list{$current_architecture} = + $arch_list{$current_architecture} . " " . $name; + unless ($component_list{$name}) { $component_list{$name} = " ";} + } +} + +sub timingmodel +{ + $line =~ /timingmodel => \"(.+)\"/ and do { + $model = $1; + $model_name{$instance_name} = $model; + }; +} + +sub begin_sdf +{ + if ( $diags ne off ) { + print "writing SDF boilerplate\n"; + } + $time = localtime; + if (open(SDF, ">$sdf_file") !=1) { die "can't open $sdf_file\n";} + print "Opening $sdf_file\n"; + print SDF "(DELAYFILE\n"; + print SDF " (SDFVERSION \"3.0\")\n"; + print SDF " (DESIGN \"$design_name\")\n"; + print SDF " (DATE \"$time\")\n"; + print SDF " (VENDOR \"Free Model Foundry\")\n"; + print SDF " (PROGRAM \"SDF timing utility(tm)\")\n"; + print SDF " (VERSION \"$version\")\n"; + print SDF " (DIVIDER /)\n"; + print SDF " (VOLTAGE)\n"; + print SDF " (PROCESS)\n"; + print SDF " (TEMPERATURE)\n"; + print SDF " (TIMESCALE 1ns)\n"; +} + +sub build_paths +{ + foreach $instance_list (@instance_list) + { + @instance = $instance_list; + foreach $instance (@instance) + { + if ( $diags ne off ) { + print "working on $instance\n"; + } + if ($gtd =~ /true/i) { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; +# $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}./$timing_dir"; + } else { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; + } + $timing_file = "$path/$instance_comp{$instance}_vhd.ftm"; + $timing_file =~ s/\s//; + if ( $diags ne off ) { + print "$instance should be in $timing_file\n"; + } + if (-e $timing_file) { + if ($model_name{$instance} ne "") { + print SDF " (CELL\n"; + print SDF " (CELLTYPE \"$instance_comp{$instance}\")\n"; + $inst = $instance; + $full_inst = $instance; + while ($component_list{$instance_isin{$inst}}) { + $full_inst = "$component_list{$instance_isin{$inst}}/$full_inst"; + $full_inst =~ s/\s+//; + $inst = $component_list{$instance_isin{$inst}}; + $inst =~ s/\s+//; +# print SDF " (INSTANCE $component_list{$instance_isin{$instance}}/$instance)\n"; + } + print SDF " (INSTANCE $full_inst)\n"; + &add_timing; + } + } else { + if ( $diags ne off ) { + print "$timing_file not found!\n"; + } + } + } + } +} + +sub add_timing +{ + $timing_found = "false"; + $part_found = "false"; +# unless ($lib_path{$comp_lib{$instance_comp{$instance}}}) + unless ($timing_file) + { + print "path to $timing_file not found\n"; + exit; + } + if ($gtd =~ /true/i) { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; +# $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}./$timing_dir"; + } else { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; + } + $timing_file = "$path/$instance_comp{$instance}_vhd.ftm"; + if (open(TF, "<$timing_file") !=1) { warn "can't open $timing_file\n"; } + if ( $diags ne off ) { + print "reading $timing_file\n"; + } + $section_found = "false"; + while () + { + next unless (/$model_name{$instance}/i || ($part_found eq "true")); + $part_found = "true"; + if ( $diags ne off ) { + print "found entry for $model_name{$instance}\n"; + } + next unless (//i || ($timing_found eq "true")); + $timing_found = "true"; + next if (//i); + if (/<\/timing>/i) + { + print SDF " )\n"; + $timing_found = "false"; + $part_found = "false"; + $section_found = "true"; + last; + } else { + if (/%LABEL%/) + { + if ($component_list{$instance_isin{$instance}}) + { + $_ =~ s/%LABEL%/$component_list{$instance_isin{$instance}}\/$instance/; + } else { + $_ =~ s/%LABEL%/$instance/; + } + } + print SDF $_; + } + } + unless ($section_found eq "true") { + print "$model_name not found\n"; + } +} + +sub close_sdf +{ + print SDF ")\n"; + print "closing $sdf_file\n"; + close(SDF); +} + +# read mk_sdf.cmd + +sub read_cmd_file { + + if (open(CMD, $CMD) !=1) { die "can't open $CMD\n"; } + while () { + chop; + @fields = ''; + @fields = split; + unless ($fields[0] =~ /#/) { + if ($fields[0] =~ /SET/) { + if ($fields[1] =~ /vhdl_file/) {$VHD = $fields[2]} + if ($fields[1] =~ /sdffile_suffix/) {$suffix = $fields[2]} + if ($fields[1] =~ /use_global_timing_dir/) {$gtd = $fields[2]} + if ($fields[1] =~ /timingfile_dir/) {$timing_dir = $fields[2]} + if ($fields[1] =~ /vendor/) {$vendor = $fields[2]} + if ($fields[1] =~ /diagnostics/) {$diags = $fields[2]} + } + } + } + if ( $diags ne off ) { + print "\nmk_sdf diagnostics on\n\n"; + print "vhdl_file $VHD\n"; + print "sdffile_suffix $suffix\n"; + print "use_global_timing_dir $gtd\n"; + print "timingfile_dir $timing_dir\n"; + print "vendor $vendor\n\n"; + } +} +# + +# get name of netlist + +sub get_names +{ + + if ($ARGV[0] ne "") { $VHD = "$ARGV[0]"; } + + if ($ARGV[1] eq "") + { + @name = split(/\./,$VHD); + $design_name = $name[0]; + } else { + $design_name = "$ARGV[1]"; + } + $sdf_file = $design_name . $suffix; + if ($gtd =~ /false/i) + { + if ($vendor =~ /modeltech/i) { &read_mti; } + if ($vendor =~ /cadence/i) { &read_cds; } + } + if ( $diags ne off ) { + print "design name is $design_name\n\n"; + } +} +# +################################################################ +# + +# reformat netlist + +sub reformat +{ + $entfound = false; + + if (open(VHD, $VHD) !=1) { die "can't open $VHD\n"; } + if (open(OUT, ">$RFV") !=1) { die "can't open $OUT\n"; } + + while () { + if (/^--|library|package/i) { next } + if (/--/) { # strip embeded comments + @line = split("--"); + $_ = $line[0]; + } + s/:/ : /g; + s/;/ ;/g; + s/\s+/ /g; # reduces spaces and tabs + s/^\s//g; # no leading spaces + if (/entity/i) { + $entfound = "true"; + } + chomp; + if ( $entfound eq true ) { + print OUT lc($_); + if (/;|is|begin/i) { print OUT "\n"; } + } + } + + close OUT; + if ( $diags ne off ) { + print "reformatted netlist written to $RFV\n\n"; + } + +} + +# read ModelTech's modelsim.ini file + +sub read_mti +{ + $lib_found = "false"; + if ($ENV{MODELPATH}) + { + $ini_file = "$ENV{MODELPATH}/../modelsim.ini"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + if ($lib_found eq "true") + { + chomp; + if (/\[.+\]/) { last; } + s/\s+//; + @lib_line = split(/=/); + $lib_line[1] =~ s/\/work//; + $lib_path{$lib_line[0]} = $lib_line[1]; + } elsif (/\[Library\]/i) + { + $lib_found = "true"; + next; + } + } + } else { + print "\$MODELPATH environment variable not found\n"; + } + $lib_found = "false"; + if (-e "modelsim.ini") + { + $ini_file = "modelsim.ini"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + if ($lib_found eq "true") + { + chomp; + if (/\[.+\]/) { last; } + s/\s+//; + @lib_line = split(/=/); + $lib_line[1] =~ s/\/work//; + $lib_path{$lib_line[0]} = $lib_line[1]; + } elsif (/\[Library\]/i) + { + $lib_found = "true"; + next; + } + } + } else { + print "local modelsim.ini file not found, may not be needed\n"; + } +} + +# read Cadence's cds.lib file + +sub read_cds +{ + if ($ENV{CDS_VHDL}) + { + $ini_file = "$ENV{CDS_VHDL}/files/cds.lib"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + chomp; + s/\s+/ /; + if (/define/i) + { + @lib_line = split; + $lib_path{$lib_line[1]} = $lib_line[2]; + } + } + } else { + print "\$CDS_VHDL environment variable not found\n"; + } + if (-e "cds.lib") + { + $ini_file = "cds.lib"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + chomp; + s/\s+/ /; + if (/define/i) + { + @lib_line = split; + $lib_path{$lib_line[1]} = $lib_line[2]; + } + } + } else { + print "local cds.lib file not found, may not be needed\n"; + } +} diff --git a/lib/models/memory/flash/serial/S25fl064k/utilities/CreateSDF/my_mem_vhd.ftm b/lib/models/memory/flash/serial/S25fl064k/utilities/CreateSDF/my_mem_vhd.ftm new file mode 100644 index 0000000..2fc35c2 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064k/utilities/CreateSDF/my_mem_vhd.ftm @@ -0,0 +1,205 @@ + +FMF Timing for testbench Parts + + +version: | author: | mod date: | changes made: + V1.0 VHD2FTM 03 July 11 Initial release + +1ns +am29lv640m + +MY_MEM +AM29LV640MH90R +AM29LV640ML90R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (90:90:90) (90:90:90)) + (IOPATH A0 DQ1 (25:25:25) (25:25:25)) + (IOPATH CENeg DQ0 (85:85:85) (85:85:85) (11:11:11) (85:85:85) (11:11:11) (85:85:85)) + (IOPATH OENeg DQ0 (20:20:20) (20:20:20) (11:11:11) (20:20:20) (11:11:11) (20:20:20)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (90)) + (IOPATH WENeg RY (0) (90)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (90:90:90)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH101 +AM29LV640ML101 +AM29LV640MH101R +AM29LV640ML101R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (100:100:100) (100:100:100)) + (IOPATH A0 DQ1 (30:30:30) (30:30:30)) + (IOPATH CENeg DQ0 (95:95:95) (95:95:95) (11:11:11) (95:95:95) (11:11:11) (95:95:95)) + (IOPATH OENeg DQ0 (25:25:25) (25:25:25) (11:11:11) (25:25:25) (11:11:11) (25:25:25)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (100)) + (IOPATH WENeg RY (0) (100)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (100:100:100)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH112 +AM29LV640ML112 +AM29LV640MH112R +AM29LV640ML112R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (110:110:110) (110:110:110)) + (IOPATH A0 DQ1 (40:40:40) (40:40:40)) + (IOPATH CENeg DQ0 (105:105:105) (105:105:105) (11:11:11) (105:105:105) (11:11:11) (105:105:105)) + (IOPATH OENeg DQ0 (35:35:35) (35:35:35) (11:11:11) (35:35:35) (11:11:11) (35:35:35)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (110)) + (IOPATH WENeg RY (0) (110)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (110:110:110)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH120 +AM29LV640ML120 +AM29LV640MH120R +AM29LV640ML120R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (120:120:120) (120:120:120)) + (IOPATH A0 DQ1 (40:40:40) (40:40:40)) + (IOPATH CENeg DQ0 (115:115:115) (115:115:115) (11:11:11) (115:115:115) (11:11:11) (115:115:115)) + (IOPATH OENeg DQ0 (35:35:35) (35:35:35) (11:11:11) (35:35:35) (11:11:11) (35:35:35)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (120)) + (IOPATH WENeg RY (0) (120)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (120:120:120)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + diff --git a/lib/models/memory/flash/serial/S25fl064k/utilities/CreateSDF/testbench.sdf b/lib/models/memory/flash/serial/S25fl064k/utilities/CreateSDF/testbench.sdf new file mode 100644 index 0000000..02495dd --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064k/utilities/CreateSDF/testbench.sdf @@ -0,0 +1,58 @@ +(DELAYFILE + (SDFVERSION "3.0") + (DESIGN "testbench") + (DATE "Wed Jan 28 15:15:41 2004") + (VENDOR "Free Model Foundry") + (PROGRAM "SDF timing utility(tm)") + (VERSION "2.0.4") + (DIVIDER /) + (VOLTAGE) + (PROCESS) + (TEMPERATURE) + (TIMESCALE 1ns) + (CELL + (CELLTYPE "my_mem") + (INSTANCE dut) + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (90:90:90) (90:90:90)) + (IOPATH A0 DQ1 (25:25:25) (25:25:25)) + (IOPATH CENeg DQ0 (85:85:85) (85:85:85) (11:11:11) (85:85:85) (11:11:11) (85:85:85)) + (IOPATH OENeg DQ0 (20:20:20) (20:20:20) (11:11:11) (20:20:20) (11:11:11) (20:20:20)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (90)) + (IOPATH WENeg RY (0) (90)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (90:90:90)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + ) +) diff --git a/lib/models/memory/flash/serial/S25fl064k/utilities/CreateSDF/testbench.vhd b/lib/models/memory/flash/serial/S25fl064k/utilities/CreateSDF/testbench.vhd new file mode 100644 index 0000000..c7d852a --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064k/utilities/CreateSDF/testbench.vhd @@ -0,0 +1,1606 @@ +------------------------------------------------------------------------------ +-- File name : testbench_640.vhd +------------------------------------------------------------------------------- +-- Copyright (C) 2003 AMD. +-- +-- MODIFICATION HISTORY : +-- +-- version: | author: | mod date: | changes made: +-- V0.1 M.Marinkovic 11 July 03 Initial +-- v0.2 M.Marinkovic 28 Aug 03 Changed protected sector selection +-- +------------------------------------------------------------------------------- +-- PART DESCRIPTION: +-- +-- Description: +-- Generic test enviroment for verification of AMD flash memory +-- VITAL models.my_mem +-- +------------------------------------------------------------------------------- +-- Note: VHDL code formating not done +-- For High/Low sector protection selection change: +-- TimingModel constant and TimingModel generic value +-- +------------------------------------------------------------------------------- +LIBRARY IEEE; + USE IEEE.std_logic_1164.ALL; +--USE IEEE.VITAL_timing.ALL; +--USE IEEE.VITAL_primitives.ALL; + USE STD.textio.ALL; + +LIBRARY VITAL2000; + USE VITAL2000.vital_timing.ALL; + USE VITAL2000.vital_primitives.ALL; + +LIBRARY FMF; + USE FMF.gen_utils.ALL; + USE FMF.conversions.ALL; + + +LIBRARY work; + USE work.amd_tc_pkg.ALL; + +------------------------------------------------------------------------------- +-- ENTITY DECLARATION +------------------------------------------------------------------------------- +ENTITY testbench_640 IS +END testbench_640; + + +------------------------------------------------------------------------------- +-- ARCHITECTURE DECLARATION +------------------------------------------------------------------------------- +ARCHITECTURE vhdl_behavioral of testbench_640 IS + COMPONENT my_mem + GENERIC ( + -- tipd delays: interconnect path delays + tipd_A0 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A1 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A2 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A3 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A4 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A5 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A6 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A7 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A8 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A9 : VitalDelayType01 := VitalZeroDelay01; --address + tipd_A10 : VitalDelayType01 := VitalZeroDelay01; --lines + tipd_A11 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A12 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A13 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A14 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A15 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A16 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A17 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A18 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A19 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A20 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A21 : VitalDelayType01 := VitalZeroDelay01; -- + + tipd_DQ0 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ1 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ2 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ3 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ4 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ5 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ6 : VitalDelayType01 := VitalZeroDelay01; -- data + tipd_DQ7 : VitalDelayType01 := VitalZeroDelay01; -- lines + tipd_DQ8 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ9 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ10 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ11 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ12 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ13 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ14 : VitalDelayType01 := VitalZeroDelay01; -- + + tipd_DQ15 : VitalDelayType01 := VitalZeroDelay01; -- DQ15/A-1 + + tipd_CENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_OENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_RESETNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; --WP#/ACC + tipd_BYTENeg : VitalDelayType01 := VitalZeroDelay01; + + -- tpd delays + tpd_A0_DQ0 : VitalDelayType01 := UnitDelay01;--tACC + tpd_A0_DQ1 : VitalDelayType01 := UnitDelay01;--tPACC + tpd_CENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(tCE,tCE,tDF,-,tDF,-) + tpd_OENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(tOE,tOE,tDF,-,tDF,-) + tpd_RESETNeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(-,-,0,-,0,-) + tpd_CENeg_RY : VitalDelayType01 := UnitDelay01; --tBUSY + tpd_WENeg_RY : VitalDelayType01 := UnitDelay01; --tBUSY + + --tsetup values + tsetup_A0_CENeg : VitalDelayType := UnitDelay; --tAS edge \ + tsetup_A0_OENeg : VitalDelayType := UnitDelay; --tASO edge \ + tsetup_DQ0_CENeg : VitalDelayType := UnitDelay; --tDS edge / + + --thold values + thold_CENeg_RESETNeg: VitalDelayType := UnitDelay; --tRH edge / + thold_OENeg_WENeg : VitalDelayType := UnitDelay; --tOEH edge / + thold_A0_CENeg : VitalDelayType := UnitDelay; --tAH edge \ + thold_A0_OENeg : VitalDelayType := UnitDelay; --tAHT edge \ + thold_DQ0_CENeg : VitalDelayType := UnitDelay; --tDH edge / + thold_WENeg_OENeg : VitalDelayType := UnitDelay; --tGHWL edge / + + --tpw values: pulse width + tpw_RESETNeg_negedge: VitalDelayType := UnitDelay; --tRP + tpw_OENeg_posedge : VitalDelayType := UnitDelay; --tOEPH + tpw_WENeg_negedge : VitalDelayType := UnitDelay; --tWP + tpw_WENeg_posedge : VitalDelayType := UnitDelay; --tWPH + tpw_CENeg_negedge : VitalDelayType := UnitDelay; --tCP + tpw_CENeg_posedge : VitalDelayType := UnitDelay; --tCEPH + tpw_A0_negedge : VitalDelayType := UnitDelay; --tWC tRC + + + -- tdevice values: values for internal delays + --Effective Write Buffer Program Operation tWHWH1 + tdevice_WBPB : VitalDelayType := 11 us; + --Program Operation + tdevice_POB : VitalDelayType := 100 us; + --Sector Erase Operation tWHWH2 + tdevice_SEO : VitalDelayType := 500 ms; + --Timing Limit Exceeded + tdevice_HANG : VitalDelayType := 400 ms; --? + --program/erase suspend timeout + tdevice_START_T1 : VitalDelayType := 5 us; + --sector erase command sequence timeout + tdevice_CTMOUT : VitalDelayType := 50 us; + --device ready after Hardware reset(during embeded algorithm) + tdevice_READY : VitalDelayType := 20 us; --tReady + + -- generic control parameters + InstancePath : STRING := DefaultInstancePath; + TimingChecksOn : BOOLEAN := DefaultTimingChecks; + MsgOn : BOOLEAN := DefaultMsgOn; + XOn : BOOLEAN := DefaultXon; + -- memory file to be loaded + mem_file_name : STRING ;--:= "am29lv640m.mem"; + prot_file_name : STRING ;--:= "am29lv640m_prot.mem"; + secsi_file_name : STRING ;--:= "am29lv_secsi.mem"; + + UserPreload : BOOLEAN ;--:= TRUE; + LongTimming : BOOLEAN ;--:= TRUE; + + -- For FMF SDF technology file usage + TimingModel : STRING --:= "AM29LV640MH90R" + ); + PORT ( + A21 : IN std_logic := 'U'; -- + A20 : IN std_logic := 'U'; -- + A19 : IN std_logic := 'U'; -- + A18 : IN std_logic := 'U'; -- + A17 : IN std_logic := 'U'; -- + A16 : IN std_logic := 'U'; -- + A15 : IN std_logic := 'U'; -- + A14 : IN std_logic := 'U'; -- + A13 : IN std_logic := 'U'; --address + A12 : IN std_logic := 'U'; --lines + A11 : IN std_logic := 'U'; -- + A10 : IN std_logic := 'U'; -- + A9 : IN std_logic := 'U'; -- + A8 : IN std_logic := 'U'; -- + A7 : IN std_logic := 'U'; -- + A6 : IN std_logic := 'U'; -- + A5 : IN std_logic := 'U'; -- + A4 : IN std_logic := 'U'; -- + A3 : IN std_logic := 'U'; -- + A2 : IN std_logic := 'U'; -- + A1 : IN std_logic := 'U'; -- + A0 : IN std_logic := 'U'; -- + + DQ15 : INOUT std_logic := 'U'; -- DQ15/A-1 + DQ14 : INOUT std_logic := 'U'; -- + DQ13 : INOUT std_logic := 'U'; -- + DQ12 : INOUT std_logic := 'U'; -- + DQ11 : INOUT std_logic := 'U'; -- + DQ10 : INOUT std_logic := 'U'; -- + DQ9 : INOUT std_logic := 'U'; -- data + DQ8 : INOUT std_logic := 'U'; -- lines + DQ7 : INOUT std_logic := 'U'; -- + DQ6 : INOUT std_logic := 'U'; -- + DQ5 : INOUT std_logic := 'U'; -- + DQ4 : INOUT std_logic := 'U'; -- + DQ3 : INOUT std_logic := 'U'; -- + DQ2 : INOUT std_logic := 'U'; -- + DQ1 : INOUT std_logic := 'U'; -- + DQ0 : INOUT std_logic := 'U'; -- + + CENeg : IN std_logic := 'U'; + OENeg : IN std_logic := 'U'; + WENeg : IN std_logic := 'U'; + RESETNeg : IN std_logic := 'U'; + WPNeg : IN std_logic := 'U'; --WP#/ACC + BYTENeg : IN std_logic := 'U'; + RY : OUT std_logic := 'U' --RY/BY# + ); + END COMPONENT; + + FOR ALL: my_mem USE ENTITY WORK.my_mem(VHDL_BEHAVIORAL); + + --------------------------------------------------------------------------- + --memory configuration + --------------------------------------------------------------------------- + CONSTANT MaxData : NATURAL := 16#FF#; --255; + CONSTANT SecSize : NATURAL := 16#FFFF#; --65535 + CONSTANT SecSiSize : NATURAL := 255; + CONSTANT SecNum : NATURAL := 127; + CONSTANT HiAddrBit : NATURAL := 21; + --Address of the Protected Sector +-- CONSTANT ProtSecNum : NATURAL := SecNum; + + --------------------------------------------------------------------------- + --model configuration + --------------------------------------------------------------------------- + CONSTANT mem_file : STRING := "am29lv640m.mem"; + CONSTANT prot_file : STRING := "am29lv640m_prot.mem"; + CONSTANT secsi_file : STRING := "am29lv_secsi.mem"; + + CONSTANT UserPreload : boolean := TRUE; + CONSTANT DebugInfo : boolean := FALSE; + CONSTANT LongTimming : boolean := TRUE; + CONSTANT TimingModel : STRING := "MY_MEM"; + -- "AM29LV640MH90R";--High sect prot. + -- "AM29LV128ML93R";--Low sect. prot. + --------------------------------------------------------------------------- + SIGNAL ProtSecNum : NATURAL := SecNum ; + + --Flash Memory Array + TYPE SecType IS ARRAY (0 TO SecSize) OF + INTEGER RANGE -1 TO MaxData; + TYPE MemArray IS ARRAY (0 TO SecNum) OF + SecType; + + --Common Flash Interface Query codes + TYPE CFItype IS ARRAY (16#10# TO 16#50#) OF + NATURAL RANGE 0 TO 16#FF#; + + --SecSi Sector + TYPE SecSiType IS ARRAY ( 0 TO SecSiSize) OF + INTEGER RANGE -1 TO MaxData; + + --------------------------------------------------------------------------- + -- memory declaration + --------------------------------------------------------------------------- + -- -- Mem(SecAddr)(Address).... + SHARED VARIABLE Mem : MemArray := (OTHERS => (OTHERS=> MaxData)); + SHARED VARIABLE CFI_array : CFItype :=(OTHERS=>0); + SHARED VARIABLE SecSi : SecSiType :=(OTHERS=>0); + + --command sequence + SHARED VARIABLE cmd_seq : cmd_seq_type; + + SIGNAL status : status_type := none; + SIGNAL sts_check : std_logic_vector(7 downto 0); + + + SIGNAL check_err : std_logic := '0'; + SIGNAL ErrorInTest : std_logic := '0'; -- + ---------------------------------------------------------------------------- + --Personality module: + -- + -- instanciates the DUT module and adapts generic test signals to it + -- TBD: block port + ---------------------------------------------------------------------------- + --DUT port + SIGNAL T_DQ : std_logic_vector(15 downto 0) := (OTHERS=>'U'); + SIGNAL T_A : std_logic_vector(HiAddrBit downto 0) := (OTHERS=>'U'); + SIGNAL T_RESETNeg : std_logic := 'U'; + SIGNAL T_CENeg : std_logic := 'U'; + SIGNAL T_WENeg : std_logic := 'U'; + SIGNAL T_OENeg : std_logic := 'U'; + SIGNAL T_WPNeg : std_logic := 'U'; + SIGNAL T_BYTENeg : std_logic := 'U'; + SIGNAL T_RY : std_logic := 'U'; + + --------------------------------------------------------------------------- + -- + --------------------------------------------------------------------------- + --SecSi ProtectionStatus + SHARED VARIABLE FactoryProt : std_logic := '1'; + --Sector Protection Status + SHARED VARIABLE Sec_Prot : std_logic_vector (SecNum downto 0) := + (OTHERS => '0'); + SHARED VARIABLE Sect : NATURAL RANGE 0 TO SecNum := 0; + SHARED VARIABLE Addr : NATURAL RANGE 0 TO SecSize := 0; + SHARED VARIABLE WriteData : NATURAL RANGE 0 TO MaxData := 0; + + + --CONSTANT + --timming parameters + CONSTANT RESETNeg_pw : time := 500 ns; --tRP + + SIGNAL pwron : std_logic := '0'; + + SIGNAL Tseries : NATURAL; + SIGNAL Tcase : NATURAL; + + SHARED VARIABLE ts_cnt : NATURAL RANGE 1 TO 30:=1; -- testseries counter + SHARED VARIABLE tc_cnt : NATURAL RANGE 0 TO 10:=0; -- testcase counter + + + BEGIN + DUT : my_mem + GENERIC MAP ( + -- tipd delays: interconnect path delays + tipd_A0 => VitalZeroDelay01, -- + tipd_A1 => VitalZeroDelay01, -- + tipd_A2 => VitalZeroDelay01, -- + tipd_A3 => VitalZeroDelay01, -- + tipd_A4 => VitalZeroDelay01, -- + tipd_A5 => VitalZeroDelay01, -- + tipd_A6 => VitalZeroDelay01, -- + tipd_A7 => VitalZeroDelay01, -- + tipd_A8 => VitalZeroDelay01, -- + tipd_A9 => VitalZeroDelay01, --address + tipd_A10 => VitalZeroDelay01, --lines + tipd_A11 => VitalZeroDelay01, -- + tipd_A12 => VitalZeroDelay01, -- + tipd_A13 => VitalZeroDelay01, -- + tipd_A14 => VitalZeroDelay01, -- + tipd_A15 => VitalZeroDelay01, -- + tipd_A16 => VitalZeroDelay01, -- + tipd_A17 => VitalZeroDelay01, -- + tipd_A18 => VitalZeroDelay01, -- + tipd_A19 => VitalZeroDelay01, -- + tipd_A20 => VitalZeroDelay01, -- + tipd_A21 => VitalZeroDelay01, -- + + tipd_DQ0 => VitalZeroDelay01, -- + tipd_DQ1 => VitalZeroDelay01, -- + tipd_DQ2 => VitalZeroDelay01, -- + tipd_DQ3 => VitalZeroDelay01, -- + tipd_DQ4 => VitalZeroDelay01, -- + tipd_DQ5 => VitalZeroDelay01, -- + tipd_DQ6 => VitalZeroDelay01, -- data + tipd_DQ7 => VitalZeroDelay01, -- lines + tipd_DQ8 => VitalZeroDelay01, -- + tipd_DQ9 => VitalZeroDelay01, -- + tipd_DQ10 => VitalZeroDelay01, -- + tipd_DQ11 => VitalZeroDelay01, -- + tipd_DQ12 => VitalZeroDelay01, -- + tipd_DQ13 => VitalZeroDelay01, -- + tipd_DQ14 => VitalZeroDelay01, -- + + tipd_DQ15 => VitalZeroDelay01, -- DQ15/A-1 + + tipd_CENeg => VitalZeroDelay01, + tipd_OENeg => VitalZeroDelay01, + tipd_WENeg => VitalZeroDelay01, + tipd_RESETNeg => VitalZeroDelay01, + tipd_WPNeg => VitalZeroDelay01,--WP#/ACC + tipd_BYTENeg => VitalZeroDelay01, + + -- tpd delays + tpd_A0_DQ0 => UnitDelay01,--tACC + tpd_A0_DQ1 => UnitDelay01,--tPACC + tpd_CENeg_DQ0 => UnitDelay01Z, + --(tCE,tCE,tDF,-,tDF + tpd_OENeg_DQ0 => UnitDelay01Z, + --(tOE,tOE,tDF,-,tDF + tpd_RESETNeg_DQ0 => UnitDelay01Z, + --(-,-,0,-,0,-) + tpd_CENeg_RY => UnitDelay01, --tBUSY + tpd_WENeg_RY => UnitDelay01, --tBUSY + + --tsetup values + tsetup_A0_CENeg => UnitDelay, --tAS edge \ + tsetup_A0_OENeg => UnitDelay, --tASO edge \ + tsetup_DQ0_CENeg => UnitDelay, --tDS edge / + + --thold values + thold_CENeg_RESETNeg=> UnitDelay, --tRH edge / + thold_OENeg_WENeg => UnitDelay, --tOEH edge / + thold_A0_CENeg => UnitDelay, --tAH edge \ + thold_A0_OENeg => UnitDelay, --tAHT edge \ + thold_DQ0_CENeg => UnitDelay, --tDH edge / + thold_WENeg_OENeg => UnitDelay, --tGHVL edge / + + --tpw values: pulse width + tpw_RESETNeg_negedge=> UnitDelay, --tRP + tpw_OENeg_posedge => UnitDelay, --tOEPH + tpw_WENeg_negedge => UnitDelay, --tWP + tpw_WENeg_posedge => UnitDelay, --tWPH + tpw_CENeg_negedge => UnitDelay, --tCP + tpw_CENeg_posedge => UnitDelay, --tCEPH + tpw_A0_negedge => UnitDelay, --tWC tRC + -- tdevice values: values for internal delays + --Effective Write Buffer Program Operation tWHWH1 + tdevice_WBPB => 11 us, + --Program Operation + tdevice_POB => 100 us, + --Sector Erase Operation tWHWH2 + tdevice_SEO => 500 ms, + --Timing Limit Exceeded + tdevice_HANG => 400 ms, --? + --program/erase suspend timeout + tdevice_START_T1 => 5 us, + --sector erase command sequence timeout + tdevice_CTMOUT => 50 us, + --device ready after Hardware reset(during embeded algorithm) + tdevice_READY => 20 us, --tReady + + -- generic control parameters + InstancePath => DefaultInstancePath, + TimingChecksOn => TRUE,--DefaultTimingChecks, + MsgOn => DefaultMsgOn, + XOn => DefaultXon, + -- memory file to be loaded + mem_file_name => mem_file, + prot_file_name => prot_file , + secsi_file_name => secsi_file, + + UserPreload => UserPreload, + LongTimming => LongTimming, + -- For FMF SDF technology file usage + TimingModel => "AM29LV640MH90R" -- TimingModel + ) + PORT MAP( + A21 => T_A(21), -- + A20 => T_A(20), -- + A19 => T_A(19), -- + A18 => T_A(18), -- + A17 => T_A(17), -- + A16 => T_A(16), -- + A15 => T_A(15), -- + A14 => T_A(14), -- + A13 => T_A(13), --address + A12 => T_A(12), --lines + A11 => T_A(11), -- + A10 => T_A(10), -- + A9 => T_A(9), -- + A8 => T_A(8), -- + A7 => T_A(7), -- + A6 => T_A(6), -- + A5 => T_A(5),-- + A4 => T_A(4),-- + A3 => T_A(3), -- + A2 => T_A(2), -- + A1 => T_A(1), -- + A0 => T_A(0), -- + + DQ15 => T_DQ(15), -- DQ15/A-1 + DQ14 => T_DQ(14), -- + DQ13 => T_DQ(13), -- + DQ12 => T_DQ(12), -- + DQ11 => T_DQ(11), -- + DQ10 => T_DQ(10), -- + DQ9 => T_DQ(9), -- data + DQ8 => T_DQ(8), -- lines + DQ7 => T_DQ(7), -- + DQ6 => T_DQ(6), -- + DQ5 => T_DQ(5), -- + DQ4 => T_DQ(4), -- + DQ3 => T_DQ(3), -- + DQ2 => T_DQ(2), -- + DQ1 => T_DQ(1), -- + DQ0 => T_DQ(0), -- + + CENeg => T_CENeg, + OENeg => T_OENeg, + WENeg => T_WENeg, + RESETNeg => T_RESETNeg, + WPNeg => T_WPNeg, --WP#/ACC + BYTENeg => T_BYTENeg, + RY => T_RY --RY/BY# + ); + + --------------------------------------------------------------------------- + --protected sector + --------------------------------------------------------------------------- + ProtSecNum <= SecNum WHEN TimingModel(11) = 'H' ELSE + 0 ;-- WHEN TimingModel = "AM29LV128ML93R" + + pwron <= '0', '1' after 1 ns; + +--At the end of the simulation, if ErrorInTest='0' there were no errors +err_ctrl : PROCESS ( check_err ) + BEGIN + IF check_err = '1' THEN + ErrorInTest <= '1'; + END IF; + END PROCESS err_ctrl; + +tb :PROCESS + + -------------------------------------------------------------------------- + --= PROCEDURE to select TC + -- can be modified to read TC list from file, or to generate random list + -------------------------------------------------------------------------- + PROCEDURE Pick_TC + (Model : IN STRING := "AM29LV640MH90R" ) + IS + BEGIN + IF TC_cnt < tc(TS_cnt) THEN + TC_cnt := TC_cnt+1; + ELSE + TC_cnt:=1; + IF TS_cnt<30 THEN + TS_cnt := TS_cnt+1; + ELSE + -- end test + IF ErrorInTest='0' THEN + REPORT "Test Ended without errors" + SEVERITY note; + ELSE + REPORT "There were errors in test" + SEVERITY note; + END IF; + WAIT; + END IF; + END IF; + END PROCEDURE Pick_TC; + + --------------------------------------------------------------------------- + --bus commands, device specific implementation + --------------------------------------------------------------------------- + TYPE bus_type IS (bus_idle, + bus_standby, --CE# deasseretd, others are don't care + bus_enable, --CE# asserted, others deasserted + bus_output_disable, + bus_reset, + bus_write, + bus_read); + + --bus drive for specific command sequence cycle + PROCEDURE bus_cycle( + bus_cmd :IN bus_type := bus_idle; + byte :IN boolean ; + data :IN INTEGER RANGE -2 TO MaxData := -2; -- -1 for all Z + dataHi :IN INTEGER RANGE -2 TO MaxData := -2; -- -2 for ignore + sector :IN INTEGER RANGE -1 TO SecNum := -1; -- -1 for ignore addr + address :IN NATURAL RANGE 0 TO SecSize := 0; + disable :IN boolean := false; + violate :IN boolean := false; + tm :IN TIME := 10 ns) + IS + + VARIABLE tmp : std_logic_vector(15 downto 0); + BEGIN + + IF data=-1 THEN -- HiZ + T_DQ(7 downto 0) <= (OTHERS => 'Z'); + END IF; + + IF (NOT byte)THEN --word access + IF dataHi=-1 THEN -- HiZ + T_DQ(15 downto 8) <= (OTHERS => 'Z'); + END IF; + T_BYTENeg <= '1'; + ELSE --byte access + T_BYTENeg <= '0'; + T_DQ(14 downto 8) <= (OTHERS => 'Z'); + END IF; + + IF sector > -1 THEN + T_A(HiAddrBit downto 15) <= to_slv(sector, HiAddrbit-14); + tmp := to_slv(address, 16); + IF byte THEN + T_A(14 downto 0) <= tmp(15 downto 1); + T_DQ(15) <= tmp(0); + ELSE + T_A(14 downto 0) <= tmp(14 downto 0); + END IF; + + END IF; + + wait for 1 ns; + + CASE bus_cmd IS + WHEN bus_output_disable => + T_OENeg <= '1'; + WAIT FOR 20 ns; + + WHEN bus_idle => + T_RESETNeg <= '1'; + T_WENeg <= '1'; + T_CENeg <= '1'; + T_OENeg <= '1'; + IF disable THEN + T_WPNeg <= '0'; + ELSE + T_WPNeg <= '1'; + END IF; + WAIT FOR 30 ns; + + WHEN bus_standby => + T_CENeg <= '1'; + WAIT FOR 30 ns; + + WHEN bus_reset => + T_RESETNeg <= '0', '1' AFTER tm ; + -- WAIT FOR 500 ns should follow this bus cmd for reset to + --complete + WAIT FOR 30 ns; + + WHEN bus_enable => + T_WENeg <= '1' AFTER 50 ns; --- + T_CENeg <= '0' AFTER 50 ns; --- + T_OENeg <= '1' AFTER 30 ns; --- + + WAIT FOR tm ; + + WHEN bus_write => + T_OENeg <= '1' ;-- AFTER 5 ns; + T_CENeg <= '0' AFTER 10 ns ; + T_WENeg <= '0' AFTER 20 ns; + + IF data>-1 THEN + T_DQ(7 downto 0) <= to_slv(data,8); + END IF; + IF NOT byte THEN + IF dataHi>-1 THEN + T_DQ(15 downto 8) <= to_slv(dataHi,8); + END IF; + END IF; + + IF violate THEN + T_WENeg <= '1'; + WAIT FOR 50 ns; + T_WENeg <= '0', '1' AFTER tm; + WAIT FOR 50 ns; + ELSE + WAIT FOR 100 ns; + END IF; + + WHEN bus_read => + + T_CENeg <= '0' ; + T_WENeg <= '1'AFTER 10 ns; + IF NOT disable THEN + T_OENeg <= '0' AFTER 15 ns; + ELSE + T_OENeg <= '1'; + END IF; + + IF NOT byte THEN + T_DQ(15 downto 8) <= (OTHERS => 'Z'); + END IF; + T_DQ(7 downto 0) <= (OTHERS => 'Z'); + + WAIT FOR 100 ns; + + -- T_OENeg <= '1' ; ----------- + + END CASE; + + + END PROCEDURE; + + + --------------------------------------------------------------------------- + --procedure to decode commands into specific bus command sequence + --------------------------------------------------------------------------- + PROCEDURE cmd_dc + ( command : IN cmd_rec ) + IS + VARIABLE D_hi : NATURAL ;--RANGE 0 to MaxData; + VARIABLE D_lo : NATURAL RANGE 0 to MaxData; + VARIABLE Addr : NATURAL RANGE 0 to SecSize :=0; + VARIABLE Addrfix : NATURAL RANGE 0 to SecSize/2:=0; + VARIABLE Sect : INTEGER RANGE -1 to SecNum :=0; + VARIABLE slv_1, slv_2 : std_logic_vector(7 downto 0); + VARIABLE byte : boolean; + VARIABLE i : NATURAL; + BEGIN + CASE command.cmd IS + WHEN idle => + bus_cycle(bus_cmd => bus_idle, + byte => command.byte, + disable => command.aux=disable); + + WHEN h_reset => + bus_cycle(bus_cmd => bus_reset, + byte => command.byte, + tm => command.wtime); + + WHEN rd => + bus_cycle(bus_cmd => bus_enable, + byte => command.byte, + data => -1, + sector => command.sect, + address => command.addr, + tm => 90 ns); + + bus_cycle(bus_cmd => bus_read, + byte => command.byte, + data => -1, + dataHi => -1, + sector => command.sect, + address => command.addr, + disable => command.aux=disable); + + bus_cycle(bus_cmd => bus_output_disable, + byte => command.byte); + + WHEN rd_page => + bus_cycle(bus_cmd => bus_enable, + byte => command.byte, + data => -1, + sector => 0, + address => 0, + tm => 90 ns); + + Addr := command.addr; + Sect := command.sect; + byte := command.byte; + ---- 08July---- + WAIT FOR 10 ns; + -------------- + i := 0; + WHILE i < command.d_hi LOOP + + IF command.wtime > 0 ns THEN + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + --byte toggle mode + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + byte := false; + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + Addrfix := Addr /2; + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + --word read; + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addrfix); + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + byte := true; + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 30 ns); + + --first byte read + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addr); + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + i := i +3; + wait for 10 ns; ------- + ELSE + byte := command.byte; + END IF; + --second byte read in byte toggle mode + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addr); + + + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + i := i +1; + WAIT FOR 10 ns; + END LOOP; + bus_cycle(bus_cmd => bus_output_disable, + byte => command.byte); + + + + WHEN w_cycle => + + D_lo := 16#AA# ; --first command data + Addr := 16#AAA#; --first command byte address + D_hi := 16#55#; --second command data + Addrfix := 16#555#; --second command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + Addrfix := 16#2AA#; --second command byte address + END IF; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_lo, + dataHi => 0, + sector => 0, + address => Addr, + violate => command.aux=violate, + tm => command.wtime); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_hi, + dataHi => 0, + sector => 0, + address => Addrfix); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_reset | w_prog | w_erase | w_unlock | + w_autoselect | w_enter_sec => + Addr := 16#AAA#; + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + + CASE command.cmd IS + WHEN w_reset => + d_lo := 16#F0#; + WHEN w_prog => + d_lo := 16#A0#; + WHEN w_erase => + d_lo := 16#80#; + WHEN w_unlock => + d_lo := 16#20#; + WHEN w_autoselect => + d_lo := 16#90#; + WHEN w_enter_sec => + d_lo := 16#88#; + WHEN OTHERS => + d_lo := 0; + END CASE; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => d_lo, + dataHi => 0, + sector => 0, + address => Addr); + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + + WHEN w_unlock_reset => + Addr := 16#AAA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#90#, + dataHi => 0, + sector => 0, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#F0#, + dataHi => 0, + sector => 0, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + WHEN w_chip_ers => + Addr := 16#AAA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#10#, + dataHi => 0, + sector => 0, + Address => Addr); + FOR i IN 0 TO SecNum LOOP + IF Sec_Prot(i)/='1' THEN + mem(i) := (OTHERS=>16#FF#); + END IF; + END LOOP; + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_cfi => + Addr := 16#AA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#55#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#98#, + dataHi => 0, + sector => 0, + Address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + + WHEN w_suspend => + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#B0#, + dataHi => 0, + sector => -1); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + WHEN w_resume => + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#30#, + dataHi => 0, + sector => -1); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_data => + + D_hi := command.d_hi MOD 16#100#; + D_lo := command.d_lo ; + Addr := command.addr; + Sect := command.sect; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_lo, + dataHi => D_hi, + sector => Sect, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + IF NOT command.byte THEN + Addr := Addr*2; + END IF; + + --write value(s) in default mem + IF status = erase_active AND Sec_Prot(Sect)/='1'THEN + --sector should be erased + mem(Sect) := (OTHERS=>16#FF#); + + ELSIF status = erase_na AND Sec_Prot(Sect)/='1'THEN + --sector erase terminated = data integrity violated + mem(Sect) := (OTHERS=>-1); + + ELSIF status = readX AND Sec_Prot(Sect)/='1' THEN + mem(Sect)(Addr) := -1; + IF NOT command.byte THEN + mem(Sect)(Addr+1) := -1; + END IF; + + -- Write to Secure Silicon Sector Region + ELSIF status = rd_SecSi AND FactoryProt/='1' THEN + slv_1 := to_slv(d_lo,8); + IF SecSi(Addr)>-1 THEN + slv_2 := to_slv(SecSi(Addr),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + SecSi(Addr) := to_nat(slv_1); + IF NOT command.byte THEN + slv_1 := to_slv(d_hi,8); + IF SecSi(Addr+1)>-1 THEN + slv_2 := to_slv(SecSi(Addr+1),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + SecSi(Addr+1) := to_nat(slv_1); + END IF; + + ELSIF status=buff_wr_busy THEN + --Write to Buffer command cycle + null; + + ELSIF status=erase_na THEN + --sector erase command sequence violation + null; + + -- Write to Flash Memory Array + ELSIF status /= err AND Sec_Prot(Sect)/='1'THEN + slv_1 := to_slv(d_lo,8); + IF mem(Sect)(Addr)>-1 THEN + slv_2 := to_slv(mem(Sect)(Addr),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + mem(Sect)(Addr) := to_nat(slv_1); + IF NOT command.byte THEN + slv_1 := to_slv(d_hi,8); + IF mem(Sect)(Addr+1)>-1 THEN + slv_2 := to_slv(mem(Sect)(Addr+1),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + mem(Sect)(Addr+1) := to_nat(slv_1); + END IF; + END IF; + + + WHEN wt => + WAIT FOR command.wtime; + + WHEN wt_rdy => + IF T_RY/='1' THEN + WAIT UNTIL rising_edge(T_RY) FOR command.wtime; + END IF; + + WHEN wt_bsy => + IF T_RY='1' THEN + WAIT UNTIL falling_edge(T_RY) FOR command.wtime; + END IF; + + WHEN OTHERS => null; + END CASE; + END PROCEDURE; + + + VARIABLE cmd_cnt : NATURAL; + VARIABLE command : cmd_rec; -- + +BEGIN + Pick_TC (Model => "AM29LV640MH90R" ); + + Tseries <= ts_cnt ; + Tcase <= tc_cnt ; + + Generate_TC + (Model => "AM29LV640MH90R" , + Series => ts_cnt, + TestCase => tc_cnt, + command_seq => cmd_seq); + + + cmd_cnt := 1; + WHILE cmd_seq(cmd_cnt).cmd/=done LOOP + command:= cmd_seq(cmd_cnt); + IF command.sect = -1 THEN + command.sect := ProtSecNum; + END IF; + status <= command.status; + sts_check<= to_slv(command.d_lo,8); --used only for toggle/status check + cmd_dc(command); + cmd_cnt :=cmd_cnt +1; + + END LOOP; + +END PROCESS tb; + +--process to monitor WP# +PROCESS(T_WPNeg) +VARIABLE reg : std_logic; +BEGIN + IF falling_edge(T_WPNeg) THEN + reg := Sec_Prot(ProtSecNum); + Sec_Prot(ProtSecNum) := '1'; + ELSIF rising_edge(T_WPNeg) THEN + Sec_Prot(ProtSecNum) := reg; + END IF; +END PROCESS; + +-------------------------------------------------------------------------------- +-- Checker process, +-- Bus transition extractor: when bus cycle is read samples addr and data +-- Transition checker : verifies correct read data using default memory +-------------------------------------------------------------------------------- +checker: PROCESS + VARIABLE RAddr : NATURAL; + VARIABLE RSect : NATURAL; + VARIABLE longread : boolean; + VARIABLE shortread : boolean; + VARIABLE toggle : boolean:=false; + VARIABLE toggle_sts : std_logic_vector(7 downto 0); + +BEGIN +-- Transition extractor + IF (T_CENeg='0'AND T_OENeg='0'AND T_WENeg='1') THEN + IF T_BYTENeg='1' THEN + RAddr := to_nat(T_A(14 downto 0)&'0'); + ELSE + RAddr := to_nat(T_A(14 downto 0)&T_DQ(15)); + END IF; + RSect := to_nat(T_A(HiAddrBit downto 15)); + + shortread:= false; + longread := false; + + --DUT specific timing + IF (T_CENeg'EVENT OR T_WENeg'EVENT OR T_A(HiAddrBit downto 2)'EVENT)AND -- + (status=read OR status=rd_cfi OR status=rd_secsi) THEN --OR status=readX) + longread := true; + CASE TimingModel IS + WHEN "AM29LV640MH90R" | + "AM29LV640ML90R" => WAIT FOR 95 ns; +-- WHEN "AM29LV640MH101" | +-- "AM29LV640ML101" => WAIT FOR 105 ns; +-- WHEN "AM29LV640MH101R" | +-- "AM29LV640ML101R" => WAIT FOR 105 ns; +-- WHEN "AM29LV640MH112" | +-- "AM29LV640ML112" => WAIT FOR 115 ns; +-- WHEN "AM29LV640MH112R" | +-- "AM29LV640ML112R" => WAIT FOR 115 ns; +-- WHEN "AM29LV640MH120" | +-- "AM29LV640ML120" => WAIT FOR 125 ns; +-- WHEN "AM29LV640MH120R" | +-- "AM29LV640ML120R" => WAIT FOR 125 ns; + WHEN OTHERS => + REPORT "Timing model NOT supported : "&TimingModel + SEVERITY error; + END CASE; + + ELSIF T_A(1 downto 0)'EVENT OR + (T_DQ(15)'EVENT AND T_BYTENeg='0')OR + (T_BYTENeg'EVENT) OR + T_OENeg'EVENT OR + (status/=read AND status/=rd_cfi AND + status/=rd_secsi) THEN --AND status/=readX) + shortread:=true; + CASE TimingModel IS + WHEN "AM29LV640MH90R" | + "AM29LV640ML90R" => WAIT FOR 30 ns; +-- WHEN "AM29LV640MH101" | +-- "AM29LV640ML101" => WAIT FOR 40 ns; +-- WHEN "AM29LV640MH101R" | +-- "AM29LV640ML101R" => WAIT FOR 40 ns; +-- WHEN "AM29LV640MH112" | +-- "AM29LV640ML112" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH112R" | +-- "AM29LV640ML112R" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH120" | +-- "AM29LV640ML120" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH120R" | +-- "AM29LV640ML120R" => WAIT FOR 45 ns; + WHEN OTHERS => + REPORT "Timing model NOT supported : "&TimingModel + SEVERITY error; + END CASE; + + END IF; + + + + --Checker + IF longread OR shortread THEN + + CASE status IS + WHEN none => + toggle := false; + + -- read memory array data + WHEN read => + toggle := false; + Check_read ( + DQ => T_DQ, + D_lo => mem(RSect)(RAddr), + D_hi => mem(RSect)(RAddr+1), + Byte => T_BYTENeg, + check_err=> check_err); + + -- read secure silicon region + WHEN rd_secsi => + toggle := false; + Check_SecSi ( + DQ => T_DQ, + D_lo => SecSi(RAddr), + D_hi => SecSi(RAddr+1), + Byte => T_BYTENeg, + check_err=>check_err); + + + --read CFI query codes + WHEN rd_cfi => + RAddr := to_nat(T_A(14 downto 0)); --x16 addressing + toggle := false; + Check_CFI ( + DQ => T_DQ, + D_lo => CFI_array(RAddr) , + D_hi => 0 , + Byte => T_BYTENeg, + check_err=>check_err); + + + + -- read Autoselect codes + WHEN rd_AS => + RAddr := to_nat(T_A(14 downto 0)); --x16 addressing + toggle := false; + Check_AS ( + DQ => T_DQ, + addr => RAddr, + ProtSecNum=>ProtSecNum, + secProt => Sec_Prot(RSect), + FactoryProt=>FactoryProt , + Byte => T_BYTENeg, + AS_E => to_slv(16#0C#,8), + AS_F => to_slv(1,8), + + check_err=>check_err); + + + WHEN rd_HiZ => + toggle:=false; + Check_Z ( + DQ => T_DQ, + check_err=>check_err); + + + + WHEN readX => + toggle:=false; + Check_X ( + DQ => T_DQ, + check_err=>check_err); + + + WHEN erase_na | erase_active => + IF toggle THEN + Check_Erase ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN ers_susp_e => + IF toggle THEN + Check_Ers_Susp ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + +-- + + WHEN ers_susp_prog_na | ers_susp_prog => + IF toggle THEN + Check_Ers_Susp_Prog ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + +-- + + WHEN prog_na | prog_active => + IF toggle THEN + Check_Progr ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN buff_wr_busy | buff_wr_N_busy => + IF toggle THEN + Check_Buff_Busy ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN buff_abort => + IF toggle THEN + Check_Abort ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + WHEN OTHERS => null; + END CASE; + + -- get firs data for toggle check + CASE status IS + WHEN prog_active | prog_na | + erase_active | erase_na | + ers_susp_e | + ers_susp_prog | ers_susp_prog_na | + buff_wr_busy | buff_wr_N_busy | + buff_abort | get_toggle => + + IF (NOT toggle) OR (status=get_toggle) THEN + toggle:=true; + toggle_sts := T_DQ(7 downto 0); + END IF; + + WHEN OTHERS => null; + END CASE; + + + END IF; + + END IF; + + WAIT ON T_A, T_CENeg, T_OENeg, T_WENeg, T_DQ(15), T_BYTENeg; + +END PROCESS checker; + + +default: PROCESS + -- text file input variables + FILE mem_f : text is mem_file; + FILE prot_f : text is prot_file; + FILE secsi_f : text is secsi_file; + + VARIABLE S_ind : NATURAL RANGE 0 TO SecNum:= 0; + VARIABLE ind : NATURAL RANGE 0 TO SecSize:= 0; + VARIABLE buf : line; + +BEGIN + --Preload Control + ----------------------------------------------------------------------- + -- File Read Section + ----------------------------------------------------------------------- + IF UserPreload THEN + --- Sector protection preload + IF (prot_file /= "none" ) THEN + ind := 0; + FactoryProt := '0'; + Sec_Prot := (OTHERS => '0'); + WHILE (not ENDFILE (prot_f)) LOOP + READLINE (prot_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 3)); --address + ELSE + IF ind > SecNum THEN + --SecSi Factory protect preload + IF buf(1)='1' THEN + FactoryProt := '1'; + END IF; + ELSE + -- Standard Sector prload + IF buf(1)='1' THEN + Sec_Prot(ind):= '1'; + END IF; + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + -- Secure Silicon Sector Region preload + IF (SecSi_file /= "none" ) THEN + SecSi := (OTHERS => MaxData); + ind := 0; + WHILE (not ENDFILE (SecSi_f)) LOOP + READLINE (SecSi_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 3)); --address + ELSE + IF ind <= SecSiSize THEN + SecSi(ind) := h(buf(1 TO 2)); + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + --- Memory Preload + IF (mem_file /= "none" ) THEN + ind := 0; + Mem := (OTHERS => (OTHERS => MaxData)); + -- load sector 0 + WHILE (not ENDFILE (mem_f)) LOOP + READLINE (mem_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 5)); --address + ELSE + IF ind <= SecSize THEN + Mem(0)(ind) := h(buf(1 to 2)); + ind := ind + 1; + END IF; + END IF; + END LOOP; + -- load other sectors + FOR i IN 1 TO SecNum LOOP + Mem(i) := Mem(0); + END LOOP; + END IF; + + END IF; + ----------------------------------------------------------------------- + --CFI array data / AM29LV640MH90R !!! DEVICE SPECIFIC + ----------------------------------------------------------------------- + --CFI query identification string + -- !!!!!! WORD ADDRESSES (x16) - for x8 addressing double addr + --CFI query identification string + CFI_array(16#10#) := 16#51#; + CFI_array(16#11#) := 16#52#; + CFI_array(16#12#) := 16#59#; + CFI_array(16#13#) := 16#02#; + CFI_array(16#14#) := 16#00#; + CFI_array(16#15#) := 16#40#; + CFI_array(16#16#) := 16#00#; + CFI_array(16#17#) := 16#00#; + CFI_array(16#18#) := 16#00#; + CFI_array(16#19#) := 16#00#; + CFI_array(16#1A#) := 16#00#; + --system interface string + CFI_array(16#1B#) := 16#27#; + CFI_array(16#1C#) := 16#36#; + CFI_array(16#1D#) := 16#00#; + CFI_array(16#1E#) := 16#00#; + CFI_array(16#1F#) := 16#07#; + CFI_array(16#20#) := 16#07#; + CFI_array(16#21#) := 16#0A#; + CFI_array(16#22#) := 16#00#; + CFI_array(16#23#) := 16#01#; + CFI_array(16#24#) := 16#05#; + CFI_array(16#25#) := 16#04#; + CFI_array(16#26#) := 16#00#; + --device geometry definition + CFI_array(16#27#) := 16#17#; + CFI_array(16#28#) := 16#02#; + CFI_array(16#29#) := 16#00#; + CFI_array(16#2A#) := 16#05#; + CFI_array(16#2B#) := 16#00#; + CFI_array(16#2C#) := 16#01#; + CFI_array(16#2D#) := 16#7F#; + CFI_array(16#2E#) := 16#00#; + CFI_array(16#2F#) := 16#00#; + CFI_array(16#30#) := 16#01#; + CFI_array(16#31#) := 16#00#; + CFI_array(16#32#) := 16#00#; + CFI_array(16#33#) := 16#00#; + CFI_array(16#34#) := 16#00#; + CFI_array(16#35#) := 16#00#; + CFI_array(16#36#) := 16#00#; + CFI_array(16#37#) := 16#00#; + CFI_array(16#38#) := 16#00#; + CFI_array(16#39#) := 16#00#; + CFI_array(16#3A#) := 16#00#; + CFI_array(16#3B#) := 16#00#; + CFI_array(16#3C#) := 16#00#; + --primary vendor-specific extended query + CFI_array(16#40#) := 16#50#; + CFI_array(16#41#) := 16#52#; + CFI_array(16#42#) := 16#49#; + CFI_array(16#43#) := 16#31#; + CFI_array(16#44#) := 16#33#; + CFI_array(16#45#) := 16#08#; + CFI_array(16#46#) := 16#02#; + CFI_array(16#47#) := 16#01#; + CFI_array(16#48#) := 16#01#; + CFI_array(16#49#) := 16#04#; + CFI_array(16#4A#) := 16#00#; + CFI_array(16#4B#) := 16#00#; + CFI_array(16#4C#) := 16#01#; + CFI_array(16#4D#) := 16#B5#; + CFI_array(16#4E#) := 16#C5#; + IF TimingModel(11) = 'L' THEN + CFI_array(16#4F#) := 16#04#; + ELSE + CFI_array(16#4F#) := 16#05#; --uniform sectors top protect + END IF; + CFI_array(16#50#) := 16#01#; + + WAIT; + +END PROCESS default; + + + +END vhdl_behavioral; + diff --git a/lib/models/memory/flash/serial/S25fl064k/utilities/conversions.vhd b/lib/models/memory/flash/serial/S25fl064k/utilities/conversions.vhd new file mode 100644 index 0000000..e5fc0d6 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064k/utilities/conversions.vhd @@ -0,0 +1,1035 @@ +-------------------------------------------------------------------------------- +-- File Name: conversions_p.vhd +-------------------------------------------------------------------------------- +-- Copyright (C) 1997, 1998, 2001 Free Model Foundry; http://eda.org/fmf/ +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License version 2 as +-- published by the Free Software Foundation. +-- +-- This package was written by SEVA Technologies, Inc. and donated to the FMF. +-- www.seva.com +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 R. Steele 97 DEC 05 Added header and formatting to SEVA file +-- V1.1 R. Munden 98 NOV 28 Corrected some comments +-- Corrected function b +-- V1.2 R. Munden 01 MAY 27 Corrected function to_nat for weak values +-- and combined into a single file +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; + +-------------------------------------------------------------------------------- +-- CONVERSION FUNCTION SELECTION TABLES +-------------------------------------------------------------------------------- +-- +-- FROM TO: std_logic_vector std_logic natural time string +-- -----------------|---------------|---------|---------|---------|----------- +-- std_logic_vector | N/A | N/A | to_nat | combine | see below +-- std_logic | N/A | N/A | to_nat | combine | see below +-- natural | to_slv | to_sl | N/A | to_time | see below +-- time | N/A | N/A | to_nat | N/A | to_time_str +-- hex string | h | N/A | h | combine | N/A +-- decimal string | d | N/A | d | combine | N/A +-- octal string | o | N/A | o | combine | N/A +-- binary string | b | N/A | b | combine | N/A +-- -----------------|---------------|---------|---------|---------|----------- +-- +-- FROM TO: hex string decimal string octal string binary string +-- -----------------|------------|-------------|------------|---------------- +-- std_logic_vector | to_hex_str | to_int_str | to_oct_str | to_bin_str +-- std_logic | N/A | N/A | N/A | to_bin_str +-- natural | to_hex_str | to_int_str | to_oct_str | to_bin_str +-- -----------------|------------|-------------|------------|---------------- +-- +-------------------------------------------------------------------------------- + +PACKAGE conversions IS + + ---------------------------------------------------------------------------- + -- the conversions in this package are not guaranteed to be synthesizable. + -- + -- others functions available + -- fill creates a variable length string of the fill character + -- + -- + -- + -- input parameters of type natural or integer can be in the form: + -- normal -> 8, 99, 4_237 + -- base#value# -> 2#0101#, 16#fa4C#, 8#6_734# + -- with exponents(x10) -> 8e4, 16#2e#E4 + -- + -- input parameters of type string can be in the form: + -- "99", "4_237", "0101", "1010_1010" + -- + -- for bit/bit_vector <-> std_logic/std_logic_vector conversions use + -- package std_logic_1164 + -- to_bit(std_logic) + -- to_bitvector(std_logic_vector) + -- to_stdlogic(bit) + -- to_stdlogicvector(bit_vector) + -- + -- for "synthesizable" signed/unsigned/std_logic_vector/integer + -- conversions use + -- package std_logic_arith + -- conv_integer(signed/unsigned) + -- conv_unsigned(integer/signed,size) + -- conv_signed(integer/unsigned,size) + -- conv_std_logic_vector(integer/signed/unsigned,size) + -- + -- for "synthesizable" std_logic_vector -> integer conversions use + -- package std_logic_unsigned/std_logic_signed + -- + -- conv_integer(std_logic_vector) + -- + -- type1'(expression of type2) + -- + -- most conversions have 4 parmeters: + -- x : value to be converted + -- rtn_len : size of the return value + -- justify : justify value 'left' or 'right', default is right + -- basespec : print the base of the value - 'yes'/'no', default is yes + -- + -- Typical ways to call these functions: + -- simple, all defaults used + -- to_bin_str(x) + -- x will be converted to a string of minimum size with a + -- base specification appended for clarity + -- if x is 10101 then return is b"10101" + -- + -- to control size of return string + -- to_hex_str(x, + -- 6) + -- length of string returned will be 6 characters + -- value will be right justified in the field + -- if x is 10101 then return is ....h"15" + -- where '.' represents a blank + -- if 'rtn_len' parm defaults or is set to 0 then + -- return string will always be minimum size + -- + -- to left justify and suppress base specification + -- to_int_str(x, + -- 6, + -- justify => left, + -- basespec => yes) + -- length of return string will be 6 characters + -- the base specification will be suppressed + -- if x is 10101 then return is 21.... + -- where '.' represents a blank + -- + -- other usage notes + -- + -- if rtn_len less than or equal to x'length then ignore + -- rtn_len and return string of x'length + -- the 'justify' parm is effectively ignored in this case + -- + -- if rtn_len greater than x'length then return string + -- of rtn_len with blanks based on 'justify' parm + -- + -- these routines do not handle negative numbers + ---------------------------------------------------------------------------- + + type justify_side is (left, right); + type b_spec is (no , yes); + + -- std_logic_vector to binary string + function to_bin_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- std_logic to binary string + function to_bin_str(x : std_logic; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to binary string + function to_bin_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to hex string + function to_hex_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to hex string + function to_hex_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to octal string + function to_oct_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to octal string + function to_oct_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- natural to integer string + function to_int_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to integer string + function to_int_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- time to string + function to_time_str (x : time) + return string; + + -- add characters to a string + function fill (fill_char : character := '*'; + rtn_len : integer := 1) + return string; + -- usage: + -- fill + -- returns * + -- fill(' ',10) + -- returns .......... when '.' represents a blank + -- fill(lf) or fill(ht) + -- returns line feed character or tab character respectively + + -- std_logic_vector to natural + function to_nat (x : std_logic_vector) + return natural; + + -- std_logic to natural + function to_nat (x : std_logic) + return natural; + + -- time to natural + function to_nat (x : time) + return natural; + + -- hex string to std_logic_vector + function h (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or a,A to f,F + -- or x,X,z,Z,u,U,-,w,W, result will be 0 + + -- decimal string to std_logic_vector + function d (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- octal string to std_logic_vector + function o (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 7 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- binary string to std_logic_vector + function b (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 1 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- hex string to natural + function h (x : string) + return natural; + -- if x is other than characters 0 to 9 or a,A to f,F, result will be 0 + + -- decimal string to natural + function d (x : string) + return natural; + -- if x is other than characters 0 to 9, result will be 0 + + -- octal string to natural + function o (x : string) + return natural; + -- if x is other than characters 0 to 7, result will be 0 + + -- binary string to natural + function b (x : string) + return natural; + -- if x is other than characters 0 to 1, result will be 0 + + -- natural to std_logic_vector + function to_slv (x : natural; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than sizeof(x), result will be truncated on the left + -- see note above regarding possible formats for x + + -- natural to std_logic + function to_sl (x : natural) + return std_logic; + + -- natural to time + function to_time (x : natural) + return time; + -- see note above regarding possible formats for x + +END conversions; +-- +-------------------------------------------------------------------------------- +-- + +PACKAGE BODY conversions IS + + -- private declarations for this package + type basetype is (binary, octal, decimal, hex); + + function max(x,y: integer) return integer is + begin + if x > y then return x; else return y; end if; + end max; + + function min(x,y: integer) return integer is + begin + if x < y then return x; else return y; end if; + end min; + + -- consider function sizeof for string/slv/???, return natural + + -- function size(len: natural) return natural is + -- begin + -- if len=0 then + -- return 31; + -- else return len; + -- end if; + -- end size; + + function nextmultof (x : positive; + size : positive) return positive is + begin + case x mod size is + when 0 => return size * x/size; + when others => return size * (x/size + 1); + end case; + end nextmultof; + + function rtn_base (base : basetype) return character is + begin + case base is + when binary => return 'b'; + when octal => return 'o'; + when decimal => return 'd'; + when hex => return 'h'; + end case; + end rtn_base; + + function format (r : string; + base : basetype; + rtn_len : natural ; + justify : justify_side; + basespec : b_spec) return string is + variable int_rtn_len : integer; + begin + if basespec=yes then + int_rtn_len := rtn_len - 3; + else + int_rtn_len := rtn_len; + end if; + if int_rtn_len <= r'length then + case basespec is + when no => return r ; + when yes => return rtn_base(base) & '"' & r & '"'; + end case; + else + case justify is + when left => + case basespec is + when no => + return r & fill(' ',int_rtn_len - r'length); + when yes => + return rtn_base(base) & '"' & r & '"' & + fill(' ',int_rtn_len - r'length); + end case; + when right => + case basespec is + when no => + return fill(' ',int_rtn_len - r'length) & r ; + when yes => + return fill(' ',int_rtn_len - r'length) & + rtn_base(base) & '"' & r & '"'; + end case; + end case; + end if; + end format; + + -- convert numeric string of any base to natural + function cnvt_base (x : string; + inbase : natural range 2 to 16) return natural is + -- assumes x is an unsigned number string of base 'inbase' + -- values larger than natural'high are not supported + variable r,t : natural := 0; + variable place : positive := 1; + begin + for i in x'reverse_range loop + case x(i) is + when '0' => t := 0; + when '1' => t := 1; + when '2' => t := 2; + when '3' => t := 3; + when '4' => t := 4; + when '5' => t := 5; + when '6' => t := 6; + when '7' => t := 7; + when '8' => t := 8; + when '9' => t := 9; + when 'a'|'A' => t := 10; + when 'b'|'B' => t := 11; + when 'c'|'C' => t := 12; + when 'd'|'D' => t := 13; + when 'e'|'E' => t := 14; + when 'f'|'F' => t := 15; + when '_' => t := 0; -- ignore these characters + place := place / inbase; + when others => + assert false + report lf & + "CNVT_BASE found input value larger than base: " & lf & + "Input value: " & x(i) & + " Base: " & to_int_str(inbase) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + if t / inbase > 1 then -- invalid value for base + assert false + report lf & + "CNVT_BASE found input value larger than base: " & lf & + "Input value: " & x(i) & + " Base: " & to_int_str(inbase) & lf & + "converting input to integer 0" + severity warning; + return 0; + else + r := r + (t * place); + place := place * inbase; + end if; + end loop; + return r; + end cnvt_base; + + function extend (x : std_logic; + len : positive) return std_logic_vector is + variable v : std_logic_vector(1 to len) := (others => x); + begin + return v; + end extend; + + + -- implementation of public declarations + + function to_bin_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + + variable int : std_logic_vector(1 to x'length):=x; + variable r : string(1 to x'length):=(others=>'$'); + begin + for i in int'range loop + r(i to i) := to_bin_str(int(i),basespec=>no); + end loop; + return format (r,binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_bin_str(x : std_logic; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable r : string(1 to 1); + begin + case x is + when '0' => r(1) := '0'; + when '1' => r(1) := '1'; + when 'U' => r(1) := 'U'; + when 'X' => r(1) := 'X'; + when 'Z' => r(1) := 'Z'; + when 'W' => r(1) := 'W'; + when 'H' => r(1) := 'H'; + when 'L' => r(1) := 'L'; + when '-' => r(1) := '-'; + end case; + return format (r,binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_bin_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 2 to 32 := 32; + variable r : string(2 to 32):=(others=>'$'); + begin + if int = 0 then + return format ("0",binary,rtn_len,justify,basespec); + end if; + + while int > 0 loop + case int rem 2 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when others => + assert false report lf & "TO_BIN_STR, shouldn't happen" + severity failure; + return "$"; + null; + end case; + int := int / 2; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 32),binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_hex_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + -- will return x'length/4 + variable nxt : positive := nextmultof(x'length,4); + variable int : std_logic_vector(1 to nxt):= (others => '0'); + variable ptr : positive range 1 to (nxt/4)+1 := 1; + variable r : string(1 to nxt/4):=(others=>'$'); + subtype slv4 is std_logic_vector(1 to 4); + begin + int(nxt-x'length+1 to nxt) := x; + if nxt-x'length > 0 and x(x'left) /= '1' then + int(1 to nxt-x'length) := extend(x(x'left),nxt-x'length); + end if; + for i in int'range loop + next when i rem 4 /= 1; + case slv4'(int(i to i+3)) is + when "0000" => r(ptr) := '0'; + when "0001" => r(ptr) := '1'; + when "0010" => r(ptr) := '2'; + when "0011" => r(ptr) := '3'; + when "0100" => r(ptr) := '4'; + when "0101" => r(ptr) := '5'; + when "0110" => r(ptr) := '6'; + when "0111" => r(ptr) := '7'; + when "1000" => r(ptr) := '8'; + when "1001" => r(ptr) := '9'; + when "1010" => r(ptr) := 'A'; + when "1011" => r(ptr) := 'B'; + when "1100" => r(ptr) := 'C'; + when "1101" => r(ptr) := 'D'; + when "1110" => r(ptr) := 'E'; + when "1111" => r(ptr) := 'F'; + when "ZZZZ" => r(ptr) := 'Z'; + when "WWWW" => r(ptr) := 'W'; + when "LLLL" => r(ptr) := 'L'; + when "HHHH" => r(ptr) := 'H'; + when "UUUU" => r(ptr) := 'U'; + when "XXXX" => r(ptr) := 'X'; + when "----" => r(ptr) := '-'; + when others => + assert false + report lf & + "TO_HEX_STR found illegal value: " & + to_bin_str(int(i to i+3)) & lf & + "converting input to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr + 1; + end loop; + return format (r,hex,rtn_len,justify,basespec); + end to_hex_str; + + function to_hex_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 20 := 20; + variable r : string(1 to 20):=(others=>'$'); + begin + if x=0 then return format ("0",hex,rtn_len,justify,basespec); end if; + while int > 0 loop + case int rem 16 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when 8 => r(ptr) := '8'; + when 9 => r(ptr) := '9'; + when 10 => r(ptr) := 'A'; + when 11 => r(ptr) := 'B'; + when 12 => r(ptr) := 'C'; + when 13 => r(ptr) := 'D'; + when 14 => r(ptr) := 'E'; + when 15 => r(ptr) := 'F'; + when others => + assert false report lf & "TO_HEX_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 16; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 20),hex,rtn_len,justify,basespec); + end to_hex_str; + + function to_oct_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + -- will return x'length/3 + variable nxt : positive := nextmultof(x'length,3); + variable int : std_logic_vector(1 to nxt):= (others => '0'); + variable ptr : positive range 1 to (nxt/3)+1 := 1; + variable r : string(1 to nxt/3):=(others=>'$'); + subtype slv3 is std_logic_vector(1 to 3); + begin + int(nxt-x'length+1 to nxt) := x; + if nxt-x'length > 0 and x(x'left) /= '1' then + int(1 to nxt-x'length) := extend(x(x'left),nxt-x'length); + end if; + for i in int'range loop + next when i rem 3 /= 1; + case slv3'(int(i to i+2)) is + when "000" => r(ptr) := '0'; + when "001" => r(ptr) := '1'; + when "010" => r(ptr) := '2'; + when "011" => r(ptr) := '3'; + when "100" => r(ptr) := '4'; + when "101" => r(ptr) := '5'; + when "110" => r(ptr) := '6'; + when "111" => r(ptr) := '7'; + when "ZZZ" => r(ptr) := 'Z'; + when "WWW" => r(ptr) := 'W'; + when "LLL" => r(ptr) := 'L'; + when "HHH" => r(ptr) := 'H'; + when "UUU" => r(ptr) := 'U'; + when "XXX" => r(ptr) := 'X'; + when "---" => r(ptr) := '-'; + when others => + assert false + report lf & + "TO_OCT_STR found illegal value: " & + to_bin_str(int(i to i+2)) & lf & + "converting input to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr + 1; + end loop; + return format (r,octal,rtn_len,justify,basespec); + end to_oct_str; + + function to_oct_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 20 := 20; + variable r : string(1 to 20):=(others=>'$'); + begin + if x=0 then return format ("0",octal,rtn_len,justify,basespec); end if; + while int > 0 loop + case int rem 8 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when others => + assert false report lf & "TO_OCT_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 8; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 20),octal,rtn_len,justify,basespec); + end to_oct_str; + + function to_int_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 32 := 32; + variable r : string(1 to 32):=(others=>'$'); + begin + if x=0 then return format ("0",hex,rtn_len,justify,basespec); + else + while int > 0 loop + case int rem 10 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when 8 => r(ptr) := '8'; + when 9 => r(ptr) := '9'; + when others => + assert false report lf & "TO_INT_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 10; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 32),decimal,rtn_len,justify,basespec); + end if; + end to_int_str; + + function to_int_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string is + begin + return to_int_str(to_nat(x),rtn_len,justify,basespec); + end to_int_str; + + + function to_time_str (x : time) + return string is + begin + return to_int_str(to_nat(x),basespec=>no) & " ns"; + end to_time_str; + + function fill (fill_char : character := '*'; + rtn_len : integer := 1) + return string is + variable r : string(1 to max(rtn_len,1)) := (others => fill_char); + variable len : integer; + begin + if rtn_len < 2 then -- always returns at least 1 fill char + len := 1; + else + len := rtn_len; + end if; + return r(1 to len); + end fill; + + function to_nat(x : std_logic_vector) return natural is + -- assumes x is an unsigned number, lsb on right, + -- more than 31 bits are truncated on left + variable t : std_logic_vector(1 to x'length) := x; + variable int : std_logic_vector(1 to 31) := (others => '0'); + variable r : natural := 0; + variable place : positive := 1; + begin + if x'length < 32 then + int(max(32-x'length,1) to 31) := t(1 to x'length); + else -- x'length >= 32 + int(1 to 31) := t(x'length-30 to x'length); + end if; + for i in int'reverse_range loop + case int(i) is + when '1' | 'H' => r := r + place; + when '0' | 'L' => null; + when others => + assert false + report lf & + "TO_NAT found illegal value: " & to_bin_str(int(i)) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + exit when i=1; + place := place * 2; + end loop; + return r; + end to_nat; + + function to_nat (x : std_logic) + return natural is + begin + case x is + when '0' => return 0 ; + when '1' => return 1 ; + when others => + assert false + report lf & + "TO_NAT found illegal value: " & to_bin_str(x) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + end to_nat; + + function to_nat (x : time) + return natural is + begin + return x / 1 ns; + end to_nat; + + function h(x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or a,A to f,F or + -- x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length*4,rtn_len); + variable ptr : integer range -3 to size := size; + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr-3 to ptr) := "0000"; + when '1' => r(ptr-3 to ptr) := "0001"; + when '2' => r(ptr-3 to ptr) := "0010"; + when '3' => r(ptr-3 to ptr) := "0011"; + when '4' => r(ptr-3 to ptr) := "0100"; + when '5' => r(ptr-3 to ptr) := "0101"; + when '6' => r(ptr-3 to ptr) := "0110"; + when '7' => r(ptr-3 to ptr) := "0111"; + when '8' => r(ptr-3 to ptr) := "1000"; + when '9' => r(ptr-3 to ptr) := "1001"; + when 'a'|'A' => r(ptr-3 to ptr) := "1010"; + when 'b'|'B' => r(ptr-3 to ptr) := "1011"; + when 'c'|'C' => r(ptr-3 to ptr) := "1100"; + when 'd'|'D' => r(ptr-3 to ptr) := "1101"; + when 'e'|'E' => r(ptr-3 to ptr) := "1110"; + when 'f'|'F' => r(ptr-3 to ptr) := "1111"; + when 'U' => r(ptr-3 to ptr) := "UUUU"; + when 'X' => r(ptr-3 to ptr) := "XXXX"; + when 'Z' => r(ptr-3 to ptr) := "ZZZZ"; + when 'W' => r(ptr-3 to ptr) := "WWWW"; + when 'H' => r(ptr-3 to ptr) := "HHHH"; + when 'L' => r(ptr-3 to ptr) := "LLLL"; + when '-' => r(ptr-3 to ptr) := "----"; + when '_' => ptr := ptr + 4; + when others => + assert false + report lf & + "O conversion found illegal input character: " & + int(i) & lf & "converting character to '----'" + severity warning; + r(ptr-3 to ptr) := "----"; + end case; + ptr := ptr - 4; + end loop; + return r(size-rtn_len+1 to size); + end h; + + function d (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than binary length of x, result will be truncated on + -- the left + -- if x is other than characters 0 to 9, result will be 0 + begin + return to_slv(cnvt_base(x,10),rtn_len); + end d; + + function o (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length*3, result will be truncated on the left + -- if x is other than characters 0 to 7 or or x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length*3,rtn_len); + variable ptr : integer range -2 to size := size; + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr-2 to ptr) := "000"; + when '1' => r(ptr-2 to ptr) := "001"; + when '2' => r(ptr-2 to ptr) := "010"; + when '3' => r(ptr-2 to ptr) := "011"; + when '4' => r(ptr-2 to ptr) := "100"; + when '5' => r(ptr-2 to ptr) := "101"; + when '6' => r(ptr-2 to ptr) := "110"; + when '7' => r(ptr-2 to ptr) := "111"; + when 'U' => r(ptr-2 to ptr) := "UUU"; + when 'X' => r(ptr-2 to ptr) := "XXX"; + when 'Z' => r(ptr-2 to ptr) := "ZZZ"; + when 'W' => r(ptr-2 to ptr) := "WWW"; + when 'H' => r(ptr-2 to ptr) := "HHH"; + when 'L' => r(ptr-2 to ptr) := "LLL"; + when '-' => r(ptr-2 to ptr) := "---"; + when '_' => ptr := ptr + 3; + when others => + assert false + report lf & + "O conversion found illegal input character: " & + int(i) & lf & "converting character to '---'" + severity warning; + r(ptr-2 to ptr) := "---"; + end case; + ptr := ptr - 3; + end loop; + return r(size-rtn_len+1 to size); + end o; + + function b (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length, result will be truncated on the left + -- if x is other than characters 0 to 1 or x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length,rtn_len); + variable ptr : integer range 0 to size+1 := size; -- csa + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr) := '0'; + when '1' => r(ptr) := '1'; + when 'U' => r(ptr) := 'U'; + when 'X' => r(ptr) := 'X'; + when 'Z' => r(ptr) := 'Z'; + when 'W' => r(ptr) := 'W'; + when 'H' => r(ptr) := 'H'; + when 'L' => r(ptr) := 'L'; + when '-' => r(ptr) := '-'; + when '_' => ptr := ptr + 1; + when others => + assert false + report lf & + "B conversion found illegal input character: " & + int(i) & lf & "converting character to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr - 1; + end loop; + return r(size-rtn_len+1 to size); + end b; + + function h (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 9 + -- a,A to f,F + -- blanks, underscore + begin + return cnvt_base(x,16); + end h; + + function d (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 9 + -- blanks, underscore + begin + return cnvt_base(x,10); + end d; + + function o (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 7 + -- blanks, underscore + begin + return cnvt_base(x,8); + end o; + + function b (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 1 + -- blanks, underscore + begin + return cnvt_base(x,2); + end b; + + function to_slv(x : natural; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than sizeof(x), result will be truncated on the left + variable int : natural := x; + variable ptr : positive := 32; + variable r : std_logic_vector(1 to 32) := (others=>'0'); + begin + while int > 0 loop + case int rem 2 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when others => + assert false report lf & "TO_SLV, shouldn't happen" + severity failure; + return "0"; + end case; + int := int / 2; + ptr := ptr - 1; + end loop; + return r(33-rtn_len to 32); + end to_slv; + + function to_sl(x : natural) + return std_logic is + variable r : std_logic := '0'; + begin + case x is + when 0 => null; + when 1 => r := '1'; + when others => + assert false + report lf & + "TO_SL found illegal input character: " & + to_int_str(x) & lf & "converting character to '-'" + severity warning; + return '-'; + end case; + return r; + end to_sl; + + function to_time (x: natural) return time is + begin + return x * 1 ns; + end to_time; + +END conversions; diff --git a/lib/models/memory/flash/serial/S25fl064k/utilities/gen_utils.vhd b/lib/models/memory/flash/serial/S25fl064k/utilities/gen_utils.vhd new file mode 100644 index 0000000..65c0e77 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064k/utilities/gen_utils.vhd @@ -0,0 +1,144 @@ +-------------------------------------------------------------------------------- +-- File name: gen_utils.vhd +-------------------------------------------------------------------------------- +-- Copyright (C) 1996, 1998, 2001 Free Model Foundry; http://eda.org/fmf/ +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License version 2 as +-- published by the Free Software Foundation. +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 R. Steele 96 SEP 26 Initial release +-- V1.1 REV3 97 Feb 27 Added Xon and MsgOn generics +-- V1.2 R. Steele 97 APR 16 Changed wired-or to wired-and +-- V1.3 R. Steele 97 APR 16 Added diff. receiver table +-- V1.4 R. Munden 98 APR 13 Added GenParity and CheckParity +-- V1.5 R. Munden 01 NOV 24 Added UnitDelay01ZX +-- +-------------------------------------------------------------------------------- +LIBRARY IEEE; USE IEEE.std_Logic_1164.ALL; + USE IEEE.VITAL_primitives.ALL; + USE IEEE.VITAL_timing.ALL; + +PACKAGE gen_utils IS + + ---------------------------------------------------------------------------- + -- Result map for Wired-and output values (open collector) + ---------------------------------------------------------------------------- + CONSTANT STD_wired_and_rmap : VitalResultMapType := ('U','X','0','Z'); + + ---------------------------------------------------------------------------- + -- Table for computing a single signal from a differential receiver input + -- pair. + ---------------------------------------------------------------------------- + CONSTANT diff_rec_tab : VitalStateTableType := ( + + ------INPUTS--|-PREV-|-OUTPUT---- + -- A ANeg | Aint | Aint' -- + --------------|------|----------- + ( 'X', '-', '-', 'X'), -- A unknown + ( '-', 'X', '-', 'X'), -- A unknown + ( '1', '-', 'X', '1'), -- Recover from 'X' + ( '0', '-', 'X', '0'), -- Recover from 'X' + ( '/', '0', '0', '1'), -- valid diff. rising edge + ( '1', '\', '0', '1'), -- valid diff. rising edge + ( '\', '1', '1', '0'), -- valid diff. falling edge + ( '0', '/', '1', '0'), -- valid diff. falling edge + ( '-', '-', '-', 'S') -- default + ); -- end of VitalStateTableType definition + + + ---------------------------------------------------------------------------- + -- Default Constants + ---------------------------------------------------------------------------- + CONSTANT UnitDelay : VitalDelayType := 1 ns; + CONSTANT UnitDelay01 : VitalDelayType01 := (1 ns, 1 ns); + CONSTANT UnitDelay01Z : VitalDelayType01Z := (others => 1 ns); + CONSTANT UnitDelay01ZX : VitalDelayType01ZX := (others => 1 ns); + + CONSTANT DefaultInstancePath : STRING := "*"; + CONSTANT DefaultTimingChecks : BOOLEAN := FALSE; + CONSTANT DefaultTimingModel : STRING := "UNIT"; + CONSTANT DefaultXon : BOOLEAN := TRUE; + CONSTANT DefaultMsgOn : BOOLEAN := TRUE; + + -- Older VITAL generic being phased out + CONSTANT DefaultXGeneration : BOOLEAN := TRUE; + + ------------------------------------------------------------------- + -- Generate Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION GenParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic_vector; + + ------------------------------------------------------------------- + -- Check Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION CheckParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic; -- '0' - Parity Error + +END gen_utils; + +PACKAGE BODY gen_utils IS + + function XOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 403 + variable result: STD_LOGIC; + begin + result := '0'; + for i in ARG'range loop + result := result xor ARG(i); + end loop; + return result; + end; + ------------------------------------------------------------------- + -- Generate Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION GenParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic_vector + IS + VARIABLE I: NATURAL; + VARIABLE Result: std_logic_vector (Data'Length - 1 DOWNTO 0); + BEGIN + I := 0; + WHILE (I < SIZE) LOOP + Result(I+7 DOWNTO I) := Data(I+7 downto I); + Result(I+8) := XOR_REDUCE( Data(I+7 downto I) ) XOR ODDEVEN; + I := I + 9; + END LOOP; + RETURN Result; + END GenParity; + + ------------------------------------------------------------------- + -- Check Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION CheckParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic -- '0' - Parity Error + IS + VARIABLE I: NATURAL; + VARIABLE Result: std_logic; + BEGIN + I := 0; Result := '1'; + WHILE (I < SIZE) LOOP + Result := Result AND + NOT (XOR_REDUCE( Data(I+8 downto I) ) XOR ODDEVEN); + I := I + 9; + END LOOP; + RETURN Result; + END CheckParity; + +END gen_utils; diff --git a/lib/models/memory/flash/serial/S25fl064p/Model_Manual_English.pdf b/lib/models/memory/flash/serial/S25fl064p/Model_Manual_English.pdf new file mode 100644 index 0000000..954c3f6 Binary files /dev/null and b/lib/models/memory/flash/serial/S25fl064p/Model_Manual_English.pdf differ diff --git a/lib/models/memory/flash/serial/S25fl064p/Model_Manual_Japanese.pdf b/lib/models/memory/flash/serial/S25fl064p/Model_Manual_Japanese.pdf new file mode 100644 index 0000000..de2f909 Binary files /dev/null and b/lib/models/memory/flash/serial/S25fl064p/Model_Manual_Japanese.pdf differ diff --git a/lib/models/memory/flash/serial/S25fl064p/model/model_release_history.txt b/lib/models/memory/flash/serial/S25fl064p/model/model_release_history.txt new file mode 100644 index 0000000..c8dc07c --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064p/model/model_release_history.txt @@ -0,0 +1,196 @@ +########################################## +Date (DD/MM/YYYY) - 22.01.2008. + +Model name - S25FL064P + +Vendor - Spansion LLC + +Publication ID - SPANSION, Rev.16 Issue Date: November 7, 2007 + +VITAL model author - Dragisa Stanojkovic + d-stanojkovic@hdl-dh.com +########################################## +########################################## +INITIAL RELEASE + +# Release Label => vital-amd-REL-s25fl064p-2008-01-22-1.tar.gz +# Release Date (DD/MM/YYYY) => 22/01/2008 +# Release Version => 1.0 + +########################################## +RELEASE 1.1 + +# Release Label => vital-amd-REL-s25fl064p-2008-02-20-2.tar.gz +# Release Date (DD/MM/YYYY) => 20/02/2008 +# Release Version => 1.1 + +# Bugs fixed (from previous release) +- Quad functionality issue + +# Files modified (from previous release) +- s25fl064p.vhd +- s25fl064p.v +- testbench_s25fl064p_vhdl.vhd +- testbench_s25fl064p_verilog.vhd +- spansion_tc_pkg.vhd +- model_release_history.txt +########################################## +########################################## +Publication ID - SPANSION, S25FL064 032P DRS Rev.19, 2008 + +VITAL model author - Dragisa Stanojkovic + d-stanojkovic@hdl-dh.com +########################################## +########################################## +RELEASE 1.2 + +# Release Label => vital-amd-REL-s25fl064p-2008-03-05-1.tar.gz +# Release Date (DD/MM/YYYY) => 05/03/2008 +# Release Version => 1.2 + +# Bugs fixed (from previous release) +- MPM mode for Dual/Quad High Performance changed + +# Files modified (from previous release) +- s25fl064p.ftm +- s25fl064p.ftmv +- s25fl064p_vhdl.sdf +- s25fl064p_verilog.sdf +- s25fl064p.vhd +- s25fl064p.v +- testbench_s25fl064p_vhdl.vhd +- testbench_s25fl064p_verilog.vhd +- spansion_tc_pkg.vhd +- model_release_history.txt +########################################## +########################################## +RELEASE 1.3 + +# Release Label => vital-amd-REL-s25fl064p-2008-03-20-1.tar.gz +# Release Date (DD/MM/YYYY) => 20/03/2008 +# Release Version => 1.3 + +# Bugs fixed (from previous release) +- MPM mode removed + +# Files modified (from previous release) +- s25fl064p.vhd +- s25fl064p.v +- testbench_s25fl064p_vhdl.vhd +- testbench_s25fl064p_verilog.vhd +- spansion_tc_pkg.vhd +- model_release_history.txt +########################################## +########################################## + +VITAL model author - Jadranka Stoickov + j-stoickov@hdl-dh.com +########################################## +########################################## +RELEASE 1.4 + +# Release Label => vital-amd-REL-s25fl064p-2008-08-07-1.tar.gz +# Release Date (DD/MM/YYYY) => 07/08/2008 +# Release Version => 1.4 + +# Bugs fixed (from previous release) +- WEL bit fixed + +# Files modified (from previous release) +- s25fl064p.v +- model_release_history.txt +########################################## +########################################## +Publication ID - SPANSION, S25FL129_064_032P_DRS Rev.23.2, Oct 13, 2008 + +VITAL model author - Jadranka Stoickov + j-stoickov@hdl-dh.com +########################################## +########################################## +RELEASE 1.5 + +# Release Label => vital-amd-REL-s25fl064p-2008-15-10-1.tar.gz +# Release Date (DD/MM/YYYY) => 15/12/2008 +# Release Version => 1.5 + +# Changes made (from previous release) +- alignment to new datasheet + +# Files modified (from previous release) +- s25fl064p.ftm +- s25fl064p.ftmv +- s25fl064p_vhdl.sdf +- s25fl064p_verilog.sdf +- s25fl064p.vhd +- s25fl064p.v +- testbench_s25fl064p_vhdl.vhd +- testbench_s25fl064p_verilog.vhd +- spansion_tc_pkg.vhd +- model_release_history.txt +########################################## +VITAL model author - Snezana Petrovic + s-petrovic@hdl-dh.com +########################################## +########################################## +RELEASE 1.6 + +# Release Label => vital-amd-REL-s25fl064p-2009-05-29-1.tar.gz +# Release Date (DD/MM/YYYY) => 29/05/2009 +# Release Version => 1.6 + +# Changes made (from previous release) +- Timing ranges in timing files corrected + +# Files modified (from previous release) +- s25fl064p.ftm +- s25fl064p.ftmv +- s25fl064p_vhdl.sdf +- s25fl064p_verilog.sdf +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +########################################## +RELEASE 1.7 + +# Release Label => vital-amd-REL-s25fl064p-2010-09-29-1.tar.gz +# Release Date (DD/MM/YYYY) => 29/09/2010 +# Release Version => 1.7 + +# Changes made (from previous release) +# 1. During the QUAD mode HOLD# input is not monitored for its normal function +# 2. Internal pull-up resistors for HOLD# and WP# inputs are implemented + +# Files modified (from previous release) +- s25fl064p.vhd +- s25fl064p.v +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +########################################## +RELEASE 1.8 + +# Release Label => vital-amd-REL-s25fl064p-2012-01-13-1.tar.gz +# Release Date (DD/MM/YYYY) => 13/01/2012 +# Release Version => 1.8 + +# Changes made (from previous release) +- alignment to new datasheet (S25FL064P_00_05, November 18, 2011) + +# Files modified (from previous release) +- s25fl064p.ftm +- s25fl064p.ftmv +- s25fl064p_vhdl.sdf +- s25fl064p_verilog.sdf +- s25fl064p.vhd +- s25fl064p.v +- testbench_s25fl064p_vhdl.vhd +- testbench_s25fl064p_verilog.vhd +- spansion_tc_pkg.vhd +- spansion_flash_testbench_struct.pdf +- spansion_flash_test_cases_list.pdf +- model_release_history.txt +########################################## \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl064p/model/s25fl064p.v b/lib/models/memory/flash/serial/S25fl064p/model/s25fl064p.v new file mode 100644 index 0000000..ec40177 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064p/model/s25fl064p.v @@ -0,0 +1,2603 @@ +////////////////////////////////////////////////////////////////////////////// +// File name : s25fl064p.v +////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2012 Spansion, LLC. +// +// MODIFICATION HISTORY : +// +// version: | author: | mod date: | changes made: +// V1.0 D.Stanojkovic 08 Jan 22 Inital Release +// V1.1 D.Stanojkovic 08 Feb 20 BP bits setting corrected +// V1.2 D.Stanojkovic 08 Mar 04 MPM mode corrected +// V1.3 D.Stanojkovic 08 Mar 20 MPM mode removed +// v1.4 J.Stoickov 08 Aug 07 WEL bit corrected +// V1.5 J.Stoickov 08 Dec 10 Latest datasheet aligned +// (S25FL129 064 032P) +// Program Error bit will not be +// set after programming in +// protect memory region +// V1.6 V.Mancev 10 Sep 29 Implementation of internal pull-up +// for HOLDNeg and WPNeg pins +// V1.7 V.Mancev 12 Jan 13 Latest datasheet aligned +// (S25FL064P_00_05) +////////////////////////////////////////////////////////////////////////////// +// PART DESCRIPTION: +// +// Library: FLASH +// Technology: FLASH MEMORY +// Part: S25FL064P +// +// Description:64 Megabit Serial Flash Memory with 104 MHz SPI Bus Interface +// Comments : +// For correct simulation, simulator resolution should be set to 1 ps +// +////////////////////////////////////////////////////////////////////////////// +// Known Bugs: +// +////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// MODULE DECLARATION // +////////////////////////////////////////////////////////////////////////////// +`timescale 1 ps/1 ps +module s25fl064p +( + SCK , + SI , + + CSNeg , + HOLDNeg , + WPNeg , + SO +); +//////////////////////////////////////////////////////////////////////// +// Port / Part SOIn Declarations +//////////////////////////////////////////////////////////////////////// + input SCK ; + inout SI ; + + input CSNeg ; + inout HOLDNeg ; + inout WPNeg ; + inout SO ; + +// interconnect path delay signals + wire SCK_ipd ; + wire SI_ipd ; + + wire SI_in ; + assign SI_in = SI_ipd ; + + wire SI_out ; + assign SI_out = SI ; + + wire CSNeg_ipd ; + wire HOLDNeg_ipd ; + wire WPNeg_ipd ; + wire SO_ipd ; + + wire HOLDNeg_in ; + //Internal pull-up + assign HOLDNeg_in = (HOLDNeg_ipd === 1'bx) ? 1'b1 : HOLDNeg_ipd; + + wire HOLDNeg_out ; + assign HOLDNeg_out = HOLDNeg ; + + wire WPNeg_in ; + //Internal pull-up + assign WPNeg_in = (WPNeg_ipd === 1'bx) ? 1'b1 : WPNeg_ipd; + + wire WPNeg_out ; + assign WPNeg_out = WPNeg ; + + wire SOIn ; + assign SOIn = SO_ipd ; + + wire SOut ; + assign SOut = SO ; + +// internal delays + reg PP_in ; + reg PP_out ; + reg PU_in ; + reg PU_out ; + reg SE_in ; + reg SE_out ; + reg BE_in ; + reg BE_out ; + reg PE_in ; + reg PE_out ; + reg WR_in ; + reg WR_out ; + reg DP_in ; + reg DP_out ; + reg EP_in ; + reg EP_out ; + reg RES_in ; + reg RES_out ; + + reg SOut_zd = 1'bZ; + reg SOut_z = 1'bZ; + + wire SI_z ; + wire SO_z ; + + reg SIOut_zd = 1'bZ ; + reg SIOut_z = 1'bZ ; + + reg WPNegOut_zd = 1'bZ ; + reg HOLDNegOut_zd = 1'bZ ; + + assign SI_z = SIOut_z; + assign SO_z = SOut_z; + + parameter UserPreload = 1; + parameter mem_file_name = "none";//"s25fl064p.mem"; + parameter otp_file_name = "none";//"s25fl064p_secsi.mem"; + + parameter TimingModel = "DefaultTimingModel"; + + parameter PartID = "s25fl064p"; + parameter MaxData = 255; + parameter SecSize = 16'hFFFF; + parameter SecSize_4 = 4095; + parameter SecSize_8 = 8191; + parameter SecNum = 127; + parameter PageNum = 16'h7FFF; + parameter OTPSize = 511; + parameter OTPLoAddr = 9'h100; + parameter OTPHiAddr = 10'h2FF; + parameter HiAddrBit = 23; + parameter AddrRANGE = 24'h7FFFFF; + parameter BYTE = 8; + parameter Manuf_ID = 8'h01; + parameter ES = 8'h16; + parameter Jedec_ID = 8'h20; // first byte of Device ID + parameter DeviceID = 16'h0216; + parameter ExtendedBytes = 8'h4D; + parameter ReservedBytes = 8'h00; + + // If speed simulation is needed uncomment following line + + //`define SPEEDSIM; + + // powerup + reg PoweredUp; + + //FSM control signals + reg PDONE ; ////Prog. Done + reg PSTART ; ////Start Programming + + reg EDONE ; ////Era. Done + reg ESTART ; ////Start Erasing + + reg WDONE ; //// Writing Done + reg WSTART ; ////Start writing + + //Command Register + reg write; + reg cfg_write; + reg read_out; + + //Status reg. + reg[7:0] Status_reg = 8'b0; + reg[7:0] Status_reg_in = 8'b0; + reg[7:0] Sec_conf_reg = 8'b0; + reg[7:0] Sec_conf_reg_in = 8'b0; + + wire FREEZE; + wire QUAD; + wire TBPARM; + wire BPNV; + wire TBPROT; + assign FREEZE = Sec_conf_reg[0]; + assign QUAD = Sec_conf_reg[1]; + assign TBPARM = Sec_conf_reg[2]; + assign BPNV = Sec_conf_reg[3]; + assign TBPROT = Sec_conf_reg[5]; + + wire WIP; + wire WEL; + wire [2:0]BP; + wire E_ERR; + wire P_ERR; + wire SRWD; + assign WIP = Status_reg[0]; + assign WEL = Status_reg[1]; + assign BP = Status_reg[4:2]; + assign E_ERR = Status_reg[5]; + assign P_ERR = Status_reg[6]; + assign SRWD = Status_reg[7]; + + integer SA = 0; // 0 TO SecNum+1 + integer Byte_number = 0; + integer sect; + + //Address + integer Address = 0; // 0 - AddrRANGE + reg change_addr; + reg rd_fast; // = 1'b1; + reg rd_slow; + reg rd_jedec; + reg change_BP = 0; + reg rd_dual; + reg dual; + wire fast_rd; + wire rd; + wire rd_jid; + + wire RD_EQU_1; + assign RD_EQU_1 = rd_slow; + + wire RD_EQU_0; + assign RD_EQU_0 = ~rd_slow; + + reg hold_mode; + reg mpm_mode = 0; + reg initial_config = 0; + wire hold; + + //Sector Protection Status + reg [SecNum:0] Sec_Prot = 127'b0; //= SecNum'b0; + + // timing check violation + reg Viol = 1'b0; + + integer Mem[0:AddrRANGE]; + integer OTPMem[OTPLoAddr: OTPHiAddr]; + + integer WByte[0:255]; + integer WOTPByte; + integer AddrLo; + integer AddrHi; + + reg[7:0] old_bit, new_bit; + integer old_int, new_int; + integer wr_cnt; + integer cnt; + + integer read_cnt = 0; + integer read_addr = 0; + reg[7:0] data_out; + reg[647:0] ident_out; + + reg oe = 1'b0; + event oe_event; + + integer CFI_array[8'h07:8'h50]; + reg [591:0] CFI_array_tmp; + reg [7:0] CFI_tmp; + + reg[15:0] PR_LOCK1; + reg[15:0] PR_LOCK2; + reg[15:0] PR_LOCK3; +/////////////////////////////////////////////////////////////////////////////// +//Interconnect Path Delay Section +/////////////////////////////////////////////////////////////////////////////// + + buf (SCK_ipd, SCK); + buf (SI_ipd, SI); + + buf (CSNeg_ipd, CSNeg); + buf (HOLDNeg_ipd, HOLDNeg); + buf (WPNeg_ipd, WPNeg); + buf (SO_ipd, SO); + +/////////////////////////////////////////////////////////////////////////////// +// Propagation delay Section +/////////////////////////////////////////////////////////////////////////////// + nmos (SO, SO_z , 1); + + nmos (SI, SI_z , 1); + nmos (HOLDNeg, HOLDNegOut_zd , 1); + nmos (WPNeg, WPNegOut_zd , 1); + + wire deg_pin; + wire deg_sin; + wire deg_holdin; + //VHDL VITAL CheckEnable equivalents + wire dual_wr; + assign dual_wr = deg_holdin && QUAD; + wire quad_wr; + assign quad_wr = SRWD && WEL ; + wire dual_rd; + assign dual_rd = dual; + wire power; + assign power = PoweredUp; + + specify + // tipd delays: interconnect path delays , mapped to input port delays. + // In Verilog is not necessary to declare any tipd_ delay variables, + // they can be taken from SDF file + // With all the other delays real delays would be taken from SDF file + + // tpd delays + specparam tpd_SCK_SO =1; + specparam tpd_SCK_SI =1; + specparam tpd_CSNeg_SO =1; + specparam tpd_HOLDNeg_SO =1; + + specparam tsetup_SI_SCK =1; //tsuDAT / + specparam tsetup_CSNeg_SCK =1; // tCSS / + specparam tsetup_HOLDNeg_SCK =1; //tHD / + specparam tsetup_SCK_HOLDNeg =1; //tCH \ + specparam tsetup_WPNeg_CSNeg =1; //tWPS \ + + // thold values: hold times + specparam thold_SI_SCK =1; //thdDAT / + specparam thold_CSNeg_SCK =1; //tCSH / + specparam thold_HOLDNeg_SCK =1; //tCHHH / + specparam thold_SCK_HOLDNeg =1; //tHC \ + specparam thold_WPNeg_CSNeg =1; //tWPH \ + + // tpw values: pulse width + specparam tpw_SCK_fast_posedge =1; //tWH + specparam tpw_SCK_posedge =1; //tWH + specparam tpw_SCK_dual_posedge =1; //tWH + specparam tpw_SCK_rdid_posedge =1; //tWH + specparam tpw_SCK_fast_negedge =1; //tWL + specparam tpw_SCK_negedge =1; //tWL + specparam tpw_SCK_dual_negedge =1; //tWL + specparam tpw_SCK_rdid_negedge =1; //tWL + specparam tpw_CSNeg_read_posedge =1; //tCS + specparam tpw_CSNeg_pgm_posedge =1; //tCS + + // tperiod min (calculated as 1/max freq) + specparam tperiod_SCK_rd =1; // fSCK = 40MHz + specparam tperiod_SCK_fast_rd =1; // fSCK = 104MHz + specparam tperiod_SCK_dual_fast_rd =1; // fSCK = 80MHz + specparam tperiod_SCK_rdid =1; // fSCK = 50MHz + + // tdevice values: values for internal delays + `ifdef SPEEDSIM + // Page Program Operation + specparam tdevice_PP = 3e7; //30 us; + //Page Program Operation (ACC=9V)) + specparam tdevice_EP = 2.4e9; //2.4 ms; + //Sector Erase Operation + specparam tdevice_SE = 2e9; //2 ms; + //Bulk Erase Operation + specparam tdevice_BE = 128e9; //128 ms; + //Write Status Register Operation + specparam tdevice_WR = 1e9; // 1 ms; + //Software Protect Mode + specparam tdevice_DP = 10000000; // 10 us; + //Release from Software Protect Mode + specparam tdevice_RES = 30000000; // 30 us; + //Parameter block erase + specparam tdevice_PE = 800e6; //800 us; + //VCC (min) to CS# Low + specparam tdevice_PU = 300000000; //300 us; + `else + // Page Program Operation + specparam tdevice_PP = 3e9; //3 ms; + //Page Program Operation (ACC=9V)) + specparam tdevice_EP = 2.4e9; //2.4 ms; + //Sector Erase Operation + specparam tdevice_SE = 2e12; //2 s; + //Bulk Erase Operation + specparam tdevice_BE = 128e12; //128 sec; + //Write Status Register Operation + specparam tdevice_WR = 100e9; // 100 ms; + //Software Protect Mode + specparam tdevice_DP = 10000000; // 10 us; + //Release from Software Protect Mode + specparam tdevice_RES = 30000000; // 30 us; + //Parameter block erase + specparam tdevice_PE = 800e9; //800 ms; + //VCC (min) to CS# Low + specparam tdevice_PU = 300000000; //300 us; + `endif//SPEEDSIM + +/////////////////////////////////////////////////////////////////////////////// +// Input Port Delays don't require Verilog description +/////////////////////////////////////////////////////////////////////////////// +// Path delays // +/////////////////////////////////////////////////////////////////////////////// + if (~dual) (SCK => SO) = tpd_SCK_SO; + if (dual) (SCK => SO) = tpd_SCK_SI; + if (CSNeg)(CSNeg => SO) = tpd_CSNeg_SO; + if (~dual) (HOLDNeg => SO) = tpd_HOLDNeg_SO; + if (dual) (HOLDNeg => SO) = tpd_HOLDNeg_SO; + + if (dual)(SCK => SI) = tpd_SCK_SI; + if (dual && CSNeg)(CSNeg => SI) = tpd_CSNeg_SO; + if (dual)(HOLDNeg => SI) = tpd_HOLDNeg_SO; + + if (dual && QUAD)(SCK => HOLDNeg) = tpd_SCK_SI; + if (dual && CSNeg && QUAD)(CSNeg => HOLDNeg) = tpd_CSNeg_SO; + + if (dual && QUAD)(SCK => WPNeg) = tpd_SCK_SI; + if (dual && CSNeg && QUAD)(CSNeg => WPNeg) = tpd_CSNeg_SO; +//////////////////////////////////////////////////////////////////////////////// +// Timing Violation // +//////////////////////////////////////////////////////////////////////////////// + $setup ( SI , posedge SCK &&& deg_sin, + tsetup_SI_SCK, Viol); + $setup ( negedge HOLDNeg, posedge SCK &&& dual_wr, + tsetup_HOLDNeg_SCK, Viol); + $setup ( posedge SCK , posedge HOLDNeg &&& dual_wr, + tsetup_SCK_HOLDNeg, Viol); + $setup ( CSNeg , posedge SCK &&& power, + tsetup_CSNeg_SCK, Viol); + $setup ( WPNeg , negedge CSNeg &&& WPNeg, + tsetup_WPNeg_CSNeg, Viol); + + $hold ( posedge SCK , SI &&& deg_sin, + thold_SI_SCK, Viol); + $hold ( posedge HOLDNeg , posedge SCK &&& dual_wr, + thold_SCK_HOLDNeg, Viol); + $hold ( posedge SCK , CSNeg &&& power, + thold_CSNeg_SCK, Viol); + $hold ( posedge CSNeg , WPNeg &&& quad_wr, + thold_WPNeg_CSNeg, Viol); + $hold ( posedge SCK , negedge HOLDNeg &&& dual_wr, + thold_HOLDNeg_SCK, Viol); + + $width (posedge SCK &&& rd , tpw_SCK_posedge); + $width (posedge SCK &&& fast_rd , tpw_SCK_fast_posedge); + $width (posedge SCK &&& dual_rd , tpw_SCK_dual_posedge); + $width (posedge SCK &&& rd_jid , tpw_SCK_rdid_posedge); + $width (negedge SCK &&& rd , tpw_SCK_negedge); + $width (negedge SCK &&& fast_rd , tpw_SCK_fast_negedge); + $width (negedge SCK &&& dual_rd , tpw_SCK_dual_negedge); + $width (negedge SCK &&& rd_jid , tpw_SCK_rdid_negedge); + + $width (posedge CSNeg &&& RD_EQU_0, tpw_CSNeg_pgm_posedge); + $width (posedge CSNeg &&& RD_EQU_1, tpw_CSNeg_read_posedge); + + $period (posedge SCK &&& rd, tperiod_SCK_rd); + $period (posedge SCK &&& fast_rd, tperiod_SCK_fast_rd); + $period (posedge SCK &&& dual_rd, tperiod_SCK_dual_fast_rd); + $period (posedge SCK &&& rd_jid, tperiod_SCK_rdid); + + endspecify + +//////////////////////////////////////////////////////////////////////////////// +// Main Behavior Block // +//////////////////////////////////////////////////////////////////////////////// +// FSM states + parameter IDLE =4'd0; + parameter WRITE_SR =4'd1; + parameter DP_DOWN_WAIT =4'd2; + parameter DP_DOWN =4'd3; + parameter SECTOR_ER =4'd4; + parameter BULK_ER =4'd5; + parameter PAGE_PG =4'd6; + parameter OTP_PG =4'd7; + parameter P4_ER =4'd8; + parameter P8_ER =4'd9; + + reg [3:0] current_state; + reg [3:0] next_state; + +// Instructions + parameter NONE =5'd0; + parameter WREN =5'd1; + parameter WRDI =5'd2; + parameter WRR =5'd3; + parameter RDSR =5'd4; + parameter READ =5'd5; + parameter READ_ID =5'd6; + parameter RDID =5'd7; + parameter FAST_READ =5'd8; + parameter DUAL_READ =5'd9; + parameter QUAD_READ =5'd10; + parameter DH_READ =5'd11; + parameter QH_READ =5'd12; + parameter SE =5'd13; + parameter BE =5'd14; + parameter PP =5'd15; + parameter QPP =5'd16; + parameter DP =5'd17; + parameter RES_READ_ES =5'd18; + parameter CLSR =5'd19; + parameter RCR =5'd20; + parameter P4E =5'd21; + parameter P8E =5'd22; + parameter OTPP =5'd23; + parameter OTPR =5'd24; + reg [4:0] Instruct; + +//Bus cycle states + parameter STAND_BY =3'd0; + parameter CODE_BYTE =3'd1; + parameter ADDRESS_BYTES =3'd2; + parameter DUMMY_BYTES =3'd3; + parameter MODE_BYTE =3'd4; + parameter DATA_BYTES =3'd5; + + reg [2:0] bus_cycle_state; + + reg deq_pin; + always @(SOIn, SO_z) + begin + if (SOIn==SO_z) + deq_pin=1'b0; + else + deq_pin=1'b1; + end + // chech when data is generated from model to avoid setuphold check in + // those occasion + assign deg_pin=deq_pin; + + reg deq_sin; + always @(SI_in, SIOut_z) + begin + if (SI_in==SIOut_z) + deq_sin=1'b0; + else + deq_sin=1'b1; + end + // chech when data is generated from model to avoid setuphold check in + // those occasion + assign deg_sin=deq_sin; + + reg deq_holdin; + always @(HOLDNeg_ipd, HOLDNegOut_zd) + begin + if (HOLDNeg_ipd==HOLDNegOut_zd) + deq_holdin=1'b0; + else + deq_holdin=1'b1; + end + // check when data is generated from model to avoid setuphold check in + // this occasion + assign deg_holdin=deq_holdin; + + initial + begin : Init + + write = 1'b0; + cfg_write = 1'b0; + read_out = 1'b0; + Address = 0; + change_addr = 1'b0; + + PDONE = 1'b1; + PSTART = 1'b0; + + EDONE = 1'b1; + ESTART = 1'b0; + + WDONE = 1'b1; + WSTART = 1'b0; + + DP_in = 1'b0; + DP_out = 1'b0; + RES_in = 1'b0; + RES_out = 1'b0; + Instruct = NONE; + + bus_cycle_state = STAND_BY; + current_state = IDLE; + next_state = IDLE; + end + + //CFI + initial + begin: InitCFI + integer i; + integer j; + + CFI_array[8'h07] = 8'hFF; + CFI_array[8'h08] = 8'hFF; + CFI_array[8'h09] = 8'hFF; + CFI_array[8'h0A] = 8'hFF; + CFI_array[8'h0B] = 8'hFF; + CFI_array[8'h0C] = 8'hFF; + CFI_array[8'h0D] = 8'hFF; + CFI_array[8'h0E] = 8'hFF; + CFI_array[8'h0F] = 8'hFF; + CFI_array[8'h10] = 8'h51; + CFI_array[8'h11] = 8'h52; + CFI_array[8'h12] = 8'h59; + CFI_array[8'h13] = 8'h02; + CFI_array[8'h14] = 8'h00; + CFI_array[8'h15] = 8'h40; + CFI_array[8'h16] = 8'h00; + CFI_array[8'h17] = 8'h00; + CFI_array[8'h18] = 8'h00; + CFI_array[8'h19] = 8'h00; + CFI_array[8'h1A] = 8'h00; + //System interface string + CFI_array[8'h1B] = 8'h27; + CFI_array[8'h1C] = 8'h36; + CFI_array[8'h1D] = 8'h00; + CFI_array[8'h1E] = 8'h00; + CFI_array[8'h1F] = 8'h0B; + CFI_array[8'h20] = 8'h0B; + CFI_array[8'h21] = 8'h09; + CFI_array[8'h22] = 8'h10; + CFI_array[8'h23] = 8'h01; + CFI_array[8'h24] = 8'h01; + CFI_array[8'h25] = 8'h02; + CFI_array[8'h26] = 8'h01; + //device geometry definition + CFI_array[8'h27] = 8'h17; + CFI_array[8'h28] = 8'h05; + CFI_array[8'h29] = 8'h05; + CFI_array[8'h2A] = 8'h08; + CFI_array[8'h2B] = 8'h00; + CFI_array[8'h2C] = 8'h02; + CFI_array[8'h2D] = 8'h1F; + CFI_array[8'h2E] = 8'h00; + CFI_array[8'h2F] = 8'h10; + CFI_array[8'h30] = 8'h00; + CFI_array[8'h31] = 8'h7D; + CFI_array[8'h32] = 8'h00; + CFI_array[8'h33] = 8'h00; + CFI_array[8'h34] = 8'h01; + CFI_array[8'h35] = 8'h00; + CFI_array[8'h36] = 8'h00; + CFI_array[8'h37] = 8'h00; + CFI_array[8'h38] = 8'h00; + CFI_array[8'h39] = 8'h00; + CFI_array[8'h3A] = 8'h00; + CFI_array[8'h3B] = 8'h00; + CFI_array[8'h3C] = 8'h00; + CFI_array[8'h3D] = 8'hFF; + CFI_array[8'h3E] = 8'hFF; + CFI_array[8'h3F] = 8'hFF; + //primary vendor-specific extended query + CFI_array[8'h40] = 8'h50; + CFI_array[8'h41] = 8'h52; + CFI_array[8'h42] = 8'h49; + CFI_array[8'h43] = 8'h31; + CFI_array[8'h44] = 8'h33; + CFI_array[8'h45] = 8'h15; + CFI_array[8'h46] = 8'h00; + CFI_array[8'h47] = 8'h02; + CFI_array[8'h48] = 8'h00; + CFI_array[8'h49] = 8'h05; + CFI_array[8'h4A] = 8'h00; + CFI_array[8'h4B] = 8'h01; + CFI_array[8'h4C] = 8'h03; + CFI_array[8'h4D] = 8'h85; + CFI_array[8'h4E] = 8'h95; + CFI_array[8'h4F] = 8'h07; + CFI_array[8'h50] = 8'h00; + + for(i=73;i>=0;i=i-1) + begin + CFI_tmp = CFI_array[8'h07-i+73]; + for(j=7;j>=0;j=j-1) + begin + CFI_array_tmp[8*i+j] = CFI_tmp[j]; + end + end + end + + // initialize memory + initial + begin: InitMemory + integer i; + + for (i=0;i<=AddrRANGE;i=i+1) + begin + Mem[i] = MaxData; + end + + if ((UserPreload) && !(mem_file_name == "none")) + begin + // Memory Preload + //s25fl064p.mem, memory preload file + // @aaaaaa - stands for address + // dd -
is byte to be written at Mem(aaaaaa++) + // (aaaaaa is incremented at every load) + $readmemh(mem_file_name,Mem); + end + + for (i=OTPLoAddr;i<=OTPHiAddr;i=i+1) + begin + OTPMem[i] = MaxData; + end + if (UserPreload && !(otp_file_name == "none")) + begin + //s25fl064p_secsi memory file + // / - comment + // @aaaaaa - stands for address within last defined + // sector + // dd -
is byte to be written at SecSi(aaaaaa++) + // (aa is incremented at every load) + // only first 1-5 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + $readmemh(otp_file_name,OTPMem); + end + PR_LOCK1[15:8] = 16'h0; + PR_LOCK1[7:0] = OTPMem[256]; + + PR_LOCK2[15:8] = OTPMem[275]; + PR_LOCK2[7:0] = OTPMem[274]; + + PR_LOCK3[15:8] = OTPMem[533]; + PR_LOCK3[7:0] = OTPMem[532]; + end + + //Power Up time; + initial + begin + PoweredUp = 1'b0; + #tdevice_PU PoweredUp = 1'b1; + end + + always @(posedge DP_in) + begin:TDPr + #tdevice_DP DP_out = DP_in; + end + always @(negedge DP_in) + begin:TDPf + #1 DP_out = DP_in; + end + + always @(posedge RES_in) + begin:TRESr + #tdevice_RES RES_out = RES_in; + end + always @(negedge RES_in) + begin:TRESf + #1 RES_out = RES_in; + end + + always @(next_state or PoweredUp) + begin: StateTransition + if (PoweredUp) + begin + current_state = next_state; + end + end + + always @(negedge CSNeg_ipd) + begin:CheckCSOnPowerUP + if (~PoweredUp) + $display ("Device is selected during Power Up"); + end + +// /////////////////////////////////////////////////////////////////////////// +// // Instruction cycle decode +// /////////////////////////////////////////////////////////////////////////// + integer data_cnt = 0; + integer addr_cnt = 0; + integer code_cnt = 0; + integer mode_cnt = 0; + integer dummy_cnt = 0; + integer bit_cnt = 0; + + reg[2047:0] Data_in = 2048'b0; + integer quad_data_in [0:511]; + reg[3:0] quad_nybble = 4'b0; + reg[3:0] Quad_slv = 4'b0; + reg[7:0] code = 8'b0; + reg[7:0] code_in = 8'b0; + reg[7:0] Byte_slv = 8'b0; + reg[HiAddrBit:0] addr_bytes; + reg[23:0] Address_in = 8'b0; + reg[7:0] mode_bytes; + reg[7:0] mode_in; + + reg rising_edge_CSNeg_ipd = 1'b0; + reg falling_edge_CSNeg_ipd = 1'b0; + reg rising_edge_SCK_ipd = 1'b0; + reg falling_edge_SCK_ipd = 1'b0; + + always @(falling_edge_CSNeg_ipd or rising_edge_CSNeg_ipd + or rising_edge_SCK_ipd or falling_edge_SCK_ipd) + begin: Buscycle1 + integer i; + integer j; + integer k; + if (falling_edge_CSNeg_ipd) + begin + if (bus_cycle_state==STAND_BY) + begin + bus_cycle_state = CODE_BYTE; + Instruct = NONE; + write = 1'b1; + code_cnt = 0; + addr_cnt = 0; + data_cnt = 0; + mode_cnt = 0; + dummy_cnt = 0; + end + end + + if (rising_edge_SCK_ipd) + begin + if (~CSNeg_ipd) + begin + case (bus_cycle_state) + CODE_BYTE : + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + code_in[code_cnt] = SI_in; + code_cnt = code_cnt + 1; + if (code_cnt == BYTE) + begin + for (i=0;i<=7;i=i+1) + begin + code[i] = code_in[7-i]; + end + case(code) + 8'b00000110 : + begin + Instruct = WREN; + bus_cycle_state = DATA_BYTES; + end + 8'b00000100 : + begin + Instruct = WRDI; + bus_cycle_state = DATA_BYTES; + end + 8'b00000001 : + begin + Instruct = WRR; + bus_cycle_state = DATA_BYTES; + end + 8'b00000101 : + begin + Instruct = RDSR; + bus_cycle_state = DATA_BYTES; + end + 8'b00000011 : + begin + Instruct = READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00001011 : + begin + Instruct = FAST_READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10011111 : + begin + Instruct = RDID; + bus_cycle_state = DATA_BYTES; + end + 8'b10010000 : + begin + Instruct = READ_ID; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10101011 : + begin + Instruct = RES_READ_ES; + bus_cycle_state = DUMMY_BYTES; + end + 8'b11011000 : + begin + Instruct = SE; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11000111 , 8'b01100000: + begin + Instruct = BE; + bus_cycle_state = DATA_BYTES; + end + 8'b00000010 : + begin + Instruct = PP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00110010 : + begin + Instruct = QPP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10111001 : + begin + Instruct = DP; + bus_cycle_state = DATA_BYTES; + end + 8'b00110000 : + begin + Instruct = CLSR; + bus_cycle_state = DATA_BYTES; + end + 8'b00110101 : + begin + Instruct = RCR; + bus_cycle_state = DATA_BYTES; + end + 8'b00100000 : + begin + Instruct = P4E; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01000000 : + begin + Instruct = P8E; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01000010 : + begin + Instruct = OTPP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01001011 : + begin + Instruct = OTPR; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00111011 : + begin + Instruct = DUAL_READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01101011 : + begin + Instruct = QUAD_READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10111011 : + begin + Instruct = DH_READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11101011 : + begin + Instruct = QH_READ; + bus_cycle_state = ADDRESS_BYTES; + end + endcase + end + end + end + + ADDRESS_BYTES : + begin + if (((Instruct == FAST_READ || Instruct == OTPR || + Instruct == DUAL_READ) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + ((Instruct == QUAD_READ) && QUAD)) + begin + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE) + begin + for (i=23;i>=23-HiAddrBit;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = DUMMY_BYTES; + end + end + else if (Instruct == DH_READ && + ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + if (SOIn !== 1'b0 && SOIn !== 1'b1) + begin + mpm_mode = 0; + bus_cycle_state = STAND_BY; + end + else + begin + Address_in[2*addr_cnt] = SOIn; + Address_in[2*addr_cnt+1] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 12) + begin + addr_cnt = 0; + for (i=23;i>=23-HiAddrBit;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + end + else if (Instruct == QH_READ) + begin + if(QUAD) + begin + if (SOIn !== 1'b0 && SOIn !== 1'b1) + begin + mpm_mode = 0; + bus_cycle_state = STAND_BY; + end + else + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SOIn; + Address_in[4*addr_cnt+3] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 6) + begin + addr_cnt = 0; + for (i=23;i>=23-HiAddrBit;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + end + else + begin + bus_cycle_state = STAND_BY; + end + end + else if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE) + begin + for (i=23;i>=23-HiAddrBit;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = DATA_BYTES; + end + end + end + + MODE_BYTE : + begin + if((Instruct == DH_READ) && + ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + mode_in[2*mode_cnt] = SOIn; + mode_in[2*mode_cnt+1] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/2) + begin + mode_cnt = 0; + for (i=7;i>=7-BYTE;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DATA_BYTES; + end + end + else if((Instruct == QH_READ) && QUAD) + begin + mode_in[4*mode_cnt] = HOLDNeg_in; + mode_in[4*mode_cnt+1] = WPNeg_in; + mode_in[4*mode_cnt+2] = SOIn; + mode_in[4*mode_cnt+3] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/4) + begin + mode_cnt = 0; + for (i=7;i>=7-BYTE;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DUMMY_BYTES; + end + end + dummy_cnt = 0; + end + + DUMMY_BYTES : + begin + if(QUAD && (Instruct == QUAD_READ || + Instruct == QH_READ)) + begin + dummy_cnt = dummy_cnt + 1; + if ((dummy_cnt == BYTE) && Instruct == QUAD_READ) + bus_cycle_state = DATA_BYTES; + else if ((dummy_cnt == BYTE/2) && + Instruct == QH_READ) + bus_cycle_state = DATA_BYTES; + end + else if((HOLDNeg_in && ~QUAD) || QUAD) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == BYTE && (Instruct == FAST_READ || + Instruct == OTPR || Instruct == DUAL_READ)) + bus_cycle_state = DATA_BYTES; + else if (dummy_cnt == 3*BYTE) + bus_cycle_state = DATA_BYTES; + end + end + + DATA_BYTES : + begin + if(QUAD && Instruct == QPP) + begin + quad_nybble = {HOLDNeg_in, WPNeg_in, SOIn, SI_in}; + if (data_cnt > 511) + begin + //In case of quad mode and QPP, + //if more than 512 bytes are sent to the device + for (i=0;i<=510;i=i+1) + begin + quad_data_in[i] = quad_data_in[i+1]; + end + quad_data_in[511] = quad_nybble; + data_cnt = data_cnt + 1; + end + else + begin + if( quad_nybble !== 4'bZZZZ) + begin + quad_data_in[data_cnt] = quad_nybble; + end + data_cnt = data_cnt + 1; + end + end + else if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt > 2047) + //In case of serial mode and PP, if more than 256 + //bytes are sent to the device + begin + if (bit_cnt == 0) + begin + for (i=0;i<=(255*BYTE-1);i=i+1) + begin + Data_in[i] = Data_in[i+8]; + end + end + Data_in[2040 + bit_cnt] = SI_in; + bit_cnt = bit_cnt + 1; + if (bit_cnt == 8) + begin + bit_cnt = 0; + end + data_cnt = data_cnt + 1; + end + else + begin + Data_in[data_cnt] = SI_in; + data_cnt = data_cnt + 1; + bit_cnt = 0; + end + end + end + endcase + end + end + if (falling_edge_SCK_ipd) + begin + if ((bus_cycle_state == DATA_BYTES) && (~CSNeg_ipd)) + begin + if (((Instruct == READ || Instruct == FAST_READ || + Instruct == DUAL_READ || Instruct == DH_READ || + Instruct == RES_READ_ES || Instruct == RDID || + Instruct == RDSR || Instruct == READ_ID || + Instruct == RCR || Instruct == OTPR) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + ((Instruct == QUAD_READ || Instruct == QH_READ) && QUAD)) + begin + read_out = 1'b1; + #1 read_out = 1'b0; + end + end + end + if (rising_edge_CSNeg_ipd) + begin + if ((bus_cycle_state != DATA_BYTES) && + (bus_cycle_state != DUMMY_BYTES)) + bus_cycle_state = STAND_BY; + else + begin + if (bus_cycle_state == DATA_BYTES) + begin + if (mpm_mode && (mode_bytes[7:4] == 4'b1010) && + (Instruct == DH_READ || Instruct == QH_READ)) + bus_cycle_state = ADDRESS_BYTES; + else + begin + mpm_mode = 0; + bus_cycle_state = STAND_BY; + end + if (Instruct == QPP) + begin + if (data_cnt > 0) + begin + if ((data_cnt % 2) == 0) + begin + write = 0; + for(i=0;i<=255;i=i+1) + begin + for(j=1;j>=0;j=j-1) + begin + Quad_slv = quad_data_in[(i*2)+(1-j)]; + for(k=3;k>=0;k=k-1) + begin + Byte_slv[4*j+k] = Quad_slv[k]; + end + end + WByte[i] = Byte_slv; + end + if (data_cnt > 512) + Byte_number = 255; + else + Byte_number = data_cnt/2 -1; + end + end + end + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + case (Instruct) + WRDI, + WREN, + DP, + BE, + SE, + P4E, + P8E, + CLSR: + begin + if (data_cnt == 0) + write = 1'b0; + end + + RES_READ_ES: + begin + write = 1'b0; + end + + WRR : + begin + if((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + begin + write = 0; + cfg_write = 1'b0; + for(i=0;i<=7;i=i+1) + begin + Status_reg_in[i]= + Data_in[7-i]; + end + end + else if (data_cnt == 16) + begin + write = 0; + cfg_write = 1'b1; + for(i=0;i<=7;i=i+1) + begin + Status_reg_in[i]= + Data_in[7-i]; + Sec_conf_reg_in[i]= + Data_in[15-i]; + end + end + end + end + + PP : + begin + if (data_cnt > 0) + begin + if ((data_cnt % 8) == 0) + begin + write = 1'b0; + for (i=0;i<=255;i=i+1) + begin + for (j=7;j>=0;j=j-1) + begin + Byte_slv[j] = + Data_in[(i*8) + (7-j)]; + end + WByte[i] = Byte_slv; + end + if (data_cnt > 256*BYTE) + Byte_number = 255; + else + Byte_number = ((data_cnt/8) - 1); + end + end + end + + OTPP : + begin + if (data_cnt == 8) + begin + write = 1'b0; + for (j=7;j>=0;j=j-1) + begin + Byte_slv[j] = Data_in[7-j]; + end + WOTPByte = Byte_slv; + end + end + endcase + end + end + else + if (bus_cycle_state == DUMMY_BYTES) + begin + bus_cycle_state = STAND_BY; + if (((HOLDNeg_in && ~QUAD) || QUAD) && + (Instruct == RES_READ_ES) && (dummy_cnt == 0)) + write = 1'b0; + end + end + end + end + +// ///////////////////////////////////////////////////////////////////////// +// // Timing control for the Program Operations +// // start +// ///////////////////////////////////////////////////////////////////////// + + event pdone_event; + + always @(PSTART) + begin + if (PSTART && PDONE) + if (Sec_Prot[SA] == 1'b0) + begin + PDONE = 1'b0; + ->pdone_event; + end + end + + always @(pdone_event) + begin:pdone_process + PDONE = 1'b0; + #tdevice_PP PDONE = 1'b1; + end + +// ///////////////////////////////////////////////////////////////////////// +// // Timing control for the Write Status Register Operation +// // start +// ///////////////////////////////////////////////////////////////////////// + + event wdone_event; + + always @(WSTART) + begin + if (WSTART && WDONE) + begin + WDONE = 1'b0; + ->wdone_event; + end + end + + always @(wdone_event) + begin:wdone_process + WDONE = 1'b0; + #tdevice_WR WDONE = 1'b1; + end + +// ///////////////////////////////////////////////////////////////////////// +// // Timing control for the Erase Operations +// ///////////////////////////////////////////////////////////////////////// + time duration_erase; + + event edone_event; + + always @(ESTART) + begin: erase + if (ESTART && EDONE) + begin + if (Instruct == BE) + begin + duration_erase = tdevice_BE; + end + else if (Instruct == P4E || Instruct == P8E) + begin + duration_erase = tdevice_PE; + end + else + begin + duration_erase = tdevice_SE; + end + + EDONE = 1'b0; + ->edone_event; + end + end + + always @(edone_event) + begin : edone_process + EDONE = 1'b0; + #duration_erase EDONE = 1'b1; + end +// ///////////////////////////////////////////////////////////////////////// +// // Main Behavior Process +// // combinational process for next state generation +// ///////////////////////////////////////////////////////////////////////// + + reg rising_edge_PDONE = 1'b0; + reg rising_edge_EDONE = 1'b0; + reg rising_edge_WDONE = 1'b0; + reg rising_edge_DP_out = 1'b0; + reg falling_edge_write = 1'b0; + integer i; + integer j; + + always @(falling_edge_write or rising_edge_PDONE or rising_edge_WDONE + or rising_edge_EDONE or rising_edge_DP_out) + begin: StateGen1 + if (falling_edge_write) + begin + case (current_state) + IDLE : + begin + if (~write) + begin + if ((Instruct == WRR) && WEL) + begin + if (~(Status_reg[7] && ~WPNeg_in && ~QUAD)) + //HPM is disabled when the Quad I/O Mode is enabled + //(Quad bit = 1 in the Configuration Register) + next_state = WRITE_SR; + end + + else if ((Instruct == PP || Instruct == QPP) && + WEL) + begin + sect = Address / 24'h10000; + if (Sec_Prot[sect] == 1'b0) + next_state = PAGE_PG; + end + + else if (Instruct == OTPP && WEL) + begin + if(Address == 256 || Address == 257 || + ((Address >= 258 && Address <= 273) && + PR_LOCK1[(Address-258)/8] == 1'b1) + || Address == 274 + || Address == 275 || ((Address >= 276 && + Address <= 531) && PR_LOCK2[(Address-276)/16] + ==1'b1) || Address == 532 || Address == 533 || + ((Address >= 534 && Address <= 767) + && PR_LOCK3[(Address-534)/16] == 1'b1)) + next_state = OTP_PG; + end + + else if (Instruct == SE && WEL) + begin + sect = Address / 24'h10000; + if (Sec_Prot[sect] == 1'b0) + next_state = SECTOR_ER; + end + + else if (Instruct == P4E && WEL) + begin + sect = Address / 24'h10000; + if (Sec_Prot[sect] == 1'b0 && (((sect == 0 || + sect == 1) && ~TBPARM) || ((sect == SecNum || + sect == SecNum-1) && TBPARM))) + next_state = P4_ER; + end + + else if (Instruct == P8E && WEL) + begin + sect = Address / 24'h10000; + if (Sec_Prot[sect] == 1'b0 && (((sect == 0 || + sect == 1) && ~TBPARM) || ((sect == SecNum || + sect == SecNum-1) && TBPARM))) + next_state = P8_ER; + end + + else if (Instruct == BE && WEL) + begin + if (Status_reg[2]==1'b0 && Status_reg[3]==1'b0 && + Status_reg[4]==1'b0) + next_state = BULK_ER; + end + else if (Instruct == DP) + next_state = DP_DOWN_WAIT; + else + next_state = IDLE; + end + end + + DP_DOWN : + begin + if (~write) + begin + if (Instruct == RES_READ_ES) + next_state = IDLE; + end + end + + endcase + end + + if (rising_edge_PDONE) + begin + if (current_state==PAGE_PG || current_state==OTP_PG) + begin + next_state = IDLE; + end + end + + if (rising_edge_WDONE) + begin + if (current_state==WRITE_SR) + begin + next_state = IDLE; + end + end + + if (rising_edge_EDONE) + begin + if (current_state==SECTOR_ER || current_state==BULK_ER + || current_state==P4_ER || current_state==P8_ER) + begin + next_state = IDLE; + end + end + + if (rising_edge_DP_out) + begin + if (current_state==DP_DOWN_WAIT) + next_state = DP_DOWN; + end + + end + + /////////////////////////////////////////////////////////////////////////// + //FSM Output generation and general functionality + /////////////////////////////////////////////////////////////////////////// + reg rising_edge_read_out = 1'b0; + reg rising_edge_RES_out = 1'b0; + reg Instruct_event = 1'b0; + reg change_addr_event = 1'b0; + reg rising_edge_powered = 1'b0; + reg current_state_event = 1'b0; + + integer WData [0:255]; + integer WOTPData; + integer Addr; + integer Addr_tmp; + + always @(oe_event) + begin + oe = 1'b1; + #1 oe = 1'b0; + end + + always @(rising_edge_read_out or Instruct_event or + change_addr_event or oe or current_state_event or + falling_edge_write or EDONE or WDONE or PDONE or + CSNeg_ipd or rising_edge_RES_out or rising_edge_powered or + rising_edge_DP_out) + begin: Functionality + integer i,j; + + if (rising_edge_read_out) + begin + if (PoweredUp == 1'b1) + ->oe_event; + end + + if (Instruct_event) + begin + read_cnt = 0; + rd_fast = 1'b1; + rd_slow = 1'b0; + rd_jedec = 1'b0; + dual = 1'b0; + if (current_state == DP_DOWN_WAIT) + begin + if (DP_in == 1'b1) + begin + $display ("Command results can be corrupted"); + end + end + if (Instruct == DH_READ || Instruct == QH_READ) + begin + mpm_mode = 1; + end + end + + if (rising_edge_powered) + begin + //The Configuration Register FREEZE bit is cleared. + Sec_conf_reg[0] = 1'b0; + + //The WEL bit resets (disables writes) on power-up + Status_reg[1] = 1'b0; + + if (BPNV == 1) + begin + //When BPNV is set to ‘1’,the BP2-0 bits in the Status Register + //are volatile and will be reset to binary 111 after power on reset. + Status_reg[4] = 1'b1;// BP2 + Status_reg[3] = 1'b1;// BP1 + Status_reg[2] = 1'b1;// BP0 + change_BP = 1'b1; + #1 change_BP = 1'b0; + end + end + + if (change_addr_event) + begin + read_addr = Address; + end + + if (oe || current_state_event) + begin + case (current_state) + IDLE : + begin + if (oe && ~RES_in) + begin + if (Instruct == RDSR) + begin + //Read Status Register + SOut_zd = Status_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + if (Instruct == RCR) + begin + //Read Security Conf. Register + SOut_zd = Sec_conf_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == READ || Instruct == FAST_READ) + begin + //Read Memory array + if (Instruct == READ) + begin + rd_fast = 1'b0; + rd_jedec = 1'b0; + rd_slow = 1'b1; + end + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else if (Instruct == DUAL_READ || Instruct == DH_READ) + begin + //Read Memory array + rd_fast = 1'b0; + rd_slow = 1'b0; + rd_jedec = 1'b0; + dual = 1'b1; + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else if (Instruct == QUAD_READ || Instruct == QH_READ) + begin + //Read Memory array + rd_fast = 1'b0; + rd_slow = 1'b0; + rd_jedec = 1'b0; + dual = 1'b1; + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else if (Instruct == OTPR) + begin + if(read_addr>=OTPLoAddr && read_addr<=OTPHiAddr) + begin + //Read OTP Memory array + rd_fast = 1'b1; + rd_slow = 1'b0; + rd_jedec = 1'b0; + dual = 1'b0; + data_out = OTPMem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + else + begin + //OTP Read operation will not wrap to the + //starting address after the OTP address is at + //its maximum; + //instead, the data will be indeterminate. + SOut_zd = 1'bX; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (Instruct == RDID) + begin + // Read ID + rd_fast = 1'b0; + rd_slow = 1'b0; + rd_jedec = 1'b1; + dual = 1'b0; + ident_out = {Manuf_ID,DeviceID,ExtendedBytes, + ReservedBytes,ReservedBytes, + ReservedBytes,CFI_array_tmp}; + SOut_zd = ident_out[647-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 648) + read_cnt = 0; + end + else if (Instruct == READ_ID) + begin + // --Read Manufacturer and Device ID + if (read_addr % 2 == 0) + begin + data_out[7:0] = Manuf_ID; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + else if (read_addr % 2 == 1) + begin + data_out[7:0] = ES; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = 0; + end + end + end + end + else if (oe && RES_in) + begin + $display ("Command results can be corrupted"); + SOut_zd = 1'bX; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + + WRITE_SR, + SECTOR_ER, + BULK_ER, + P4_ER, + P8_ER, + OTP_PG, + PAGE_PG : + begin + if (oe && Instruct == RDSR) + begin + //Read Status Register + SOut_zd = Status_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + if (oe && Instruct == RCR) + begin + //Read Security Conf. Register + SOut_zd = Sec_conf_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + DP_DOWN : + begin + if (oe && Instruct == RES_READ_ES) + begin + // Read ID + data_out[7:0] = ES; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + + endcase + end + + if (falling_edge_write) + begin + case (current_state) + IDLE : + begin + if (~write) + begin + if (RES_in == 1'b1 && Instruct != DP) + begin + $display ("Command results can be corrupted"); + end + if (Instruct == WREN) + Status_reg[1] = 1'b1; + else if (Instruct == WRDI) + Status_reg[1] = 1'b0; + else if (Instruct == WRR && WEL) + begin + if (~(Status_reg[7] && ~WPNeg_in && ~QUAD)) + begin + WSTART = 1'b1; + WSTART <= #1 1'b0; + Status_reg[0] = 1'b1; + end + else + begin + Status_reg[1] = 0; + end + end + else if ((Instruct == PP || Instruct == QPP) && + WEL) + begin + sect = Address / 24'h10000; + if (Sec_Prot[sect] == 1'b0) + begin + PSTART = 1'b1; + PSTART <= #1 1'b0; + initial_config = 1; + Status_reg[0] = 1'b1; //WIP + Addr = Address; + Addr_tmp = Address; + SA = sect; + wr_cnt = Byte_number; + for (i=0;i<=wr_cnt;i=i+1) + begin + if (Viol != 1'b0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + Status_reg[1] = 1'b0; + end + end + else if (Instruct == OTPP && WEL) + begin + if(Address == 256 || Address == 257 || + ((Address >= 258 && Address <= 273) && + PR_LOCK1[(Address-258)/8] == 1'b1) + || Address == 274 + || Address == 275 || ((Address >= 276 && + Address <= 531) && PR_LOCK2[(Address-276)/16] + ==1'b1) || Address == 532 || Address == 533 || + ((Address >= 534 && Address <= 767) + && PR_LOCK3[(Address-534)/16] == 1'b1)) + begin + PSTART = 1'b1; + PSTART <= #1 1'b0; + Status_reg[0] = 1'b1; //WIP + Addr = Address; + if (Viol != 1'b0 ) + WOTPData = -1; + else + WOTPData = WOTPByte; + end + else if (Address < 100 || Address > 767 ) + begin + Status_reg[6] = 1'b1; + Status_reg[1] = 1'b0; + end + else + begin + Status_reg[1] = 1'b0; + end + end + else if (Instruct == SE && WEL) + begin + sect = Address / 24'h10000; + if (Sec_Prot[sect] == 1'b0) + begin + ESTART = 1'b1; + ESTART <= #1 1'b0; + initial_config = 1; + Status_reg[0] = 1'b1; + Addr = Address; + end + else + begin + Status_reg[1] = 1'b0; + end + end + else if (Instruct == BE && WEL) + begin + if(Status_reg[2]==1'b0 && Status_reg[3]==1'b0 && + Status_reg[4]==1'b0) + begin + ESTART = 1'b1; + ESTART <= #1 1'b0; + initial_config = 1; + Status_reg[0] = 1'b1; + end + else + begin + Status_reg[1] = 1'b0; + end + end + else if (Instruct == P4E && WEL) + begin + sect = Address / 24'h10000; + if (((sect == 0 || + sect == 1) && ~TBPARM) || ((sect == SecNum || + sect == SecNum-1) && TBPARM)) + begin + if (Sec_Prot[sect] == 1'b0) + begin + ESTART = 1'b1; + ESTART <= #1 1'b0; + initial_config = 1; + Status_reg[0] = 1'b1; + Addr = Address; + end + else + begin + Status_reg[1] = 1'b0; + end + end + else + begin + Status_reg[5] = 1'b1; + Status_reg[1] = 1'b0; + end + end + else if (Instruct == P8E && WEL) + begin + sect = Address / 24'h10000; + if (((sect == 0 || + sect == 1) && ~TBPARM) || ((sect == SecNum || + sect == SecNum-1) && TBPARM)) + begin + if (Sec_Prot[sect] == 1'b0) + begin + ESTART = 1'b1; + ESTART <= #1 1'b0; + initial_config = 1; + Status_reg[0] = 1'b1; + Addr = Address; + end + else + begin + Status_reg[1] = 1'b0; + end + end + else + begin + Status_reg[5] = 1'b1; + Status_reg[1] = 1'b0; + end + end + else if (Instruct == CLSR) + begin + Status_reg[5] = 1'b0; + Status_reg[6] = 1'b0; + end + else if (Instruct == DP) + begin + RES_in <= 1'b0; + DP_in = 1'b1; + end + else if (Instruct == RES_READ_ES) + begin + RES_in <= 1'b1; + end + end + + end + + DP_DOWN : + begin + if (~write) + begin + if (Instruct == RES_READ_ES) + RES_in = #1 1'b1; + end + end + + endcase + end + + if(current_state_event || EDONE) + begin + case (current_state) + + SECTOR_ER : + begin + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = -1; + end + if (EDONE) + begin + Status_reg[0] = 1'b0; + Status_reg[1] = 1'b0; + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = MaxData; + end + end + end + BULK_ER : + begin + for (i=0;i<=AddrRANGE;i=i+1) + begin + Mem[i] = -1; + end + + if (EDONE) + begin + Status_reg[0] = 1'b0; + Status_reg[1] = 1'b0; + for (i=0;i<=AddrRANGE;i=i+1) + begin + Mem[i] = MaxData; + end + end + end + P4_ER : + begin + ADDRHILO_PB4(AddrLo, AddrHi, Addr); + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = -1; + end + if (EDONE) + begin + Status_reg[0] = 1'b0; + Status_reg[1] = 1'b0; + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = MaxData; + end + end + end + P8_ER : + begin + ADDRHILO_PB8(AddrLo, AddrHi, Addr); + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = -1; + end + if (EDONE) + begin + Status_reg[0] = 1'b0; + Status_reg[1] = 1'b0; + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = MaxData; + end + end + end + endcase + end + + if(current_state_event || WDONE) + begin + if (current_state == WRITE_SR) + begin + if (WDONE) + begin + Status_reg[0] = 1'b0;//WIP + Status_reg[1] = 1'b0;//WEL + //SRWD bit + Status_reg[7] = Status_reg_in[7];//MSB first + + if (FREEZE == 0) + begin + //The Freeze Bit, when set to 1, locks the current + //state of the BP2-0 bits in Status Register, + //the TBPROT and TBPARM bits in the Config Register + //As long as the FREEZE bit remains cleared to logic + //'0', the other bits of the Configuration register + //including FREEZE are writeable. + Status_reg[4] = Status_reg_in[4];// BP2 + Status_reg[3] = Status_reg_in[3];// BP1 + Status_reg[2] = Status_reg_in[2];// BP0 + + if (cfg_write) + begin + Sec_conf_reg[0] = Sec_conf_reg_in[0];// FREEZE + + if (TBPARM == 1'b0 && initial_config == 1'b0) + begin + Sec_conf_reg[2] = Sec_conf_reg_in[2];//TBPARM + end + + if (TBPROT == 1'b0 && initial_config == 1'b0) + begin + Sec_conf_reg[5] = Sec_conf_reg_in[5];//TBPROT + end + end + + change_BP = 1'b1; + #1 change_BP = 1'b0; + end + + if (cfg_write) + begin + Sec_conf_reg[1] = Sec_conf_reg_in[1];// QUAD + + if (BPNV == 1'b0) + begin + Sec_conf_reg[3] = Sec_conf_reg_in[3];//BPNV + end + end + + end + end + end + + if(current_state_event || PDONE) + begin + if (current_state == PAGE_PG) + begin + ADDRHILO_PG(AddrLo, AddrHi, Addr); + cnt = 0; + + for (i=0;i<=wr_cnt;i=i+1) + begin + new_int = WData[i]; + old_int = Mem[Addr + i - cnt]; + if (new_int > -1) + begin + new_bit = new_int; + if (old_int > -1) + begin + old_bit = old_int; + for(j=0;j<=7;j=j+1) + if (~old_bit[j]) + new_bit[j]=1'b0; + new_int=new_bit; + end + + WData[i]= new_int; + end + else + begin + WData[i] = -1; + end + + Mem[Addr + i -cnt] = - 1; + + if ((Addr + i) == AddrHi) + begin + Addr = AddrLo; + cnt = i + 1; + end + end + + cnt = 0; + + if (PDONE) + begin + Status_reg[0] = 1'b0;//wip + Status_reg[1] = 1'b0;// wel + for (i=0;i<=wr_cnt;i=i+1) + begin + Mem[Addr_tmp + i - cnt] = WData[i]; + if ((Addr_tmp + i) == AddrHi) + begin + Addr_tmp = AddrLo; + cnt = i + 1; + end + end + end + end + end + + if(current_state_event || PDONE) + begin + if (current_state == OTP_PG) + begin + new_int = WOTPData; + old_int = OTPMem[Addr]; + if (new_int > -1) + begin + new_bit = new_int; + if (old_int > -1) + begin + old_bit = old_int; + for(j=0;j<=7;j=j+1) + begin + if (~old_bit[j]) + new_bit[j] = 1'b0; + end + new_int = new_bit; + end + WOTPData = new_int; + end + else + begin + WOTPData = -1; + end + OTPMem[Addr] = -1; + if (PDONE) + begin + Status_reg[0] = 1'b0; + Status_reg[1] = 1'b0; + OTPMem[Addr] = WOTPData; + PR_LOCK1 = {OTPMem[257],OTPMem[256]}; + + PR_LOCK1[15:8] = OTPMem[257]; + PR_LOCK1[7:0] = OTPMem[256]; + PR_LOCK2[15:8] = OTPMem[275]; + PR_LOCK2[7:0] = OTPMem[274]; + PR_LOCK3[15:8] = OTPMem[533]; + PR_LOCK3[7:0] = OTPMem[532]; + end + end + end + + //Output Disable Control + if (CSNeg_ipd ) + begin + SIOut_zd = 1'bZ; + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + end + + if (rising_edge_RES_out) + begin + if(RES_out) + begin + RES_in = 1'b0; + end + end + + if (rising_edge_DP_out) + begin + if (current_state == DP_DOWN_WAIT) + begin + DP_in = 1'b0; + end + end + + end + + always @(change_BP) + begin + if (change_BP) + begin + case (Status_reg[4:2]) + 3'b000 : + begin + Sec_Prot = 256'h0; + end + + 3'b001 : + begin + if (~Sec_conf_reg[5]) + begin + Sec_Prot[SecNum : (SecNum+1)*63/64] = 2'b11; + Sec_Prot[(SecNum+1)*63/64 - 1 : 0] = 126'h0; + end + else + begin + Sec_Prot[(SecNum+1)/64 - 1 : 0] = 2'b11; + Sec_Prot[SecNum : (SecNum+1)/64] = 126'h0; + end + end + + 3'b010 : + begin + if (~Sec_conf_reg[5]) + begin + Sec_Prot[SecNum : (SecNum+1)*31/32] = 4'hF; + Sec_Prot[(SecNum+1)*31/32 - 1 : 0] = 124'h0; + end + else + begin + Sec_Prot[(SecNum+1)/32 - 1 : 0] = 4'hF; + Sec_Prot[SecNum : (SecNum+1)/32] = 124'h0; + end + end + + 3'b011 : + begin + if (~Sec_conf_reg[5]) + begin + Sec_Prot[SecNum : (SecNum+1)*15/16] = 8'hFF; + Sec_Prot[(SecNum+1)*15/16 - 1 : 0] = 120'h0; + end + else + begin + Sec_Prot[(SecNum+1)/16 - 1 : 0] = 8'hFF; + Sec_Prot[SecNum : (SecNum+1)/16] = 120'h0; + end + end + + 3'b100 : + begin + if (~Sec_conf_reg[5]) + begin + Sec_Prot[SecNum : (SecNum+1)*7/8] = 16'hFFFF; + Sec_Prot[(SecNum+1)*7/8 - 1 : 0] = 112'h0; + end + else + begin + Sec_Prot[(SecNum+1)/8 - 1 : 0] = 16'hFFFF; + Sec_Prot[SecNum : (SecNum+1)/8] = 112'h0; + end + end + + 3'b101 : + begin + if (~Sec_conf_reg[5]) + begin + Sec_Prot[SecNum : (SecNum+1)*3/4] + = 32'hFFFFFFFF; + Sec_Prot[(SecNum+1)*3/4 - 1 : 0] = 96'h0; + end + else + begin + Sec_Prot[(SecNum+1)/4 - 1 : 0] + = 32'hFFFFFFFF; + Sec_Prot[SecNum : (SecNum+1)/4] = 96'h0; + end + end + + 3'b110 : + begin + if (~Sec_conf_reg[5]) + begin + Sec_Prot[SecNum : (SecNum+1)/2] + = 64'hFFFFFFFFFFFFFFFF; + Sec_Prot[(SecNum+1)/2 - 1 : 0] = 64'h0; + end + else + begin + Sec_Prot[(SecNum+1)/2 - 1 : 0] + = 64'hFFFFFFFFFFFFFFFF; + Sec_Prot[SecNum : (SecNum+1)/2] = 64'h0; + end + end + + 3'b111 : + begin + Sec_Prot = 128'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + end + + endcase + end + end + + assign fast_rd = rd_fast; + assign rd = rd_slow; + assign rd_jid = rd_jedec; + + always @(SOut_zd or HOLDNeg_in or SIOut_zd) + begin + if (~HOLDNeg_in && ~QUAD) + begin + hold_mode = 1'b1; + SIOut_z = 1'bZ; + SOut_z = 1'bZ; + end + else + begin + if (hold_mode) + begin + SIOut_z <= #(tpd_HOLDNeg_SO) SIOut_zd; + SOut_z <= #(tpd_HOLDNeg_SO) SOut_zd; + hold_mode = 1'b0; + end + else + begin + SIOut_z = SIOut_zd; + SOut_z = SOut_zd; + hold_mode = 1'b0; + end + end + end + +// Procedure ADDRHILO_SEC + task ADDRHILO_SEC; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer sector; + begin + sector = Addr / 20'h10000; + AddrLOW = sector * 20'h10000; + AddrHIGH = sector * 20'h10000 + 16'hFFFF; + end + endtask + +// Procedure ADDRHILO_PG + task ADDRHILO_PG; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer page; + begin + + page = Addr / 16'h100; + AddrLOW = page * 16'h100; + AddrHIGH = page * 16'h100 + 8'hFF; + + end + endtask + +// Procedure ADDRHILO_PB4 + task ADDRHILO_PB4; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer sector; + begin + sector = Addr / 20'h10000; + if (sector == 0 || sector == 1 || + sector == SecNum || sector == SecNum-1) + begin + AddrLOW = (Address/(SecSize_4+1))*(SecSize_4+1); + AddrHIGH = (Address/(SecSize_4+1))*(SecSize_4+1) + SecSize_4; + end + end + endtask + +// Procedure ADDRHILO_PB8 + task ADDRHILO_PB8; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer sector; + begin + sector = Addr / 20'h10000; + if (sector == 0 || sector == SecNum-1) + begin + AddrLOW = (Address/(SecSize_8+1))*(SecSize_8+1); + AddrHIGH = (Address/(SecSize_8+1))*(SecSize_8+1) + SecSize_8; + end + if (sector == 1) + begin + AddrLOW = (Address/(SecSize_8+1))*(SecSize_8+1); + AddrHIGH = (Address/(SecSize_8+1))*(SecSize_8+1) + SecSize_8; + if (AddrHIGH > 20'h1FFFF) + AddrHIGH = 20'h1FFFF; + end + if (sector == SecNum) + begin + AddrLOW = (Address/(SecSize_8+1))*(SecSize_8+1); + AddrHIGH = (Address/(SecSize_8+1))*(SecSize_8+1) + SecSize_8; + if (AddrHIGH > 24'h7FFFFF) + AddrHIGH = 24'h7FFFFF; + end + end + endtask + + always @(negedge CSNeg_ipd) + begin + falling_edge_CSNeg_ipd = 1'b1; + #1 falling_edge_CSNeg_ipd = 1'b0; + end + + always @(posedge SCK_ipd) + begin + rising_edge_SCK_ipd = 1'b1; + #1 rising_edge_SCK_ipd = 1'b0; + end + + always @(negedge SCK_ipd) + begin + falling_edge_SCK_ipd = 1'b1; + #1 falling_edge_SCK_ipd = 1'b0; + end + + always @(posedge CSNeg_ipd) + begin + rising_edge_CSNeg_ipd = 1'b1; + #1 rising_edge_CSNeg_ipd = 1'b0; + end + + always @(negedge write) + begin + falling_edge_write = 1'b1; + #1 falling_edge_write = 1'b0; + end + + always @(posedge PDONE) + begin + rising_edge_PDONE = 1'b1; + #1 rising_edge_PDONE = 1'b0; + end + + always @(posedge WDONE) + begin + rising_edge_WDONE = 1'b1; + #1 rising_edge_WDONE = 1'b0; + end + + always @(posedge EDONE) + begin + rising_edge_EDONE = 1'b1; + #1 rising_edge_EDONE = 1'b0; + end + + always @(posedge DP_out) + begin + rising_edge_DP_out = 1'b1; + #1 rising_edge_DP_out = 1'b0; + end + + always @(posedge RES_out) + begin + rising_edge_RES_out = 1'b1; + #1 rising_edge_RES_out = 1'b0; + end + + always @(posedge read_out) + begin + rising_edge_read_out = 1'b1; + #1 rising_edge_read_out = 1'b0; + end + + always @(posedge PoweredUp) + begin + rising_edge_powered = 1'b1; + #1 rising_edge_powered = 1'b0; + end + + always @(Instruct) + begin + Instruct_event = 1'b1; + #1 Instruct_event = 1'b0; + end + + always @(change_addr) + begin + change_addr_event = 1'b1; + #1 change_addr_event = 1'b0; + end + + always @(current_state) + begin + current_state_event = 1'b1; + #1 current_state_event = 1'b0; + end + +endmodule \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl064p/model/s25fl064p.vhd b/lib/models/memory/flash/serial/S25fl064p/model/s25fl064p.vhd new file mode 100644 index 0000000..d63c5d0 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064p/model/s25fl064p.vhd @@ -0,0 +1,2562 @@ +------------------------------------------------------------------------------- +-- File Name: s25fl064p.vhd +------------------------------------------------------------------------------- +-- Copyright (C) 2012 Spansion, LLC. +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 D.Stanojkovic 08 Jan 22 Inital Release +-- V1.1 D.Stanojkovic 08 Feb 20 BP bits setting corrected +-- V1.2 D.Stanojkovic 08 Mar 04 MPM mode corrected +-- V1.3 D.Stanojkovic 08 Mar 20 MPM mode removed +-- V1.4 J.Stoickov 08 Dec 10 Latest datasheet aligned +-- (S25FL129 064 032P) +-- Program Error bit will not be +-- set after programming +-- in protect memory region +-- V1.5 V.Mancev 10 Sep 29 Implementation of internal pull-up +-- for HOLDNeg and WPNeg pins +-- V1.6 V.Mancev 12 Jan 13 Latest datasheet aligned +-- (S25FL064P_00_05) +------------------------------------------------------------------------------- +-- PART DESCRIPTION: +-- +-- Library: FLASH +-- Technology: FLASH MEMORY +-- Part: S25FL064P +-- +-- Description: 64 Megabit Serial Flash Memory with 104 MHz SPI Bus Interface +-- +------------------------------------------------------------------------------- +-- Known Bugs: +-- +------------------------------------------------------------------------------- +LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; + USE STD.textio.ALL; + USE IEEE.VITAL_timing.ALL; + USE IEEE.VITAL_primitives.ALL; + +LIBRARY FMF; USE FMF.gen_utils.ALL; + USE FMF.conversions.ALL; +------------------------------------------------------------------------------- +-- ENTITY DECLARATION +------------------------------------------------------------------------------- +ENTITY s25fl064p IS + GENERIC ( + -- tipd delays: interconnect path delays + tipd_SCK : VitalDelayType01 := VitalZeroDelay01; + tipd_SI : VitalDelayType01 := VitalZeroDelay01; + tipd_SO : VitalDelayType01 := VitalZeroDelay01; + + tipd_CSNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_HOLDNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; + + -- tpd delays + tpd_SCK_SO : VitalDelayType01Z := UnitDelay01Z; -- tV + tpd_SCK_SI : VitalDelayType01Z := UnitDelay01Z; -- tV + tpd_CSNeg_SO : VitalDelayType01Z := UnitDelay01Z; -- tDIS + tpd_HOLDNeg_SO : VitalDelayType01Z := UnitDelay01Z; -- tLZ,tHZ + + --tsetup values + tsetup_CSNeg_SCK : VitalDelayType := UnitDelay; -- tCSS / + tsetup_HOLDNeg_SCK : VitalDelayType := UnitDelay; -- tHC / + tsetup_SI_SCK : VitalDelayType := UnitDelay; -- tsuDAT / + tsetup_WPNeg_CSNeg : VitalDelayType := UnitDelay; -- tWPS \ + + --thold values + thold_CSNeg_SCK : VitalDelayType := UnitDelay; -- tCSH / + thold_HOLDNeg_SCK : VitalDelayType := UnitDelay; -- tCHHH / + thold_SI_SCK : VitalDelayType := UnitDelay; -- thdDAT / + thold_WPNeg_CSNeg : VitalDelayType := UnitDelay; -- tWPH \ + + --tpw values: pulse width + tpw_SCK_serial_fast_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_serial_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_dual_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_rd_jid_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_serial_fast_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_SCK_serial_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_SCK_dual_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_SCK_rd_jid_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_CSNeg_read_posedge : VitalDelayType := UnitDelay; -- tCS + tpw_CSNeg_pgm_posedge : VitalDelayType := UnitDelay; -- tCS + + -- tperiod min (calculated as 1/max freq) + tperiod_SCK_serial_rd : VitalDelayType := UnitDelay;--fSCK=40MHz + tperiod_SCK_serial_fast_rd : VitalDelayType := UnitDelay;--fSCK=104MHz + tperiod_SCK_dual_fast_rd : VitalDelayType := UnitDelay;--fSCK=80MHz + tperiod_SCK_serial_rd_jid : VitalDelayType := UnitDelay;--fSCK=50MHz + + -- tdevice values: values for internal delays + -- Page Program Operation + tdevice_PP : VitalDelayType := 3 ms; + -- Page Program Operation (ACC=9V)) + tdevice_EP : VitalDelayType := 2.4 ms; --tPP + -- Sector Erase Operation + tdevice_SE : VitalDelayType := 2 sec; --tSE + -- Bulk Erase Operation + tdevice_BE : VitalDelayType := 128 sec; --tBE + -- Write Status Register Operation + tdevice_WR : VitalDelayType := 100 ms; --tW + -- Deep Power Down + tdevice_DP : VitalDelayType := 10 us; --tDP + -- Release from Software Protect Mode + tdevice_RES : VitalDelayType := 30 us; --tRES + -- Parameter block erase + tdevice_PE : VitalDelayType := 800 ms; --tPE + -- VCC (min) to CS# Low + tdevice_PU : VitalDelayType := 300 us; --tPU + -- generic control parameters + InstancePath : STRING := DefaultInstancePath; + TimingChecksOn : BOOLEAN := DefaultTimingChecks; + MsgOn : BOOLEAN := DefaultMsgOn; + XOn : BOOLEAN := DefaultXon; + -- memory file to be loaded + mem_file_name : STRING := "s25fl064p.mem"; + otp_file_name : STRING := "s25fl064pOTP.mem"; + + UserPreload : BOOLEAN := FALSE; --TRUE; + LongTimming : BOOLEAN := TRUE; + + -- For FMF SDF technology file usage + TimingModel : STRING := DefaultTimingModel + ); + PORT ( + SCK : IN std_ulogic := 'U'; -- serial clock input + SI : INOUT std_ulogic := 'U'; -- serial data input + CSNeg : IN std_ulogic := 'U'; -- chip select input + HOLDNeg : INOUT std_ulogic := 'U'; -- hold input + WPNeg : INOUT std_ulogic := 'U'; -- write protect input + SO : INOUT std_ulogic := 'U' -- SO + ); + ATTRIBUTE VITAL_LEVEL0 of s25fl064p : ENTITY IS TRUE; +END s25fl064p; + +------------------------------------------------------------------------------- +-- ARCHITECTURE DECLARATION +------------------------------------------------------------------------------- +ARCHITECTURE vhdl_behavioral of s25fl064p IS + ATTRIBUTE VITAL_LEVEL0 OF vhdl_behavioral : ARCHITECTURE IS TRUE; + + CONSTANT PartID : STRING := "s25fl064p"; + CONSTANT MaxData : NATURAL := 16#FF#; --255; + CONSTANT SecSize : NATURAL := 16#FFFF#; --65535 + CONSTANT SecSize_4 : NATURAL := 16#FFF#; --4095 + CONSTANT SecSize_8 : NATURAL := 16#1FFF#; --8191 + CONSTANT OTPSize : NATURAL := 511; + CONSTANT OTPLoAddr : NATURAL := 16#100#; + CONSTANT OTPHiAddr : NATURAL := 16#2FF#; + CONSTANT SecNum : NATURAL := 127; + CONSTANT PageNum : NATURAL := 16#7FFF#; + CONSTANT HiAddrBit : NATURAL := 23; + CONSTANT AddrRANGE : NATURAL := 16#7FFFFF#; + CONSTANT BYTE : NATURAL := 8; + --Manufacturer Identification + CONSTANT Manuf_ID : NATURAL := 16#01#; + --Electronic Signature + CONSTANT ES : NATURAL := 16#16#; + --Device ID + --Manufacturer Identification && Memory Type && Memory Capacity + CONSTANT Jedec_ID : NATURAL := 16#20#; -- first byte of Device ID + CONSTANT DeviceID : NATURAL := 16#0216#; + CONSTANT ExtendedBytes : NATURAL := 16#4D#; + CONSTANT ReservedBytes : NATURAL := 16#00#; + +-- interconnect path delay signals + SIGNAL SCK_ipd : std_ulogic := 'U'; + SIGNAL SI_ipd : std_ulogic := 'U'; + SIGNAL SO_ipd : std_ulogic := 'U'; + SIGNAL CSNeg_ipd : std_ulogic := 'U'; + SIGNAL HOLDNeg_ipd : std_ulogic := 'U'; + SIGNAL WPNeg_ipd : std_ulogic := 'U'; + SIGNAL HOLDNeg_pullup : std_ulogic := 'U'; + SIGNAL WPNeg_pullup : std_ulogic := 'U'; + + --- internal delays + SIGNAL PP_in : std_ulogic := '0'; + SIGNAL PP_out : std_ulogic := '0'; + SIGNAL PU_in : std_ulogic := '0'; + SIGNAL PU_out : std_ulogic := '0'; + SIGNAL SE_in : std_ulogic := '0'; + SIGNAL SE_out : std_ulogic := '0'; + SIGNAL BE_in : std_ulogic := '0'; + SIGNAL BE_out : std_ulogic := '0'; + SIGNAL EP_in : std_ulogic := '0'; + SIGNAL EP_out : std_ulogic := '0'; + SIGNAL WR_in : std_ulogic := '0'; + SIGNAL WR_out : std_ulogic := '0'; + SIGNAL DP_in : std_ulogic := '0'; + SIGNAL DP_out : std_ulogic := '0'; + SIGNAL PE_in : std_ulogic := '0'; + SIGNAL PE_out : std_ulogic := '0'; + SIGNAL RES_in : std_ulogic := '0'; + SIGNAL RES_out : std_ulogic := '0'; + +BEGIN + --------------------------------------------------------------------------- + -- Internal Delays + --------------------------------------------------------------------------- + -- Artificial VITAL primitives to incorporate internal delays + PP :VitalBuf(PP_out, PP_in, (tdevice_PP ,UnitDelay)); + PU :VitalBuf(PU_out, PU_in, (tdevice_PU ,UnitDelay)); + SE :VitalBuf(SE_out, SE_in, (tdevice_SE ,UnitDelay)); + BE :VitalBuf(BE_out, BE_in, (tdevice_BE ,UnitDelay)); + EP :VitalBuf(EP_out, EP_in, (tdevice_EP ,UnitDelay)); + WR :VitalBuf(WR_out, WR_in, (tdevice_WR ,UnitDelay)); + DP :VitalBuf(DP_out, DP_in, (tdevice_DP ,UnitDelay)); + PE :VitalBuf(PE_out, PE_in, (tdevice_PE ,UnitDelay)); + RES :VitalBuf(RES_out, RES_in, (tdevice_RES ,UnitDelay)); + + --------------------------------------------------------------------------- + -- Wire Delays + --------------------------------------------------------------------------- + WireDelay : BLOCK + BEGIN + + w_1 : VitalWireDelay (SCK_ipd, SCK, tipd_SCK); + w_2 : VitalWireDelay (SI_ipd, SI, tipd_SI); + w_3 : VitalWireDelay (SO_ipd, SO, tipd_SO); + + w_4: VitalWireDelay (CSNeg_ipd, CSNeg, tipd_CSNeg); + w_5: VitalWireDelay (HOLDNeg_ipd, HOLDNeg, tipd_HOLDNeg); + w_6: VitalWireDelay (WPNeg_ipd, WPNeg, tipd_WPNeg); + + END BLOCK; + + --------------------------------------------------------------------------- + -- Main Behavior Block + --------------------------------------------------------------------------- + Behavior: BLOCK + + PORT ( + SCK : IN std_ulogic := 'U'; + SIIn : IN std_ulogic := 'U'; + SIOut : OUT std_ulogic := 'U'; + SOIn : IN std_logic := 'U'; + SOut : OUT std_logic := 'U'; + CSNeg : IN std_ulogic := 'U'; + HOLDNegIn : IN std_ulogic := 'U'; + HOLDNegOut : OUT std_ulogic := 'U'; + WPNegIn : IN std_ulogic := 'U'; + WPNegOut : OUT std_ulogic := 'U' + ); + PORT MAP ( + SCK => SCK_ipd, + SIIn => SI_ipd, + + SOIn => SO_ipd, + + SOut => SO, + + CSNeg => CSNeg_ipd, + + HOLDNegIn => HOLDNeg_ipd, + WPNegIn => WPNeg_ipd, + + SIOut => SI, + WPNegOut => WPNeg, + HOLDNegOut => HOLDNeg + ); + + -- State Machine : State_Type + TYPE state_type IS (IDLE, + WRITE_SR, + PAGE_PG, + OTP_PG, + SECTOR_ER, + BULK_ER, + P4_ER, + P8_ER, + DP_DOWN_WAIT, + DP_DOWN + ); + + -- Instruction Type + TYPE instruction_type IS (NONE, + WREN, + WRDI, + WRR, + RDSR, + READ, + READ_ID, + RDID, + FAST_READ, + DUAL_READ, + QUAD_READ, + DH_READ, + QH_READ, + SE, + BE, + PP, + QPP, + DP, + RES_READ_ES, + ENTER_PRL, + EXIT_PRL, + CLSR, + RCR, + P4E, + P8E, + OTPR, + OTPP + ); + + TYPE WByteType IS ARRAY (0 TO 255) OF INTEGER RANGE -1 TO MaxData; + --Flash Memory Array + TYPE MemArray IS ARRAY (0 TO AddrRANGE) OF INTEGER + RANGE -1 TO MaxData; + --OTP Memory Array + TYPE OTPArr IS ARRAY (OTPLoAddr TO OTPHiAddr) OF INTEGER + RANGE -1 TO MaxData; + + --------------------------------------------------------------------------- + -- memory declaration + --------------------------------------------------------------------------- + SHARED VARIABLE Mem : MemArray := (OTHERS => MaxData); + -- OTP Sector + SHARED VARIABLE OTPMem : OTPArr := (OTHERS => MaxData); + + SIGNAL WByte : WByteType := (OTHERS => 0); + SIGNAL WOTPByte : INTEGER RANGE -1 TO MaxData; + -- states + SIGNAL current_state : state_type; + SIGNAL next_state : state_type; + + SIGNAL Instruct : instruction_type; + --zero delay signal + SIGNAL SOut_zd : std_logic := 'Z'; + SIGNAL SIOut_zd : std_logic := 'Z'; + SIGNAL HOLDNegOut_zd : std_logic := 'Z'; + SIGNAL WPNegOut_zd : std_logic := 'Z'; + --HOLD delay on output data + SIGNAL SOut_z : std_logic := 'Z'; + SIGNAL SIOut_z : std_logic := 'Z'; + -- powerup + SIGNAL PoweredUp : std_logic := '0'; + + SHARED VARIABLE Status_reg : std_logic_vector(7 downto 0) + := (others => '0'); + + SIGNAL Status_reg_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Status register Write In Progress Bit + ALIAS WIP :std_logic IS Status_reg(0); + -- Status register Write Enable Latch Bit + ALIAS WEL :std_logic IS Status_reg(1); + -- Status register block protect Bits + ALIAS BP0 :std_logic IS Status_reg(2); + ALIAS BP1 :std_logic IS Status_reg(3); + ALIAS BP2 :std_logic IS Status_reg(4); + -- status register Erase Error bit + ALIAS E_ERR :std_logic IS Status_reg(5); + -- status register Program Error bit + ALIAS P_ERR :std_logic IS Status_reg(6); + -- status register write disable + ALIAS SRWD :std_logic IS Status_reg(7); + + SHARED VARIABLE Sec_conf_reg : std_logic_vector(7 downto 0) + := (others => '0'); + + SIGNAL Sec_conf_reg_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Configuration Register FREEZE bit + ALIAS FREEZE :std_logic IS Sec_conf_reg(0); + -- Configuration Register QUAD bit + ALIAS QUAD :std_logic IS Sec_conf_reg(1); + -- Configuration Register TBPARM bit + ALIAS TBPARM :std_logic IS Sec_conf_reg(2); + -- Configuration Register BPNV bit + ALIAS BPNV :std_logic IS Sec_conf_reg(3); + -- Security Configuration Register the TBPROT bit + ALIAS TBPROT :std_logic IS Sec_conf_reg(5); + + -- The Lock Protection Registers for OTP Memory space + SHARED VARIABLE PR_LOCK1 :std_logic_vector(15 downto 0); + SHARED VARIABLE PR_LOCK2 :std_logic_vector(15 downto 0); + SHARED VARIABLE PR_LOCK3 :std_logic_vector(15 downto 0); + + --Command Register + SIGNAL write : std_logic := '0'; + SIGNAL cfg_write : std_logic := '0'; + SIGNAL read_out : std_logic := '0'; + + SIGNAL fast_rd : boolean := true; + SIGNAL rd : boolean := false; + SIGNAL dual : boolean := false; + SIGNAL rd_jid : boolean := false; + + SHARED VARIABLE hold_mode : boolean := false; + SHARED VARIABLE mpm_mode : boolean := false; + + SHARED VARIABLE read_cnt : NATURAL := 0; + + SIGNAL change_addr : std_logic := '0'; + + SIGNAL change_BP : std_logic := '0'; + + --FSM control signals + SIGNAL PDONE : std_logic := '1'; -- Page Prog. Done + SIGNAL PSTART : std_logic := '0'; --Start Page Programming + + SIGNAL WDONE : std_logic := '1'; -- Write. Done + SIGNAL WSTART : std_logic := '0'; --Start Write + + SIGNAL ESTART : std_logic := '0'; --Start Erase + SIGNAL EDONE : std_logic := '1'; --Erase Done + + SIGNAL INITIAL_CONFIG : std_logic := '0'; + + -- Sector and subsector addresses + SIGNAL SA : NATURAL RANGE 0 TO SecNum := 0; + SHARED VARIABLE sect : NATURAL RANGE 0 TO SecNum; + + SIGNAL Byte_number : NATURAL RANGE 0 TO 255 := 0; + + -- Sector is protect if '1' + SHARED VARIABLE Sec_Prot : std_logic_vector(SecNum downto 0) := + (OTHERS => '0'); + + SHARED VARIABLE BP : std_logic_vector(2 downto 0) := "000"; + + SIGNAL Address : NATURAL RANGE 0 TO AddrRANGE := 0; + + -- timing check violation + SIGNAL Viol : X01 := '0'; + + PROCEDURE ADDRHILO_SEC( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE Addr : NATURAL) IS + VARIABLE sector : NATURAL RANGE 0 TO SecNum; + BEGIN + sector := Addr/16#10000#; + AddrLOW := sector*16#10000#; + AddrHIGH := sector*16#10000# + 16#0FFFF#; + END ADDRHILO_SEC; + + PROCEDURE ADDRHILO_PG( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE Addr : NATURAL) IS + VARIABLE page : NATURAL RANGE 0 TO PageNum; + BEGIN + page := Addr/16#100#; + AddrLOW := Page*16#100#; + AddrHIGH := Page*16#100# + 16#FF#; + END AddrHILO_PG; + + PROCEDURE ADDRHILO_PB4( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE Addr : NATURAL) IS + VARIABLE Sec : NATURAL RANGE 0 TO SecNum; + BEGIN + Sec := Addr/16#10000#; + IF Sec = 0 OR Sec = 1 OR Sec = SecNum OR Sec = SecNum - 1 THEN + AddrLOW := (Address/(SecSize_4+1))*(SecSize_4+1); + AddrHIGH := (Address/(SecSize_4+1))*(SecSize_4+1) + SecSize_4; + END IF; + END ADDRHILO_PB4; + + PROCEDURE ADDRHILO_PB8( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE Addr : NATURAL) IS + VARIABLE Sec : NATURAL RANGE 0 TO SecNum; + BEGIN + Sec := Addr/16#10000#; + IF Sec = 0 OR Sec = SecNum - 1 THEN + AddrLOW := (Address/(SecSize_8+1))*(SecSize_8+1); + AddrHIGH := (Address/(SecSize_8+1))*(SecSize_8+1) + SecSize_8; + ELSIF Sec = 1 THEN + AddrLOW := (Address/(SecSize_8+1))*(SecSize_8+1); + AddrHIGH := (Address/(SecSize_8+1))*(SecSize_8+1) + SecSize_8; + IF AddrHIGH > 16#1FFFF# THEN + AddrHIGH := 16#1FFFF#; + END IF; + ELSIF Sec = SecNum THEN + AddrLOW := (Address/(SecSize_8+1))*(SecSize_8+1); + AddrHIGH := (Address/(SecSize_8+1))*(SecSize_8+1) + SecSize_8; + IF AddrHIGH > 16#7FFFFF# THEN + AddrHIGH := 16#7FFFFF#; + END IF; + END IF; + END ADDRHILO_PB8; + + BEGIN + + ---------------------------------------------------------------------------- + --Power Up time; + --------------------------------------------------------------------------- + PoweredUp <= '1' AFTER tdevice_PU; + + --------------------------------------------------------------------------- + -- VITAL Timing Checks Procedures + --------------------------------------------------------------------------- + VITALTimingCheck: PROCESS(SIIn, SOIn, SCK_ipd, CSNeg_ipd, HOLDNegIn, + WPNegIn) + -- Timing Check Variables + VARIABLE Tviol_SI_SCK : X01 := '0'; + VARIABLE TD_SI_SCK : VitalTimingDataType; + + VARIABLE Tviol_HOLD_SCK : X01 := '0'; + VARIABLE TD_HOLD_SCK : VitalTimingDataType; + + VARIABLE Tviol_CS_SCK : X01 := '0'; + VARIABLE TD_CS_SCK : VitalTimingDataType; + + VARIABLE Tviol_WS_CS : X01 := '0'; + VARIABLE TD_WS_CS : VitalTimingDataType; + + VARIABLE Tviol_WH_CS : X01 := '0'; + VARIABLE TD_WH_CS : VitalTimingDataType; + + VARIABLE Pviol_CS_read : X01 := '0'; + VARIABLE PD_CS_read : VitalPeriodDataType := VitalPeriodDataInit; + + VARIABLE Pviol_CS_pgm : X01 := '0'; + VARIABLE PD_CS_pgm : VitalPeriodDataType := VitalPeriodDataInit; + + VARIABLE Pviol_SCK_serial_fast : X01 := '0'; + VARIABLE PD_SCK_serial_fast : VitalPeriodDataType := + VitalPeriodDataInit; + + VARIABLE Pviol_SCK_dual : X01 := '0'; + VARIABLE PD_SCK_dual : VitalPeriodDataType := VitalPeriodDataInit; + + VARIABLE Pviol_SCK_rdid : X01 := '0'; + VARIABLE PD_SCK_rdid : VitalPeriodDataType := VitalPeriodDataInit; + + VARIABLE Pviol_SCK_serial : X01 := '0'; + VARIABLE PD_SCK_serial : VitalPeriodDataType := VitalPeriodDataInit; + + VARIABLE Pviol_SCK_serial_fast_rd: X01 := '0'; + VARIABLE PD_SCK_serial_fast_rd : VitalPeriodDataType := + VitalPeriodDataInit; + + VARIABLE Pviol_SCK_serial_rd : X01 := '0'; + VARIABLE PD_SCK_serial_rd : VitalPeriodDataType := VitalPeriodDataInit; + + VARIABLE Pviol_SCK_serial_rdid : X01 := '0'; + VARIABLE PD_SCK_serial_rdid: VitalPeriodDataType := VitalPeriodDataInit; + + VARIABLE Pviol_SCK_dual_fast_rd: X01 := '0'; + VARIABLE PD_SCK_dual_fast_rd : VitalPeriodDataType := + VitalPeriodDataInit; + + VARIABLE Violation : X01 := '0'; + + BEGIN + --------------------------------------------------------------------------- + -- Timing Check Section + --------------------------------------------------------------------------- + IF (TimingChecksOn) THEN + + -- Setup/Hold Check between SI and SCK, serial mode + VitalSetupHoldCheck ( + TestSignal => SIIn, + TestSignalName => "SI", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK, + SetupLow => tsetup_SI_SCK, + HoldHigh => thold_SI_SCK, + HoldLow => thold_SI_SCK, + CheckEnabled => SIOut_z /= SIIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_SI_SCK, + Violation => Tviol_SI_SCK + ); + + -- Setup/Hold Check between HOLD# and SCK / + VitalSetupHoldCheck ( + TestSignal => HOLDNegIn, + TestSignalName => "HOLD#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupLow => tsetup_HOLDNeg_SCK, + SetupHigh => tsetup_HOLDNeg_SCK, + HoldLow => thold_HOLDNeg_SCK, + HoldHigh => thold_HOLDNeg_SCK, + CheckEnabled => QUAD = '1' + AND HOLDNegOut_zd /= HOLDNegIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_HOLD_SCK, + Violation => Tviol_HOLD_SCK + ); + + -- Setup/Hold Check between CS# and SCK + VitalSetupHoldCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_CSNeg_SCK, + SetupLow => tsetup_CSNeg_SCK, + HoldHigh => thold_CSNeg_SCK, + HoldLow => thold_CSNeg_SCK, + CheckEnabled => true, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_CS_SCK, + Violation => Tviol_CS_SCK + ); + + -- Setup Check between WP# and CS# \ + VitalSetupHoldCheck ( + TestSignal => WPNegIn, + TestSignalName => "WP#", + RefSignal => CSNeg_ipd, + RefSignalName => "CS#", + SetupHigh => tsetup_WPNeg_CSNeg, + CheckEnabled => true, + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WS_CS, + Violation => Tviol_WS_CS + ); + + -- Hold Check between WP# and CS# / + VitalSetupHoldCheck ( + TestSignal => WPNegIn, + TestSignalName => "WP#", + RefSignal => CSNeg_ipd, + RefSignalName => "CS#", + HoldHigh => thold_WPNeg_CSNeg, + CheckEnabled => SRWD = '1' AND WEL = '1' AND QUAD = '0', + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WH_CS, + Violation => Tviol_WH_CS + ); + + -- Period Check CS# for Program/Erase, serial mode + VitalPeriodPulseCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + PulseWidthHigh => tpw_CSNeg_pgm_posedge, + PeriodData => PD_CS_pgm, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_CS_pgm, + HeaderMsg => InstancePath & PartID, + CheckEnabled => TRUE ); + + -- Period Check CS# for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + PulseWidthHigh => tpw_CSNeg_read_posedge, + PeriodData => PD_CS_read, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_CS_read, + HeaderMsg => InstancePath & PartID, + CheckEnabled => rd ); + + -- Period Check SCK for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_serial_negedge, + PulseWidthHigh => tpw_SCK_serial_posedge, + PeriodData => PD_SCK_serial, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_serial, + HeaderMsg => InstancePath & PartID, + CheckEnabled => rd); + + -- Period Check SCK for RDID, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_rd_jid_negedge, + PulseWidthHigh => tpw_SCK_rd_jid_posedge, + PeriodData => PD_SCK_rdid, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_rdid, + HeaderMsg => InstancePath & PartID, + CheckEnabled => rd_jid); + + -- Period Check SCK for FAST_READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_serial_fast_negedge, + PulseWidthHigh => tpw_SCK_serial_fast_posedge, + PeriodData => PD_SCK_serial_fast, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_serial_fast, + HeaderMsg => InstancePath & PartID, + CheckEnabled => fast_rd ); + + -- Period Check SCK for DUAL_READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_dual_negedge, + PulseWidthHigh => tpw_SCK_dual_posedge, + PeriodData => PD_SCK_dual, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_dual, + HeaderMsg => InstancePath & PartID, + CheckEnabled => dual); + + -- Period Check SCK for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_serial_rd, + PeriodData => PD_SCK_serial_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_serial_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => rd ); + + -- Period Check SCK for RDID, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_serial_rd_jid, + PeriodData => PD_SCK_serial_rdid, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_serial_rdid, + HeaderMsg => InstancePath & PartID, + CheckEnabled => rd_jid ); + + -- Period Check SCK for other than READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_serial_fast_rd, + PeriodData => PD_SCK_serial_fast_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_serial_fast_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => fast_rd ); + + -- Period Check SCK for other than READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_dual_fast_rd, + PeriodData => PD_SCK_dual_fast_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_dual_fast_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => dual ); + + Violation := Tviol_SI_SCK OR + Tviol_HOLD_SCK OR + Tviol_CS_SCK OR + Tviol_WS_CS OR + Tviol_WH_CS OR + Pviol_CS_read OR + Pviol_CS_pgm OR + Pviol_SCK_serial_fast OR + Pviol_SCK_dual OR + Pviol_SCK_rdid OR + Pviol_SCK_serial OR + Pviol_SCK_serial_rd OR + Pviol_SCK_serial_rdid OR + Pviol_SCK_serial_fast_rd OR + Pviol_SCK_dual_fast_rd; + + Viol <= Violation; + + ASSERT Violation = '0' + REPORT InstancePath & partID & ": simulation may be" & + " inaccurate due to timing violations" + SEVERITY WARNING; + + END IF; + END PROCESS VITALTimingCheck; + +---------------------------------------------------------------------------- +-- sequential process for FSM state transition +---------------------------------------------------------------------------- + StateTransition : PROCESS(next_state, PoweredUp) + + BEGIN + IF PoweredUp = '1' THEN + current_state <= next_state; + END IF; + END PROCESS StateTransition; + + --------------------------------------------------------------------------- + -- Write cycle decode + --------------------------------------------------------------------------- + BusCycleDecode : PROCESS(SCK_ipd, CSNeg_ipd, HOLDNeg_pullup, SIIn, RES_in) + + TYPE bus_cycle_type IS (STAND_BY, + CODE_BYTE, + ADDRESS_BYTES, + DUMMY_BYTES, + MODE_BYTE, + DATA_BYTES + ); + TYPE quad_data_type IS ARRAY (0 TO 511) OF INTEGER RANGE 0 TO 15; + + VARIABLE bus_cycle_state : bus_cycle_type; + + VARIABLE data_cnt : NATURAL := 0; + VARIABLE addr_cnt : NATURAL := 0; + VARIABLE code_cnt : NATURAL := 0; + VARIABLE mode_cnt : NATURAL := 0; + VARIABLE dummy_cnt : NATURAL := 0; + VARIABLE bit_cnt : NATURAL := 0; + VARIABLE Data_in : std_logic_vector(2047 downto 0) + := (others => '0'); + VARIABLE quad_data_in : quad_data_type; + VARIABLE quad_nybble : std_logic_vector(3 downto 0); + VARIABLE Quad_slv : std_logic_vector(3 downto 0); + VARIABLE code : std_logic_vector(7 downto 0); + VARIABLE code_in : std_logic_vector(7 downto 0); + VARIABLE Byte_slv : std_logic_vector(7 downto 0); + VARIABLE addr_bytes : std_logic_vector(HiAddrBit downto 0); + VARIABLE Address_in : std_logic_vector(23 downto 0); + VARIABLE mode_bytes : std_logic_vector(7 downto 0); + VARIABLE mode_in : std_logic_vector(7 downto 0); + BEGIN + + IF rising_edge(CSNeg_ipd) AND NOT(bus_cycle_state = DATA_BYTES) + AND NOT(bus_cycle_state = DUMMY_BYTES) THEN + bus_cycle_state := STAND_BY; + ELSE + CASE bus_cycle_state IS + WHEN STAND_BY => + IF falling_edge(CSNeg_ipd) THEN + Instruct <= NONE; + write <= '1'; + code_cnt := 0; + addr_cnt := 0; + data_cnt := 0; + mode_cnt := 0; + dummy_cnt := 0; + bus_cycle_state := CODE_BYTE; + END IF; + + WHEN CODE_BYTE => + IF rising_edge(SCK_ipd) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD ='1') THEN + Code_in(code_cnt) := SIIn; + code_cnt := code_cnt + 1; + IF code_cnt = BYTE THEN + --MSB first + FOR I IN 7 DOWNTO 0 LOOP + code(i) := code_in(7-i); + END LOOP; + + CASE code IS + WHEN "00000110" => --06h + Instruct <= WREN; + bus_cycle_state := DATA_BYTES; + WHEN "00000100" => --04h + Instruct <= WRDI; + bus_cycle_state := DATA_BYTES; + WHEN "00000001" => --01h + Instruct <= WRR; + bus_cycle_state := DATA_BYTES; + WHEN "00000101" => --05h + Instruct <= RDSR; + bus_cycle_state := DATA_BYTES; + WHEN "00000011" => --03h + Instruct <= READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00001011" => --0Bh + Instruct <= FAST_READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10011111" => --9Fh + Instruct <= RDID; + bus_cycle_state := DATA_BYTES; + WHEN "10010000" => + Instruct <= READ_ID; --90h + bus_cycle_state := ADDRESS_BYTES; + WHEN "10101011" => + Instruct <= RES_READ_ES; --ABh + bus_cycle_state := DUMMY_BYTES; + WHEN "11011000" => --D8h + Instruct <= SE; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11000111" | "01100000" => --C7h or 60h + Instruct <= BE; + bus_cycle_state := DATA_BYTES; + WHEN "00000010" => --02h + Instruct <= PP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00110010" => --32h + Instruct <= QPP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10111001" => --B9h + Instruct <= DP; + bus_cycle_state := DATA_BYTES; + WHEN "00110000" => --30h + Instruct <= CLSR; + bus_cycle_state := DATA_BYTES; + WHEN "00110101" => --35h + Instruct <= RCR; + bus_cycle_state := DATA_BYTES; + WHEN "00100000" => --20h + Instruct <= P4E; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01000000" =>--40h + Instruct <= P8E; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01000010" => --42h + Instruct <= OTPP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01001011" => --4Bh + Instruct <= OTPR; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00111011" => --3Bh + Instruct <= DUAL_READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01101011" => --6Bh + Instruct <= QUAD_READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10111011" => --BBh + Instruct <= DH_READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11101011" => --EBh + Instruct <= QH_READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN others => + null; + END CASE; + END IF; + END IF; + + WHEN ADDRESS_BYTES => + IF rising_edge(SCK_ipd) THEN + IF ((Instruct=FAST_READ OR Instruct=OTPR + OR Instruct=DUAL_READ) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD ='1')) + OR (Instruct=QUAD_READ AND QUAD = '1') THEN + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 3*BYTE THEN + FOR I IN 23 DOWNTO 23-HiAddrBit LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := DUMMY_BYTES; + END IF; + ELSIF Instruct = DH_READ AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD ='1') THEN + IF SOIn /= 'Z' THEN + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt+1) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 12 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 23-HiAddrBit LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + ELSE + mpm_mode := FALSE; + bus_cycle_state := STAND_BY; + END IF; + ELSIF Instruct = QH_READ THEN + IF QUAD = '1' THEN + IF SOIn /= 'Z' THEN + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 6 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 23-HiAddrBit LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + ELSE + mpm_mode := FALSE; + bus_cycle_state := STAND_BY; + END IF; + ELSE + bus_cycle_state := STAND_BY; + END IF; + ELSIF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD ='1') THEN + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 3*BYTE THEN + FOR I IN 23 DOWNTO 23-HiAddrBit LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + END IF; + + WHEN MODE_BYTE => + IF rising_edge(SCK_ipd) THEN + IF Instruct=DH_READ AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD ='1') THEN + mode_in(2*mode_cnt) := SOIn; + mode_in(2*mode_cnt+1) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/2 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF Instruct=QH_READ AND QUAD = '1' THEN + mode_in(4*mode_cnt) := HOLDNegIn; + mode_in(4*mode_cnt+1) := WPNegIn; + mode_in(4*mode_cnt+2) := SOIn; + mode_in(4*mode_cnt+3) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/4 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + dummy_cnt := 0; + END IF; + + WHEN DUMMY_BYTES => + IF rising_edge(SCK_ipd) THEN + IF QUAD = '1' AND (Instruct=QUAD_READ + OR Instruct=QH_READ) THEN + dummy_cnt := dummy_cnt + 1; + IF dummy_cnt = BYTE AND Instruct=QUAD_READ THEN + bus_cycle_state := DATA_BYTES; + ELSIF dummy_cnt = BYTE/2 AND Instruct=QH_READ THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD ='1') THEN + dummy_cnt := dummy_cnt + 1; + IF dummy_cnt = BYTE THEN + IF Instruct=FAST_READ OR Instruct=OTPR OR + Instruct=DUAL_READ THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF dummy_cnt = 3*BYTE THEN + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + END IF; + + IF rising_edge(CSNeg_ipd) THEN + IF (((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD ='1') + AND dummy_cnt = 0 AND Instruct = RES_READ_ES) THEN + write <= '0'; + END IF; + bus_cycle_state := STAND_BY; + END IF; + + WHEN DATA_BYTES => + IF falling_edge(SCK_ipd) AND CSNeg_ipd = '0' THEN + IF ((Instruct = READ OR Instruct = FAST_READ + OR Instruct = DUAL_READ OR Instruct = DH_READ + OR Instruct = RES_READ_ES OR Instruct = RDID + OR Instruct = READ_ID OR Instruct = RDSR + OR Instruct = RCR OR Instruct = OTPR) + AND ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD ='1')) + OR ((Instruct=QUAD_READ OR Instruct=QH_READ) + AND QUAD = '1') THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + IF rising_edge(SCK_ipd) THEN + IF QUAD = '1' AND Instruct=QPP THEN + quad_nybble := HOLDNegIn & WPNegIn & SOIn & SIIn; + IF data_cnt > 511 THEN + --In case of quad mode and QPP, + --if more than 512 bytes are sent to the device + FOR I IN 0 TO 510 LOOP + quad_data_in(i) := quad_data_in(i+1); + END LOOP; + quad_data_in(511) := to_nat(quad_nybble); + data_cnt := data_cnt +1; + ELSE + IF quad_nybble /= "ZZZZ" THEN + quad_data_in(data_cnt) := + to_nat(quad_nybble); + END IF; + data_cnt := data_cnt +1; + END IF; + ELSIF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD ='1') THEN + IF data_cnt > 2047 THEN + --In case of serial mode and PP, + --if more than 256 bytes are sent to the device + IF bit_cnt = 0 THEN + FOR I IN 0 TO (255*BYTE - 1) LOOP + Data_in(i) := Data_in(i+8); + END LOOP; + END IF; + Data_in(2040 + bit_cnt) := SIIn; + bit_cnt := bit_cnt + 1; + IF bit_cnt = 8 THEN + bit_cnt := 0; + END IF; + data_cnt := data_cnt + 1; + ELSE + Data_in(data_cnt) := SIIn; + data_cnt := data_cnt + 1; + bit_cnt := 0; + END IF; + END IF; + END IF; + + IF rising_edge(CSNeg_ipd) THEN + IF mpm_mode AND mode_bytes(7 downto 4) = "1010" + AND (Instruct = DH_READ OR Instruct = QH_READ) THEN + bus_cycle_state := ADDRESS_BYTES; + ELSE + mpm_mode := FALSE; + bus_cycle_state := STAND_BY; + END IF; + CASE Instruct IS + WHEN WREN | WRDI | DP | BE | SE | P4E | P8E + | CLSR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD ='1') THEN + IF data_cnt = 0 THEN + write <= '0'; + END IF; + END IF; + WHEN RES_READ_ES => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD ='1') THEN + write <= '0'; + END IF; + WHEN WRR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD ='1') THEN + IF ((data_cnt mod 8) = 0 AND + data_cnt > 0) THEN + IF data_cnt = 8 THEN + write <= '0'; + cfg_write <= '0'; + FOR i IN 0 TO 7 LOOP + Status_reg_in(i) <= + Data_in(7-i); + END LOOP; + ELSIF data_cnt = 16 THEN + --After the 16th cycle both the + --Status and Configuration Registers + --are written to. + write <= '0'; + cfg_write <= '1'; + FOR i IN 0 TO 7 LOOP + Status_reg_in(i) <= + Data_in(7-i); + Sec_conf_reg_in(i) <= + Data_in(15-i); + END LOOP; + END IF; + END IF; + END IF; + + WHEN PP => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD ='1') THEN + IF data_cnt > 0 THEN + IF data_cnt mod 8 = 0 THEN + write <= '0'; + FOR I IN 0 TO 255 LOOP + FOR J IN 7 DOWNTO 0 LOOP + Byte_slv(j) := + Data_in((i*8) + (7-j)); + END LOOP; + WByte(i) <= + to_nat(Byte_slv); + END LOOP; + IF data_cnt > 256*BYTE THEN + Byte_number <= 255; + ELSE + Byte_number <= data_cnt/8-1; + END IF; + END IF; + END IF; + END IF; + + WHEN QPP => + IF data_cnt > 0 THEN + IF data_cnt mod 2 = 0 THEN + write <= '0'; + FOR I IN 0 TO 255 LOOP + FOR J IN 1 DOWNTO 0 LOOP + Quad_slv := + to_slv(quad_data_in((i*2) + + (1-j)),4); + + Byte_slv(4*j+3 DOWNTO 4*j) := + Quad_slv; + END LOOP; + WByte(i) <= + to_nat(Byte_slv); + END LOOP; + IF data_cnt > 512 THEN + Byte_number <= 255; + ELSE + Byte_number <= data_cnt/2-1; + END IF; + END IF; + END IF; + + WHEN OTPP => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD ='1') THEN + IF data_cnt = 8 THEN + write <= '0'; + FOR J IN 7 DOWNTO 0 LOOP + Byte_slv(j) := Data_in(7-j); + END LOOP; + WOTPByte <= to_nat(Byte_slv); + END IF; + END IF; + + WHEN others => + null; + END CASE; + END IF; + + END CASE; + END IF; + + END PROCESS BusCycleDecode; + + --------------------------------------------------------------------------- + -- Timing control for the Page Program + --------------------------------------------------------------------------- + ProgTime : PROCESS(PSTART) + VARIABLE pob : time; + BEGIN + IF LongTimming THEN + pob := tdevice_PP; + ELSE + pob := tdevice_PP / 100; + END IF; + IF rising_edge(PSTART) AND PDONE = '1' THEN + IF Sec_Prot(SA) = '0' THEN + PDONE <= '0', '1' AFTER pob; + END IF; + END IF; + END PROCESS ProgTime; + + --------------------------------------------------------------------------- + -- Timing control for the Write Status Register + --------------------------------------------------------------------------- + WriteTime : PROCESS(WSTART) + VARIABLE wob : time; + BEGIN + IF LongTimming THEN + wob := tdevice_WR; + ELSE + wob := tdevice_WR / 100; + END IF; + IF rising_edge(WSTART) AND WDONE = '1' THEN + WDONE <= '0', '1' AFTER wob; + END IF; + END PROCESS WriteTime; + + --------------------------------------------------------------------------- + -- Timing control for the Bulk Erase + --------------------------------------------------------------------------- + ErsTime : PROCESS(ESTART) + VARIABLE seo : time; + VARIABLE beo : time; + VARIABLE peo : time; + VARIABLE duration : time; + BEGIN + IF LongTimming THEN + seo := tdevice_SE; + beo := tdevice_BE; + peo := tdevice_PE; + ELSE + seo := tdevice_SE / 1000; + beo := tdevice_BE / 1000; + peo := tdevice_PE / 1000; + END IF; + IF rising_edge(ESTART) AND EDONE = '1' THEN + IF Instruct = BE THEN + duration := beo; + ELSIF Instruct = P4E OR Instruct = P8E THEN + duration := peo; + ELSE --Instruct = SE + duration := seo; + END IF; + EDONE <= '0', '1' AFTER duration; + END IF; + END PROCESS ErsTime; + + CheckCEOnPowerUP :PROCESS + BEGIN + IF CSNeg /= '1' THEN + REPORT InstancePath & partID & + ": Device is selected during Power Up" + SEVERITY WARNING; + END IF; + WAIT; + END PROCESS; + + --------------------------------------------------------------------------- + -- Main Behavior Process + -- combinational process for next state generation + --------------------------------------------------------------------------- + StateGen :PROCESS(write, CSNeg, WDONE, PDONE, EDONE, DP_out) + + BEGIN + ----------------------------------------------------------------------- + -- Functionality Section + ----------------------------------------------------------------------- + + CASE current_state IS + WHEN IDLE => + IF falling_edge(write) THEN + IF Instruct = WRR AND WEL = '1' + AND not(SRWD='1' AND WPNeg_pullup='0' AND QUAD='0') THEN + -- can not execute if HPM is entered + -- or if WEL bit is zero + next_state <= WRITE_SR; + ELSIF (Instruct = PP OR Instruct = QPP) AND WEL = '1' THEN + sect := Address / 16#10000#; + IF Sec_Prot(sect) = '0' THEN + next_state <= PAGE_PG; + END IF; + ELSIF Instruct = OTPP AND WEL = '1' THEN + IF Address = 256 OR Address = 257 OR + ((Address >= 258 AND Address <= 273) AND + PR_LOCK1((Address-258)/8) = '1') OR Address = 274 OR + Address = 275 OR((Address >= 276 AND Address <= 531) + AND PR_LOCK2((Address-276)/16) = '1') OR Address = 532 + OR Address = 533 OR((Address >= 534 AND Address <= 767) + AND PR_LOCK3((Address-534)/16) = '1') THEN + next_state <= OTP_PG; + END IF; + ELSIF Instruct = SE AND WEL = '1' THEN + sect := Address / 16#10000#; + IF Sec_Prot(sect) = '0' THEN + next_state <= SECTOR_ER; + END IF; + ELSIF Instruct = P4E AND WEL = '1' THEN + sect := Address / 16#10000#; + IF Sec_Prot(sect) = '0' AND (((sect=0 OR sect=1) + AND TBPARM='0') OR ((sect=SecNum OR sect=SecNum-1) + AND TBPARM='1')) THEN + next_state <= P4_ER; + END IF; + ELSIF Instruct = P8E AND WEL = '1' THEN + sect := Address / 16#10000#; + IF Sec_Prot(sect) = '0' AND (((sect=0 OR sect=1) + AND TBPARM='0') OR ((sect=SecNum OR sect=SecNum-1) + AND TBPARM='1')) THEN + next_state <= P8_ER; + END IF; + ELSIF Instruct = BE AND WEL = '1' AND + (BP0='0' AND BP1='0' AND BP2='0') THEN + next_state <= BULK_ER; + ELSIF Instruct = DP THEN + next_state <= DP_DOWN_WAIT; + ELSE + next_state <= IDLE; + END IF; + END IF; + + WHEN WRITE_SR => + IF rising_edge(WDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PAGE_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN OTP_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN BULK_ER | SECTOR_ER | P4_ER | P8_ER => + IF rising_edge(EDONE) THEN + next_state <= IDLE; + END IF; + + WHEN DP_DOWN_WAIT => + IF rising_edge(DP_out) THEN + next_state <= DP_DOWN; + END IF; + + WHEN DP_DOWN => + IF falling_edge(write) AND Instruct = RES_READ_ES THEN + next_state <= IDLE; + END IF; + + END CASE; + + END PROCESS StateGen; + + --------------------------------------------------------------------------- + --FSM Output generation and general funcionality + --------------------------------------------------------------------------- + Functional : PROCESS(write,read_out, WDONE, PDONE, EDONE, current_state, + CSNeg_ipd, HOLDNeg_pullup, Instruct, Address, WByte, + DP_out, RES_out, change_addr, PoweredUp, WPNeg_pullup) + --Common Flash Interface Query codes + TYPE CFItype IS ARRAY (16#07# TO 16#50#) OF + INTEGER RANGE -1 TO 16#FF#; + TYPE WDataType IS ARRAY (0 TO 255) OF INTEGER RANGE -1 TO MaxData; + + VARIABLE CFI_array : CFItype := (OTHERS => -1); + VARIABLE WData : WDataType := (OTHERS => 0); + VARIABLE WOTPData : INTEGER RANGE -1 to MaxData; + VARIABLE oe : boolean := FALSE; + + VARIABLE AddrLo : NATURAL; + VARIABLE AddrHi : NATURAL; + VARIABLE Addr : NATURAL; + VARIABLE Addr_tmp : NATURAL; + + VARIABLE read_addr : NATURAL RANGE 0 TO AddrRANGE; + VARIABLE data_out : std_logic_vector(7 downto 0); + VARIABLE ident_out : std_logic_vector(647 downto 0); + VARIABLE CFI_array_tmp : std_logic_vector(591 downto 0); + + VARIABLE old_bit : std_logic_vector(7 downto 0); + VARIABLE new_bit : std_logic_vector(7 downto 0); + VARIABLE old_int : INTEGER RANGE -1 to MaxData; + VARIABLE new_int : INTEGER RANGE -1 to MaxData; + VARIABLE wr_cnt : NATURAL RANGE 0 TO 255; + + VARIABLE sect : NATURAL RANGE 0 TO SecNum; + VARIABLE cnt : NATURAL RANGE 0 TO 256 := 0; + + BEGIN + ----------------------------------------------------------------------- + -- Functionality Section + ----------------------------------------------------------------------- + + oe := rising_edge(read_out) AND PoweredUp = '1'; + + IF Instruct'EVENT THEN + read_cnt := 0; + fast_rd <= true; + rd_jid <= false; + dual <= false; + rd <= false; + IF Instruct = DH_READ OR Instruct = QH_READ THEN + mpm_mode := TRUE; + END IF; + END IF; + + IF rising_edge(PoweredUp) THEN + + FREEZE := '0'; + --When BPNV is set to '1'. the BP2-0 bits in Status Register are + --volatile and will be reset binary 111 after power-on reset + IF BPNV = '1' THEN + BP0 := '1'; + BP1 := '1'; + BP2 := '1'; + BP := BP2 & BP1 & BP0; + change_BP <= '1', '0' AFTER 1 ns; + END IF; + END IF; + + IF rising_edge(change_addr) THEN + read_addr := Address; + END IF; + + IF RES_out'EVENT AND RES_out = '1' THEN + RES_in <= '0'; + END IF; + + CASE current_state IS + WHEN IDLE => + IF falling_edge(write) THEN + read_cnt := 0; + IF RES_in = '1' AND Instruct /= DP THEN + ASSERT false + REPORT InstancePath & partID & "Command results" & + " can be corrupted, a delay of tRES" & + " currently in progress." + SEVERITY WARNING; + END IF; + IF Instruct = WREN THEN + WEL := '1'; + ELSIF Instruct = WRDI THEN + WEL := '0'; + ELSIF Instruct = WRR AND WEL = '1' THEN + IF not(SRWD='1' AND WPNeg_pullup='0' AND QUAD='0') THEN + -- can not execute if HPM is entered + -- or if WEL bit is zero + WSTART <= '1', '0' AFTER 1 ns; + WIP := '1'; + ELSE + WEL := '0'; + END IF; + ELSIF (Instruct = PP OR Instruct = QPP) AND WEL = '1' THEN + sect := Address / 16#10000#; + IF Sec_Prot(sect) = '0' THEN + PSTART <= '1', '0' AFTER 1 ns; + INITIAL_CONFIG <= '1'; + WIP := '1'; + SA <= sect; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + WEL := '0'; + END IF; + ELSIF Instruct = OTPP AND WEL = '1' THEN + IF Address = 256 OR Address = 257 OR + ((Address >= 258 AND Address <= 273) AND + PR_LOCK1((Address-258)/8)='1') OR Address=274 OR + Address=275 OR ((Address>=276 AND Address<=531) + AND PR_LOCK2((Address-276)/16)='1') OR Address=532 + OR Address=533 OR ((Address>=534 AND Address<=767) + AND PR_LOCK3((Address-534)/16) = '1') THEN + PSTART <= '1', '0' AFTER 1 ns; + WIP := '1'; + Addr := Address; + IF Viol /= '0' THEN + WOTPData := -1; + ELSE + WOTPData := WOTPByte; + END IF; + ELSIF (Address < 100 OR Address > 767 ) THEN + P_ERR := '1'; + WEL := '0'; + ELSE + WEL := '0'; + END IF; + ELSIF Instruct = SE AND WEL = '1' THEN + sect := Address / 16#10000#; + IF Sec_Prot(sect) = '0' THEN + ESTART <= '1', '0' AFTER 1 ns; + INITIAL_CONFIG <= '1'; + WIP := '1'; + Addr := Address; + ELSE + WEL := '0'; + END IF; + ELSIF Instruct = BE AND WEL = '1' THEN + IF (BP0='0' AND BP1='0' AND BP2='0') THEN + ESTART <= '1', '0' AFTER 1 ns; + INITIAL_CONFIG <= '1'; + WIP := '1'; + ELSE + WEL := '0'; + END IF; + ELSIF Instruct = P4E AND WEL = '1' THEN + sect := Address / 16#10000#; + IF ((sect=0 OR sect=1) AND TBPARM='0') + OR ((sect=SecNum OR sect=SecNum-1) + AND TBPARM='1') THEN + IF Sec_Prot(sect) = '0' THEN + ESTART <= '1', '0' AFTER 1 ns; + INITIAL_CONFIG <= '1'; + WIP := '1'; + Addr := Address; + ELSE + WEL := '0'; + END IF; + ELSE + E_ERR := '1'; + WEL := '0'; + END IF; + ELSIF Instruct = P8E AND WEL = '1' THEN + sect := Address / 16#10000#; + IF ((sect=0 OR sect=1) AND TBPARM='0') + OR ((sect=SecNum OR sect=SecNum-1) + AND TBPARM='1') THEN + IF Sec_Prot(sect) = '0' THEN + ESTART <= '1', '0' AFTER 1 ns; + INITIAL_CONFIG <= '1'; + WIP := '1'; + Addr := Address; + ELSE + WEL := '0'; + END IF; + ELSE + E_ERR := '1'; + WEL := '0'; + END IF; + ELSIF Instruct = CLSR THEN + E_ERR := '0'; + P_ERR := '0'; + ELSIF Instruct = DP THEN + RES_in <= '0'; + DP_in <= '1'; + ELSIF Instruct = RES_READ_ES THEN + RES_in <= '1'; + END IF; + + ELSIF oe AND RES_in = '0' THEN + IF Instruct = RDSR THEN + --Read Status Register + SOut_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RCR THEN + --Read Security Conf. Register + SOut_zd <= Sec_conf_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = READ OR Instruct = FAST_READ THEN + --Read Memory array + IF Instruct = READ THEN + fast_rd <= false; + rd_jid <= false; + rd <= true; + END IF; + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSIF Instruct = DUAL_READ OR Instruct = DH_READ THEN + --Read Memory array + fast_rd <= false; + rd <= false; + rd_jid <= false; + dual <= true; + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSIF (Instruct = QUAD_READ OR Instruct = QH_READ) + AND QUAD = '1' THEN + --Read Memory array + fast_rd <= false; + rd <= false; + rd_jid <= false; + dual <= true; + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSIF Instruct = OTPR THEN + IF (read_addr>=OTPLoAddr) AND (read_addr<=OTPHiAddr) + THEN + --Read OTP Memory array + fast_rd <= true; + rd_jid <= false; + rd <= false; + data_out := to_slv(OTPMem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + ELSIF (read_addr > OTPHiAddr) THEN + --OTP Read operation will not wrap to the + --starting address after the OTP address is at + --its maximum or Read Password Protection Mode + --is selected; instead, the data beyond the + --maximum OTP address will be undefined. + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF Instruct = RDID THEN + --Read Device ID + --can be terminated by driving CSNeg high + --at any time + fast_rd <= false; + rd_jid <= true; + rd <= false; + ident_out := to_slv(Manuf_ID,8) & to_slv(DeviceID,16) & + to_slv(ExtendedBytes,8) & to_slv(ReservedBytes,8) & + to_slv(ReservedBytes,8) & to_slv(ReservedBytes,8) & + CFI_array_tmp; + SOut_zd <= ident_out(647-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 648 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = READ_ID THEN + --Read Manufacturer and Device ID + IF read_addr MOD 2 = 0 THEN + data_out := to_slv(Manuf_ID,8); + SOut_zd <= data_out(7 - read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + ELSE + data_out := to_slv(ES,8); + SOut_zd <= data_out(7 - read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := 0; + END IF; + END IF; + END IF; + ELSIF oe AND RES_in = '1' THEN + SOut_zd <= 'X'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ASSERT false + REPORT InstancePath & partID & "Command results" & + " can be corrupted, a delay of tRES" & + " currently in progress." + SEVERITY WARNING; + END IF; + + WHEN WRITE_SR => + IF oe AND Instruct = RDSR THEN + --Read Status Register + SOut_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + IF oe AND Instruct = RCR THEN + SOut_zd <= Sec_conf_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + + IF WDONE = '1' THEN + WIP := '0'; + WEL := '0'; + SRWD := Status_reg_in(7);--MSB first + + IF FREEZE='0' THEN + --The Freeze Bit, when set to 1, locks the current + --state of the BP2-0 bits in Status Register, + --the TBPROT and TBPARM bits in the Config Register + --As long as the FREEZE bit remains cleared to logic + --'0', the other bits of the Configuration register + --including FREEZE are writeable. + + BP2 := Status_reg_in(4); + BP1 := Status_reg_in(3); + BP0 := Status_reg_in(2); + + BP := BP2 & BP1 & BP0; + + IF cfg_write = '1' THEN + + FREEZE := Sec_conf_reg_in(0);--MSB first + + IF TBPARM = '0' AND INITIAL_CONFIG = '0' THEN + TBPARM := Sec_conf_reg_in(2); + END IF; + + IF TBPROT = '0' AND INITIAL_CONFIG = '0' THEN + TBPROT := Sec_conf_reg_in(5); + END IF; + + END IF; + + change_BP <= '1', '0' AFTER 1 ns; + END IF; + + IF cfg_write = '1' THEN + QUAD := Sec_conf_reg_in(1); + + IF BPNV = '0' THEN + BPNV := Sec_conf_reg_in(3); + END IF; + END IF; + END IF; + + WHEN PAGE_PG => + IF oe AND Instruct = RDSR THEN + --Read Status Register + SOut_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + IF oe AND Instruct = RCR THEN + SOut_zd <= Sec_conf_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + + ADDRHILO_PG(AddrLo, AddrHi, Addr); + cnt := 0; + + FOR i IN 0 TO wr_cnt LOOP + new_int := WData(i); + old_int := Mem(Addr + i - cnt); + IF new_int > -1 THEN + new_bit := to_slv(new_int,8); + IF old_int > -1 THEN + old_bit := to_slv(old_int,8); + FOR j IN 0 TO 7 LOOP + IF old_bit(j) = '0' THEN + new_bit(j) := '0'; + END IF; + END LOOP; + new_int := to_nat(new_bit); + END IF; + WData(i) := new_int; + ELSE + WData(i) := -1; + END IF; + + Mem(Addr + i - cnt) := -1; + + IF (Addr + i) = AddrHi THEN + Addr := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + cnt :=0; + IF PDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO wr_cnt LOOP + Mem(Addr_tmp + i - cnt) := WData(i); + IF (Addr_tmp + i) = AddrHi THEN + Addr_tmp := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + END IF; + + WHEN OTP_PG => + IF oe AND Instruct = RDSR THEN + --Read Status Register + SOut_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + IF oe AND Instruct = RCR THEN + SOut_zd <= Sec_conf_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + + new_int := WOTPData; + old_int := OTPMem(Addr); + IF new_int > -1 THEN + new_bit := to_slv(new_int,8); + IF old_int > -1 THEN + old_bit := to_slv(old_int,8); + FOR j IN 0 TO 7 LOOP + IF old_bit(j) = '0' THEN + new_bit(j) := '0'; + END IF; + END LOOP; + new_int := to_nat(new_bit); + END IF; + WOTPData := new_int; + ELSE + WOTPData := -1; + END IF; + OTPMem(Addr) := -1; + IF PDONE = '1' THEN + WIP := '0'; + WEL := '0'; + OTPMem(Addr) := WOTPData; + PR_LOCK1 := to_slv(OTPMem(257),8) & to_slv(OTPMem(256),8); + PR_LOCK2 := to_slv(OTPMem(275),8) & to_slv(OTPMem(274),8); + PR_LOCK3 := to_slv(OTPMem(533),8) & to_slv(OTPMem(532),8); + END IF; + + WHEN SECTOR_ER => + IF oe AND Instruct = RDSR THEN + --Read Status Register + SOut_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + IF oe AND Instruct = RCR THEN + SOut_zd <= Sec_conf_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := -1; + END LOOP; + IF EDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := MaxData; + END LOOP; + END IF; + + WHEN BULK_ER => + IF oe AND Instruct = RDSR THEN + --Read Status Register + SOut_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + IF oe AND Instruct = RCR THEN + SOut_zd <= Sec_conf_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + FOR i IN 0 TO AddrRANGE LOOP + Mem(i) := -1; + END LOOP; + IF EDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO AddrRANGE LOOP + Mem(i) := MaxData; + END LOOP; + END IF; + + WHEN P4_ER => + IF oe AND Instruct = RDSR THEN + --Read Status Register + SOut_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + IF oe AND Instruct = RCR THEN + SOut_zd <= Sec_conf_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ADDRHILO_PB4(AddrLo, AddrHi, Addr); + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := -1; + END LOOP; + IF EDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := MaxData; + END LOOP; + END IF; + + WHEN P8_ER => + IF oe AND Instruct = RDSR THEN + --Read Status Register + SOut_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + IF oe AND Instruct = RCR THEN + SOut_zd <= Sec_conf_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ADDRHILO_PB8(AddrLo, AddrHi, Addr); + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := -1; + END LOOP; + IF EDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := MaxData; + END LOOP; + END IF; + + WHEN DP_DOWN_WAIT => + IF rising_edge(DP_out) THEN + DP_in <= '0'; + ELSIF DP_in = '1' AND Instruct'EVENT THEN + ASSERT false + REPORT InstancePath & partID & "Command results" & + " can be corrupted, a delay of tPD" & + " currently in progress." + SEVERITY WARNING; + END IF; + + WHEN DP_DOWN => + IF falling_edge(write) THEN + IF Instruct = RES_READ_ES THEN + RES_in <= '1'; + END IF; + ELSIF oe AND Instruct = RES_READ_ES THEN + --Read Electronic Signature + data_out := to_slv(ES,8); + SOut_zd <= data_out(7 - read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + + END CASE; + + --Output Disable Control + IF (CSNeg_ipd = '1') THEN + SIOut_zd <= 'Z'; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + END IF; + + IF NOW = 0 ns THEN + CFI_array(16#07#) := 16#FF#; + CFI_array(16#08#) := 16#FF#; + CFI_array(16#09#) := 16#FF#; + CFI_array(16#0A#) := 16#FF#; + CFI_array(16#0B#) := 16#FF#; + CFI_array(16#0C#) := 16#FF#; + CFI_array(16#0D#) := 16#FF#; + CFI_array(16#0E#) := 16#FF#; + CFI_array(16#0F#) := 16#FF#; + --Product Group CFI Query Identification String + CFI_array(16#10#) := 16#51#; + CFI_array(16#11#) := 16#52#; + CFI_array(16#12#) := 16#59#; + CFI_array(16#13#) := 16#02#; + CFI_array(16#14#) := 16#00#; + CFI_array(16#15#) := 16#40#; + CFI_array(16#16#) := 16#00#; + CFI_array(16#17#) := 16#00#; + CFI_array(16#18#) := 16#00#; + CFI_array(16#19#) := 16#00#; + CFI_array(16#1A#) := 16#00#; + --Product Group CFI system interface string + CFI_array(16#1B#) := 16#27#; + CFI_array(16#1C#) := 16#36#; + CFI_array(16#1D#) := 16#00#; + CFI_array(16#1E#) := 16#00#; + CFI_array(16#1F#) := 16#0B#; + CFI_array(16#20#) := 16#0B#; + CFI_array(16#21#) := 16#09#; + CFI_array(16#22#) := 16#10#; + CFI_array(16#23#) := 16#01#; + CFI_array(16#24#) := 16#01#; + CFI_array(16#25#) := 16#02#; + CFI_array(16#26#) := 16#01#; + --Product Group CFI Device Geometry Definition + CFI_array(16#27#) := 16#17#; + CFI_array(16#28#) := 16#05#; + CFI_array(16#29#) := 16#05#; + CFI_array(16#2A#) := 16#08#; + CFI_array(16#2B#) := 16#00#; + CFI_array(16#2C#) := 16#02#; + CFI_array(16#2D#) := 16#1F#; + CFI_array(16#2E#) := 16#00#; + CFI_array(16#2F#) := 16#10#; + CFI_array(16#30#) := 16#00#; + CFI_array(16#31#) := 16#7D#; + CFI_array(16#32#) := 16#00#; + CFI_array(16#33#) := 16#00#; + CFI_array(16#34#) := 16#01#; + CFI_array(16#35#) := 16#00#; + CFI_array(16#36#) := 16#00#; + CFI_array(16#37#) := 16#00#; + CFI_array(16#38#) := 16#00#; + CFI_array(16#39#) := 16#00#; + CFI_array(16#3A#) := 16#00#; + CFI_array(16#3B#) := 16#00#; + CFI_array(16#3C#) := 16#00#; + CFI_array(16#3D#) := 16#FF#; + CFI_array(16#3E#) := 16#FF#; + CFI_array(16#3F#) := 16#FF#; + --Product Group CFI Primary Vendor-Specific Extended Query + CFI_array(16#40#) := 16#50#; + CFI_array(16#41#) := 16#52#; + CFI_array(16#42#) := 16#49#; + CFI_array(16#43#) := 16#31#; + CFI_array(16#44#) := 16#33#; + CFI_array(16#45#) := 16#15#; + CFI_array(16#46#) := 16#00#; + CFI_array(16#47#) := 16#02#; + CFI_array(16#48#) := 16#00#; + CFI_array(16#49#) := 16#05#; + CFI_array(16#4A#) := 16#00#; + CFI_array(16#4B#) := 16#01#; + CFI_array(16#4C#) := 16#03#; + CFI_array(16#4D#) := 16#85#; + CFI_array(16#4E#) := 16#95#; + CFI_array(16#4F#) := 16#07#; + CFI_array(16#50#) := 16#00#; + END IF; + + CFI_array_tmp :=to_slv(CFI_array(16#07#), 8) & + to_slv(CFI_array(16#08#), 8) & + to_slv(CFI_array(16#09#), 8) & + to_slv(CFI_array(16#0A#), 8) & + to_slv(CFI_array(16#0B#), 8) & + to_slv(CFI_array(16#0C#), 8) & + to_slv(CFI_array(16#0D#), 8) & + to_slv(CFI_array(16#0E#), 8) & + to_slv(CFI_array(16#0F#), 8) & + to_slv(CFI_array(16#10#), 8) & + to_slv(CFI_array(16#11#), 8) & + to_slv(CFI_array(16#12#), 8) & + to_slv(CFI_array(16#13#), 8) & + to_slv(CFI_array(16#14#), 8) & + to_slv(CFI_array(16#15#), 8) & + to_slv(CFI_array(16#16#), 8) & + to_slv(CFI_array(16#17#), 8) & + to_slv(CFI_array(16#18#), 8) & + to_slv(CFI_array(16#19#), 8) & + to_slv(CFI_array(16#1A#), 8) & + to_slv(CFI_array(16#1B#), 8) & + to_slv(CFI_array(16#1C#), 8) & + to_slv(CFI_array(16#1D#), 8) & + to_slv(CFI_array(16#1E#), 8) & + to_slv(CFI_array(16#1F#), 8) & + to_slv(CFI_array(16#20#), 8) & + to_slv(CFI_array(16#21#), 8) & + to_slv(CFI_array(16#22#), 8) & + to_slv(CFI_array(16#23#), 8) & + to_slv(CFI_array(16#24#), 8) & + to_slv(CFI_array(16#25#), 8) & + to_slv(CFI_array(16#26#), 8) & + to_slv(CFI_array(16#27#), 8) & + to_slv(CFI_array(16#28#), 8) & + to_slv(CFI_array(16#29#), 8) & + to_slv(CFI_array(16#2A#), 8) & + to_slv(CFI_array(16#2B#), 8) & + to_slv(CFI_array(16#2C#), 8) & + to_slv(CFI_array(16#2D#), 8) & + to_slv(CFI_array(16#2E#), 8) & + to_slv(CFI_array(16#2F#), 8) & + to_slv(CFI_array(16#30#), 8) & + to_slv(CFI_array(16#31#), 8) & + to_slv(CFI_array(16#32#), 8) & + to_slv(CFI_array(16#33#), 8) & + to_slv(CFI_array(16#34#), 8) & + to_slv(CFI_array(16#35#), 8) & + to_slv(CFI_array(16#36#), 8) & + to_slv(CFI_array(16#37#), 8) & + to_slv(CFI_array(16#38#), 8) & + to_slv(CFI_array(16#39#), 8) & + to_slv(CFI_array(16#3A#), 8) & + to_slv(CFI_array(16#3B#), 8) & + to_slv(CFI_array(16#3C#), 8) & + to_slv(CFI_array(16#3D#), 8) & + to_slv(CFI_array(16#3E#), 8) & + to_slv(CFI_array(16#3F#), 8) & + to_slv(CFI_array(16#40#), 8) & + to_slv(CFI_array(16#41#), 8) & + to_slv(CFI_array(16#42#), 8) & + to_slv(CFI_array(16#43#), 8) & + to_slv(CFI_array(16#44#), 8) & + to_slv(CFI_array(16#45#), 8) & + to_slv(CFI_array(16#46#), 8) & + to_slv(CFI_array(16#47#), 8) & + to_slv(CFI_array(16#48#), 8) & + to_slv(CFI_array(16#49#), 8) & + to_slv(CFI_array(16#4A#), 8) & + to_slv(CFI_array(16#4B#), 8) & + to_slv(CFI_array(16#4C#), 8) & + to_slv(CFI_array(16#4D#), 8) & + to_slv(CFI_array(16#4E#), 8) & + to_slv(CFI_array(16#4F#), 8) & + to_slv(CFI_array(16#50#), 8); + + END PROCESS Functional; + + Protect : PROCESS(change_BP) + BEGIN + IF rising_edge(change_BP) THEN + + CASE BP IS + WHEN "000" => + Sec_Prot := (others => '0'); + WHEN "001" => + IF TBPROT = '0' THEN + Sec_Prot(SecNum downto (SecNum+1)*63/64) + := (others => '1'); + Sec_Prot((SecNum+1)*63/64 - 1 downto 0) + := (others => '0'); + ELSE + Sec_Prot((SecNum+1)/64 - 1 downto 0) + := (others => '1'); + Sec_Prot(SecNum downto (SecNum+1)/64) + := (others => '0'); + END IF; + WHEN "010" => + IF TBPROT = '0' THEN + Sec_Prot(SecNum downto (SecNum+1)*31/32) + := (others => '1'); + Sec_Prot((SecNum+1)*31/32 - 1 downto 0) + := (others => '0'); + ELSE + Sec_Prot((SecNum+1)/32 - 1 downto 0) + := (others => '1'); + Sec_Prot(SecNum downto (SecNum+1)/32) + := (others => '0'); + END IF; + WHEN "011" => + IF TBPROT = '0' THEN + Sec_Prot(SecNum downto (SecNum+1)*15/16) + := (others => '1'); + Sec_Prot((SecNum+1)*15/16 - 1 downto 0) + := (others => '0'); + ELSE + Sec_Prot((SecNum+1)/16 - 1 downto 0) + := (others => '1'); + Sec_Prot(SecNum downto (SecNum+1)/16) + := (others => '0'); + END IF; + WHEN "100" => + IF TBPROT = '0' THEN + Sec_Prot(SecNum downto (SecNum+1)*7/8) + := (others => '1'); + Sec_Prot((SecNum+1)*7/8 - 1 downto 0) + := (others => '0'); + ELSE + Sec_Prot((SecNum+1)/8 - 1 downto 0) + := (others => '1'); + Sec_Prot(SecNum downto (SecNum+1)/8) + := (others => '0'); + END IF; + WHEN "101" => + IF TBPROT = '0' THEN + Sec_Prot(SecNum downto (SecNum+1)*3/4) + := (others => '1'); + Sec_Prot((SecNum+1)*3/4 - 1 downto 0) + := (others => '0'); + ELSE + Sec_Prot((SecNum+1)/4 - 1 downto 0) + := (others => '1'); + Sec_Prot(SecNum downto (SecNum+1)/4) + := (others => '0'); + END IF; + WHEN "110" => + IF TBPROT = '0' THEN + Sec_Prot(SecNum downto (SecNum+1)/2) + := (others => '1'); + Sec_Prot((SecNum+1)/2 - 1 downto 0) + := (others => '0'); + ELSE + Sec_Prot((SecNum+1)/2 - 1 downto 0) + := (others => '1'); + Sec_Prot(SecNum downto (SecNum+1)/2) + := (others => '0'); + END IF; + WHEN OTHERS => + Sec_Prot := (others => '1'); + END CASE; + END IF; + END PROCESS Protect; + + HOLD_FRAME_ON_PO_ZD : PROCESS(SOut_zd, SIOut_zd, HOLDNeg_pullup) + BEGIN + IF (HOLDNeg_pullup = '0' AND QUAD /= '1') THEN + hold_mode := TRUE; + SIOut_z <= 'Z'; + SOut_z <= 'Z'; + ELSE + IF hold_mode THEN + SIOut_z <= SIOut_zd AFTER tpd_HOLDNeg_SO(trz0); + SOut_z <= SOut_zd AFTER tpd_HOLDNeg_SO(trz0); + hold_mode := FALSE; + ELSE + SIOut_z <= SIOut_zd; + SOut_z <= SOut_zd; + hold_mode := FALSE; + END IF; + END IF; + END PROCESS HOLD_FRAME_ON_PO_ZD; + + HOLD_PULL_UP : PROCESS(HOLDNegIn) + BEGIN + IF (QUAD = '0') THEN + IF (HOLDNegIn = 'Z') THEN + HOLDNeg_pullup <= '1'; + ELSE + HOLDNeg_pullup <= HOLDNegIn; + END IF; + END IF; + END PROCESS HOLD_PULL_UP; + + WP_PULL_UP : PROCESS(WPNegIn) + BEGIN + IF (QUAD = '0') THEN + IF (WPNegIn = 'Z') THEN + WPNeg_pullup <= '1'; + ELSE + WPNeg_pullup <= WPNegIn; + END IF; + END IF; + END PROCESS WP_PULL_UP; + + --------------------------------------------------------------------------- + ---- File Read Section - Preload Control + --------------------------------------------------------------------------- + MemPreload : PROCESS + + -- text file input variables + FILE mem_file : text is mem_file_name; + FILE otp_file : text is otp_file_name; + VARIABLE ind : NATURAL RANGE 0 TO AddrRANGE := 0; + VARIABLE secsi_ind : NATURAL RANGE 16#100# TO 16#2FF# := 16#100#; + VARIABLE buf : line; + + BEGIN + --------------------------------------------------------------------------- + --s25fl064p memory preload file format +----------------------------------- + --------------------------------------------------------------------------- + -- / - comment + -- @aaaaaa - stands for address + -- dd -
is byte to be written at Mem(aaaaaa++) + -- (aaaaaa is incremented at every load) + -- only first 1-7 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + --------------------------------------------------------------------------- + + -- memory preload + IF (mem_file_name /= "none" AND UserPreload) THEN + ind := 0; + Mem := (OTHERS => MaxData); + WHILE (not ENDFILE (mem_file)) LOOP + READLINE (mem_file, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + IF ind > AddrRANGE THEN + ASSERT false + REPORT "Given preload address is out of" & + "memory address range" + SEVERITY warning; + ELSE + ind := h(buf(2 to 7)); --address + END IF; + ELSE + Mem(ind) := h(buf(1 to 2)); + ind := ind + 1; + END IF; + END LOOP; + END IF; + + --------------------------------------------------------------------------- + --s25fl064p_otp memory preload file format +----------------------------------- + --------------------------------------------------------------------------- + -- / - comment + -- @aaa - stands for address + -- dd -
is byte to be written at OTPMem(aaa++) + -- (aaa is incremented at every load) + -- only first 1-4 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + --------------------------------------------------------------------------- + + -- memory preload + IF (otp_file_name /= "none" AND UserPreload) THEN + secsi_ind := 16#100#; + OTPMem := (OTHERS => MaxData); + WHILE (not ENDFILE (otp_file)) LOOP + READLINE (otp_file, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + IF secsi_ind > 16#2FF# OR secsi_ind < 16#100# THEN + ASSERT false + REPORT "Given preload address is out of" & + "OTP address range" + SEVERITY warning; + ELSE + secsi_ind := h(buf(2 to 4)); --address + END IF; + ELSE + OTPMem(secsi_ind) := h(buf(1 to 2)); + PR_LOCK1 := to_slv(OTPMem(257),8) & to_slv(OTPMem(256),8); + PR_LOCK2 := to_slv(OTPMem(275),8) & to_slv(OTPMem(274),8); + PR_LOCK3 := to_slv(OTPMem(533),8) & to_slv(OTPMem(532),8); + secsi_ind := secsi_ind + 1; + END IF; + END LOOP; + END IF; + + WAIT; + END PROCESS MemPreload; + + ---------------------------------------------------------------------------- + -- Path Delay Section + ---------------------------------------------------------------------------- + + S_Out_PathDelay_Gen : PROCESS(SOut_z) + + VARIABLE SO_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => SOut, + OutSignalName => "PO", + OutTemp => SOut_z, + GlitchData => SO_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO), + PathCondition => SOut_z /= 'Z' + AND (NOT dual)), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SI), + PathCondition => SOut_z /= 'Z' + AND dual), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1'), + 3 => (InputChangeTime => HOLDNegIn'LAST_EVENT, + PathDelay => tpd_HOLDNeg_SO, + PathCondition => TRUE) + ) + ); + END PROCESS; + + SI_Out_PathDelay : PROCESS(SIOut_z) + + VARIABLE SI_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => SIOut, + OutSignalName => "SI", + OutTemp => SIOut_z, + GlitchData => SI_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SI), + PathCondition => SIOut_z /= 'Z' AND dual), + 1 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND dual), + 2 => (InputChangeTime => HOLDNegIn'LAST_EVENT, + PathDelay => tpd_HOLDNeg_SO, + PathCondition => dual) + ) + ); + END PROCESS; + + HOLD_Out_PathDelay : PROCESS(HOLDNegOut_zd) + + VARIABLE HOLD_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => HOLDNegOut, + OutSignalName => "HOLDNeg", + OutTemp => HOLDNegOut_zd, + GlitchData => HOLD_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SI), + PathCondition => HOLDNegOut_zd /= 'Z' AND dual + AND QUAD = '1'), + 1 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND dual + AND QUAD = '1') + ) + ); + END PROCESS; + + WP_Out_PathDelay : PROCESS(WPNegOut_zd) + + VARIABLE WP_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => WPNegOut, + OutSignalName => "WPNeg", + OutTemp => WPNegOut_zd, + GlitchData => WP_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SI), + PathCondition => HOLDNegOut_zd /= 'Z'AND dual + AND QUAD = '1'), + 1 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND dual + AND QUAD = '1') + ) + ); + END PROCESS; + END BLOCK behavior; +END vhdl_behavioral; diff --git a/lib/models/memory/flash/serial/S25fl064p/model/s25fl064p_ver.ftm b/lib/models/memory/flash/serial/S25fl064p/model/s25fl064p_ver.ftm new file mode 100644 index 0000000..b448a6c --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064p/model/s25fl064p_ver.ftm @@ -0,0 +1,230 @@ + +FMF Timing for s25fl064p Parts + + +version: | author: | mod date: | changes made: + V1.0 D.Stanojkovic 08 Jan 11 Initial release + V1.1 D.Stanojkovic 08 Mar 04 New timmings added and changed + timming model labeling + V1.2 J.Stoickov 08 Dec 10 Changed timming model labeling + V1.3 S.Petrovic 09 May 29 Timing ranges corrected + V1.4 V.Mancev 12 Jan 10 Latest datasheet update + +1ns +s25fl064p + +S25FL064P0XMFI000_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFI001_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFI003_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFI000_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFI001_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFI003_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFV000_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFV001_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFV003_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFV000_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFV001_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFV003_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI020_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI023_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI030_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI033_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV020_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV023_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV030_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV033_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +The values listed are for VCC=2.7V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + + (DELAY (ABSOLUTE + (COND ~dual (IOPATH SCK SO (5.4:6.7:8) (5.4:6.7:8) () (5.4:6.7:8) () (5.4:6.7:8))) + (COND dual (IOPATH SCK SO (6.5:8:9.5) (6.5:8:9.5) () (6.5:8:9.5) () (6.5:8:9.5))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~dual (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND dual (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + + (COND dual (IOPATH SCK SI (6.5:8:9.5) (6.5:8:9.5) () (6.5:8:9.5) () (6.5:8:9.5))) + (COND dual (IOPATH HOLDNeg SI () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND dual && CSNeg (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND dual && QUAD (IOPATH SCK HOLDNeg (6.5:8:9.5) (6.5:8:9.5) () (6.5:8:9.5) () (6.5:8:9.5))) + (COND dual && CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND dual && QUAD (IOPATH SCK WPNeg (6.5:8:9.5) (6.5:8:9.5) () (6.5:8:9.5) () (6.5:8:9.5))) + (COND dual && CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) +)) +(TIMINGCHECK + (SETUP CSNeg SCK (3)) + (SETUP HOLDNeg SCK (3)) + (SETUP SI SCK (3)) + (SETUP WPNeg CSNeg (20)) + + (HOLD CSNeg SCK (3)) + (HOLD HOLDNeg SCK (3)) + (HOLD SI SCK (2)) + (HOLD WPNeg CSNeg (100)) + + (WIDTH (COND fast_rd (negedge SCK)) (4.5)) + (WIDTH (COND fast_rd (posedge SCK)) (4.5)) + (WIDTH (COND dual_rd (negedge SCK)) (4.5)) + (WIDTH (COND dual_rd (posedge SCK)) (4.5)) + (WIDTH (COND rd (negedge SCK)) (4.5)) + (WIDTH (COND rd (posedge SCK)) (4.5)) + (WIDTH (COND rd_jid (negedge SCK)) (4.5)) + (WIDTH (COND rd_jid (posedge SCK)) (4.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (PERIOD (COND fast_rd SCK) (9.6)) + (PERIOD (COND rd SCK) (25.0)) + (PERIOD (COND rd_jid SCK) (20.0)) + (PERIOD (COND dual_rd SCK) (12.5)) +) + + + + +S25FL064P0XMFI000_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFI001_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFI003_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFI000_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFI001_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFI003_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFV000_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFV001_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFV003_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFV000_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFV001_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFV003_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI020_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI023_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI030_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI033_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV020_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV023_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV030_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV033_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + + (DELAY (ABSOLUTE + (COND ~dual (IOPATH SCK SO (4.5:5.5:6.5) (4.5:5.5:6.5) () (4.5:5.5:6.5) () (4.5:5.5:6.5))) + (COND dual (IOPATH SCK SO (5.4:6.7:8) (5.4:6.7:8) () (5.4:6.7:8) () (5.4:6.7:8))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~dual (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND dual (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + + (COND dual (IOPATH SCK SI (5.4:6.7:8) (5.4:6.7:8) () (5.4:6.7:8) () (5.4:6.7:8))) + (COND dual (IOPATH HOLDNeg SI () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND dual && CSNeg (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND dual && QUAD (IOPATH SCK HOLDNeg (5.4:6.7:8) (5.4:6.7:8) () (5.4:6.7:8) () (5.4:6.7:8))) + (COND dual && CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND dual && QUAD (IOPATH SCK WPNeg (5.4:6.7:8) (5.4:6.7:8) () (5.4:6.7:8) () (5.4:6.7:8))) + (COND dual && CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) +)) +(TIMINGCHECK + (SETUP CSNeg SCK (3)) + (SETUP HOLDNeg SCK (3)) + (SETUP SI SCK (3)) + (SETUP WPNeg CSNeg (20)) + + (HOLD CSNeg SCK (3)) + (HOLD HOLDNeg SCK (3)) + (HOLD SI SCK (2)) + (HOLD WPNeg CSNeg (100)) + + (WIDTH (COND fast_rd (negedge SCK)) (4.5)) + (WIDTH (COND fast_rd (posedge SCK)) (4.5)) + (WIDTH (COND dual_rd (negedge SCK)) (4.5)) + (WIDTH (COND dual_rd (posedge SCK)) (4.5)) + (WIDTH (COND rd (negedge SCK)) (4.5)) + (WIDTH (COND rd (posedge SCK)) (4.5)) + (WIDTH (COND rd_jid (negedge SCK)) (4.5)) + (WIDTH (COND rd_jid (posedge SCK)) (4.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (PERIOD (COND fast_rd SCK) (9.6)) + (PERIOD (COND rd SCK) (25.0)) + (PERIOD (COND rd_jid SCK) (20.0)) + (PERIOD (COND dual_rd SCK) (12.5)) +) + + + + +S25FL064P0XMFI000_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFI001_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFI003_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFI000_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFI001_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFI003_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFV000_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFV001_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFV003_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFV000_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFV001_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFV003_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI020_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI023_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI030_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI033_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV020_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV023_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV030_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV033_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=15pF, +Industrial Ta=-40 to +85 Celsius + + (DELAY (ABSOLUTE + (COND ~dual (IOPATH SCK SO (4.5:5.5:6.5) (4.5:5.5:6.5) () (4.5:5.5:6.5) () (4.5:5.5:6.5))) + (COND dual (IOPATH SCK SO (4.7:5.8:7) (4.7:5.8:7) () (4.7:5.8:7) () (4.7:5.8:7))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~dual (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND dual (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + + (COND dual (IOPATH SCK SI (4.7:5.8:7) (4.7:5.8:7) () (4.7:5.8:7) () (4.7:5.8:7))) + (COND dual (IOPATH HOLDNeg SI () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND dual && CSNeg (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND dual && QUAD (IOPATH SCK HOLDNeg (4.7:5.8:7) (4.7:5.8:7) () (4.7:5.8:7) () (4.7:5.8:7))) + (COND dual && CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND dual && QUAD (IOPATH SCK WPNeg (4.7:5.8:7) (4.7:5.8:7) () (4.7:5.8:7) () (4.7:5.8:7))) + (COND dual && CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) +)) +(TIMINGCHECK + (SETUP CSNeg SCK (3)) + (SETUP HOLDNeg SCK (3)) + (SETUP SI SCK (3)) + (SETUP WPNeg CSNeg (20)) + + (HOLD CSNeg SCK (3)) + (HOLD HOLDNeg SCK (3)) + (HOLD SI SCK (2)) + (HOLD WPNeg CSNeg (100)) + + (WIDTH (COND fast_rd (negedge SCK)) (4.5)) + (WIDTH (COND fast_rd (posedge SCK)) (4.5)) + (WIDTH (COND dual_rd (negedge SCK)) (4.5)) + (WIDTH (COND dual_rd (posedge SCK)) (4.5)) + (WIDTH (COND rd (negedge SCK)) (4.5)) + (WIDTH (COND rd (posedge SCK)) (4.5)) + (WIDTH (COND rd_jid (negedge SCK)) (4.5)) + (WIDTH (COND rd_jid (posedge SCK)) (4.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (PERIOD (COND fast_rd SCK) (9.6)) + (PERIOD (COND rd SCK) (25.0)) + (PERIOD (COND rd_jid SCK) (20.0)) + (PERIOD (COND dual_rd SCK) (12.5)) +) + + + diff --git a/lib/models/memory/flash/serial/S25fl064p/model/s25fl064p_vhd.ftm b/lib/models/memory/flash/serial/S25fl064p/model/s25fl064p_vhd.ftm new file mode 100644 index 0000000..dde01da --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064p/model/s25fl064p_vhd.ftm @@ -0,0 +1,242 @@ + +FMF Timing for s25fl064p Parts + + +version: | author: | mod date: | changes made: + V1.0 D.Stanojkovic 08 Jan 22 Initial release + V1.1 D.Stanojkovic 08 Mar 04 New timmings added and changed + timming model labeling + V1.2 J.Stoickov 08 Dec 10 Changed timming model labeling + V1.3 S.Petrovic 09 May 29 Timing ranges corrected + V1.4 V.Mancev 12 Jan 12 Latest datasheet update + +1ns +s25fl064p + +S25FL064P0XMFI000_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFI001_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFI003_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFI000_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFI001_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFI003_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFV000_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFV001_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFV003_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFV000_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFV001_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFV003_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI020_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI023_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI030_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI033_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV020_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV023_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV030_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV033_F_30pF Spansion, S25FL064P_00_05, November 18, 2011 +The values listed are for VCC=2.7V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (IOPATH SCK SO (5.4:6.7:8) (5.4:6.7:8) () (5.4:6.7:8) () (5.4:6.7:8)) + (IOPATH SCK SI (6.5:8:9.5) (6.5:8:9.5) () (6.5:8:9.5) () (6.5:8:9.5)) + (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + )) + (TIMINGCHECK + (SETUP CSNeg SCK (3)) + (SETUP HOLDNeg SCK (3)) + (SETUP SI SCK (3)) + (SETUP WPNeg CSNeg (20)) + + (HOLD CSNeg SCK (3)) + (HOLD HOLDNeg SCK (3)) + (HOLD SI SCK (2)) + (HOLD WPNeg CSNeg (100)) + + (WIDTH (COND serial_fast (negedge SCK)) (4.5)) + (WIDTH (COND serial_fast (posedge SCK)) (4.5)) + (WIDTH (COND dual (negedge SCK)) (4.5)) + (WIDTH (COND dual (posedge SCK)) (4.5)) + (WIDTH (COND serial (negedge SCK)) (4.5)) + (WIDTH (COND serial (posedge SCK)) (4.5)) + (WIDTH (COND rd_jid (negedge SCK)) (4.5)) + (WIDTH (COND rd_jid (posedge SCK)) (4.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgm (posedge CSNeg)) (50)) + (PERIOD (COND serial_fast_rd SCK) (9.6)) + (PERIOD (COND serial_rd SCK) (25.0)) + (PERIOD (COND serial_rd_jid SCK) (20.0)) + (PERIOD (COND dual_fast_rd SCK) (12.5)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP) (DELAY (ABSOLUTE (DEVICE(1200000:1500000:3000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/EP) (DELAY (ABSOLUTE (DEVICE(1000000:1200000:2400000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE) (DELAY (ABSOLUTE (DEVICE(40e7:50e7:2e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(50e9:64e9:128e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WR) (DELAY (ABSOLUTE(DEVICE(100000000:100000000:100000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300000:300000:300000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/DP) (DELAY (ABSOLUTE (DEVICE(10000:10000:10000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PE) (DELAY (ABSOLUTE (DEVICE(20e7:20e7:80e7) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/RES) (DELAY (ABSOLUTE (DEVICE(30000:30000:30000) ) ) ) + + + +S25FL064P0XMFI000_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFI001_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFI003_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFI000_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFI001_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFI003_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFV000_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFV001_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFV003_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFV000_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFV001_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFV003_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI020_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI023_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI030_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI033_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV020_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV023_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV030_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV033_R_30pF Spansion, S25FL064P_00_05, November 18, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (IOPATH SCK SO (4.5:5.5:6.5) (4.5:5.5:6.5) () (4.5:5.5:6.5) () (4.5:5.5:6.5)) + (IOPATH SCK SI (5.4:6.7:8) (5.4:6.7:8) () (5.4:6.7:8) () (5.4:6.7:8)) + (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + )) + (TIMINGCHECK + (SETUP CSNeg SCK (3)) + (SETUP HOLDNeg SCK (3)) + (SETUP SI SCK (3)) + (SETUP WPNeg CSNeg (20)) + + (HOLD CSNeg SCK (3)) + (HOLD HOLDNeg SCK (3)) + (HOLD SI SCK (2)) + (HOLD WPNeg CSNeg (100)) + + (WIDTH (COND serial_fast (negedge SCK)) (4.5)) + (WIDTH (COND serial_fast (posedge SCK)) (4.5)) + (WIDTH (COND dual (negedge SCK)) (4.5)) + (WIDTH (COND dual (posedge SCK)) (4.5)) + (WIDTH (COND serial (negedge SCK)) (4.5)) + (WIDTH (COND serial (posedge SCK)) (4.5)) + (WIDTH (COND rd_jid (negedge SCK)) (4.5)) + (WIDTH (COND rd_jid (posedge SCK)) (4.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgm (posedge CSNeg)) (50)) + (PERIOD (COND serial_fast_rd SCK) (9.6)) + (PERIOD (COND serial_rd SCK) (25.0)) + (PERIOD (COND serial_rd_jid SCK) (20.0)) + (PERIOD (COND dual_fast_rd SCK) (12.5)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP) (DELAY (ABSOLUTE (DEVICE(1200000:1500000:3000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/EP) (DELAY (ABSOLUTE (DEVICE(1000000:1200000:2400000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE) (DELAY (ABSOLUTE (DEVICE(40e7:50e7:2e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(50e9:64e9:128e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WR) (DELAY (ABSOLUTE(DEVICE(100000000:100000000:100000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300000:300000:300000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/DP) (DELAY (ABSOLUTE (DEVICE(10000:10000:10000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PE) (DELAY (ABSOLUTE (DEVICE(20e7:20e7:80e7) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/RES) (DELAY (ABSOLUTE (DEVICE(30000:30000:30000) ) ) ) + + + +S25FL064P0XMFI000_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFI001_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFI003_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFI000_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFI001_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFI003_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFV000_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFV001_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XMFV003_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFV000_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFV001_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XNFV003_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI020_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI023_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI030_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHI033_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV020_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV023_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV030_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +S25FL064P0XBHV033_R_15pF Spansion, S25FL064P_00_05, November 18, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=15pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (IOPATH SCK SO (4.5:5.5:6.5) (4.5:5.5:6.5) () (4.5:5.5:6.5) () (4.5:5.5:6.5)) + (IOPATH SCK SI (4.7:5.8:7) (4.7:5.8:7) () (4.7:5.8:7) () (4.7:5.8:7)) + (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + )) + (TIMINGCHECK + (SETUP CSNeg SCK (3)) + (SETUP HOLDNeg SCK (3)) + (SETUP SI SCK (3)) + (SETUP WPNeg CSNeg (20)) + + (HOLD CSNeg SCK (3)) + (HOLD HOLDNeg SCK (3)) + (HOLD SI SCK (2)) + (HOLD WPNeg CSNeg (100)) + + (WIDTH (COND serial_fast (negedge SCK)) (4.5)) + (WIDTH (COND serial_fast (posedge SCK)) (4.5)) + (WIDTH (COND dual (negedge SCK)) (4.5)) + (WIDTH (COND dual (posedge SCK)) (4.5)) + (WIDTH (COND serial (negedge SCK)) (4.5)) + (WIDTH (COND serial (posedge SCK)) (4.5)) + (WIDTH (COND rd_jid (negedge SCK)) (4.5)) + (WIDTH (COND rd_jid (posedge SCK)) (4.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgm (posedge CSNeg)) (50)) + (PERIOD (COND serial_fast_rd SCK) (9.6)) + (PERIOD (COND serial_rd SCK) (25.0)) + (PERIOD (COND serial_rd_jid SCK) (20.0)) + (PERIOD (COND dual_fast_rd SCK) (12.5)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP) (DELAY (ABSOLUTE (DEVICE(1200000:1500000:3000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/EP) (DELAY (ABSOLUTE (DEVICE(1000000:1200000:2400000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE) (DELAY (ABSOLUTE (DEVICE(40e7:50e7:2e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(50e9:64e9:128e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WR) (DELAY (ABSOLUTE(DEVICE(100000000:100000000:100000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300000:300000:300000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/DP) (DELAY (ABSOLUTE (DEVICE(10000:10000:10000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PE) (DELAY (ABSOLUTE (DEVICE(20e7:20e7:80e7) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/RES) (DELAY (ABSOLUTE (DEVICE(30000:30000:30000) ) ) ) + + \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl064p/utilities/CreateSDF/mk_sdf.cmd b/lib/models/memory/flash/serial/S25fl064p/utilities/CreateSDF/mk_sdf.cmd new file mode 100644 index 0000000..f6d6cc7 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064p/utilities/CreateSDF/mk_sdf.cmd @@ -0,0 +1,10 @@ +SET sdffile_suffix .sdf +SET use_global_timing_dir false +SET timingfile_dir /user/USERNAME/CreateSDF +SET timingfile_suffix .ftm +SET time_scale 1ns +SET local_path . +SET vendor MODELSIM_HOME +SET diagnostics on +SET vhdl_file testbench.vhd +SET lwb false diff --git a/lib/models/memory/flash/serial/S25fl064p/utilities/CreateSDF/mk_sdf_204.pl b/lib/models/memory/flash/serial/S25fl064p/utilities/CreateSDF/mk_sdf_204.pl new file mode 100644 index 0000000..5f2f2b8 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064p/utilities/CreateSDF/mk_sdf_204.pl @@ -0,0 +1,462 @@ +#!/usr/local/bin/perl +# +# mk_sdf : Perl replacement for C mk_sdf +# +# Copyright (C) 2000, 1999 Free Model Foundry; http:/vhdl.org/fmf/ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# Author : R. Munden +# Date : 20001115 +# Version : 2.0.4 +# +# Revision history: +# 2.0: 19990702 +# o Intial release of perl version +# 2.0.1: 19990722 +# o fixed problem with . in path for TimingModels +# 2.0.2: 20000616 +# o changed instance search to work with Mentor +# 2.0.3: 20001115 +# o changed to parse ":" without leading space +# o fixed problem with . in path for TimingModels again +# 2.0.4: 20030405 +# o chaged SDF version to 3.0 +# +################################################################# +# +# command line arguments: + +# ARGV[0] - name of VHDL netlist + +# global variables: + +# %component_list - list of instance names by component name +# %instance_isin - list architectures by instances contained therein +# %instance_comp - list of component names by instance name +# %comp_lib - library each component (by name) is configured to +# @instance_list - array of all instance names in design in order found + +$version = "2.0.4"; +$design_name = ''; +$timing_dir = ''; +$diags = "off"; + +%keywords = (architecture => 1, + component => 1, + timingmodel => 1); + +# INPUT files +$CMD = "mk_sdf.cmd"; +$VHD = ''; # name of VHDL netlist + +# OUTPUT files +$RFV = "/tmp/short.vhd"; # reformatted VHDL +$sdf_file = ''; # name of SDF file + +&read_cmd_file; +&get_names; +&reformat; + +open INPUT, $RFV; +@lines = ; +close INPUT; + +$current_architecture = ""; + +foreach $line (@lines) +{ + @words = split / /, $line; + foreach $word (@words) + { + $keywords{$word} == "1" and do { &$word(@words);}; + if ($component_list{$word}) + { + $line =~ /(.+) : $word/ and do { + if ($1 !~ /for/) { # instantiation found + $component_list{$word} = $component_list{$word} . $1; + push (@instance_list, $1); + $instance_name = $1; + } + }; + $instance_comp{$1} = $word; + $instance_isin{$1} = $current_architecture; + if ( $diags ne off ) { + print "reading instance $instance_name: $word in $current_architecture\n"; + } + $line =~ /for all : $word use entity (.+)/ and do + { + @config = split(/\./, $1); + $comp_lib{$word} = $config[0];}; + } + } +} +if ( $diags ne off ) { + print "finished with netlist\n\n"; +} + +&begin_sdf; +&build_paths; +&close_sdf; +`rm $RFV`; + +print "$time\n"; + +sub architecture +{ + $current_architecture = $_[3]; + push (@architectures, $current_architecture); +} + +sub component +{ + if ($_[0] ne "end") + { + $name = $_[1]; + $arch_list{$current_architecture} = + $arch_list{$current_architecture} . " " . $name; + unless ($component_list{$name}) { $component_list{$name} = " ";} + } +} + +sub timingmodel +{ + $line =~ /timingmodel => \"(.+)\"/ and do { + $model = $1; + $model_name{$instance_name} = $model; + }; +} + +sub begin_sdf +{ + if ( $diags ne off ) { + print "writing SDF boilerplate\n"; + } + $time = localtime; + if (open(SDF, ">$sdf_file") !=1) { die "can't open $sdf_file\n";} + print "Opening $sdf_file\n"; + print SDF "(DELAYFILE\n"; + print SDF " (SDFVERSION \"3.0\")\n"; + print SDF " (DESIGN \"$design_name\")\n"; + print SDF " (DATE \"$time\")\n"; + print SDF " (VENDOR \"Free Model Foundry\")\n"; + print SDF " (PROGRAM \"SDF timing utility(tm)\")\n"; + print SDF " (VERSION \"$version\")\n"; + print SDF " (DIVIDER /)\n"; + print SDF " (VOLTAGE)\n"; + print SDF " (PROCESS)\n"; + print SDF " (TEMPERATURE)\n"; + print SDF " (TIMESCALE 1ns)\n"; +} + +sub build_paths +{ + foreach $instance_list (@instance_list) + { + @instance = $instance_list; + foreach $instance (@instance) + { + if ( $diags ne off ) { + print "working on $instance\n"; + } + if ($gtd =~ /true/i) { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; +# $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}./$timing_dir"; + } else { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; + } + $timing_file = "$path/$instance_comp{$instance}_vhd.ftm"; + $timing_file =~ s/\s//; + if ( $diags ne off ) { + print "$instance should be in $timing_file\n"; + } + if (-e $timing_file) { + if ($model_name{$instance} ne "") { + print SDF " (CELL\n"; + print SDF " (CELLTYPE \"$instance_comp{$instance}\")\n"; + $inst = $instance; + $full_inst = $instance; + while ($component_list{$instance_isin{$inst}}) { + $full_inst = "$component_list{$instance_isin{$inst}}/$full_inst"; + $full_inst =~ s/\s+//; + $inst = $component_list{$instance_isin{$inst}}; + $inst =~ s/\s+//; +# print SDF " (INSTANCE $component_list{$instance_isin{$instance}}/$instance)\n"; + } + print SDF " (INSTANCE $full_inst)\n"; + &add_timing; + } + } else { + if ( $diags ne off ) { + print "$timing_file not found!\n"; + } + } + } + } +} + +sub add_timing +{ + $timing_found = "false"; + $part_found = "false"; +# unless ($lib_path{$comp_lib{$instance_comp{$instance}}}) + unless ($timing_file) + { + print "path to $timing_file not found\n"; + exit; + } + if ($gtd =~ /true/i) { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; +# $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}./$timing_dir"; + } else { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; + } + $timing_file = "$path/$instance_comp{$instance}_vhd.ftm"; + if (open(TF, "<$timing_file") !=1) { warn "can't open $timing_file\n"; } + if ( $diags ne off ) { + print "reading $timing_file\n"; + } + $section_found = "false"; + while () + { + next unless (/$model_name{$instance}/i || ($part_found eq "true")); + $part_found = "true"; + if ( $diags ne off ) { + print "found entry for $model_name{$instance}\n"; + } + next unless (//i || ($timing_found eq "true")); + $timing_found = "true"; + next if (//i); + if (/<\/timing>/i) + { + print SDF " )\n"; + $timing_found = "false"; + $part_found = "false"; + $section_found = "true"; + last; + } else { + if (/%LABEL%/) + { + if ($component_list{$instance_isin{$instance}}) + { + $_ =~ s/%LABEL%/$component_list{$instance_isin{$instance}}\/$instance/; + } else { + $_ =~ s/%LABEL%/$instance/; + } + } + print SDF $_; + } + } + unless ($section_found eq "true") { + print "$model_name not found\n"; + } +} + +sub close_sdf +{ + print SDF ")\n"; + print "closing $sdf_file\n"; + close(SDF); +} + +# read mk_sdf.cmd + +sub read_cmd_file { + + if (open(CMD, $CMD) !=1) { die "can't open $CMD\n"; } + while () { + chop; + @fields = ''; + @fields = split; + unless ($fields[0] =~ /#/) { + if ($fields[0] =~ /SET/) { + if ($fields[1] =~ /vhdl_file/) {$VHD = $fields[2]} + if ($fields[1] =~ /sdffile_suffix/) {$suffix = $fields[2]} + if ($fields[1] =~ /use_global_timing_dir/) {$gtd = $fields[2]} + if ($fields[1] =~ /timingfile_dir/) {$timing_dir = $fields[2]} + if ($fields[1] =~ /vendor/) {$vendor = $fields[2]} + if ($fields[1] =~ /diagnostics/) {$diags = $fields[2]} + } + } + } + if ( $diags ne off ) { + print "\nmk_sdf diagnostics on\n\n"; + print "vhdl_file $VHD\n"; + print "sdffile_suffix $suffix\n"; + print "use_global_timing_dir $gtd\n"; + print "timingfile_dir $timing_dir\n"; + print "vendor $vendor\n\n"; + } +} +# + +# get name of netlist + +sub get_names +{ + + if ($ARGV[0] ne "") { $VHD = "$ARGV[0]"; } + + if ($ARGV[1] eq "") + { + @name = split(/\./,$VHD); + $design_name = $name[0]; + } else { + $design_name = "$ARGV[1]"; + } + $sdf_file = $design_name . $suffix; + if ($gtd =~ /false/i) + { + if ($vendor =~ /modeltech/i) { &read_mti; } + if ($vendor =~ /cadence/i) { &read_cds; } + } + if ( $diags ne off ) { + print "design name is $design_name\n\n"; + } +} +# +################################################################ +# + +# reformat netlist + +sub reformat +{ + $entfound = false; + + if (open(VHD, $VHD) !=1) { die "can't open $VHD\n"; } + if (open(OUT, ">$RFV") !=1) { die "can't open $OUT\n"; } + + while () { + if (/^--|library|package/i) { next } + if (/--/) { # strip embeded comments + @line = split("--"); + $_ = $line[0]; + } + s/:/ : /g; + s/;/ ;/g; + s/\s+/ /g; # reduces spaces and tabs + s/^\s//g; # no leading spaces + if (/entity/i) { + $entfound = "true"; + } + chomp; + if ( $entfound eq true ) { + print OUT lc($_); + if (/;|is|begin/i) { print OUT "\n"; } + } + } + + close OUT; + if ( $diags ne off ) { + print "reformatted netlist written to $RFV\n\n"; + } + +} + +# read ModelTech's modelsim.ini file + +sub read_mti +{ + $lib_found = "false"; + if ($ENV{MODELPATH}) + { + $ini_file = "$ENV{MODELPATH}/../modelsim.ini"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + if ($lib_found eq "true") + { + chomp; + if (/\[.+\]/) { last; } + s/\s+//; + @lib_line = split(/=/); + $lib_line[1] =~ s/\/work//; + $lib_path{$lib_line[0]} = $lib_line[1]; + } elsif (/\[Library\]/i) + { + $lib_found = "true"; + next; + } + } + } else { + print "\$MODELPATH environment variable not found\n"; + } + $lib_found = "false"; + if (-e "modelsim.ini") + { + $ini_file = "modelsim.ini"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + if ($lib_found eq "true") + { + chomp; + if (/\[.+\]/) { last; } + s/\s+//; + @lib_line = split(/=/); + $lib_line[1] =~ s/\/work//; + $lib_path{$lib_line[0]} = $lib_line[1]; + } elsif (/\[Library\]/i) + { + $lib_found = "true"; + next; + } + } + } else { + print "local modelsim.ini file not found, may not be needed\n"; + } +} + +# read Cadence's cds.lib file + +sub read_cds +{ + if ($ENV{CDS_VHDL}) + { + $ini_file = "$ENV{CDS_VHDL}/files/cds.lib"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + chomp; + s/\s+/ /; + if (/define/i) + { + @lib_line = split; + $lib_path{$lib_line[1]} = $lib_line[2]; + } + } + } else { + print "\$CDS_VHDL environment variable not found\n"; + } + if (-e "cds.lib") + { + $ini_file = "cds.lib"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + chomp; + s/\s+/ /; + if (/define/i) + { + @lib_line = split; + $lib_path{$lib_line[1]} = $lib_line[2]; + } + } + } else { + print "local cds.lib file not found, may not be needed\n"; + } +} diff --git a/lib/models/memory/flash/serial/S25fl064p/utilities/CreateSDF/my_mem_vhd.ftm b/lib/models/memory/flash/serial/S25fl064p/utilities/CreateSDF/my_mem_vhd.ftm new file mode 100644 index 0000000..2fc35c2 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064p/utilities/CreateSDF/my_mem_vhd.ftm @@ -0,0 +1,205 @@ + +FMF Timing for testbench Parts + + +version: | author: | mod date: | changes made: + V1.0 VHD2FTM 03 July 11 Initial release + +1ns +am29lv640m + +MY_MEM +AM29LV640MH90R +AM29LV640ML90R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (90:90:90) (90:90:90)) + (IOPATH A0 DQ1 (25:25:25) (25:25:25)) + (IOPATH CENeg DQ0 (85:85:85) (85:85:85) (11:11:11) (85:85:85) (11:11:11) (85:85:85)) + (IOPATH OENeg DQ0 (20:20:20) (20:20:20) (11:11:11) (20:20:20) (11:11:11) (20:20:20)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (90)) + (IOPATH WENeg RY (0) (90)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (90:90:90)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH101 +AM29LV640ML101 +AM29LV640MH101R +AM29LV640ML101R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (100:100:100) (100:100:100)) + (IOPATH A0 DQ1 (30:30:30) (30:30:30)) + (IOPATH CENeg DQ0 (95:95:95) (95:95:95) (11:11:11) (95:95:95) (11:11:11) (95:95:95)) + (IOPATH OENeg DQ0 (25:25:25) (25:25:25) (11:11:11) (25:25:25) (11:11:11) (25:25:25)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (100)) + (IOPATH WENeg RY (0) (100)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (100:100:100)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH112 +AM29LV640ML112 +AM29LV640MH112R +AM29LV640ML112R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (110:110:110) (110:110:110)) + (IOPATH A0 DQ1 (40:40:40) (40:40:40)) + (IOPATH CENeg DQ0 (105:105:105) (105:105:105) (11:11:11) (105:105:105) (11:11:11) (105:105:105)) + (IOPATH OENeg DQ0 (35:35:35) (35:35:35) (11:11:11) (35:35:35) (11:11:11) (35:35:35)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (110)) + (IOPATH WENeg RY (0) (110)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (110:110:110)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH120 +AM29LV640ML120 +AM29LV640MH120R +AM29LV640ML120R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (120:120:120) (120:120:120)) + (IOPATH A0 DQ1 (40:40:40) (40:40:40)) + (IOPATH CENeg DQ0 (115:115:115) (115:115:115) (11:11:11) (115:115:115) (11:11:11) (115:115:115)) + (IOPATH OENeg DQ0 (35:35:35) (35:35:35) (11:11:11) (35:35:35) (11:11:11) (35:35:35)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (120)) + (IOPATH WENeg RY (0) (120)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (120:120:120)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + diff --git a/lib/models/memory/flash/serial/S25fl064p/utilities/CreateSDF/testbench.sdf b/lib/models/memory/flash/serial/S25fl064p/utilities/CreateSDF/testbench.sdf new file mode 100644 index 0000000..02495dd --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064p/utilities/CreateSDF/testbench.sdf @@ -0,0 +1,58 @@ +(DELAYFILE + (SDFVERSION "3.0") + (DESIGN "testbench") + (DATE "Wed Jan 28 15:15:41 2004") + (VENDOR "Free Model Foundry") + (PROGRAM "SDF timing utility(tm)") + (VERSION "2.0.4") + (DIVIDER /) + (VOLTAGE) + (PROCESS) + (TEMPERATURE) + (TIMESCALE 1ns) + (CELL + (CELLTYPE "my_mem") + (INSTANCE dut) + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (90:90:90) (90:90:90)) + (IOPATH A0 DQ1 (25:25:25) (25:25:25)) + (IOPATH CENeg DQ0 (85:85:85) (85:85:85) (11:11:11) (85:85:85) (11:11:11) (85:85:85)) + (IOPATH OENeg DQ0 (20:20:20) (20:20:20) (11:11:11) (20:20:20) (11:11:11) (20:20:20)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (90)) + (IOPATH WENeg RY (0) (90)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (90:90:90)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + ) +) diff --git a/lib/models/memory/flash/serial/S25fl064p/utilities/CreateSDF/testbench.vhd b/lib/models/memory/flash/serial/S25fl064p/utilities/CreateSDF/testbench.vhd new file mode 100644 index 0000000..c7d852a --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064p/utilities/CreateSDF/testbench.vhd @@ -0,0 +1,1606 @@ +------------------------------------------------------------------------------ +-- File name : testbench_640.vhd +------------------------------------------------------------------------------- +-- Copyright (C) 2003 AMD. +-- +-- MODIFICATION HISTORY : +-- +-- version: | author: | mod date: | changes made: +-- V0.1 M.Marinkovic 11 July 03 Initial +-- v0.2 M.Marinkovic 28 Aug 03 Changed protected sector selection +-- +------------------------------------------------------------------------------- +-- PART DESCRIPTION: +-- +-- Description: +-- Generic test enviroment for verification of AMD flash memory +-- VITAL models.my_mem +-- +------------------------------------------------------------------------------- +-- Note: VHDL code formating not done +-- For High/Low sector protection selection change: +-- TimingModel constant and TimingModel generic value +-- +------------------------------------------------------------------------------- +LIBRARY IEEE; + USE IEEE.std_logic_1164.ALL; +--USE IEEE.VITAL_timing.ALL; +--USE IEEE.VITAL_primitives.ALL; + USE STD.textio.ALL; + +LIBRARY VITAL2000; + USE VITAL2000.vital_timing.ALL; + USE VITAL2000.vital_primitives.ALL; + +LIBRARY FMF; + USE FMF.gen_utils.ALL; + USE FMF.conversions.ALL; + + +LIBRARY work; + USE work.amd_tc_pkg.ALL; + +------------------------------------------------------------------------------- +-- ENTITY DECLARATION +------------------------------------------------------------------------------- +ENTITY testbench_640 IS +END testbench_640; + + +------------------------------------------------------------------------------- +-- ARCHITECTURE DECLARATION +------------------------------------------------------------------------------- +ARCHITECTURE vhdl_behavioral of testbench_640 IS + COMPONENT my_mem + GENERIC ( + -- tipd delays: interconnect path delays + tipd_A0 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A1 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A2 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A3 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A4 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A5 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A6 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A7 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A8 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A9 : VitalDelayType01 := VitalZeroDelay01; --address + tipd_A10 : VitalDelayType01 := VitalZeroDelay01; --lines + tipd_A11 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A12 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A13 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A14 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A15 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A16 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A17 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A18 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A19 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A20 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A21 : VitalDelayType01 := VitalZeroDelay01; -- + + tipd_DQ0 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ1 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ2 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ3 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ4 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ5 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ6 : VitalDelayType01 := VitalZeroDelay01; -- data + tipd_DQ7 : VitalDelayType01 := VitalZeroDelay01; -- lines + tipd_DQ8 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ9 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ10 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ11 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ12 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ13 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ14 : VitalDelayType01 := VitalZeroDelay01; -- + + tipd_DQ15 : VitalDelayType01 := VitalZeroDelay01; -- DQ15/A-1 + + tipd_CENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_OENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_RESETNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; --WP#/ACC + tipd_BYTENeg : VitalDelayType01 := VitalZeroDelay01; + + -- tpd delays + tpd_A0_DQ0 : VitalDelayType01 := UnitDelay01;--tACC + tpd_A0_DQ1 : VitalDelayType01 := UnitDelay01;--tPACC + tpd_CENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(tCE,tCE,tDF,-,tDF,-) + tpd_OENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(tOE,tOE,tDF,-,tDF,-) + tpd_RESETNeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(-,-,0,-,0,-) + tpd_CENeg_RY : VitalDelayType01 := UnitDelay01; --tBUSY + tpd_WENeg_RY : VitalDelayType01 := UnitDelay01; --tBUSY + + --tsetup values + tsetup_A0_CENeg : VitalDelayType := UnitDelay; --tAS edge \ + tsetup_A0_OENeg : VitalDelayType := UnitDelay; --tASO edge \ + tsetup_DQ0_CENeg : VitalDelayType := UnitDelay; --tDS edge / + + --thold values + thold_CENeg_RESETNeg: VitalDelayType := UnitDelay; --tRH edge / + thold_OENeg_WENeg : VitalDelayType := UnitDelay; --tOEH edge / + thold_A0_CENeg : VitalDelayType := UnitDelay; --tAH edge \ + thold_A0_OENeg : VitalDelayType := UnitDelay; --tAHT edge \ + thold_DQ0_CENeg : VitalDelayType := UnitDelay; --tDH edge / + thold_WENeg_OENeg : VitalDelayType := UnitDelay; --tGHWL edge / + + --tpw values: pulse width + tpw_RESETNeg_negedge: VitalDelayType := UnitDelay; --tRP + tpw_OENeg_posedge : VitalDelayType := UnitDelay; --tOEPH + tpw_WENeg_negedge : VitalDelayType := UnitDelay; --tWP + tpw_WENeg_posedge : VitalDelayType := UnitDelay; --tWPH + tpw_CENeg_negedge : VitalDelayType := UnitDelay; --tCP + tpw_CENeg_posedge : VitalDelayType := UnitDelay; --tCEPH + tpw_A0_negedge : VitalDelayType := UnitDelay; --tWC tRC + + + -- tdevice values: values for internal delays + --Effective Write Buffer Program Operation tWHWH1 + tdevice_WBPB : VitalDelayType := 11 us; + --Program Operation + tdevice_POB : VitalDelayType := 100 us; + --Sector Erase Operation tWHWH2 + tdevice_SEO : VitalDelayType := 500 ms; + --Timing Limit Exceeded + tdevice_HANG : VitalDelayType := 400 ms; --? + --program/erase suspend timeout + tdevice_START_T1 : VitalDelayType := 5 us; + --sector erase command sequence timeout + tdevice_CTMOUT : VitalDelayType := 50 us; + --device ready after Hardware reset(during embeded algorithm) + tdevice_READY : VitalDelayType := 20 us; --tReady + + -- generic control parameters + InstancePath : STRING := DefaultInstancePath; + TimingChecksOn : BOOLEAN := DefaultTimingChecks; + MsgOn : BOOLEAN := DefaultMsgOn; + XOn : BOOLEAN := DefaultXon; + -- memory file to be loaded + mem_file_name : STRING ;--:= "am29lv640m.mem"; + prot_file_name : STRING ;--:= "am29lv640m_prot.mem"; + secsi_file_name : STRING ;--:= "am29lv_secsi.mem"; + + UserPreload : BOOLEAN ;--:= TRUE; + LongTimming : BOOLEAN ;--:= TRUE; + + -- For FMF SDF technology file usage + TimingModel : STRING --:= "AM29LV640MH90R" + ); + PORT ( + A21 : IN std_logic := 'U'; -- + A20 : IN std_logic := 'U'; -- + A19 : IN std_logic := 'U'; -- + A18 : IN std_logic := 'U'; -- + A17 : IN std_logic := 'U'; -- + A16 : IN std_logic := 'U'; -- + A15 : IN std_logic := 'U'; -- + A14 : IN std_logic := 'U'; -- + A13 : IN std_logic := 'U'; --address + A12 : IN std_logic := 'U'; --lines + A11 : IN std_logic := 'U'; -- + A10 : IN std_logic := 'U'; -- + A9 : IN std_logic := 'U'; -- + A8 : IN std_logic := 'U'; -- + A7 : IN std_logic := 'U'; -- + A6 : IN std_logic := 'U'; -- + A5 : IN std_logic := 'U'; -- + A4 : IN std_logic := 'U'; -- + A3 : IN std_logic := 'U'; -- + A2 : IN std_logic := 'U'; -- + A1 : IN std_logic := 'U'; -- + A0 : IN std_logic := 'U'; -- + + DQ15 : INOUT std_logic := 'U'; -- DQ15/A-1 + DQ14 : INOUT std_logic := 'U'; -- + DQ13 : INOUT std_logic := 'U'; -- + DQ12 : INOUT std_logic := 'U'; -- + DQ11 : INOUT std_logic := 'U'; -- + DQ10 : INOUT std_logic := 'U'; -- + DQ9 : INOUT std_logic := 'U'; -- data + DQ8 : INOUT std_logic := 'U'; -- lines + DQ7 : INOUT std_logic := 'U'; -- + DQ6 : INOUT std_logic := 'U'; -- + DQ5 : INOUT std_logic := 'U'; -- + DQ4 : INOUT std_logic := 'U'; -- + DQ3 : INOUT std_logic := 'U'; -- + DQ2 : INOUT std_logic := 'U'; -- + DQ1 : INOUT std_logic := 'U'; -- + DQ0 : INOUT std_logic := 'U'; -- + + CENeg : IN std_logic := 'U'; + OENeg : IN std_logic := 'U'; + WENeg : IN std_logic := 'U'; + RESETNeg : IN std_logic := 'U'; + WPNeg : IN std_logic := 'U'; --WP#/ACC + BYTENeg : IN std_logic := 'U'; + RY : OUT std_logic := 'U' --RY/BY# + ); + END COMPONENT; + + FOR ALL: my_mem USE ENTITY WORK.my_mem(VHDL_BEHAVIORAL); + + --------------------------------------------------------------------------- + --memory configuration + --------------------------------------------------------------------------- + CONSTANT MaxData : NATURAL := 16#FF#; --255; + CONSTANT SecSize : NATURAL := 16#FFFF#; --65535 + CONSTANT SecSiSize : NATURAL := 255; + CONSTANT SecNum : NATURAL := 127; + CONSTANT HiAddrBit : NATURAL := 21; + --Address of the Protected Sector +-- CONSTANT ProtSecNum : NATURAL := SecNum; + + --------------------------------------------------------------------------- + --model configuration + --------------------------------------------------------------------------- + CONSTANT mem_file : STRING := "am29lv640m.mem"; + CONSTANT prot_file : STRING := "am29lv640m_prot.mem"; + CONSTANT secsi_file : STRING := "am29lv_secsi.mem"; + + CONSTANT UserPreload : boolean := TRUE; + CONSTANT DebugInfo : boolean := FALSE; + CONSTANT LongTimming : boolean := TRUE; + CONSTANT TimingModel : STRING := "MY_MEM"; + -- "AM29LV640MH90R";--High sect prot. + -- "AM29LV128ML93R";--Low sect. prot. + --------------------------------------------------------------------------- + SIGNAL ProtSecNum : NATURAL := SecNum ; + + --Flash Memory Array + TYPE SecType IS ARRAY (0 TO SecSize) OF + INTEGER RANGE -1 TO MaxData; + TYPE MemArray IS ARRAY (0 TO SecNum) OF + SecType; + + --Common Flash Interface Query codes + TYPE CFItype IS ARRAY (16#10# TO 16#50#) OF + NATURAL RANGE 0 TO 16#FF#; + + --SecSi Sector + TYPE SecSiType IS ARRAY ( 0 TO SecSiSize) OF + INTEGER RANGE -1 TO MaxData; + + --------------------------------------------------------------------------- + -- memory declaration + --------------------------------------------------------------------------- + -- -- Mem(SecAddr)(Address).... + SHARED VARIABLE Mem : MemArray := (OTHERS => (OTHERS=> MaxData)); + SHARED VARIABLE CFI_array : CFItype :=(OTHERS=>0); + SHARED VARIABLE SecSi : SecSiType :=(OTHERS=>0); + + --command sequence + SHARED VARIABLE cmd_seq : cmd_seq_type; + + SIGNAL status : status_type := none; + SIGNAL sts_check : std_logic_vector(7 downto 0); + + + SIGNAL check_err : std_logic := '0'; + SIGNAL ErrorInTest : std_logic := '0'; -- + ---------------------------------------------------------------------------- + --Personality module: + -- + -- instanciates the DUT module and adapts generic test signals to it + -- TBD: block port + ---------------------------------------------------------------------------- + --DUT port + SIGNAL T_DQ : std_logic_vector(15 downto 0) := (OTHERS=>'U'); + SIGNAL T_A : std_logic_vector(HiAddrBit downto 0) := (OTHERS=>'U'); + SIGNAL T_RESETNeg : std_logic := 'U'; + SIGNAL T_CENeg : std_logic := 'U'; + SIGNAL T_WENeg : std_logic := 'U'; + SIGNAL T_OENeg : std_logic := 'U'; + SIGNAL T_WPNeg : std_logic := 'U'; + SIGNAL T_BYTENeg : std_logic := 'U'; + SIGNAL T_RY : std_logic := 'U'; + + --------------------------------------------------------------------------- + -- + --------------------------------------------------------------------------- + --SecSi ProtectionStatus + SHARED VARIABLE FactoryProt : std_logic := '1'; + --Sector Protection Status + SHARED VARIABLE Sec_Prot : std_logic_vector (SecNum downto 0) := + (OTHERS => '0'); + SHARED VARIABLE Sect : NATURAL RANGE 0 TO SecNum := 0; + SHARED VARIABLE Addr : NATURAL RANGE 0 TO SecSize := 0; + SHARED VARIABLE WriteData : NATURAL RANGE 0 TO MaxData := 0; + + + --CONSTANT + --timming parameters + CONSTANT RESETNeg_pw : time := 500 ns; --tRP + + SIGNAL pwron : std_logic := '0'; + + SIGNAL Tseries : NATURAL; + SIGNAL Tcase : NATURAL; + + SHARED VARIABLE ts_cnt : NATURAL RANGE 1 TO 30:=1; -- testseries counter + SHARED VARIABLE tc_cnt : NATURAL RANGE 0 TO 10:=0; -- testcase counter + + + BEGIN + DUT : my_mem + GENERIC MAP ( + -- tipd delays: interconnect path delays + tipd_A0 => VitalZeroDelay01, -- + tipd_A1 => VitalZeroDelay01, -- + tipd_A2 => VitalZeroDelay01, -- + tipd_A3 => VitalZeroDelay01, -- + tipd_A4 => VitalZeroDelay01, -- + tipd_A5 => VitalZeroDelay01, -- + tipd_A6 => VitalZeroDelay01, -- + tipd_A7 => VitalZeroDelay01, -- + tipd_A8 => VitalZeroDelay01, -- + tipd_A9 => VitalZeroDelay01, --address + tipd_A10 => VitalZeroDelay01, --lines + tipd_A11 => VitalZeroDelay01, -- + tipd_A12 => VitalZeroDelay01, -- + tipd_A13 => VitalZeroDelay01, -- + tipd_A14 => VitalZeroDelay01, -- + tipd_A15 => VitalZeroDelay01, -- + tipd_A16 => VitalZeroDelay01, -- + tipd_A17 => VitalZeroDelay01, -- + tipd_A18 => VitalZeroDelay01, -- + tipd_A19 => VitalZeroDelay01, -- + tipd_A20 => VitalZeroDelay01, -- + tipd_A21 => VitalZeroDelay01, -- + + tipd_DQ0 => VitalZeroDelay01, -- + tipd_DQ1 => VitalZeroDelay01, -- + tipd_DQ2 => VitalZeroDelay01, -- + tipd_DQ3 => VitalZeroDelay01, -- + tipd_DQ4 => VitalZeroDelay01, -- + tipd_DQ5 => VitalZeroDelay01, -- + tipd_DQ6 => VitalZeroDelay01, -- data + tipd_DQ7 => VitalZeroDelay01, -- lines + tipd_DQ8 => VitalZeroDelay01, -- + tipd_DQ9 => VitalZeroDelay01, -- + tipd_DQ10 => VitalZeroDelay01, -- + tipd_DQ11 => VitalZeroDelay01, -- + tipd_DQ12 => VitalZeroDelay01, -- + tipd_DQ13 => VitalZeroDelay01, -- + tipd_DQ14 => VitalZeroDelay01, -- + + tipd_DQ15 => VitalZeroDelay01, -- DQ15/A-1 + + tipd_CENeg => VitalZeroDelay01, + tipd_OENeg => VitalZeroDelay01, + tipd_WENeg => VitalZeroDelay01, + tipd_RESETNeg => VitalZeroDelay01, + tipd_WPNeg => VitalZeroDelay01,--WP#/ACC + tipd_BYTENeg => VitalZeroDelay01, + + -- tpd delays + tpd_A0_DQ0 => UnitDelay01,--tACC + tpd_A0_DQ1 => UnitDelay01,--tPACC + tpd_CENeg_DQ0 => UnitDelay01Z, + --(tCE,tCE,tDF,-,tDF + tpd_OENeg_DQ0 => UnitDelay01Z, + --(tOE,tOE,tDF,-,tDF + tpd_RESETNeg_DQ0 => UnitDelay01Z, + --(-,-,0,-,0,-) + tpd_CENeg_RY => UnitDelay01, --tBUSY + tpd_WENeg_RY => UnitDelay01, --tBUSY + + --tsetup values + tsetup_A0_CENeg => UnitDelay, --tAS edge \ + tsetup_A0_OENeg => UnitDelay, --tASO edge \ + tsetup_DQ0_CENeg => UnitDelay, --tDS edge / + + --thold values + thold_CENeg_RESETNeg=> UnitDelay, --tRH edge / + thold_OENeg_WENeg => UnitDelay, --tOEH edge / + thold_A0_CENeg => UnitDelay, --tAH edge \ + thold_A0_OENeg => UnitDelay, --tAHT edge \ + thold_DQ0_CENeg => UnitDelay, --tDH edge / + thold_WENeg_OENeg => UnitDelay, --tGHVL edge / + + --tpw values: pulse width + tpw_RESETNeg_negedge=> UnitDelay, --tRP + tpw_OENeg_posedge => UnitDelay, --tOEPH + tpw_WENeg_negedge => UnitDelay, --tWP + tpw_WENeg_posedge => UnitDelay, --tWPH + tpw_CENeg_negedge => UnitDelay, --tCP + tpw_CENeg_posedge => UnitDelay, --tCEPH + tpw_A0_negedge => UnitDelay, --tWC tRC + -- tdevice values: values for internal delays + --Effective Write Buffer Program Operation tWHWH1 + tdevice_WBPB => 11 us, + --Program Operation + tdevice_POB => 100 us, + --Sector Erase Operation tWHWH2 + tdevice_SEO => 500 ms, + --Timing Limit Exceeded + tdevice_HANG => 400 ms, --? + --program/erase suspend timeout + tdevice_START_T1 => 5 us, + --sector erase command sequence timeout + tdevice_CTMOUT => 50 us, + --device ready after Hardware reset(during embeded algorithm) + tdevice_READY => 20 us, --tReady + + -- generic control parameters + InstancePath => DefaultInstancePath, + TimingChecksOn => TRUE,--DefaultTimingChecks, + MsgOn => DefaultMsgOn, + XOn => DefaultXon, + -- memory file to be loaded + mem_file_name => mem_file, + prot_file_name => prot_file , + secsi_file_name => secsi_file, + + UserPreload => UserPreload, + LongTimming => LongTimming, + -- For FMF SDF technology file usage + TimingModel => "AM29LV640MH90R" -- TimingModel + ) + PORT MAP( + A21 => T_A(21), -- + A20 => T_A(20), -- + A19 => T_A(19), -- + A18 => T_A(18), -- + A17 => T_A(17), -- + A16 => T_A(16), -- + A15 => T_A(15), -- + A14 => T_A(14), -- + A13 => T_A(13), --address + A12 => T_A(12), --lines + A11 => T_A(11), -- + A10 => T_A(10), -- + A9 => T_A(9), -- + A8 => T_A(8), -- + A7 => T_A(7), -- + A6 => T_A(6), -- + A5 => T_A(5),-- + A4 => T_A(4),-- + A3 => T_A(3), -- + A2 => T_A(2), -- + A1 => T_A(1), -- + A0 => T_A(0), -- + + DQ15 => T_DQ(15), -- DQ15/A-1 + DQ14 => T_DQ(14), -- + DQ13 => T_DQ(13), -- + DQ12 => T_DQ(12), -- + DQ11 => T_DQ(11), -- + DQ10 => T_DQ(10), -- + DQ9 => T_DQ(9), -- data + DQ8 => T_DQ(8), -- lines + DQ7 => T_DQ(7), -- + DQ6 => T_DQ(6), -- + DQ5 => T_DQ(5), -- + DQ4 => T_DQ(4), -- + DQ3 => T_DQ(3), -- + DQ2 => T_DQ(2), -- + DQ1 => T_DQ(1), -- + DQ0 => T_DQ(0), -- + + CENeg => T_CENeg, + OENeg => T_OENeg, + WENeg => T_WENeg, + RESETNeg => T_RESETNeg, + WPNeg => T_WPNeg, --WP#/ACC + BYTENeg => T_BYTENeg, + RY => T_RY --RY/BY# + ); + + --------------------------------------------------------------------------- + --protected sector + --------------------------------------------------------------------------- + ProtSecNum <= SecNum WHEN TimingModel(11) = 'H' ELSE + 0 ;-- WHEN TimingModel = "AM29LV128ML93R" + + pwron <= '0', '1' after 1 ns; + +--At the end of the simulation, if ErrorInTest='0' there were no errors +err_ctrl : PROCESS ( check_err ) + BEGIN + IF check_err = '1' THEN + ErrorInTest <= '1'; + END IF; + END PROCESS err_ctrl; + +tb :PROCESS + + -------------------------------------------------------------------------- + --= PROCEDURE to select TC + -- can be modified to read TC list from file, or to generate random list + -------------------------------------------------------------------------- + PROCEDURE Pick_TC + (Model : IN STRING := "AM29LV640MH90R" ) + IS + BEGIN + IF TC_cnt < tc(TS_cnt) THEN + TC_cnt := TC_cnt+1; + ELSE + TC_cnt:=1; + IF TS_cnt<30 THEN + TS_cnt := TS_cnt+1; + ELSE + -- end test + IF ErrorInTest='0' THEN + REPORT "Test Ended without errors" + SEVERITY note; + ELSE + REPORT "There were errors in test" + SEVERITY note; + END IF; + WAIT; + END IF; + END IF; + END PROCEDURE Pick_TC; + + --------------------------------------------------------------------------- + --bus commands, device specific implementation + --------------------------------------------------------------------------- + TYPE bus_type IS (bus_idle, + bus_standby, --CE# deasseretd, others are don't care + bus_enable, --CE# asserted, others deasserted + bus_output_disable, + bus_reset, + bus_write, + bus_read); + + --bus drive for specific command sequence cycle + PROCEDURE bus_cycle( + bus_cmd :IN bus_type := bus_idle; + byte :IN boolean ; + data :IN INTEGER RANGE -2 TO MaxData := -2; -- -1 for all Z + dataHi :IN INTEGER RANGE -2 TO MaxData := -2; -- -2 for ignore + sector :IN INTEGER RANGE -1 TO SecNum := -1; -- -1 for ignore addr + address :IN NATURAL RANGE 0 TO SecSize := 0; + disable :IN boolean := false; + violate :IN boolean := false; + tm :IN TIME := 10 ns) + IS + + VARIABLE tmp : std_logic_vector(15 downto 0); + BEGIN + + IF data=-1 THEN -- HiZ + T_DQ(7 downto 0) <= (OTHERS => 'Z'); + END IF; + + IF (NOT byte)THEN --word access + IF dataHi=-1 THEN -- HiZ + T_DQ(15 downto 8) <= (OTHERS => 'Z'); + END IF; + T_BYTENeg <= '1'; + ELSE --byte access + T_BYTENeg <= '0'; + T_DQ(14 downto 8) <= (OTHERS => 'Z'); + END IF; + + IF sector > -1 THEN + T_A(HiAddrBit downto 15) <= to_slv(sector, HiAddrbit-14); + tmp := to_slv(address, 16); + IF byte THEN + T_A(14 downto 0) <= tmp(15 downto 1); + T_DQ(15) <= tmp(0); + ELSE + T_A(14 downto 0) <= tmp(14 downto 0); + END IF; + + END IF; + + wait for 1 ns; + + CASE bus_cmd IS + WHEN bus_output_disable => + T_OENeg <= '1'; + WAIT FOR 20 ns; + + WHEN bus_idle => + T_RESETNeg <= '1'; + T_WENeg <= '1'; + T_CENeg <= '1'; + T_OENeg <= '1'; + IF disable THEN + T_WPNeg <= '0'; + ELSE + T_WPNeg <= '1'; + END IF; + WAIT FOR 30 ns; + + WHEN bus_standby => + T_CENeg <= '1'; + WAIT FOR 30 ns; + + WHEN bus_reset => + T_RESETNeg <= '0', '1' AFTER tm ; + -- WAIT FOR 500 ns should follow this bus cmd for reset to + --complete + WAIT FOR 30 ns; + + WHEN bus_enable => + T_WENeg <= '1' AFTER 50 ns; --- + T_CENeg <= '0' AFTER 50 ns; --- + T_OENeg <= '1' AFTER 30 ns; --- + + WAIT FOR tm ; + + WHEN bus_write => + T_OENeg <= '1' ;-- AFTER 5 ns; + T_CENeg <= '0' AFTER 10 ns ; + T_WENeg <= '0' AFTER 20 ns; + + IF data>-1 THEN + T_DQ(7 downto 0) <= to_slv(data,8); + END IF; + IF NOT byte THEN + IF dataHi>-1 THEN + T_DQ(15 downto 8) <= to_slv(dataHi,8); + END IF; + END IF; + + IF violate THEN + T_WENeg <= '1'; + WAIT FOR 50 ns; + T_WENeg <= '0', '1' AFTER tm; + WAIT FOR 50 ns; + ELSE + WAIT FOR 100 ns; + END IF; + + WHEN bus_read => + + T_CENeg <= '0' ; + T_WENeg <= '1'AFTER 10 ns; + IF NOT disable THEN + T_OENeg <= '0' AFTER 15 ns; + ELSE + T_OENeg <= '1'; + END IF; + + IF NOT byte THEN + T_DQ(15 downto 8) <= (OTHERS => 'Z'); + END IF; + T_DQ(7 downto 0) <= (OTHERS => 'Z'); + + WAIT FOR 100 ns; + + -- T_OENeg <= '1' ; ----------- + + END CASE; + + + END PROCEDURE; + + + --------------------------------------------------------------------------- + --procedure to decode commands into specific bus command sequence + --------------------------------------------------------------------------- + PROCEDURE cmd_dc + ( command : IN cmd_rec ) + IS + VARIABLE D_hi : NATURAL ;--RANGE 0 to MaxData; + VARIABLE D_lo : NATURAL RANGE 0 to MaxData; + VARIABLE Addr : NATURAL RANGE 0 to SecSize :=0; + VARIABLE Addrfix : NATURAL RANGE 0 to SecSize/2:=0; + VARIABLE Sect : INTEGER RANGE -1 to SecNum :=0; + VARIABLE slv_1, slv_2 : std_logic_vector(7 downto 0); + VARIABLE byte : boolean; + VARIABLE i : NATURAL; + BEGIN + CASE command.cmd IS + WHEN idle => + bus_cycle(bus_cmd => bus_idle, + byte => command.byte, + disable => command.aux=disable); + + WHEN h_reset => + bus_cycle(bus_cmd => bus_reset, + byte => command.byte, + tm => command.wtime); + + WHEN rd => + bus_cycle(bus_cmd => bus_enable, + byte => command.byte, + data => -1, + sector => command.sect, + address => command.addr, + tm => 90 ns); + + bus_cycle(bus_cmd => bus_read, + byte => command.byte, + data => -1, + dataHi => -1, + sector => command.sect, + address => command.addr, + disable => command.aux=disable); + + bus_cycle(bus_cmd => bus_output_disable, + byte => command.byte); + + WHEN rd_page => + bus_cycle(bus_cmd => bus_enable, + byte => command.byte, + data => -1, + sector => 0, + address => 0, + tm => 90 ns); + + Addr := command.addr; + Sect := command.sect; + byte := command.byte; + ---- 08July---- + WAIT FOR 10 ns; + -------------- + i := 0; + WHILE i < command.d_hi LOOP + + IF command.wtime > 0 ns THEN + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + --byte toggle mode + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + byte := false; + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + Addrfix := Addr /2; + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + --word read; + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addrfix); + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + byte := true; + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 30 ns); + + --first byte read + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addr); + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + i := i +3; + wait for 10 ns; ------- + ELSE + byte := command.byte; + END IF; + --second byte read in byte toggle mode + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addr); + + + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + i := i +1; + WAIT FOR 10 ns; + END LOOP; + bus_cycle(bus_cmd => bus_output_disable, + byte => command.byte); + + + + WHEN w_cycle => + + D_lo := 16#AA# ; --first command data + Addr := 16#AAA#; --first command byte address + D_hi := 16#55#; --second command data + Addrfix := 16#555#; --second command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + Addrfix := 16#2AA#; --second command byte address + END IF; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_lo, + dataHi => 0, + sector => 0, + address => Addr, + violate => command.aux=violate, + tm => command.wtime); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_hi, + dataHi => 0, + sector => 0, + address => Addrfix); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_reset | w_prog | w_erase | w_unlock | + w_autoselect | w_enter_sec => + Addr := 16#AAA#; + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + + CASE command.cmd IS + WHEN w_reset => + d_lo := 16#F0#; + WHEN w_prog => + d_lo := 16#A0#; + WHEN w_erase => + d_lo := 16#80#; + WHEN w_unlock => + d_lo := 16#20#; + WHEN w_autoselect => + d_lo := 16#90#; + WHEN w_enter_sec => + d_lo := 16#88#; + WHEN OTHERS => + d_lo := 0; + END CASE; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => d_lo, + dataHi => 0, + sector => 0, + address => Addr); + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + + WHEN w_unlock_reset => + Addr := 16#AAA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#90#, + dataHi => 0, + sector => 0, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#F0#, + dataHi => 0, + sector => 0, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + WHEN w_chip_ers => + Addr := 16#AAA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#10#, + dataHi => 0, + sector => 0, + Address => Addr); + FOR i IN 0 TO SecNum LOOP + IF Sec_Prot(i)/='1' THEN + mem(i) := (OTHERS=>16#FF#); + END IF; + END LOOP; + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_cfi => + Addr := 16#AA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#55#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#98#, + dataHi => 0, + sector => 0, + Address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + + WHEN w_suspend => + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#B0#, + dataHi => 0, + sector => -1); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + WHEN w_resume => + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#30#, + dataHi => 0, + sector => -1); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_data => + + D_hi := command.d_hi MOD 16#100#; + D_lo := command.d_lo ; + Addr := command.addr; + Sect := command.sect; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_lo, + dataHi => D_hi, + sector => Sect, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + IF NOT command.byte THEN + Addr := Addr*2; + END IF; + + --write value(s) in default mem + IF status = erase_active AND Sec_Prot(Sect)/='1'THEN + --sector should be erased + mem(Sect) := (OTHERS=>16#FF#); + + ELSIF status = erase_na AND Sec_Prot(Sect)/='1'THEN + --sector erase terminated = data integrity violated + mem(Sect) := (OTHERS=>-1); + + ELSIF status = readX AND Sec_Prot(Sect)/='1' THEN + mem(Sect)(Addr) := -1; + IF NOT command.byte THEN + mem(Sect)(Addr+1) := -1; + END IF; + + -- Write to Secure Silicon Sector Region + ELSIF status = rd_SecSi AND FactoryProt/='1' THEN + slv_1 := to_slv(d_lo,8); + IF SecSi(Addr)>-1 THEN + slv_2 := to_slv(SecSi(Addr),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + SecSi(Addr) := to_nat(slv_1); + IF NOT command.byte THEN + slv_1 := to_slv(d_hi,8); + IF SecSi(Addr+1)>-1 THEN + slv_2 := to_slv(SecSi(Addr+1),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + SecSi(Addr+1) := to_nat(slv_1); + END IF; + + ELSIF status=buff_wr_busy THEN + --Write to Buffer command cycle + null; + + ELSIF status=erase_na THEN + --sector erase command sequence violation + null; + + -- Write to Flash Memory Array + ELSIF status /= err AND Sec_Prot(Sect)/='1'THEN + slv_1 := to_slv(d_lo,8); + IF mem(Sect)(Addr)>-1 THEN + slv_2 := to_slv(mem(Sect)(Addr),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + mem(Sect)(Addr) := to_nat(slv_1); + IF NOT command.byte THEN + slv_1 := to_slv(d_hi,8); + IF mem(Sect)(Addr+1)>-1 THEN + slv_2 := to_slv(mem(Sect)(Addr+1),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + mem(Sect)(Addr+1) := to_nat(slv_1); + END IF; + END IF; + + + WHEN wt => + WAIT FOR command.wtime; + + WHEN wt_rdy => + IF T_RY/='1' THEN + WAIT UNTIL rising_edge(T_RY) FOR command.wtime; + END IF; + + WHEN wt_bsy => + IF T_RY='1' THEN + WAIT UNTIL falling_edge(T_RY) FOR command.wtime; + END IF; + + WHEN OTHERS => null; + END CASE; + END PROCEDURE; + + + VARIABLE cmd_cnt : NATURAL; + VARIABLE command : cmd_rec; -- + +BEGIN + Pick_TC (Model => "AM29LV640MH90R" ); + + Tseries <= ts_cnt ; + Tcase <= tc_cnt ; + + Generate_TC + (Model => "AM29LV640MH90R" , + Series => ts_cnt, + TestCase => tc_cnt, + command_seq => cmd_seq); + + + cmd_cnt := 1; + WHILE cmd_seq(cmd_cnt).cmd/=done LOOP + command:= cmd_seq(cmd_cnt); + IF command.sect = -1 THEN + command.sect := ProtSecNum; + END IF; + status <= command.status; + sts_check<= to_slv(command.d_lo,8); --used only for toggle/status check + cmd_dc(command); + cmd_cnt :=cmd_cnt +1; + + END LOOP; + +END PROCESS tb; + +--process to monitor WP# +PROCESS(T_WPNeg) +VARIABLE reg : std_logic; +BEGIN + IF falling_edge(T_WPNeg) THEN + reg := Sec_Prot(ProtSecNum); + Sec_Prot(ProtSecNum) := '1'; + ELSIF rising_edge(T_WPNeg) THEN + Sec_Prot(ProtSecNum) := reg; + END IF; +END PROCESS; + +-------------------------------------------------------------------------------- +-- Checker process, +-- Bus transition extractor: when bus cycle is read samples addr and data +-- Transition checker : verifies correct read data using default memory +-------------------------------------------------------------------------------- +checker: PROCESS + VARIABLE RAddr : NATURAL; + VARIABLE RSect : NATURAL; + VARIABLE longread : boolean; + VARIABLE shortread : boolean; + VARIABLE toggle : boolean:=false; + VARIABLE toggle_sts : std_logic_vector(7 downto 0); + +BEGIN +-- Transition extractor + IF (T_CENeg='0'AND T_OENeg='0'AND T_WENeg='1') THEN + IF T_BYTENeg='1' THEN + RAddr := to_nat(T_A(14 downto 0)&'0'); + ELSE + RAddr := to_nat(T_A(14 downto 0)&T_DQ(15)); + END IF; + RSect := to_nat(T_A(HiAddrBit downto 15)); + + shortread:= false; + longread := false; + + --DUT specific timing + IF (T_CENeg'EVENT OR T_WENeg'EVENT OR T_A(HiAddrBit downto 2)'EVENT)AND -- + (status=read OR status=rd_cfi OR status=rd_secsi) THEN --OR status=readX) + longread := true; + CASE TimingModel IS + WHEN "AM29LV640MH90R" | + "AM29LV640ML90R" => WAIT FOR 95 ns; +-- WHEN "AM29LV640MH101" | +-- "AM29LV640ML101" => WAIT FOR 105 ns; +-- WHEN "AM29LV640MH101R" | +-- "AM29LV640ML101R" => WAIT FOR 105 ns; +-- WHEN "AM29LV640MH112" | +-- "AM29LV640ML112" => WAIT FOR 115 ns; +-- WHEN "AM29LV640MH112R" | +-- "AM29LV640ML112R" => WAIT FOR 115 ns; +-- WHEN "AM29LV640MH120" | +-- "AM29LV640ML120" => WAIT FOR 125 ns; +-- WHEN "AM29LV640MH120R" | +-- "AM29LV640ML120R" => WAIT FOR 125 ns; + WHEN OTHERS => + REPORT "Timing model NOT supported : "&TimingModel + SEVERITY error; + END CASE; + + ELSIF T_A(1 downto 0)'EVENT OR + (T_DQ(15)'EVENT AND T_BYTENeg='0')OR + (T_BYTENeg'EVENT) OR + T_OENeg'EVENT OR + (status/=read AND status/=rd_cfi AND + status/=rd_secsi) THEN --AND status/=readX) + shortread:=true; + CASE TimingModel IS + WHEN "AM29LV640MH90R" | + "AM29LV640ML90R" => WAIT FOR 30 ns; +-- WHEN "AM29LV640MH101" | +-- "AM29LV640ML101" => WAIT FOR 40 ns; +-- WHEN "AM29LV640MH101R" | +-- "AM29LV640ML101R" => WAIT FOR 40 ns; +-- WHEN "AM29LV640MH112" | +-- "AM29LV640ML112" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH112R" | +-- "AM29LV640ML112R" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH120" | +-- "AM29LV640ML120" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH120R" | +-- "AM29LV640ML120R" => WAIT FOR 45 ns; + WHEN OTHERS => + REPORT "Timing model NOT supported : "&TimingModel + SEVERITY error; + END CASE; + + END IF; + + + + --Checker + IF longread OR shortread THEN + + CASE status IS + WHEN none => + toggle := false; + + -- read memory array data + WHEN read => + toggle := false; + Check_read ( + DQ => T_DQ, + D_lo => mem(RSect)(RAddr), + D_hi => mem(RSect)(RAddr+1), + Byte => T_BYTENeg, + check_err=> check_err); + + -- read secure silicon region + WHEN rd_secsi => + toggle := false; + Check_SecSi ( + DQ => T_DQ, + D_lo => SecSi(RAddr), + D_hi => SecSi(RAddr+1), + Byte => T_BYTENeg, + check_err=>check_err); + + + --read CFI query codes + WHEN rd_cfi => + RAddr := to_nat(T_A(14 downto 0)); --x16 addressing + toggle := false; + Check_CFI ( + DQ => T_DQ, + D_lo => CFI_array(RAddr) , + D_hi => 0 , + Byte => T_BYTENeg, + check_err=>check_err); + + + + -- read Autoselect codes + WHEN rd_AS => + RAddr := to_nat(T_A(14 downto 0)); --x16 addressing + toggle := false; + Check_AS ( + DQ => T_DQ, + addr => RAddr, + ProtSecNum=>ProtSecNum, + secProt => Sec_Prot(RSect), + FactoryProt=>FactoryProt , + Byte => T_BYTENeg, + AS_E => to_slv(16#0C#,8), + AS_F => to_slv(1,8), + + check_err=>check_err); + + + WHEN rd_HiZ => + toggle:=false; + Check_Z ( + DQ => T_DQ, + check_err=>check_err); + + + + WHEN readX => + toggle:=false; + Check_X ( + DQ => T_DQ, + check_err=>check_err); + + + WHEN erase_na | erase_active => + IF toggle THEN + Check_Erase ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN ers_susp_e => + IF toggle THEN + Check_Ers_Susp ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + +-- + + WHEN ers_susp_prog_na | ers_susp_prog => + IF toggle THEN + Check_Ers_Susp_Prog ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + +-- + + WHEN prog_na | prog_active => + IF toggle THEN + Check_Progr ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN buff_wr_busy | buff_wr_N_busy => + IF toggle THEN + Check_Buff_Busy ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN buff_abort => + IF toggle THEN + Check_Abort ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + WHEN OTHERS => null; + END CASE; + + -- get firs data for toggle check + CASE status IS + WHEN prog_active | prog_na | + erase_active | erase_na | + ers_susp_e | + ers_susp_prog | ers_susp_prog_na | + buff_wr_busy | buff_wr_N_busy | + buff_abort | get_toggle => + + IF (NOT toggle) OR (status=get_toggle) THEN + toggle:=true; + toggle_sts := T_DQ(7 downto 0); + END IF; + + WHEN OTHERS => null; + END CASE; + + + END IF; + + END IF; + + WAIT ON T_A, T_CENeg, T_OENeg, T_WENeg, T_DQ(15), T_BYTENeg; + +END PROCESS checker; + + +default: PROCESS + -- text file input variables + FILE mem_f : text is mem_file; + FILE prot_f : text is prot_file; + FILE secsi_f : text is secsi_file; + + VARIABLE S_ind : NATURAL RANGE 0 TO SecNum:= 0; + VARIABLE ind : NATURAL RANGE 0 TO SecSize:= 0; + VARIABLE buf : line; + +BEGIN + --Preload Control + ----------------------------------------------------------------------- + -- File Read Section + ----------------------------------------------------------------------- + IF UserPreload THEN + --- Sector protection preload + IF (prot_file /= "none" ) THEN + ind := 0; + FactoryProt := '0'; + Sec_Prot := (OTHERS => '0'); + WHILE (not ENDFILE (prot_f)) LOOP + READLINE (prot_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 3)); --address + ELSE + IF ind > SecNum THEN + --SecSi Factory protect preload + IF buf(1)='1' THEN + FactoryProt := '1'; + END IF; + ELSE + -- Standard Sector prload + IF buf(1)='1' THEN + Sec_Prot(ind):= '1'; + END IF; + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + -- Secure Silicon Sector Region preload + IF (SecSi_file /= "none" ) THEN + SecSi := (OTHERS => MaxData); + ind := 0; + WHILE (not ENDFILE (SecSi_f)) LOOP + READLINE (SecSi_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 3)); --address + ELSE + IF ind <= SecSiSize THEN + SecSi(ind) := h(buf(1 TO 2)); + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + --- Memory Preload + IF (mem_file /= "none" ) THEN + ind := 0; + Mem := (OTHERS => (OTHERS => MaxData)); + -- load sector 0 + WHILE (not ENDFILE (mem_f)) LOOP + READLINE (mem_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 5)); --address + ELSE + IF ind <= SecSize THEN + Mem(0)(ind) := h(buf(1 to 2)); + ind := ind + 1; + END IF; + END IF; + END LOOP; + -- load other sectors + FOR i IN 1 TO SecNum LOOP + Mem(i) := Mem(0); + END LOOP; + END IF; + + END IF; + ----------------------------------------------------------------------- + --CFI array data / AM29LV640MH90R !!! DEVICE SPECIFIC + ----------------------------------------------------------------------- + --CFI query identification string + -- !!!!!! WORD ADDRESSES (x16) - for x8 addressing double addr + --CFI query identification string + CFI_array(16#10#) := 16#51#; + CFI_array(16#11#) := 16#52#; + CFI_array(16#12#) := 16#59#; + CFI_array(16#13#) := 16#02#; + CFI_array(16#14#) := 16#00#; + CFI_array(16#15#) := 16#40#; + CFI_array(16#16#) := 16#00#; + CFI_array(16#17#) := 16#00#; + CFI_array(16#18#) := 16#00#; + CFI_array(16#19#) := 16#00#; + CFI_array(16#1A#) := 16#00#; + --system interface string + CFI_array(16#1B#) := 16#27#; + CFI_array(16#1C#) := 16#36#; + CFI_array(16#1D#) := 16#00#; + CFI_array(16#1E#) := 16#00#; + CFI_array(16#1F#) := 16#07#; + CFI_array(16#20#) := 16#07#; + CFI_array(16#21#) := 16#0A#; + CFI_array(16#22#) := 16#00#; + CFI_array(16#23#) := 16#01#; + CFI_array(16#24#) := 16#05#; + CFI_array(16#25#) := 16#04#; + CFI_array(16#26#) := 16#00#; + --device geometry definition + CFI_array(16#27#) := 16#17#; + CFI_array(16#28#) := 16#02#; + CFI_array(16#29#) := 16#00#; + CFI_array(16#2A#) := 16#05#; + CFI_array(16#2B#) := 16#00#; + CFI_array(16#2C#) := 16#01#; + CFI_array(16#2D#) := 16#7F#; + CFI_array(16#2E#) := 16#00#; + CFI_array(16#2F#) := 16#00#; + CFI_array(16#30#) := 16#01#; + CFI_array(16#31#) := 16#00#; + CFI_array(16#32#) := 16#00#; + CFI_array(16#33#) := 16#00#; + CFI_array(16#34#) := 16#00#; + CFI_array(16#35#) := 16#00#; + CFI_array(16#36#) := 16#00#; + CFI_array(16#37#) := 16#00#; + CFI_array(16#38#) := 16#00#; + CFI_array(16#39#) := 16#00#; + CFI_array(16#3A#) := 16#00#; + CFI_array(16#3B#) := 16#00#; + CFI_array(16#3C#) := 16#00#; + --primary vendor-specific extended query + CFI_array(16#40#) := 16#50#; + CFI_array(16#41#) := 16#52#; + CFI_array(16#42#) := 16#49#; + CFI_array(16#43#) := 16#31#; + CFI_array(16#44#) := 16#33#; + CFI_array(16#45#) := 16#08#; + CFI_array(16#46#) := 16#02#; + CFI_array(16#47#) := 16#01#; + CFI_array(16#48#) := 16#01#; + CFI_array(16#49#) := 16#04#; + CFI_array(16#4A#) := 16#00#; + CFI_array(16#4B#) := 16#00#; + CFI_array(16#4C#) := 16#01#; + CFI_array(16#4D#) := 16#B5#; + CFI_array(16#4E#) := 16#C5#; + IF TimingModel(11) = 'L' THEN + CFI_array(16#4F#) := 16#04#; + ELSE + CFI_array(16#4F#) := 16#05#; --uniform sectors top protect + END IF; + CFI_array(16#50#) := 16#01#; + + WAIT; + +END PROCESS default; + + + +END vhdl_behavioral; + diff --git a/lib/models/memory/flash/serial/S25fl064p/utilities/conversions.vhd b/lib/models/memory/flash/serial/S25fl064p/utilities/conversions.vhd new file mode 100644 index 0000000..e5fc0d6 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064p/utilities/conversions.vhd @@ -0,0 +1,1035 @@ +-------------------------------------------------------------------------------- +-- File Name: conversions_p.vhd +-------------------------------------------------------------------------------- +-- Copyright (C) 1997, 1998, 2001 Free Model Foundry; http://eda.org/fmf/ +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License version 2 as +-- published by the Free Software Foundation. +-- +-- This package was written by SEVA Technologies, Inc. and donated to the FMF. +-- www.seva.com +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 R. Steele 97 DEC 05 Added header and formatting to SEVA file +-- V1.1 R. Munden 98 NOV 28 Corrected some comments +-- Corrected function b +-- V1.2 R. Munden 01 MAY 27 Corrected function to_nat for weak values +-- and combined into a single file +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; + +-------------------------------------------------------------------------------- +-- CONVERSION FUNCTION SELECTION TABLES +-------------------------------------------------------------------------------- +-- +-- FROM TO: std_logic_vector std_logic natural time string +-- -----------------|---------------|---------|---------|---------|----------- +-- std_logic_vector | N/A | N/A | to_nat | combine | see below +-- std_logic | N/A | N/A | to_nat | combine | see below +-- natural | to_slv | to_sl | N/A | to_time | see below +-- time | N/A | N/A | to_nat | N/A | to_time_str +-- hex string | h | N/A | h | combine | N/A +-- decimal string | d | N/A | d | combine | N/A +-- octal string | o | N/A | o | combine | N/A +-- binary string | b | N/A | b | combine | N/A +-- -----------------|---------------|---------|---------|---------|----------- +-- +-- FROM TO: hex string decimal string octal string binary string +-- -----------------|------------|-------------|------------|---------------- +-- std_logic_vector | to_hex_str | to_int_str | to_oct_str | to_bin_str +-- std_logic | N/A | N/A | N/A | to_bin_str +-- natural | to_hex_str | to_int_str | to_oct_str | to_bin_str +-- -----------------|------------|-------------|------------|---------------- +-- +-------------------------------------------------------------------------------- + +PACKAGE conversions IS + + ---------------------------------------------------------------------------- + -- the conversions in this package are not guaranteed to be synthesizable. + -- + -- others functions available + -- fill creates a variable length string of the fill character + -- + -- + -- + -- input parameters of type natural or integer can be in the form: + -- normal -> 8, 99, 4_237 + -- base#value# -> 2#0101#, 16#fa4C#, 8#6_734# + -- with exponents(x10) -> 8e4, 16#2e#E4 + -- + -- input parameters of type string can be in the form: + -- "99", "4_237", "0101", "1010_1010" + -- + -- for bit/bit_vector <-> std_logic/std_logic_vector conversions use + -- package std_logic_1164 + -- to_bit(std_logic) + -- to_bitvector(std_logic_vector) + -- to_stdlogic(bit) + -- to_stdlogicvector(bit_vector) + -- + -- for "synthesizable" signed/unsigned/std_logic_vector/integer + -- conversions use + -- package std_logic_arith + -- conv_integer(signed/unsigned) + -- conv_unsigned(integer/signed,size) + -- conv_signed(integer/unsigned,size) + -- conv_std_logic_vector(integer/signed/unsigned,size) + -- + -- for "synthesizable" std_logic_vector -> integer conversions use + -- package std_logic_unsigned/std_logic_signed + -- + -- conv_integer(std_logic_vector) + -- + -- type1'(expression of type2) + -- + -- most conversions have 4 parmeters: + -- x : value to be converted + -- rtn_len : size of the return value + -- justify : justify value 'left' or 'right', default is right + -- basespec : print the base of the value - 'yes'/'no', default is yes + -- + -- Typical ways to call these functions: + -- simple, all defaults used + -- to_bin_str(x) + -- x will be converted to a string of minimum size with a + -- base specification appended for clarity + -- if x is 10101 then return is b"10101" + -- + -- to control size of return string + -- to_hex_str(x, + -- 6) + -- length of string returned will be 6 characters + -- value will be right justified in the field + -- if x is 10101 then return is ....h"15" + -- where '.' represents a blank + -- if 'rtn_len' parm defaults or is set to 0 then + -- return string will always be minimum size + -- + -- to left justify and suppress base specification + -- to_int_str(x, + -- 6, + -- justify => left, + -- basespec => yes) + -- length of return string will be 6 characters + -- the base specification will be suppressed + -- if x is 10101 then return is 21.... + -- where '.' represents a blank + -- + -- other usage notes + -- + -- if rtn_len less than or equal to x'length then ignore + -- rtn_len and return string of x'length + -- the 'justify' parm is effectively ignored in this case + -- + -- if rtn_len greater than x'length then return string + -- of rtn_len with blanks based on 'justify' parm + -- + -- these routines do not handle negative numbers + ---------------------------------------------------------------------------- + + type justify_side is (left, right); + type b_spec is (no , yes); + + -- std_logic_vector to binary string + function to_bin_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- std_logic to binary string + function to_bin_str(x : std_logic; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to binary string + function to_bin_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to hex string + function to_hex_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to hex string + function to_hex_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to octal string + function to_oct_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to octal string + function to_oct_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- natural to integer string + function to_int_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to integer string + function to_int_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- time to string + function to_time_str (x : time) + return string; + + -- add characters to a string + function fill (fill_char : character := '*'; + rtn_len : integer := 1) + return string; + -- usage: + -- fill + -- returns * + -- fill(' ',10) + -- returns .......... when '.' represents a blank + -- fill(lf) or fill(ht) + -- returns line feed character or tab character respectively + + -- std_logic_vector to natural + function to_nat (x : std_logic_vector) + return natural; + + -- std_logic to natural + function to_nat (x : std_logic) + return natural; + + -- time to natural + function to_nat (x : time) + return natural; + + -- hex string to std_logic_vector + function h (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or a,A to f,F + -- or x,X,z,Z,u,U,-,w,W, result will be 0 + + -- decimal string to std_logic_vector + function d (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- octal string to std_logic_vector + function o (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 7 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- binary string to std_logic_vector + function b (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 1 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- hex string to natural + function h (x : string) + return natural; + -- if x is other than characters 0 to 9 or a,A to f,F, result will be 0 + + -- decimal string to natural + function d (x : string) + return natural; + -- if x is other than characters 0 to 9, result will be 0 + + -- octal string to natural + function o (x : string) + return natural; + -- if x is other than characters 0 to 7, result will be 0 + + -- binary string to natural + function b (x : string) + return natural; + -- if x is other than characters 0 to 1, result will be 0 + + -- natural to std_logic_vector + function to_slv (x : natural; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than sizeof(x), result will be truncated on the left + -- see note above regarding possible formats for x + + -- natural to std_logic + function to_sl (x : natural) + return std_logic; + + -- natural to time + function to_time (x : natural) + return time; + -- see note above regarding possible formats for x + +END conversions; +-- +-------------------------------------------------------------------------------- +-- + +PACKAGE BODY conversions IS + + -- private declarations for this package + type basetype is (binary, octal, decimal, hex); + + function max(x,y: integer) return integer is + begin + if x > y then return x; else return y; end if; + end max; + + function min(x,y: integer) return integer is + begin + if x < y then return x; else return y; end if; + end min; + + -- consider function sizeof for string/slv/???, return natural + + -- function size(len: natural) return natural is + -- begin + -- if len=0 then + -- return 31; + -- else return len; + -- end if; + -- end size; + + function nextmultof (x : positive; + size : positive) return positive is + begin + case x mod size is + when 0 => return size * x/size; + when others => return size * (x/size + 1); + end case; + end nextmultof; + + function rtn_base (base : basetype) return character is + begin + case base is + when binary => return 'b'; + when octal => return 'o'; + when decimal => return 'd'; + when hex => return 'h'; + end case; + end rtn_base; + + function format (r : string; + base : basetype; + rtn_len : natural ; + justify : justify_side; + basespec : b_spec) return string is + variable int_rtn_len : integer; + begin + if basespec=yes then + int_rtn_len := rtn_len - 3; + else + int_rtn_len := rtn_len; + end if; + if int_rtn_len <= r'length then + case basespec is + when no => return r ; + when yes => return rtn_base(base) & '"' & r & '"'; + end case; + else + case justify is + when left => + case basespec is + when no => + return r & fill(' ',int_rtn_len - r'length); + when yes => + return rtn_base(base) & '"' & r & '"' & + fill(' ',int_rtn_len - r'length); + end case; + when right => + case basespec is + when no => + return fill(' ',int_rtn_len - r'length) & r ; + when yes => + return fill(' ',int_rtn_len - r'length) & + rtn_base(base) & '"' & r & '"'; + end case; + end case; + end if; + end format; + + -- convert numeric string of any base to natural + function cnvt_base (x : string; + inbase : natural range 2 to 16) return natural is + -- assumes x is an unsigned number string of base 'inbase' + -- values larger than natural'high are not supported + variable r,t : natural := 0; + variable place : positive := 1; + begin + for i in x'reverse_range loop + case x(i) is + when '0' => t := 0; + when '1' => t := 1; + when '2' => t := 2; + when '3' => t := 3; + when '4' => t := 4; + when '5' => t := 5; + when '6' => t := 6; + when '7' => t := 7; + when '8' => t := 8; + when '9' => t := 9; + when 'a'|'A' => t := 10; + when 'b'|'B' => t := 11; + when 'c'|'C' => t := 12; + when 'd'|'D' => t := 13; + when 'e'|'E' => t := 14; + when 'f'|'F' => t := 15; + when '_' => t := 0; -- ignore these characters + place := place / inbase; + when others => + assert false + report lf & + "CNVT_BASE found input value larger than base: " & lf & + "Input value: " & x(i) & + " Base: " & to_int_str(inbase) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + if t / inbase > 1 then -- invalid value for base + assert false + report lf & + "CNVT_BASE found input value larger than base: " & lf & + "Input value: " & x(i) & + " Base: " & to_int_str(inbase) & lf & + "converting input to integer 0" + severity warning; + return 0; + else + r := r + (t * place); + place := place * inbase; + end if; + end loop; + return r; + end cnvt_base; + + function extend (x : std_logic; + len : positive) return std_logic_vector is + variable v : std_logic_vector(1 to len) := (others => x); + begin + return v; + end extend; + + + -- implementation of public declarations + + function to_bin_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + + variable int : std_logic_vector(1 to x'length):=x; + variable r : string(1 to x'length):=(others=>'$'); + begin + for i in int'range loop + r(i to i) := to_bin_str(int(i),basespec=>no); + end loop; + return format (r,binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_bin_str(x : std_logic; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable r : string(1 to 1); + begin + case x is + when '0' => r(1) := '0'; + when '1' => r(1) := '1'; + when 'U' => r(1) := 'U'; + when 'X' => r(1) := 'X'; + when 'Z' => r(1) := 'Z'; + when 'W' => r(1) := 'W'; + when 'H' => r(1) := 'H'; + when 'L' => r(1) := 'L'; + when '-' => r(1) := '-'; + end case; + return format (r,binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_bin_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 2 to 32 := 32; + variable r : string(2 to 32):=(others=>'$'); + begin + if int = 0 then + return format ("0",binary,rtn_len,justify,basespec); + end if; + + while int > 0 loop + case int rem 2 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when others => + assert false report lf & "TO_BIN_STR, shouldn't happen" + severity failure; + return "$"; + null; + end case; + int := int / 2; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 32),binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_hex_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + -- will return x'length/4 + variable nxt : positive := nextmultof(x'length,4); + variable int : std_logic_vector(1 to nxt):= (others => '0'); + variable ptr : positive range 1 to (nxt/4)+1 := 1; + variable r : string(1 to nxt/4):=(others=>'$'); + subtype slv4 is std_logic_vector(1 to 4); + begin + int(nxt-x'length+1 to nxt) := x; + if nxt-x'length > 0 and x(x'left) /= '1' then + int(1 to nxt-x'length) := extend(x(x'left),nxt-x'length); + end if; + for i in int'range loop + next when i rem 4 /= 1; + case slv4'(int(i to i+3)) is + when "0000" => r(ptr) := '0'; + when "0001" => r(ptr) := '1'; + when "0010" => r(ptr) := '2'; + when "0011" => r(ptr) := '3'; + when "0100" => r(ptr) := '4'; + when "0101" => r(ptr) := '5'; + when "0110" => r(ptr) := '6'; + when "0111" => r(ptr) := '7'; + when "1000" => r(ptr) := '8'; + when "1001" => r(ptr) := '9'; + when "1010" => r(ptr) := 'A'; + when "1011" => r(ptr) := 'B'; + when "1100" => r(ptr) := 'C'; + when "1101" => r(ptr) := 'D'; + when "1110" => r(ptr) := 'E'; + when "1111" => r(ptr) := 'F'; + when "ZZZZ" => r(ptr) := 'Z'; + when "WWWW" => r(ptr) := 'W'; + when "LLLL" => r(ptr) := 'L'; + when "HHHH" => r(ptr) := 'H'; + when "UUUU" => r(ptr) := 'U'; + when "XXXX" => r(ptr) := 'X'; + when "----" => r(ptr) := '-'; + when others => + assert false + report lf & + "TO_HEX_STR found illegal value: " & + to_bin_str(int(i to i+3)) & lf & + "converting input to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr + 1; + end loop; + return format (r,hex,rtn_len,justify,basespec); + end to_hex_str; + + function to_hex_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 20 := 20; + variable r : string(1 to 20):=(others=>'$'); + begin + if x=0 then return format ("0",hex,rtn_len,justify,basespec); end if; + while int > 0 loop + case int rem 16 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when 8 => r(ptr) := '8'; + when 9 => r(ptr) := '9'; + when 10 => r(ptr) := 'A'; + when 11 => r(ptr) := 'B'; + when 12 => r(ptr) := 'C'; + when 13 => r(ptr) := 'D'; + when 14 => r(ptr) := 'E'; + when 15 => r(ptr) := 'F'; + when others => + assert false report lf & "TO_HEX_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 16; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 20),hex,rtn_len,justify,basespec); + end to_hex_str; + + function to_oct_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + -- will return x'length/3 + variable nxt : positive := nextmultof(x'length,3); + variable int : std_logic_vector(1 to nxt):= (others => '0'); + variable ptr : positive range 1 to (nxt/3)+1 := 1; + variable r : string(1 to nxt/3):=(others=>'$'); + subtype slv3 is std_logic_vector(1 to 3); + begin + int(nxt-x'length+1 to nxt) := x; + if nxt-x'length > 0 and x(x'left) /= '1' then + int(1 to nxt-x'length) := extend(x(x'left),nxt-x'length); + end if; + for i in int'range loop + next when i rem 3 /= 1; + case slv3'(int(i to i+2)) is + when "000" => r(ptr) := '0'; + when "001" => r(ptr) := '1'; + when "010" => r(ptr) := '2'; + when "011" => r(ptr) := '3'; + when "100" => r(ptr) := '4'; + when "101" => r(ptr) := '5'; + when "110" => r(ptr) := '6'; + when "111" => r(ptr) := '7'; + when "ZZZ" => r(ptr) := 'Z'; + when "WWW" => r(ptr) := 'W'; + when "LLL" => r(ptr) := 'L'; + when "HHH" => r(ptr) := 'H'; + when "UUU" => r(ptr) := 'U'; + when "XXX" => r(ptr) := 'X'; + when "---" => r(ptr) := '-'; + when others => + assert false + report lf & + "TO_OCT_STR found illegal value: " & + to_bin_str(int(i to i+2)) & lf & + "converting input to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr + 1; + end loop; + return format (r,octal,rtn_len,justify,basespec); + end to_oct_str; + + function to_oct_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 20 := 20; + variable r : string(1 to 20):=(others=>'$'); + begin + if x=0 then return format ("0",octal,rtn_len,justify,basespec); end if; + while int > 0 loop + case int rem 8 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when others => + assert false report lf & "TO_OCT_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 8; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 20),octal,rtn_len,justify,basespec); + end to_oct_str; + + function to_int_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 32 := 32; + variable r : string(1 to 32):=(others=>'$'); + begin + if x=0 then return format ("0",hex,rtn_len,justify,basespec); + else + while int > 0 loop + case int rem 10 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when 8 => r(ptr) := '8'; + when 9 => r(ptr) := '9'; + when others => + assert false report lf & "TO_INT_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 10; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 32),decimal,rtn_len,justify,basespec); + end if; + end to_int_str; + + function to_int_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string is + begin + return to_int_str(to_nat(x),rtn_len,justify,basespec); + end to_int_str; + + + function to_time_str (x : time) + return string is + begin + return to_int_str(to_nat(x),basespec=>no) & " ns"; + end to_time_str; + + function fill (fill_char : character := '*'; + rtn_len : integer := 1) + return string is + variable r : string(1 to max(rtn_len,1)) := (others => fill_char); + variable len : integer; + begin + if rtn_len < 2 then -- always returns at least 1 fill char + len := 1; + else + len := rtn_len; + end if; + return r(1 to len); + end fill; + + function to_nat(x : std_logic_vector) return natural is + -- assumes x is an unsigned number, lsb on right, + -- more than 31 bits are truncated on left + variable t : std_logic_vector(1 to x'length) := x; + variable int : std_logic_vector(1 to 31) := (others => '0'); + variable r : natural := 0; + variable place : positive := 1; + begin + if x'length < 32 then + int(max(32-x'length,1) to 31) := t(1 to x'length); + else -- x'length >= 32 + int(1 to 31) := t(x'length-30 to x'length); + end if; + for i in int'reverse_range loop + case int(i) is + when '1' | 'H' => r := r + place; + when '0' | 'L' => null; + when others => + assert false + report lf & + "TO_NAT found illegal value: " & to_bin_str(int(i)) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + exit when i=1; + place := place * 2; + end loop; + return r; + end to_nat; + + function to_nat (x : std_logic) + return natural is + begin + case x is + when '0' => return 0 ; + when '1' => return 1 ; + when others => + assert false + report lf & + "TO_NAT found illegal value: " & to_bin_str(x) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + end to_nat; + + function to_nat (x : time) + return natural is + begin + return x / 1 ns; + end to_nat; + + function h(x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or a,A to f,F or + -- x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length*4,rtn_len); + variable ptr : integer range -3 to size := size; + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr-3 to ptr) := "0000"; + when '1' => r(ptr-3 to ptr) := "0001"; + when '2' => r(ptr-3 to ptr) := "0010"; + when '3' => r(ptr-3 to ptr) := "0011"; + when '4' => r(ptr-3 to ptr) := "0100"; + when '5' => r(ptr-3 to ptr) := "0101"; + when '6' => r(ptr-3 to ptr) := "0110"; + when '7' => r(ptr-3 to ptr) := "0111"; + when '8' => r(ptr-3 to ptr) := "1000"; + when '9' => r(ptr-3 to ptr) := "1001"; + when 'a'|'A' => r(ptr-3 to ptr) := "1010"; + when 'b'|'B' => r(ptr-3 to ptr) := "1011"; + when 'c'|'C' => r(ptr-3 to ptr) := "1100"; + when 'd'|'D' => r(ptr-3 to ptr) := "1101"; + when 'e'|'E' => r(ptr-3 to ptr) := "1110"; + when 'f'|'F' => r(ptr-3 to ptr) := "1111"; + when 'U' => r(ptr-3 to ptr) := "UUUU"; + when 'X' => r(ptr-3 to ptr) := "XXXX"; + when 'Z' => r(ptr-3 to ptr) := "ZZZZ"; + when 'W' => r(ptr-3 to ptr) := "WWWW"; + when 'H' => r(ptr-3 to ptr) := "HHHH"; + when 'L' => r(ptr-3 to ptr) := "LLLL"; + when '-' => r(ptr-3 to ptr) := "----"; + when '_' => ptr := ptr + 4; + when others => + assert false + report lf & + "O conversion found illegal input character: " & + int(i) & lf & "converting character to '----'" + severity warning; + r(ptr-3 to ptr) := "----"; + end case; + ptr := ptr - 4; + end loop; + return r(size-rtn_len+1 to size); + end h; + + function d (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than binary length of x, result will be truncated on + -- the left + -- if x is other than characters 0 to 9, result will be 0 + begin + return to_slv(cnvt_base(x,10),rtn_len); + end d; + + function o (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length*3, result will be truncated on the left + -- if x is other than characters 0 to 7 or or x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length*3,rtn_len); + variable ptr : integer range -2 to size := size; + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr-2 to ptr) := "000"; + when '1' => r(ptr-2 to ptr) := "001"; + when '2' => r(ptr-2 to ptr) := "010"; + when '3' => r(ptr-2 to ptr) := "011"; + when '4' => r(ptr-2 to ptr) := "100"; + when '5' => r(ptr-2 to ptr) := "101"; + when '6' => r(ptr-2 to ptr) := "110"; + when '7' => r(ptr-2 to ptr) := "111"; + when 'U' => r(ptr-2 to ptr) := "UUU"; + when 'X' => r(ptr-2 to ptr) := "XXX"; + when 'Z' => r(ptr-2 to ptr) := "ZZZ"; + when 'W' => r(ptr-2 to ptr) := "WWW"; + when 'H' => r(ptr-2 to ptr) := "HHH"; + when 'L' => r(ptr-2 to ptr) := "LLL"; + when '-' => r(ptr-2 to ptr) := "---"; + when '_' => ptr := ptr + 3; + when others => + assert false + report lf & + "O conversion found illegal input character: " & + int(i) & lf & "converting character to '---'" + severity warning; + r(ptr-2 to ptr) := "---"; + end case; + ptr := ptr - 3; + end loop; + return r(size-rtn_len+1 to size); + end o; + + function b (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length, result will be truncated on the left + -- if x is other than characters 0 to 1 or x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length,rtn_len); + variable ptr : integer range 0 to size+1 := size; -- csa + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr) := '0'; + when '1' => r(ptr) := '1'; + when 'U' => r(ptr) := 'U'; + when 'X' => r(ptr) := 'X'; + when 'Z' => r(ptr) := 'Z'; + when 'W' => r(ptr) := 'W'; + when 'H' => r(ptr) := 'H'; + when 'L' => r(ptr) := 'L'; + when '-' => r(ptr) := '-'; + when '_' => ptr := ptr + 1; + when others => + assert false + report lf & + "B conversion found illegal input character: " & + int(i) & lf & "converting character to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr - 1; + end loop; + return r(size-rtn_len+1 to size); + end b; + + function h (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 9 + -- a,A to f,F + -- blanks, underscore + begin + return cnvt_base(x,16); + end h; + + function d (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 9 + -- blanks, underscore + begin + return cnvt_base(x,10); + end d; + + function o (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 7 + -- blanks, underscore + begin + return cnvt_base(x,8); + end o; + + function b (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 1 + -- blanks, underscore + begin + return cnvt_base(x,2); + end b; + + function to_slv(x : natural; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than sizeof(x), result will be truncated on the left + variable int : natural := x; + variable ptr : positive := 32; + variable r : std_logic_vector(1 to 32) := (others=>'0'); + begin + while int > 0 loop + case int rem 2 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when others => + assert false report lf & "TO_SLV, shouldn't happen" + severity failure; + return "0"; + end case; + int := int / 2; + ptr := ptr - 1; + end loop; + return r(33-rtn_len to 32); + end to_slv; + + function to_sl(x : natural) + return std_logic is + variable r : std_logic := '0'; + begin + case x is + when 0 => null; + when 1 => r := '1'; + when others => + assert false + report lf & + "TO_SL found illegal input character: " & + to_int_str(x) & lf & "converting character to '-'" + severity warning; + return '-'; + end case; + return r; + end to_sl; + + function to_time (x: natural) return time is + begin + return x * 1 ns; + end to_time; + +END conversions; diff --git a/lib/models/memory/flash/serial/S25fl064p/utilities/gen_utils.vhd b/lib/models/memory/flash/serial/S25fl064p/utilities/gen_utils.vhd new file mode 100644 index 0000000..65c0e77 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl064p/utilities/gen_utils.vhd @@ -0,0 +1,144 @@ +-------------------------------------------------------------------------------- +-- File name: gen_utils.vhd +-------------------------------------------------------------------------------- +-- Copyright (C) 1996, 1998, 2001 Free Model Foundry; http://eda.org/fmf/ +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License version 2 as +-- published by the Free Software Foundation. +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 R. Steele 96 SEP 26 Initial release +-- V1.1 REV3 97 Feb 27 Added Xon and MsgOn generics +-- V1.2 R. Steele 97 APR 16 Changed wired-or to wired-and +-- V1.3 R. Steele 97 APR 16 Added diff. receiver table +-- V1.4 R. Munden 98 APR 13 Added GenParity and CheckParity +-- V1.5 R. Munden 01 NOV 24 Added UnitDelay01ZX +-- +-------------------------------------------------------------------------------- +LIBRARY IEEE; USE IEEE.std_Logic_1164.ALL; + USE IEEE.VITAL_primitives.ALL; + USE IEEE.VITAL_timing.ALL; + +PACKAGE gen_utils IS + + ---------------------------------------------------------------------------- + -- Result map for Wired-and output values (open collector) + ---------------------------------------------------------------------------- + CONSTANT STD_wired_and_rmap : VitalResultMapType := ('U','X','0','Z'); + + ---------------------------------------------------------------------------- + -- Table for computing a single signal from a differential receiver input + -- pair. + ---------------------------------------------------------------------------- + CONSTANT diff_rec_tab : VitalStateTableType := ( + + ------INPUTS--|-PREV-|-OUTPUT---- + -- A ANeg | Aint | Aint' -- + --------------|------|----------- + ( 'X', '-', '-', 'X'), -- A unknown + ( '-', 'X', '-', 'X'), -- A unknown + ( '1', '-', 'X', '1'), -- Recover from 'X' + ( '0', '-', 'X', '0'), -- Recover from 'X' + ( '/', '0', '0', '1'), -- valid diff. rising edge + ( '1', '\', '0', '1'), -- valid diff. rising edge + ( '\', '1', '1', '0'), -- valid diff. falling edge + ( '0', '/', '1', '0'), -- valid diff. falling edge + ( '-', '-', '-', 'S') -- default + ); -- end of VitalStateTableType definition + + + ---------------------------------------------------------------------------- + -- Default Constants + ---------------------------------------------------------------------------- + CONSTANT UnitDelay : VitalDelayType := 1 ns; + CONSTANT UnitDelay01 : VitalDelayType01 := (1 ns, 1 ns); + CONSTANT UnitDelay01Z : VitalDelayType01Z := (others => 1 ns); + CONSTANT UnitDelay01ZX : VitalDelayType01ZX := (others => 1 ns); + + CONSTANT DefaultInstancePath : STRING := "*"; + CONSTANT DefaultTimingChecks : BOOLEAN := FALSE; + CONSTANT DefaultTimingModel : STRING := "UNIT"; + CONSTANT DefaultXon : BOOLEAN := TRUE; + CONSTANT DefaultMsgOn : BOOLEAN := TRUE; + + -- Older VITAL generic being phased out + CONSTANT DefaultXGeneration : BOOLEAN := TRUE; + + ------------------------------------------------------------------- + -- Generate Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION GenParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic_vector; + + ------------------------------------------------------------------- + -- Check Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION CheckParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic; -- '0' - Parity Error + +END gen_utils; + +PACKAGE BODY gen_utils IS + + function XOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 403 + variable result: STD_LOGIC; + begin + result := '0'; + for i in ARG'range loop + result := result xor ARG(i); + end loop; + return result; + end; + ------------------------------------------------------------------- + -- Generate Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION GenParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic_vector + IS + VARIABLE I: NATURAL; + VARIABLE Result: std_logic_vector (Data'Length - 1 DOWNTO 0); + BEGIN + I := 0; + WHILE (I < SIZE) LOOP + Result(I+7 DOWNTO I) := Data(I+7 downto I); + Result(I+8) := XOR_REDUCE( Data(I+7 downto I) ) XOR ODDEVEN; + I := I + 9; + END LOOP; + RETURN Result; + END GenParity; + + ------------------------------------------------------------------- + -- Check Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION CheckParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic -- '0' - Parity Error + IS + VARIABLE I: NATURAL; + VARIABLE Result: std_logic; + BEGIN + I := 0; Result := '1'; + WHILE (I < SIZE) LOOP + Result := Result AND + NOT (XOR_REDUCE( Data(I+8 downto I) ) XOR ODDEVEN); + I := I + 9; + END LOOP; + RETURN Result; + END CheckParity; + +END gen_utils; diff --git a/lib/models/memory/flash/serial/S25fl128k/Model_Manual_English.pdf b/lib/models/memory/flash/serial/S25fl128k/Model_Manual_English.pdf new file mode 100644 index 0000000..954c3f6 Binary files /dev/null and b/lib/models/memory/flash/serial/S25fl128k/Model_Manual_English.pdf differ diff --git a/lib/models/memory/flash/serial/S25fl128k/Model_Manual_Japanese.pdf b/lib/models/memory/flash/serial/S25fl128k/Model_Manual_Japanese.pdf new file mode 100644 index 0000000..de2f909 Binary files /dev/null and b/lib/models/memory/flash/serial/S25fl128k/Model_Manual_Japanese.pdf differ diff --git a/lib/models/memory/flash/serial/S25fl128k/model/model_release_history.txt b/lib/models/memory/flash/serial/S25fl128k/model/model_release_history.txt new file mode 100644 index 0000000..533c2b4 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128k/model/model_release_history.txt @@ -0,0 +1,21 @@ +########################################## +Date (DD/MM/YYYY) - 08.10.2010 + +Model name - S25FL128K + +Vendor - SPANSION (www.spansion.com) + +Publication ID - Document No. P/N: S25FL128K_00_01, July 22. 2010, + Spansion Inc. + +VITAL model author - Ranko Prokopovic + r-prokopovic@hdl-dh.com +########################################## +########################################## +INITIAL RELEASE + +# Release Label => vital-amd-serial-s25fl-REL-s25fl128k-2010-10-08-1.tar.gz +# Release Date (DD/MM/YYYY) => 08/10/2010 +# Release Version => 1.0 + +########################################## diff --git a/lib/models/memory/flash/serial/S25fl128k/model/s25fl128k.v b/lib/models/memory/flash/serial/S25fl128k/model/s25fl128k.v new file mode 100644 index 0000000..50cdf02 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128k/model/s25fl128k.v @@ -0,0 +1,4276 @@ +/////////////////////////////////////////////////////////////////////////////// +// File name : s25fl128k.v +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2010 Spansion, LLC. +// +// MODIFICATION HISTORY : +// +// version: | author: | mod date: | changes made: +// V1.0 R.Prokopovic 10 Oct 08 Initial +// +/////////////////////////////////////////////////////////////////////////////// +// PART DESCRIPTION: +// +// Library: FLASH +// Technology: FLASH MEMORY +// Part: S25FL128K +// +// Description: 128 Megabit Serial Flash Memory +// +/////////////////////////////////////////////////////////////////////////////// +// Comments : +// +////////////////////////////////////////////////////////////////////////////// +// Known Bugs: +// +////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// MODULE DECLARATION // +////////////////////////////////////////////////////////////////////////////// +`timescale 1 ps/1 ps + +module s25fl128k + ( + // Data Inputs/Outputs + SI , + SO , + // Controls + SCK , + CSNeg , + HOLDNeg, + WPNeg + +); + +/////////////////////////////////////////////////////////////////////////////// +// Port / Part Pin Declarations +/////////////////////////////////////////////////////////////////////////////// + inout SI ; + inout SO ; + input SCK ; + input CSNeg ; + inout HOLDNeg ; + inout WPNeg ; + + // interconnect path delay signals + wire SCK_ipd ; + wire SI_ipd ; + wire SO_ipd ; + + wire SI_in ; + assign SI_in = SI_ipd ; + + wire SI_out ; + assign SI_out = SI ; + + wire SO_in ; + assign SO_in = SO_ipd ; + + wire SO_out ; + assign SO_out = SO ; + + wire CSNeg_ipd ; + wire HOLDNeg_ipd ; + wire WPNeg_ipd ; + + wire HOLDNeg_in ; + //Internal pull-up + assign HOLDNeg_in = (HOLDNeg_ipd === 1'bx) ? 1'b1 : HOLDNeg_ipd; + + wire HOLDNeg_out ; + assign HOLDNeg_out = HOLDNeg ; + + wire WPNeg_in ; + //Internal pull-up + assign WPNeg_in = (WPNeg_ipd === 1'bx) ? 1'b1 : WPNeg_ipd; + + wire WPNeg_out ; + assign WPNeg_out = WPNeg ; + + // ***** internal delays ********************* + reg PP_in ; + reg PP_out ; + reg BP_in ; + reg BP_out ; + reg SE_in ; + reg SE_out ; + reg BE_in ; + reg BE_out ; + reg PRGSUSP_in ; + reg PRGSUSP_out ; + reg ERSSUSP_in ; + reg ERSSUSP_out ; + reg PRGRES_out ; + reg ERSRES_out ; + reg PRGRES_in ; + reg ERSRES_in ; + reg WRR_in ; + reg WRR_out ; + reg DP_in ; + reg DP_out ; + reg RES_in ; + reg RES_out ; + // ******* event control registers ************ + reg PRGSUSP_out_event; + reg PRGRES_out_event; + reg ERSSUSP_out_event; + reg ERSRES_out_event; + reg PGSUSP_event; + reg PGRES_event; + reg ESUSP_event; + reg ERES_event; + reg next_state_event; + + reg rising_edge_PoweredUp; + reg rising_edge_RES_out; + reg rising_edge_PRGRES_out; + reg rising_edge_PSTART; + reg rising_edge_WSTART; + reg rising_edge_VLTSTART; + reg rising_edge_ESTART; + reg rising_edge_prot_bits; + reg rising_edge_CSNeg_ipd = 1'b0; + reg falling_edge_CSNeg_ipd = 1'b0; + reg rising_edge_SCK_ipd = 1'b0; + reg falling_edge_SCK_ipd = 1'b0; + + reg SOut_zd = 1'bZ ; + reg SOut_z = 1'bZ ; + + reg DataDriveOut_SO = 1'bZ ; + reg DataDriveOut_SI = 1'bZ ; + reg DataDriveOut_HOLD = 1'bZ ; + reg DataDriveOut_WP = 1'bZ ; + + wire SI_z ; + wire SO_z ; + + reg SIOut_zd = 1'bZ ; + reg SIOut_z = 1'bZ ; + + reg WPNegOut_zd = 1'bZ ; + reg HOLDNegOut_zd = 1'bZ ; + + assign SI_z = SIOut_z; + assign SO_z = SOut_z; + + parameter UserPreload = 1; + parameter mem_file_name = "none";//"s25fl128k.mem"; + parameter screg_file_name = "s25fl128kscreg.mem";//"none"; + parameter TimingModel = "DefaultTimingModel"; + + parameter PartID = "s25fl128k"; + parameter MaxData = 255; + parameter AddrRANGE = 24'hFFFFFF; + parameter PageNum = 16'hFFFF; + parameter SecSize_4 = 12'hFFF; + parameter SecSize_32 = 16'h7FFF; + parameter SecSize_64 = 16'hFFFF; + parameter Blk_4_Num = 4095; + parameter Blk_64_Num = 255; + parameter Blk_32_Num = 511; + parameter SFDP_HiAddr = 8'hFF; + parameter SFDP_LoAddr = 8'h00; + parameter SecReg_HiAddr = 8'hFF; + parameter SecReg_LoAddr = 8'h00; + parameter SCREG_LoAddr = 12'h000; + parameter SCREG_HiAddr = 12'h2FF; + parameter BYTE = 8; + + // Manufacturer Identification and Device Identification + parameter Manuf_ID = 8'hEF; + parameter Device_ID1 = 8'h17; + parameter Device_ID2 = 8'h40; + parameter Device_ID3 = 8'h18; + parameter unique_id = 64'h000000000000ABAB; + + // If speedsimulation is needed uncomment following line + +// `define SPEEDSIM; + + // powerup + reg PoweredUp; + + // FSM control signals + reg PDONE ; + reg PSTART ; + reg PGSUSP ; + reg PGRES ; +// reg ERSRES ; + + reg WDONE ; + reg WSTART ; + reg VLTSTART ; + reg VLTDONE ; + + reg EDONE ; + reg ESTART ; + reg ESUSP ; + reg ERES ; + + // Programming buffer + integer WByte[0:255]; + + // Flash Memory Array + integer Mem[0:AddrRANGE]; + + // Registers + // Status Register 1 + reg[7:0] Status_reg1 = 8'h00; + reg[7:0] Status_reg1_in = 8'h00; + + wire SRP0; + wire SEC; + wire TB; + wire BP2; + wire BP1; + wire BP0; + wire WEL; + wire BUSY; + assign SRP0 = Status_reg1[7]; + assign SEC = Status_reg1[6]; + assign TB = Status_reg1[5]; + assign BP2 = Status_reg1[4]; + assign BP1 = Status_reg1[3]; + assign BP0 = Status_reg1[2]; + assign WEL = Status_reg1[1]; + assign BUSY = Status_reg1[0]; + + // Status Register 2 + reg[7:0] Status_reg2 = 8'h00; + reg[7:0] Status_reg2_in = 8'h00; + + wire SUS; + wire CMP; + + wire [2:0]LB; + wire QE; + wire SRP1; + assign SUS = Status_reg2[7]; + assign CMP = Status_reg2[6]; + assign LB = Status_reg2[5:3]; + assign QE = Status_reg2[1]; + assign SRP1 = Status_reg2[0]; + + reg[15:0] Status_reg; // Status_reg2 & Status_reg1 + reg[15:0] Status_reg_in; // Status_reg2 & Status_reg1 + + // Sector is protect if Sec_Prot(SecNum) = '1' + reg [Blk_4_Num:0] Sec_Prot = {4095{1'b0}}; + + // Security registers array + integer Security_Reg[SCREG_LoAddr:SCREG_HiAddr]; + integer Security_Reg1[SecReg_LoAddr:SecReg_HiAddr]; + integer Security_Reg2[SecReg_LoAddr:SecReg_HiAddr]; + integer Security_Reg3[SecReg_LoAddr:SecReg_HiAddr]; + + // SFDP register array + integer SFDP_array[SFDP_LoAddr:SFDP_HiAddr]; + + /////////////////////////////////////////////////////////////////////////// + // Command Register + reg write; + reg read_out; + reg slow_read; + reg dual_read; + reg fast_read; + reg quad_read; + reg pp_quad; + reg oe = 1'b0; + event oe_event; + + reg[7:0] old_bit, new_bit; + integer old_int, new_int; + integer wr_cnt; + integer cnt; + integer Byte_number = 0; + integer read_cnt = 0; + integer read_addr = 0; + reg[7:0] data_out; + reg[23:0] ident_out; + reg[15:0] ident_out2; + integer AddrLo; + integer AddrHi; + integer AddrLo_ers; + integer AddrHi_ers; + integer AddrLo_wrap; + integer AddrHi_wrap; + + reg change_prot_bits = 0; + + //Address + integer Address = 0; // 0 - AddrRANGE + reg change_addr; + + //Sector and subsector addresses + integer SA = 0; + integer sect; + integer sect_tmp_pg; + integer sect_tmp_ers; + integer sfdp_addr; + integer w_size; + + reg hold_mode = 1'b0; + + time SCK_cycle = 0; + time prev_SCK; + + // Flag for release from deep power down, read ID or not + reg res_flag; + reg pg_screg_flag = 1'b0; + reg ers_screg_flag = 1'b0; + reg wren_vlt_flag = 1'b0; + reg susp_flag = 1'b0; + // timing check violation + reg Viol = 1'b0; + reg sr_read = 1'b0; + reg read_id = 1'b0; + + reg glitch = 1'b0; + time SCK_SO_2; + time start_rdid; + time out_time; +/////////////////////////////////////////////////////////////////////////////// +//Interconnect Path Delay Section +/////////////////////////////////////////////////////////////////////////////// + buf (SCK_ipd, SCK); + buf (SI_ipd, SI); + + buf (SO_ipd, SO); + buf (CSNeg_ipd, CSNeg); + buf (HOLDNeg_ipd, HOLDNeg); + buf (WPNeg_ipd, WPNeg); + +/////////////////////////////////////////////////////////////////////////////// +// Propagation delay Section +/////////////////////////////////////////////////////////////////////////////// + nmos (SI, SI_z , 1); + + nmos (SO, SO_z , 1); + nmos (HOLDNeg, HOLDNegOut_zd , 1); + nmos (WPNeg, WPNegOut_zd , 1); + + wire deg_pin; + wire deg_sin; + wire deg_holdin; + + reg deq_holdin; + always @(HOLDNeg_ipd, HOLDNegOut_zd) + begin + if (HOLDNeg_ipd==HOLDNegOut_zd) + deq_holdin=1'b0; + else + deq_holdin=1'b1; + end + //VHDL VITAL CheckEnable equivalents + wire rd_slow; + assign rd_slow = slow_read; + wire rd_fast; + assign rd_fast = fast_read && ~quad_read; + wire quad_spi; + assign quad_spi = pp_quad || quad_read; + wire quad_rd; + assign quad_rd = deg_holdin && QE && ~dual_read && (SIOut_z != 1'bz); + wire quad_pg; + assign quad_pg = QE && WEL && pp_quad; + wire wr_prot; + assign wr_prot = SRP0 && WEL; + wire dual_rd; + assign dual_rd = dual_read ; + wire power; + assign power = PoweredUp; + wire hold_cond; + assign hold_cond = PoweredUp && ~QE && HOLDNeg_in != 1'bX; + wire any_read; + assign any_read = (dual_read || quad_read || slow_read || fast_read) + && ~WEL && ~sr_read; + // check when data is generated from model to avoid setuphold check in + // this occasion + assign deg_holdin=deq_holdin; + + reg deq_sin; + always @(SI_in, SIOut_z) + begin + if (SI_in !== 1'bZ) + deq_sin=1'b0; + else + deq_sin=1'b1; + end + assign deg_sin = deq_sin && ~read_out; /*&& (~any_read);*/ + + wire pg_ers; + assign pg_ers = PSTART || ESTART || sr_read; + +specify + // tipd delays: interconnect path delays , mapped to input port delays. + // In Verilog is not necessary to declare any tipd_ delay variables, + // they can be taken from SDF file + // With all the other delays real delays would be taken from SDF file + + // tpd delays + specparam tpd_SCK_SO_1 =1; // tCLQV1 + specparam tpd_SCK_SO_2 =1; // tCLQV2 -for read ID instructions + specparam tpd_CSNeg_SO =1; // tSHQZ (tDIS) + specparam tpd_HOLDNeg_SO =1; // tHLQZ, tHHQX + + //tsetup values: setup times + specparam tsetup_CSNeg_SCK =1; // tSLCH, tSHCH + specparam tsetup_SI_SCK =1; // tDVCH + specparam tsetup_HOLDNeg_SCK =1; // tHLCH, tHHCH + specparam tsetup_WPNeg_CSNeg =1; // tWHSL + + //thold values: hold times + specparam thold_CSNeg_SCK =1; // tCHSL, tCHSH + specparam thold_SI_SCK =1; // tCHDX + specparam thold_HOLDNeg_SCK =1; // tCHHL, tCHHH + specparam thold_WPNeg_CSNeg =1; // tSHWL + + // tpw values: pulse width + specparam tpw_SCK_slow_posedge =1; // tCH + specparam tpw_SCK_slow_negedge =1; // tCL + specparam tpw_SCK_fast_posedge =1; // tCH + specparam tpw_SCK_fast_negedge =1; // tCL + specparam tpw_SCK_quad_posedge =1; // tCH + specparam tpw_SCK_quad_negedge =1; // tCL + specparam tpw_CSNeg_read_posedge =1; // tSHSL1 + specparam tpw_CSNeg_pger_posedge =1; // tSHSL2 + + // tperiod min (calculated as 1/max freq) + specparam tperiod_SCK_slow =1; + specparam tperiod_SCK_fast =1; + specparam tperiod_SCK_quad =1; + + // tdevice values: values for internal delays + + // VCC (min) to CS# Low + specparam tdevice_PU = 1e7; // 10 us + // CS# High to Power Down Mode -- tDP + specparam tdevice_DP = 3e6; // 3 us + // CS# High to StandBy mode without Electronic Signature read + specparam tdevice_RES1 = 3e6; // 3 us + // CS# High to StandBy mode with Electronic Signature read + specparam tdevice_RES2 = 18e5; // 1.8 us + // CS# High to next Instruction after Suspend + specparam tdevice_SUS = 2e7; // 20 us + // Resume Suspend to Program/Erase time + specparam tdevice_PRGSUSP = 2e5; // 200 ns + + `ifdef SPEEDSIM + // Page Program Time + specparam tdevice_PP = 3e8; // 30 us + // Byte Program Time (First Byte) + specparam tdevice_BP1 = 5e5; // 0.5 us + // Additional Byte Program Time (After First Byte) + specparam tdevice_BP2 = 12e4; // 120 ns + // Sector Erase Time (4KB) + specparam tdevice_SE = 4e9; // 4 ms + // Block Erase Time (32KB) + specparam tdevice_BE1 = 8e9; // 8 ms + // Block Erase Time (64KB) + specparam tdevice_BE2 = 1e10; // 10 ms + // Chip Erase Time + specparam tdevice_CE = 40e10; // 400 ms + // Write Status Register Time + specparam tdevice_WRR = 15e7; // 150 us + // Write Volatile Status Register Time + specparam tdevice_VRR = 5e4; // 50 ns + `else + // Page Program Time + specparam tdevice_PP = 3e9; // 3 ms + // Byte Program Time (First Byte) + specparam tdevice_BP1 = 5e7; // 50 us + // Additional Byte Program Time (After First Byte) + specparam tdevice_BP2 = 12e6; // 12 us + // Sector Erase Time (4KB) + specparam tdevice_SE = 4e11; // 400 ms + // Block Erase Time (32KB) + specparam tdevice_BE1 = 8e11; // 800 ms + // Block Erase Time (64KB) + specparam tdevice_BE2 = 1e12; // 1000 ms + // Chip Erase Time + specparam tdevice_CE = 40e12; // 40 s + // Write Status Register Time + specparam tdevice_WRR = 15e9; // 15 ms + // Write Volatile Status Register Time + specparam tdevice_VRR = 5e4; // 50 ns + `endif // SPEEDSIM + +/////////////////////////////////////////////////////////////////////////////// +// Input Port Delays don't require Verilog description +/////////////////////////////////////////////////////////////////////////////// +// Path delays // +/////////////////////////////////////////////////////////////////////////////// + if (~read_id) (SCK => SO) = tpd_SCK_SO_1; + if ((~glitch || quad_read) && read_id) (SCK => SO) = tpd_SCK_SO_2; + if (CSNeg) (CSNeg => SO) = tpd_CSNeg_SO; + if (~quad_read) (HOLDNeg => SO) = tpd_HOLDNeg_SO; + if ((dual_read || quad_read) && ~read_id) (SCK => SI) = tpd_SCK_SO_1; + if (dual_read && read_id && ~glitch) (SCK => SI) = tpd_SCK_SO_2; + if (quad_read && read_id) (SCK => SI) = tpd_SCK_SO_2; + if (CSNeg && ~deg_sin) (CSNeg => SI) = tpd_CSNeg_SO; + if (~quad_read && dual_read) (HOLDNeg => SI) = tpd_HOLDNeg_SO; + + if (quad_read && ~read_id) (SCK => WPNeg) = tpd_SCK_SO_1; + if (quad_read && read_id) (SCK => WPNeg) = tpd_SCK_SO_2; + if (quad_read && ~read_id) (SCK => HOLDNeg) = tpd_SCK_SO_1; + if (quad_read && read_id) (SCK => HOLDNeg) = tpd_SCK_SO_2; + if (CSNeg && QE) (CSNeg => SI) = tpd_CSNeg_SO; + if (CSNeg && QE) (CSNeg => WPNeg) = tpd_CSNeg_SO; + if (CSNeg && QE) (CSNeg => HOLDNeg) = tpd_CSNeg_SO; +/////////////////////////////////////////////////////////////////////////////// +// Timing Violation // +/////////////////////////////////////////////////////////////////////////////// + $setup ( CSNeg , posedge SCK &&& power, + tsetup_CSNeg_SCK , Viol); + $setup ( SI , posedge SCK &&& deg_sin, + tsetup_SI_SCK , Viol); + $setup ( SO , posedge SCK &&& quad_pg, + tsetup_SI_SCK , Viol); + $setup ( WPNeg , posedge SCK &&& quad_pg, + tsetup_SI_SCK , Viol); + $setup ( HOLDNeg , posedge SCK &&& quad_pg, + tsetup_SI_SCK , Viol); + $setup ( HOLDNeg , posedge SCK &&& hold_cond, + tsetup_HOLDNeg_SCK , Viol); + $setup ( WPNeg , negedge CSNeg &&& WPNeg, + tsetup_WPNeg_CSNeg , Viol); + + $hold ( posedge SCK &&& power, CSNeg, + thold_CSNeg_SCK , Viol); + $hold ( posedge SCK &&& deg_sin, SI , + thold_SI_SCK , Viol); + $hold ( posedge SCK &&& quad_pg, SO , + thold_SI_SCK , Viol); + $hold ( posedge SCK &&& quad_pg, WPNeg, + thold_SI_SCK , Viol); + $hold ( posedge SCK &&& quad_pg, HOLDNeg, + thold_SI_SCK , Viol); + $hold ( posedge SCK &&& hold_cond, HOLDNeg, + thold_HOLDNeg_SCK, Viol); + $hold ( posedge CSNeg &&& wr_prot, WPNeg, + thold_WPNeg_CSNeg, Viol); + + $width ( posedge SCK &&& rd_slow , tpw_SCK_slow_posedge); + $width ( negedge SCK &&& rd_slow , tpw_SCK_slow_negedge); + $width ( posedge SCK &&& rd_fast , tpw_SCK_fast_posedge); + $width ( negedge SCK &&& rd_fast , tpw_SCK_fast_negedge); + $width ( posedge SCK &&& quad_spi , tpw_SCK_quad_posedge); + $width ( negedge SCK &&& quad_spi , tpw_SCK_quad_negedge); + $width ( posedge CSNeg &&& any_read , tpw_CSNeg_read_posedge); + $width ( posedge CSNeg &&& pg_ers , tpw_CSNeg_pger_posedge); + + $period ( posedge SCK &&& rd_slow , tperiod_SCK_slow); + $period ( posedge SCK &&& rd_fast , tperiod_SCK_fast); + $period ( posedge SCK &&& quad_spi , tperiod_SCK_quad); + +endspecify + +/////////////////////////////////////////////////////////////////////////////// +// Main Behavior Block // +/////////////////////////////////////////////////////////////////////////////// +// FSM states + parameter IDLE = 4'd0; + parameter WRITE_SR = 4'd1; + parameter PAGE_PG = 4'd2; + parameter PG_SUSP = 4'd3; + parameter SECTOR_ERS = 4'd4; + parameter BULK_ERS = 4'd5; + parameter ERS_SUSP = 4'd6; + parameter ERS_SUSP_PG = 4'd7; + parameter PG_SUSP_ERS = 4'd8; + parameter DP_DOWN = 4'd9; + parameter WRITE_SR_V = 4'd10; + + reg [3:0] current_state; + reg [3:0] next_state; + +// Instruction type + parameter NONE = 6'd0; + parameter WREN = 6'd1; // 06h + parameter WRENV = 6'd2; // 50h + parameter WRDI = 6'd3; // 04h + parameter RDSR = 6'd4; // 05h + parameter RDSR2 = 6'd5; // 35h + parameter WRR = 6'd6; // 01h + parameter READ = 6'd7; // 03h + parameter FAST_READ = 6'd8; // 0Bh + parameter FAST_DREAD = 6'd9; // 3Bh + parameter FAST_QREAD = 6'd10; // 6Bh + parameter FAST_DREAD_2 = 6'd11; // BBh + parameter FAST_QREAD_4 = 6'd12; // EBh + parameter W_QREAD = 6'd13; // E7h + parameter WOCT_QREAD = 6'd14; // E3h + parameter SET_BURST_WRAP = 6'd15; // 77h + parameter CONT_RD_RST = 6'd16; // FFh or FFFFH + parameter PP = 6'd17; // 02h + parameter QPP = 6'd18; // 32h + parameter SE = 6'd19; // 20h + parameter BE_32 = 6'd20; // 52h + parameter BE_64 = 6'd21; // D8h + parameter CE = 6'd22; // C7h or 60h + parameter ERS_PG_SUSP = 6'd23; // 75h + parameter ERS_PG_RES = 6'd24; // 7Ah + parameter DP = 6'd25; // B9h + parameter RES_RD_ID = 6'd26; // ABh + parameter RDID = 6'd27; // 90h + parameter RDID_DUAL = 6'd28; // 92h + parameter RDID_QUAD = 6'd29; // 94h + parameter RD_UNIQ_ID = 6'd30; // 4Bh + parameter RDIDJ = 6'd31; // 9Fh + parameter RD_SFDP = 6'd32; // 5Ah + parameter ERS_SCREG = 6'd33; // 44h + parameter PG_SCREG = 6'd34; // 42h + parameter RD_SCREG = 6'd35; // 48h + + reg [5:0] Instruct; + +//Bus cycle state + parameter STAND_BY = 3'd0; + parameter OPCODE_BYTE = 3'd1; + parameter ADDRESS_BYTES = 3'd2; + parameter DUMMY_BYTES = 3'd3; + parameter MODE_BYTE = 3'd4; + parameter DATA_BYTES = 3'd5; + + reg [2:0] bus_cycle_state; + + + //Power Up time; + initial + begin + PoweredUp = 1'b0; + #tdevice_PU PoweredUp = 1'b1; + end + + always @(PoweredUp or falling_edge_CSNeg_ipd) + begin:CheckCEOnPowerUP + if ((~PoweredUp) && falling_edge_CSNeg_ipd) + $display ("Device is selected during Power Up"); + end + + initial + begin : Init + write = 1'b0; + read_out = 1'b0; + Address = 0; + change_addr = 1'b0; +// cnt = 0; + PGSUSP = 1'b0; + PGRES = 1'b0; + ESUSP = 1'b0; + ERES = 1'b0; + PDONE = 1'b1; + PSTART = 1'b0; + EDONE = 1'b1; + ESTART = 1'b0; + WDONE = 1'b1; + WSTART = 1'b0; + VLTDONE = 1'b1; + VLTSTART = 1'b0; + + DP_in = 1'b0; + DP_out = 1'b0; + RES_in = 1'b0; + RES_out = 1'b0; + PRGRES_in = 1'b0; + ERSRES_in = 1'b0; + Instruct = NONE; + bus_cycle_state = STAND_BY; + current_state = IDLE; + next_state = IDLE; + + end + + // initialize memory and load preload files if any + initial + begin: InitMemory + integer i; + + for (i=0;i<=AddrRANGE;i=i+1) + begin + Mem[i] = MaxData; + end + + if ((UserPreload) && !(mem_file_name == "none")) + begin + // Memory Preload + //s25fl128k.mem, memory preload file + // @aaaaaa - stands for address + // dd -
is byte to be written at Mem(aaaaaa++) + // (aaaaaa is incremented at every load) + $readmemh(mem_file_name,Mem); + end + + for (i=SCREG_LoAddr;i<=SCREG_HiAddr;i=i+1) + begin + Security_Reg[i] = MaxData; + end + + if (UserPreload && !(screg_file_name == "none")) + begin + //s25fl128kSCREG memory file + // / - comment + // @aaa - stands for address of specific Security register + // dd -
is byte to be written at SCREG(aaa++) + // (aa is incremented at every load) + // only first 1-4 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + $readmemh(screg_file_name,Security_Reg); + end + for (i=0;i<=255;i=i+1) + begin + Security_Reg1[i] = Security_Reg[i]; + Security_Reg2[i] = Security_Reg[256+i]; + Security_Reg3[i] = Security_Reg[512+i]; + end + end + + /////////////////////////////////////////////////////////////////////////// + // SFDP - Serial Flash Discoverable Parameter register + initial + begin: InitSFDP + integer i; + integer j; + SFDP_array[8'h00] = 8'h53; + SFDP_array[8'h01] = 8'h46; + SFDP_array[8'h02] = 8'h44; + SFDP_array[8'h03] = 8'h50; + SFDP_array[8'h04] = 8'h01; + SFDP_array[8'h05] = 8'h01; + SFDP_array[8'h06] = 8'h00; + SFDP_array[8'h07] = 8'hFF; + SFDP_array[8'h08] = 8'hEF; + SFDP_array[8'h09] = 8'h00; + SFDP_array[8'h0A] = 8'h01; + SFDP_array[8'h0B] = 8'h04; + SFDP_array[8'h0C] = 8'h80; + SFDP_array[8'h0D] = 8'h00; + SFDP_array[8'h0E] = 8'h00; + SFDP_array[8'h0F] = 8'hFF; + SFDP_array[8'h10] = 8'hEF; + SFDP_array[8'h11] = 8'h00; + SFDP_array[8'h12] = 8'h01; + SFDP_array[8'h13] = 8'h00; + SFDP_array[8'h14] = 8'h90; + SFDP_array[8'h15] = 8'h00; + SFDP_array[8'h16] = 8'h00; + SFDP_array[8'h17] = 8'hFF; + + for (i=24;i<=127;i=i+1) + begin + SFDP_array[i] = MaxData; + end + + SFDP_array[8'h80] = 8'hE5; + SFDP_array[8'h81] = 8'h20; + SFDP_array[8'h82] = 8'hF1; + SFDP_array[8'h83] = 8'hFF; + SFDP_array[8'h84] = 8'hFF; + SFDP_array[8'h85] = 8'hFF; + SFDP_array[8'h86] = 8'hFF; + SFDP_array[8'h87] = 8'h07; + SFDP_array[8'h88] = 8'h44; + SFDP_array[8'h89] = 8'hEB; + SFDP_array[8'h8A] = 8'h08; + SFDP_array[8'h8B] = 8'h6B; + SFDP_array[8'h8C] = 8'h08; + SFDP_array[8'h8D] = 8'h3B; + SFDP_array[8'h8E] = 8'h80; + SFDP_array[8'h8F] = 8'hBB; + + for (i=144;i<=255;i=i+1) + begin + SFDP_array[i] = MaxData; + end + + end + /////////////////////////////////////////////////////////////////////////// + //// Internal Delays + /////////////////////////////////////////////////////////////////////////// + always @(posedge DP_in) + begin:TDPr + #tdevice_DP DP_out = DP_in; + end + always @(negedge DP_in) + begin:TDPf + #1 DP_out = DP_in; + end + + always @(posedge RES_in) + begin:TRESr + if (res_flag) // res_flag is '1' when read ID after resume DP + // res_flag will be set to '1' in DUMMY_BYTES if read ID + #tdevice_RES2 RES_out = RES_in; + else + #tdevice_RES1 RES_out = RES_in; + end + always @(negedge RES_in) + begin:TRESf + #1 RES_out = RES_in; + end + + always @(posedge PRGSUSP_in) + begin:PRGSuspend + PRGSUSP_out = 1'b0; + #tdevice_SUS PRGSUSP_out = 1'b1; + end + + always @(posedge PRGRES_in) + begin:ProgSuspend + PRGRES_out = 1'b0; + #tdevice_PRGSUSP PRGRES_out = 1'b1; + end + + always @(posedge ERSSUSP_in) + begin:ERSSuspend + ERSSUSP_out = 1'b0; + #tdevice_SUS ERSSUSP_out = 1'b1; + end + + always @(posedge ERSRES_in) + begin:ERSresume + ERSRES_out = 1'b0; + #tdevice_PRGSUSP ERSRES_out = 1'b1; + end + + always @(posedge ERSRES_in or posedge PRGRES_in) + begin + susp_flag = 1'b1; + #tdevice_SUS susp_flag = 1'b0; + end + + always @(next_state or PoweredUp) + begin: StateTransition + if (PoweredUp) + begin + current_state = next_state; + end + end + +/////////////////////////////////////////////////////////////////////////////// +// write cycle decode +/////////////////////////////////////////////////////////////////////////////// + integer opcode_cnt = 0; + integer addr_cnt = 0; + integer mode_cnt = 0; + integer wrap_cnt = 0; + integer dummy_cnt = 0; + integer data_cnt = 0; + integer bit_cnt = 0; + + reg [4095:0] Data_in = 4096'b0; + reg [7:0] opcode; + reg [15:0] opcode_double; + reg [7:0] opcode_in; + reg [15:0] opcode_double_in; + reg [23:0] addr_bytes; + reg [23:0] Address_in; + reg [7:0] mode_byte; + reg [7:0] mode_in; + reg [7:0] wrap_in; + reg [7:0] wrap_byte; + + integer quad_data_in [0:511]; + reg [3:0] quad_nybble = 4'b0; + reg [3:0] Quad_slv; + reg [7:0] Byte_slv; + + always @(rising_edge_CSNeg_ipd or falling_edge_CSNeg_ipd or + rising_edge_SCK_ipd or falling_edge_SCK_ipd) + begin: Buscycle + integer i; + integer j; + integer k; + if (falling_edge_CSNeg_ipd) + begin + if (bus_cycle_state==STAND_BY) + begin + bus_cycle_state = OPCODE_BYTE; + Instruct = NONE; + write = 1'b1; + opcode_cnt = 0; + addr_cnt = 0; + data_cnt = 0; + mode_cnt = 0; + wrap_cnt = 0; + dummy_cnt = 0; + end + else if (bus_cycle_state==DATA_BYTES && (mode_byte[5:4]==2'b10)) + begin + bus_cycle_state = ADDRESS_BYTES; + dummy_cnt = 0; + opcode_cnt = 0; + end + end + if (rising_edge_SCK_ipd && PoweredUp) + begin + if (~CSNeg_ipd) + begin + case (bus_cycle_state) + OPCODE_BYTE : + begin + if ((HOLDNeg_in && ~QE) || QE) + begin + opcode_in[opcode_cnt] = SI_in; + opcode_cnt = opcode_cnt + 1; + if (opcode_cnt == BYTE) + begin + for (i=0;i<=7;i=i+1) + begin + opcode[i] = opcode_in[7-i]; + end + case(opcode) + 8'b00000110 : // 06h + begin + Instruct = WREN; + bus_cycle_state = DATA_BYTES; + end + 8'b01010000 : // 50h + begin + Instruct = WRENV; + bus_cycle_state = DATA_BYTES; + end + 8'b00000100 : // 04h + begin + Instruct = WRDI; + bus_cycle_state = DATA_BYTES; + end + 8'b00000101 : // 05h + begin + Instruct = RDSR; + bus_cycle_state = DATA_BYTES; + end + 8'b00110101 : // 05h + begin + Instruct = RDSR2; + bus_cycle_state = DATA_BYTES; + end + 8'b00000001 : // 01h + begin + Instruct = WRR; + bus_cycle_state = DATA_BYTES; + end + 8'b00000011 : // 03h + begin + Instruct = READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00001011 : // 0Bh + begin + Instruct = FAST_READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00111011 : // 3Bh + begin + Instruct = FAST_DREAD; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01101011 : // 6Bh + begin + Instruct = FAST_QREAD; + if (QE) + bus_cycle_state = ADDRESS_BYTES; + else + bus_cycle_state = STAND_BY; + end + 8'b10111011 : // BBh + begin + Instruct = FAST_DREAD_2; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11101011 : // EBh + begin + Instruct = FAST_QREAD_4; + if (QE) + bus_cycle_state = ADDRESS_BYTES; + else + bus_cycle_state = STAND_BY; + end + 8'b11100111 : // E7h + begin + Instruct = W_QREAD; + if (QE) + bus_cycle_state = ADDRESS_BYTES; + else + bus_cycle_state = STAND_BY; + end + 8'b11100011 : // E3h + begin + Instruct = WOCT_QREAD; + if (QE) + bus_cycle_state = ADDRESS_BYTES; + else + bus_cycle_state = STAND_BY; + end + 8'b01110111 : // 77h + begin + Instruct = SET_BURST_WRAP; + if (QE) + bus_cycle_state = DUMMY_BYTES; + else + bus_cycle_state = STAND_BY; + end + 8'b11111111 : // FFh + begin + Instruct = CONT_RD_RST; + bus_cycle_state = MODE_BYTE; + end + 8'b00000010 : // 02h + begin + Instruct = PP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00110010 : // 32h + begin + Instruct = QPP; + if (QE) + bus_cycle_state = ADDRESS_BYTES; + else + bus_cycle_state = STAND_BY; + end + 8'b00100000 : // 20h + begin + Instruct = SE; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01010010 : // 52h + begin + Instruct = BE_32; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11011000 : // D8h + begin + Instruct = BE_64; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11000111, 8'b01100000 : // C7h or 60h + begin + Instruct = CE; + bus_cycle_state = DATA_BYTES; + end + 8'b01110101 : // 75h + begin + Instruct = ERS_PG_SUSP; + bus_cycle_state = DATA_BYTES; + end + 8'b01111010 : // 7Ah + begin + Instruct = ERS_PG_RES; + bus_cycle_state = DATA_BYTES; + end + 8'b10111001 : // B9h + begin + Instruct = DP; + bus_cycle_state = DATA_BYTES; + end + 8'b10101011: // ABh + begin + Instruct = RES_RD_ID; + bus_cycle_state = DUMMY_BYTES; + end + 8'b10010000: // 90h + begin + Instruct = RDID; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10010010: // 92h + begin + Instruct = RDID_DUAL; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10010100: // 94h + begin + Instruct = RDID_QUAD; + if (QE) + bus_cycle_state = ADDRESS_BYTES; + else + bus_cycle_state = STAND_BY; + end + 8'b01001011: // 4Bh + begin + Instruct = RD_UNIQ_ID; + bus_cycle_state = DUMMY_BYTES; + end + 8'b10011111: // 9Fh + begin + Instruct = RDIDJ; + bus_cycle_state = DATA_BYTES; + end + 8'b01011010: // 5Ah + begin + Instruct = RD_SFDP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01000100: // 44h + begin + Instruct = ERS_SCREG; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01000010: // 42h + begin + Instruct = PG_SCREG; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01001000: // 48h + begin + Instruct = RD_SCREG; + bus_cycle_state = ADDRESS_BYTES; + end + endcase + end + end + else + $display("Device is in HOLD mode, opcode"); + end // end of OPCODE_BYTE + + ADDRESS_BYTES : + begin + if ((HOLDNeg_in && ~QE) || QE) + begin + if (Instruct == READ || Instruct == FAST_READ || + Instruct == FAST_DREAD || Instruct == RDID || + Instruct == SE || Instruct == PP || + Instruct == RD_SCREG || Instruct == PG_SCREG || + Instruct == RD_SFDP || Instruct == BE_32 || + Instruct == BE_64 || Instruct == ERS_SCREG || + ((Instruct == QPP || Instruct == FAST_QREAD) + && QE)) + begin + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE) + begin + for (i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + Address = addr_bytes ; + change_addr = 1'b1; + #1000 change_addr = 1'b0; + if (Instruct == PP || Instruct == QPP + || Instruct == READ || Instruct == SE + || Instruct == BE_32 || Instruct == BE_64 + || Instruct == RDID || Instruct == PG_SCREG + || Instruct == ERS_SCREG) + bus_cycle_state = DATA_BYTES; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if (Instruct == RDID_DUAL || + Instruct == FAST_DREAD_2) + begin + if (SO_in !== 1'bX) + begin + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt + 1] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE/2) + begin + addr_cnt = 0; + for (i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + Address = addr_bytes ; + change_addr = 1'b1; + #1000 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + else + begin + if (mode_byte[5:4] == 2'b10) + begin + opcode_double_in[opcode_cnt] = SI_in; + opcode_cnt = opcode_cnt + 1; + + if (opcode_cnt == 2*BYTE) + begin + for (i=0;i<=15;i=i+1) + begin + opcode_double[i] = + opcode_double_in[15-i]; + end + if (opcode_double == 16'hFFFF) + begin + Instruct = CONT_RD_RST; + bus_cycle_state = MODE_BYTE; + end + end + end + end + end + else if (QE && (Instruct == FAST_QREAD_4 || + Instruct == W_QREAD || + Instruct == WOCT_QREAD || + Instruct == RDID_QUAD)) + begin + if (SO_in !== 1'bX) + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE/4) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + Address = addr_bytes ; + change_addr = 1'b1; + #1000 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + else + begin + if (mode_byte[5:4] == 2'b10) + begin + opcode_in[opcode_cnt] = SI_in; + opcode_cnt = opcode_cnt + 1; + if (opcode_cnt == BYTE) + begin + for (i=0;i<=7;i=i+1) + begin + opcode[i] = opcode_in[7-i]; + end + if (opcode == 8'hFF) + begin + Instruct = CONT_RD_RST; + bus_cycle_state = MODE_BYTE; + end + end + end + end + end + end + else + $display("Device is in HOLD mode, addr"); + end // end of ADDRESS_BYTES + + MODE_BYTE: + begin + if (QE || (HOLDNeg_in && ~QE)) + begin + if (Instruct == SET_BURST_WRAP && QE) + begin + wrap_in[4*wrap_cnt] = HOLDNeg_in; + wrap_in[4*wrap_cnt+1] = WPNeg_in; + wrap_in[4*wrap_cnt+2] = SO_in; + wrap_in[4*wrap_cnt+3] = SI_in; + wrap_cnt = wrap_cnt + 1; + if (wrap_cnt == BYTE/4) + begin + wrap_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + wrap_byte[i] = wrap_in[7-i]; + end + bus_cycle_state = DATA_BYTES; + end + case (wrap_byte[6:5]) + 2'b00: + w_size = 8; + 2'b01: + w_size = 16; + 2'b10: + w_size = 32; + 2'b11: + w_size = 64; + endcase + end + else if ((Instruct == FAST_QREAD_4 || + Instruct == WOCT_QREAD || + Instruct == W_QREAD || + Instruct == RDID_QUAD ) && QE) + // FAST_QREAD_4,WOCT_QREAD,W_QREAD,RDID_QUAD + begin + mode_in[4*mode_cnt] = HOLDNeg_in; + mode_in[4*mode_cnt+1] = WPNeg_in; + mode_in[4*mode_cnt+2] = SO_in; + mode_in[4*mode_cnt+3] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/4) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_byte[i] = mode_in[7-i]; + end + if (Instruct == WOCT_QREAD) + bus_cycle_state = DATA_BYTES; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if (Instruct == RDID_DUAL || + Instruct == FAST_DREAD_2) + begin + mode_in[2*mode_cnt] = SO_in; + mode_in[2*mode_cnt+1] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/2) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_byte[i] = mode_in[7-i]; + end + bus_cycle_state = DATA_BYTES; + end + end + end + else + $display("Device is in HOLD mode, mode"); + + end // end of MODE_BYTE + + DUMMY_BYTES: + begin + if (QE || (HOLDNeg_in && ~QE)) + begin + if ((Instruct == FAST_QREAD_4 || + Instruct == RDID_QUAD) && QE) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == BYTE/2) + bus_cycle_state = DATA_BYTES; + end + else if (Instruct == W_QREAD && QE) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == BYTE/4) + bus_cycle_state = DATA_BYTES; + end + else if (Instruct == SET_BURST_WRAP && QE) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == 3*BYTE/4) + bus_cycle_state = MODE_BYTE; + end + else if (Instruct == FAST_QREAD && QE) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == BYTE) + bus_cycle_state = DATA_BYTES; + end + else if (Instruct==FAST_READ || Instruct==RD_SFDP + || Instruct == FAST_DREAD || Instruct == RD_SCREG) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == BYTE) + bus_cycle_state = DATA_BYTES; + end + else if (Instruct == RD_UNIQ_ID) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == 4*BYTE) + bus_cycle_state = DATA_BYTES; + end + else // for RES_RD_ID + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == 3*BYTE) + bus_cycle_state = DATA_BYTES; + end + end + else + $display("Device is in HOLD mode, dummy"); + end // end of DUMMY_BYTES + + DATA_BYTES: + begin + if (Instruct == PP || Instruct == WRR || + Instruct == PG_SCREG) + begin + if ((HOLDNeg_in && ~QE) || QE) + begin + if (data_cnt > 2047) + //In case of serial mode and PP,if more than + //256 bytes are sent to the device + begin + if (bit_cnt == 0) + begin + for (i=0;i<=(255*BYTE-1);i=i+1) + begin + Data_in[i] = Data_in[i+8]; + end + end + Data_in[2040 + bit_cnt] = SI_in; + bit_cnt = bit_cnt + 1; + if (bit_cnt == 8) + begin + bit_cnt = 0; + end + data_cnt = data_cnt + 1; + end + else + begin + Data_in[data_cnt] = SI_in; + data_cnt = data_cnt + 1; + bit_cnt = 0; + end + end + else + $display("Device is in HOLD mode, data"); + end + else if (Instruct == QPP && QE) + begin + pp_quad = 1'b1; + quad_nybble = {HOLDNeg_in, WPNeg_in, + SO_in, SI_in}; + if (data_cnt > 511) + begin + //In case of quad mode and QPP,if more than + // 256 bytes are sent to the device + for(i=0;i<=510;i=i+1) + begin + quad_data_in[i] = quad_data_in[i+1]; + end + quad_data_in[511] = quad_nybble; + data_cnt = data_cnt +1; + end + else + begin + if (quad_nybble !== 4'bZZZZ) + begin + quad_data_in[data_cnt] = quad_nybble; + end + data_cnt = data_cnt +1; + end + end + end // end of DATA_BYTES + endcase // end of case bus_cycle_state + end // end of ~CSNeg + end // end of rising_edge_SCK + + if (falling_edge_SCK_ipd) + begin + if ((bus_cycle_state == DATA_BYTES) && (~CSNeg_ipd)) + begin + if (((Instruct == RDSR || Instruct == RDSR2 || + Instruct == FAST_READ || Instruct == FAST_DREAD || + Instruct == FAST_DREAD_2 || Instruct == RES_RD_ID || + Instruct == RDID || Instruct == RDID_DUAL || + Instruct == RD_UNIQ_ID || Instruct == RDIDJ || + Instruct == RD_SFDP || Instruct == RD_SCREG || + Instruct == READ) && ((HOLDNeg_in && ~QE) || QE)) || + ((Instruct == FAST_QREAD || Instruct == FAST_QREAD_4 || + Instruct == W_QREAD || Instruct == RDID_QUAD || + Instruct == WOCT_QREAD) && QE)) + begin + read_out = 1'b1; + #1 read_out = 1'b0; + end + end // end of ~CSNeg_ipd + end // end of falling_edge_SCK_ipd + + if (rising_edge_CSNeg_ipd) + begin + if (bus_cycle_state==MODE_BYTE && Instruct == CONT_RD_RST) + begin + mode_byte[5:4] = 2'b11; + mode_byte[7:6] = 2'b00; + mode_byte[3:0] = 4'b0000; + bus_cycle_state = STAND_BY; + end + else if (bus_cycle_state==DATA_BYTES && ~(mode_byte[5:4]==2'b10)) + begin + bus_cycle_state = STAND_BY; + case (Instruct) + WREN, + WRDI, + SET_BURST_WRAP, + SE, + BE_32, + BE_64, + CE, + ERS_PG_RES, + DP, + ERS_SCREG: + begin + if (data_cnt == 0) + write = 1'b0; + end + + WRENV: + begin + write = 1'b0; + wren_vlt_flag = 1'b1; + end + + RES_RD_ID: + begin + write = 1'b0; + res_flag = 1'b1; + end + + WRR: + begin + if (data_cnt == 8) + //If CS# is driven high after eight + //cycle,only the Status Register is + //written to. + begin + write = 1'b0; + for(i=0;i<=7;i=i+1) + begin + Status_reg1_in[i]= + Data_in[7-i]; + end + end + else if (data_cnt == 16) + //After the 16th cycle both the + //Status and Configuration Registers + //are written to. + begin + write = 1'b0; + for(i=0;i<=7;i=i+1) + begin + Status_reg1_in[i]= + Data_in[7-i]; + Status_reg2_in[i]= + Data_in[15-i]; + end + end + end + + PP, + PG_SCREG: + begin + if (data_cnt > 0) + begin + if ((data_cnt % 8) == 0) + begin + write = 1'b0; + for (i=0;i<=255;i=i+1) + begin + for (j=7;j>=0;j=j-1) + begin + Byte_slv[j] = + Data_in[(i*8) + (7-j)]; + end + WByte[i] = Byte_slv; + end + if (data_cnt > 256*BYTE) + Byte_number = 255; + else + Byte_number = ((data_cnt/8) - 1); + end + end + end + + QPP: + begin + if (data_cnt >0) + begin + if ((data_cnt % 2) == 0) + begin + write = 1'b0; + for (i=0;i<=255;i=i+1) + begin + for(j=1;j>=0;j=j-1) + begin + Quad_slv = + quad_data_in[(i*2)+(1-j)]; + if (j==1) + Byte_slv[7:4] = Quad_slv; + else // if (j==0) + Byte_slv[3:0] = Quad_slv; + end + WByte[i] = Byte_slv; + end + if (data_cnt > 256*BYTE/4) + Byte_number = 255; + else + Byte_number = ((data_cnt/2) - 1); + end + end + end + + endcase + end + else if (bus_cycle_state==DATA_BYTES && (mode_byte[5:4]==2'b10)) + begin + bus_cycle_state = DATA_BYTES; + end + else + begin + bus_cycle_state = STAND_BY; + if (HOLDNeg_in && (Instruct == RES_RD_ID) && + (dummy_cnt == 0)) + begin + write = 1'b0; + res_flag = 1'b0; + end + end + end // end of rising_edge_CSNeg_ipd + + end // end of Buscycle + + /////////////////////////////////////////////////////////////////////////// + // Timing control for the Page Program + /////////////////////////////////////////////////////////////////////////// + time pob; + time elapsed; + time start; + time duration; + event pdone_event; + + always @(rising_edge_PSTART) + begin + if ((Instruct == PP) || (Instruct == QPP) || (Instruct == PG_SCREG)) + pob = tdevice_PP; + else + pob = tdevice_BP1; + if ((rising_edge_PSTART) && PDONE) + begin + elapsed = 0; + PDONE = 1'b0; + ->pdone_event; + start = $time; + end + end + + always @(PGSUSP_event) + begin + if ((PGSUSP_event) && PGSUSP && (~PDONE)) + begin + disable pdone_process; + elapsed = $time - start; + duration = pob - elapsed; + PDONE = 1'b0; + end + end + + always @(PGRES_event) + begin + if ((PGRES_event) && PGRES && (~PDONE)) + begin + start = $time; + ->pdone_event; + end + end + + always @(pdone_event) + begin:pdone_process + PDONE = 1'b0; + #pob PDONE = 1'b1; + end + + /////////////////////////////////////////////////////////////////////////// + // Timing control for the Write Status Register Operation + // start + /////////////////////////////////////////////////////////////////////////// + time wob; + always @(WSTART) + begin + wob = tdevice_WRR; + if ((rising_edge_WSTART) && WDONE) + begin + WDONE = 1'b0; + #wob WDONE = 1'b1; + end + end + /////////////////////////////////////////////////////////////////////////// + // Timing control for the Volatile Write Status Register Operation + // start + /////////////////////////////////////////////////////////////////////////// + time vob; + always @(VLTSTART) + begin + vob = tdevice_VRR; + if (rising_edge_VLTSTART && VLTDONE) + begin + VLTDONE = 1'b0; + #vob VLTDONE = 1'b1; + end + end + + /////////////////////////////////////////////////////////////////////////// + // Timing control for the Erase Operations + /////////////////////////////////////////////////////////////////////////// + time seo; + time beo32; + time beo64; + time ceo; + event edone_event; + + always @(rising_edge_ESTART) + begin + seo = tdevice_SE; + beo32 = tdevice_BE1; + beo64 = tdevice_BE2; + ceo = tdevice_CE; + if ((rising_edge_ESTART) && EDONE) + begin + if (Instruct == CE) + begin + duration = ceo; + end + else if (Instruct == BE_64) + begin + duration = beo64; + end + else if (Instruct == BE_32) + begin + duration = beo32; + end + else + begin + duration = seo; + end + elapsed = 0; + EDONE = 1'b0; + ->edone_event; + start = $time; + end + end + + always @(ESUSP_event) + begin + if ((ESUSP_event) && ESUSP && (~EDONE)) + begin + disable edone_process; + elapsed = $time - start; + duration = duration - elapsed; + EDONE = 1'b0; + end + end + + always @(ERES_event) + begin + if ((ERES_event) && ERES && (~EDONE)) + begin + start = $time; + ->edone_event; + end + end + + always @(edone_event) + begin : edone_process + EDONE = 1'b0; + #duration EDONE = 1'b1; + end + + /////////////////////////////////////////////////////////////////// + // Process for clock frequency determination + /////////////////////////////////////////////////////////////////// + always @(posedge SCK_ipd) + begin : clock_period + if (SCK_ipd) + begin + SCK_cycle = $time - prev_SCK; + prev_SCK = $time; + end + end + + /////////////////////////////////////////////////////////////////////////// + // Main Behavior Process + // combinational process for next state generation + /////////////////////////////////////////////////////////////////////////// + reg rising_edge_PDONE = 1'b0; + reg rising_edge_EDONE = 1'b0; + reg rising_edge_WDONE = 1'b0; + reg rising_edge_VLTDONE = 1'b0; + reg falling_edge_write = 1'b0; + reg rising_edge_DP_out = 1'b0; + + integer i; + integer j; + + always @(rising_edge_PoweredUp or falling_edge_write or rising_edge_DP_out + or rising_edge_PDONE or rising_edge_WDONE or rising_edge_EDONE or + ERSSUSP_out_event or ERSRES_out_event or RES_out or + PRGSUSP_out_event or PRGRES_out_event or rising_edge_VLTDONE) + begin: StateGen1 + + if (rising_edge_PoweredUp) + next_state = IDLE; + else + begin + case (current_state) + IDLE : + begin + if (falling_edge_write) + begin + if (Instruct == WRR && (~SRP1 && + (~SRP0 || (SRP0 && WPNeg)))) + begin + if (WEL && ~wren_vlt_flag) + next_state = WRITE_SR; + else if (~WEL && wren_vlt_flag) + next_state = WRITE_SR_V; + end + else if (Instruct == PP && WEL) + begin + sect = Address / 16'h1000; + sect_tmp_pg = sect; + if (Sec_Prot[sect] == 0) + next_state = PAGE_PG; + end + else if (Instruct == QPP && WEL && QE) + begin + sect = Address / 16'h1000; + sect_tmp_pg = sect; + if (Sec_Prot[sect] == 0) + next_state = PAGE_PG; + end + else if (Instruct == PG_SCREG && WEL) + begin + sect = Address / 16'h1000; + if ((sect < 4 && sect > 0) && LB[sect-1]==0) + next_state = PAGE_PG; + end + else if (Instruct == ERS_SCREG && WEL) + begin + sect = Address / 16'h1000; + if ((sect <= 3) && LB[sect-1]==0) + next_state = SECTOR_ERS; + end + else if ((Instruct == SE || Instruct == BE_32 || + Instruct == BE_64) && WEL) + begin + sect = Address / 16'h1000; + sect_tmp_ers = sect; + if (Sec_Prot[sect] == 0) + next_state = SECTOR_ERS; + end + else if (Instruct == CE && WEL && + ((~CMP && ~BP2 && ~BP1 && ~BP0) || + (CMP && BP2 && BP1 && BP0))) + next_state = BULK_ERS; + else + next_state = IDLE; + end + else if (rising_edge_DP_out) + next_state = DP_DOWN; + end // end of IDLE + + WRITE_SR: + begin + if (rising_edge_WDONE) + next_state = IDLE; + end // end of WRITE_SR + + WRITE_SR_V: + begin + if (rising_edge_VLTDONE) + next_state = IDLE; + end + + PAGE_PG: + begin + if (PRGSUSP_out_event && PRGSUSP_out == 1) + next_state = PG_SUSP; + else if (rising_edge_PDONE) + next_state = IDLE; + end // end of PAGE_PG + + PG_SUSP: + begin + if (PRGRES_out_event && PRGRES_out == 1) + next_state = PAGE_PG; + else if (falling_edge_write) + begin + if (Instruct == SE || Instruct == BE_32 || + Instruct == BE_64) + begin + sect = Address / 16'h1000; + if ((Sec_Prot[sect] == 0) && (sect != sect_tmp_pg)) + next_state = PG_SUSP_ERS; + end + end + end // end of PG_SUSP + + PG_SUSP_ERS: + begin + if (rising_edge_EDONE) + next_state = PG_SUSP; + else + next_state = PG_SUSP_ERS; + end + + BULK_ERS: + begin + if (rising_edge_EDONE) + next_state = IDLE; + end + + SECTOR_ERS: + begin + if (ERSSUSP_out_event && ERSSUSP_out == 1) + next_state = ERS_SUSP; + else if (rising_edge_EDONE) + next_state = IDLE; + end + + ERS_SUSP: + begin + if (ERSRES_out_event && ERSRES_out == 1) + next_state = SECTOR_ERS; + else if (falling_edge_write) + begin + if (Instruct == PP || (Instruct == QPP && QE)) + begin + sect = Address / 16'h1000; + if ((Sec_Prot[sect] == 0)&&(sect != sect_tmp_ers)) + next_state = ERS_SUSP_PG; + end + else if (Instruct == PG_SCREG) + begin + sect = Address / 16'h1000; + if ((sect < 4 && sect > 0) && LB[sect-1]==0) + next_state = ERS_SUSP_PG; + end + end + end + + ERS_SUSP_PG: + begin + if (rising_edge_PDONE) + next_state = ERS_SUSP; + else + next_state = ERS_SUSP_PG; + end + + DP_DOWN: + begin + if (rising_edge_RES_out) + next_state = IDLE; + end + + endcase // end case of current_state + end // + end // end of StateGen1 + + /////////////////////////////////////////////////////////////////////////// + //FSM Output generation and general functionality + /////////////////////////////////////////////////////////////////////////// + reg rising_edge_read_out = 1'b0; + reg Instruct_event = 1'b0; + reg change_addr_event = 1'b0; + reg current_state_event = 1'b0; + + integer WData [0:255]; + integer Addr; + integer Addr_ers; + integer Addr_tmp; + integer Addr_tmp_2; + integer Addr_tmp_3; + integer Addr_screg; + + always @(oe_event) + begin + oe = 1'b1; + #1000 oe = 1'b0; + end + + always @(rising_edge_read_out or Instruct or rising_edge_SCK_ipd or + change_addr_event or oe or current_state_event or Address or + falling_edge_write or PDONE or rising_edge_WDONE or Instruct_event + or rising_edge_EDONE or ERSSUSP_out or rising_edge_PoweredUp or + rising_edge_CSNeg_ipd or rising_edge_RES_out or ERSRES_out or + PRGSUSP_out or PRGRES_out_event or rising_edge_VLTDONE or + rising_edge_DP_out) + + begin: Functionality + integer i,j; + + if (rising_edge_read_out) + begin + if (PoweredUp == 1'b1) + ->oe_event; + end + + if (Instruct_event) + begin + read_cnt = 0; + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + read_id = 1'b0; + pp_quad = 1'b0; + if (current_state == IDLE) + begin + if (DP_in == 1'b1) + begin + $display ("Command results can be corrupted "); + end + end + end + + if (rising_edge_PoweredUp) + begin + Status_reg1[1] = 1'b0; // WEL bit + Status_reg1[0] = 1'b0; // BUSY bit + + Status_reg2[7] = 1'b0; // SUS bit + end + + if (change_addr_event) + begin + read_addr = Address; + end + + if (rising_edge_RES_out) + begin + if(RES_out) + begin + RES_in = 1'b0; + end + end + + case (current_state) + IDLE : + begin + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + res_flag = 1'b0; + pg_screg_flag = 1'b0; + ers_screg_flag = 1'b0; + if (falling_edge_write && ~DP_in) + begin + read_cnt = 0; + if (Instruct == WREN) + Status_reg1[1] = 1'b1; + else if (Instruct == WRDI) + Status_reg1[1] = 1'b0; + else if (Instruct == WRR) + begin + if(~SRP1 && (~SRP0 || (SRP0 && WPNeg))) + begin + if (WEL && ~wren_vlt_flag) + begin + WSTART = 1'b1; + WSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (~WEL && wren_vlt_flag) + begin + VLTSTART = 1'b1; + VLTSTART <= #5 1'b0; + end + end + else + Status_reg1[1] = 1'b0; + end + else if ((Instruct == PP || (Instruct == QPP && QE)) + && WEL && PDONE) + begin + sect = Address / 16'h1000; + if (Sec_Prot[sect] == 0) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 1'b0; + PGRES = 1'b0; + Status_reg1[0] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + Status_reg1[1] = 1'b0; + end + else if (Instruct == PG_SCREG && WEL) + begin + sect = Address / 16'h1000; + if ((sect <= 3) && LB[sect-1]==0) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 1'b0; + PGRES = 1'b0; + Status_reg1[0] = 1'b1; + SA = sect; + wr_cnt = Byte_number; + Addr_screg = Address % 16'h1000; + pg_screg_flag = 1'b1; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + Status_reg1[1] = 1'b0; + end + end + else if ((Instruct == SE || Instruct == BE_32 || + Instruct == BE_64) && WEL) + begin + sect = Address / 16'h1000; + if (Sec_Prot[sect] == 0) + begin + ESTART = 1'b1; + ESTART <= #5 1'b0; + ESUSP = 1'b0; + ERES = 1'b0; + Status_reg1[0] = 1'b1; + Addr_ers = Address; + end + else + Status_reg1[1] = 1'b0; + end + else if (Instruct == CE && WEL) + begin +// if ((~CMP && ~BP2 && ~BP1 && ~BP0) || +// (CMP && BP2 && BP1 && BP0)) + if (Sec_Prot == 0) + begin + ESTART = 1'b1; + ESTART <= #5 1'b0; + ESUSP = 1'b0; + ERES = 1'b0; + Status_reg1[0] = 1'b1; + end + else + Status_reg1[1] = 1'b0; + end + else if (Instruct == ERS_SCREG && WEL) + begin + sect = Address / 16'h1000; + if ((sect <= 3) && LB[sect-1]==0) + begin + ESTART = 1'b1; + ESTART <= #5 1'b0; + ESUSP = 1'b0; + ERES = 1'b0; + Status_reg1[0] = 1'b1; + SA = sect; + ers_screg_flag = 1'b1; + end + else + Status_reg1[1] = 1'b0; + end + else if (Instruct == DP) + begin + RES_in <= 1'b0; + DP_in <= 1'b1; + end + end // end of falling_edge_write + else if (oe && ~DP_in) + begin + if (Instruct == RDSR) + begin //Read Status Register + sr_read = 1'b1; + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + sr_read = 1'b1; + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == READ || Instruct == FAST_READ) + begin + if (Instruct == READ) + begin + fast_read = 1'b0; + dual_read = 1'b0; + slow_read = 1'b1; + quad_read = 1'b0; + sr_read = 1'b0; + end + else + begin + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + end + if (Mem[read_addr] !== -1) + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + end + else + begin + SOut_zd = 8'bx; + end + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else if (Instruct==FAST_DREAD || Instruct==FAST_DREAD_2) + begin + fast_read = 1'b0; + dual_read = 1'b1; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else if ((Instruct==FAST_QREAD || Instruct==FAST_QREAD_4 || + Instruct==W_QREAD || Instruct==WOCT_QREAD) + && QE) + begin + if ((Instruct==W_QREAD && Address[0]) || + (Instruct==WOCT_QREAD && ~(Address[3:0] == 4'h0))) + begin + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + $display("Word Read could not execute"); + $display("Wrong Read Address"); + end + end + else + begin + fast_read = 1'b0; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b1; + sr_read = 1'b0; + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (wrap_byte[4]==1'b0 && + (Instruct==FAST_QREAD_4 || Instruct==W_QREAD)) + begin + ADDRHILO_WRAP(AddrLo_wrap,AddrHi_wrap, + Address,w_size); + if (read_addr == AddrHi_wrap) + read_addr = AddrLo_wrap; + else + read_addr = read_addr + 1; + end + else + begin + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + end + else if (Instruct==RDID || Instruct==RDID_DUAL || + Instruct==RDID_QUAD) + begin + if (read_addr % 2 == 0) + begin + ident_out2 = {Manuf_ID,Device_ID1}; + end + else + begin + ident_out2 = {Device_ID1,Manuf_ID}; + end + read_id = 1'b1; + if (Instruct == RDID) + begin + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + DataDriveOut_SO = ident_out2[15-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 16) + read_cnt = 0; + end + else if (Instruct == RDID_DUAL) + begin + fast_read = 1'b0; + dual_read = 1'b1; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + DataDriveOut_SO = ident_out2[15-2*read_cnt]; + DataDriveOut_SI = ident_out2[14-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else // (Instruct == RDID_QUAD) + begin + fast_read = 1'b0; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b1; + sr_read = 1'b0; + HOLDNegOut_zd = ident_out2[15-4*read_cnt]; + WPNegOut_zd = ident_out2[14-4*read_cnt]; + SOut_zd = ident_out2[13-4*read_cnt]; + SIOut_zd = ident_out2[12-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + read_cnt = 0; + end + end + else if (Instruct == RD_UNIQ_ID) + begin + // unique ID number is not in data sheet + read_id = 1'b1; + DataDriveOut_SO = unique_id[63-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 64) + read_cnt = 0; + end + else if (Instruct == RDIDJ) + begin + read_id = 1'b1; + ident_out = {Manuf_ID,Device_ID2,Device_ID3}; + DataDriveOut_SO = ident_out[23-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 24) + read_cnt = 0; + end + else if (Instruct == RD_SFDP) + begin + sfdp_addr = read_addr / 12'h100; + if (sfdp_addr == 0) + begin + Addr_tmp_2 = (read_addr % 12'h100); + data_out[7:0] = SFDP_array[Addr_tmp_2]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == SFDP_HiAddr) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + $display("Given SFDP address is out of range"); + end + end + end + else if (Instruct == RD_SCREG) + begin + Addr_tmp_2 = read_addr / 12'h100; + Addr_tmp_3 = read_addr % 12'h100; + if (Addr_tmp_2 == 16) + begin + // Security Register No.1 + data_out[7:0] = Security_Reg1[Addr_tmp_3]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + end + else if (Addr_tmp_2 == 32) + begin + // Security Register No.2 + data_out[7:0] = Security_Reg2[Addr_tmp_3]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + end + else if (Addr_tmp_2 == 48) + // Security Register No.2 + begin + data_out[7:0] = Security_Reg3[Addr_tmp_3]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + $display("Given Security Register Read "); + $display("address is out of range "); + end + end + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr % 256 == SecReg_HiAddr) + read_addr = (read_addr/256)*(SecReg_HiAddr+1); + else + read_addr = read_addr + 1; + end + end + else if (Instruct == RES_RD_ID) + begin + read_id = 1'b1; + data_out[7:0] = Device_ID1; + DataDriveOut_SO = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end // end of oe + else if (rising_edge_DP_out) + DP_in = 1'b0; + end // end of IDLE state + + WRITE_SR: + begin + if (WDONE) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + + Status_reg1[7:2] = Status_reg1_in[7:2]; + Status_reg2[6] = Status_reg2_in[6]; + Status_reg2[1] = Status_reg2_in[1]; + // SRP1 bit will only change value from '0' to '1' + // if SRP1 is '1' than Status Register is protected + //and is not possible to write it + Status_reg2[0] = Status_reg2_in[0]; + for(i=5;i>=3;i=i-1) + begin + if (Status_reg2[i] == 1'b0) + Status_reg2[i] = Status_reg2_in[i]; + else + begin + $display("LB bit is set to '1'"); + $display("No change allowed"); + end + end + change_prot_bits = 1'b1; + #1000 change_prot_bits = 1'b0; + end // end of WDONE + + if (oe) + begin + if (Instruct == RDSR) + begin + //Read Status Register 1 + sr_read = 1'b1; + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end // end of oe + end // end of WRITE_SR + + WRITE_SR_V: + begin + if (VLTDONE) + begin + Status_reg1[7:2] = Status_reg1_in[7:2]; + Status_reg2[6] = Status_reg2_in[6]; + Status_reg2[1] = Status_reg2_in[1]; + // SRP1 bit will only change value from '0' to '1' + // if SRP1 is '1' than Status Register is protected + //and is not possible to write it + Status_reg2[0] = Status_reg2_in[0]; + for(i=5;i>=3;i=i-1) + begin + if (Status_reg2[i] == 1'b0) + Status_reg2[i] = Status_reg2_in[i]; + else + begin + $display("LB bit is set to '1'"); + $display("No change allowed"); + end + end + change_prot_bits = 1'b1; + #1000 change_prot_bits = 1'b0; + wren_vlt_flag = 1'b0; + end + end + + PAGE_PG, + ERS_SUSP_PG: + begin + if (current_state_event && ~PDONE) + begin + if (Instruct !== PG_SCREG) + begin + ADDRHILO_PG(AddrLo, AddrHi, Addr); + end + cnt = 0; + + for (i=0;i<=wr_cnt;i=i+1) + begin + new_int = WData[i]; + if (Instruct == PG_SCREG) + begin + if (sect == 1) + old_int = Security_Reg1[Addr_screg + i - cnt]; + else if (sect == 2) + old_int = Security_Reg2[Addr_screg + i - cnt]; + else + old_int = Security_Reg3[Addr_screg + i - cnt]; + end + else + begin + old_int = Mem[Addr + i - cnt]; + end + if (new_int > -1) + begin + new_bit = new_int; + if (old_int > -1) + begin + old_bit = old_int; + for(j=0;j<=7;j=j+1) + begin + if (~old_bit[j]) + new_bit[j]=1'b0; + end + new_int=new_bit; + end + WData[i]= new_int; + end + else + begin + WData[i] = -1; + end + if (Instruct == PG_SCREG) + begin + if (sect == 1) + Security_Reg1[Addr_screg + i - cnt] = - 1; + else if (sect == 2) + Security_Reg2[Addr_screg + i - cnt] = - 1; + else + Security_Reg3[Addr_screg + i - cnt] = - 1; + end + else + Mem[Addr + i - cnt] = - 1; + if ((Addr + i) == AddrHi) + begin + + Addr = AddrLo; + cnt = i + 1; + end + end + cnt = 0; + end // end of current_state_event + + if (PDONE) + begin + if (current_state !== ERS_SUSP_PG) + begin + Status_reg1[0] = 1'b0; + end + Status_reg1[1] = 1'b0; + for (i=0;i<=wr_cnt;i=i+1) + begin + if (pg_screg_flag ) + begin + if (sect == 1) + Security_Reg1[Addr_screg + i - cnt] = WData[i]; + else if (sect == 2) + Security_Reg2[Addr_screg + i - cnt] = WData[i]; + else + Security_Reg3[Addr_screg + i - cnt] = WData[i]; + + if ((Addr_screg + i) == SecReg_HiAddr) + begin + Addr_screg = SecReg_LoAddr; + cnt = i + 1; + end + end + else + begin + Mem[Addr_tmp + i - cnt] = WData[i]; + if ((Addr_tmp + i) == AddrHi) + begin + Addr_tmp = AddrLo; + cnt = i + 1; + end + end + end + end // end of PDONE + + if (Instruct == ERS_PG_SUSP && current_state == PAGE_PG && ~susp_flag) + begin + PGSUSP = 1'b1; + PGSUSP <= #1000 1'b0; + PRGSUSP_in = 1'b1; + end + + if (oe) + begin + if (Instruct == RDSR) + begin + //Read Status Register 1 + sr_read = 1'b1; + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + end // end of PAGE_PG + + PG_SUSP: + begin + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + if (PRGSUSP_out == 1 && ~(Instruct == ERS_PG_RES)) + begin + PRGSUSP_in = 1'b0; + //The BUSY bit in the Status Register will indicate that + //the device is ready for another operation. + Status_reg1[0] = 1'b0; + //The Suspend (SUS) bit in the Status Register2 will + //be set to the logical “1” state to indicate that the + //program operation has been suspended. + Status_reg2[7] = 1'b1; + end + if (PRGRES_out_event && PRGRES_out == 1) + begin + PRGRES_in = 1'b0; + Status_reg1[0] = 1'b1; + end + if (SUS) + begin + if (falling_edge_write) + begin + if (Instruct == ERS_PG_RES) + begin + Status_reg2[7] = 1'b0; + PRGRES_in = 1'b1; + PGRES = 1'b1; + PGRES <= #1000 1'b0; + end + else if ((Instruct == SE || Instruct == BE_32 || + Instruct == BE_64) && WEL) + begin + sect = Address / 16'h1000; + if (sect !== sect_tmp_pg && Sec_Prot[sect] == 0) + begin + ESTART = 1'b1; + ESTART <= #5 1'b0; + ESUSP = 1'b0; + ERES = 1'b0; + Status_reg1[0] = 1'b1; + Addr_ers = Address; + end + else + begin + Status_reg1[0] = 1'b0; + $display("Can't erase sector/block"); + $display("Block is protected or suspended"); + end + end + end + else if (oe) + begin + if (Instruct == RDSR) + begin + //Read Status Register 1 + sr_read = 1'b1; + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + sr_read = 1'b1; + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == READ || Instruct == FAST_READ) + begin + if (sect_tmp_pg !== read_addr / 16'h1000) + begin + if (Instruct == READ) + begin + fast_read = 1'b0; + dual_read = 1'b0; + slow_read = 1'b1; + quad_read = 1'b0; + sr_read = 1'b0; + end + else + begin + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + end + if (Mem[read_addr] !== -1) + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + end + else + begin + SOut_zd = 8'bx; + end + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + $display("Can't read suspended sector"); + read_cnt = 0; + end + end + end + else if (Instruct==FAST_DREAD || + Instruct==FAST_DREAD_2) + begin + if (sect_tmp_pg !== read_addr / 16'h1000) + begin + fast_read = 1'b0; + dual_read = 1'b1; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + if (Mem[read_addr] !== -1) + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + end + else + begin + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + end + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + $display("Can't read suspended sector"); + read_cnt = 0; + end + end + end + else if ((Instruct==FAST_QREAD || Instruct==W_QREAD + || Instruct==FAST_QREAD_4 || Instruct==WOCT_QREAD) + && QE) + begin + if (sect_tmp_pg !== read_addr / 16'h1000) + begin + if ((Instruct==W_QREAD && Address[0]) || + (Instruct==WOCT_QREAD && + ~(Address[3:0] == 4'h0))) + begin + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + $display("Word Read can't execute"); + $display("Wrong Read Address"); + end + end + else + begin + fast_read = 1'b0; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b1; + sr_read = 1'b0; + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (wrap_byte[4]==0 && + (Instruct==FAST_QREAD_4 || + Instruct==W_QREAD)) + begin + ADDRHILO_WRAP(AddrLo_wrap, + AddrHi_wrap, Address,w_size); + if (read_addr == AddrHi_wrap) + read_addr = AddrLo_wrap; + else + read_addr = read_addr + 1; + end + else + begin + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + $display("Can't read suspended sector"); + read_cnt = 0; + end + end + end + else if (Instruct==RDID || Instruct==RDID_DUAL || + Instruct==RDID_QUAD) + begin + if (read_addr % 2 == 0) + begin + ident_out2 = {Manuf_ID,Device_ID1}; + end + else + begin + ident_out2 = {Device_ID1,Manuf_ID}; + end + read_id = 1'b1; + if (Instruct == RDID) + begin + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + DataDriveOut_SO = ident_out2[15-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 16) + read_cnt = 0; + end + else if (Instruct == RDID_DUAL) + begin + fast_read = 1'b0; + dual_read = 1'b1; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + DataDriveOut_SO = ident_out2[15-2*read_cnt]; + DataDriveOut_SI = ident_out2[14-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else // (Instruct == RDID_QUAD) + begin + fast_read = 1'b0; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b1; + sr_read = 1'b0; + HOLDNegOut_zd = ident_out2[15-4*read_cnt]; + WPNegOut_zd = ident_out2[14-4*read_cnt]; + SOut_zd = ident_out2[13-4*read_cnt]; + SIOut_zd = ident_out2[12-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + read_cnt = 0; + end + end + else if (Instruct == RD_UNIQ_ID) + begin + // unique ID number is not in data sheet + read_id = 1'b1; + DataDriveOut_SO = unique_id[63-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 64) + read_cnt = 0; + end + else if (Instruct == RDIDJ) + begin + read_id = 1'b1; + ident_out = {Manuf_ID,Device_ID2,Device_ID3}; + DataDriveOut_SO = ident_out[23-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 24) + read_cnt = 0; + end + else if (Instruct == RD_SFDP) + begin + sfdp_addr = read_addr / 12'h100; + if (sfdp_addr == 0) + begin + Addr_tmp_2 = (read_addr % 12'h100); + data_out[7:0] = SFDP_array[Addr_tmp_2]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == SFDP_HiAddr) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + $display("SFDP address is out of range"); + end + end + end + else if (Instruct == RD_SCREG) + begin + Addr_tmp_2 = read_addr / 12'h100; + Addr_tmp_3 = read_addr % 12'h100; + if (Addr_tmp_2 == 16) + begin + // Security Register No.1 + data_out[7:0] = Security_Reg1[Addr_tmp_3]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + end + else if (Addr_tmp_2 == 32) + begin + // Security Register No.2 + data_out[7:0] = Security_Reg2[Addr_tmp_3]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + end + else if (Addr_tmp_2 == 48) + // Security Register No.2 + begin + data_out[7:0] = Security_Reg3[Addr_tmp_3]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + $display("Given Security Register Read "); + $display("address is out of range "); + end + end + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr % 256 == SecReg_HiAddr) + read_addr=(read_addr/256)* + (SecReg_HiAddr+1); + else + read_addr = read_addr + 1; + end + end + end // end of 'oe' + end + end // end of PG_SUSP + + SECTOR_ERS, + PG_SUSP_ERS: + begin + if (current_state_event && ~EDONE) + begin + if (Instruct == SE) + ADDRHILO_SEC4(AddrLo_ers, AddrHi_ers, Addr_ers); + else if (Instruct == BE_32) + ADDRHILO_SEC32(AddrLo_ers, AddrHi_ers, Addr_ers); + else if (Instruct == BE_64) + begin + ADDRHILO_SEC64(AddrLo_ers, AddrHi_ers, Addr_ers); + end + if (Instruct !== ERS_SCREG) + begin + for (i=AddrLo_ers;i<=AddrHi_ers;i=i+1) + begin + Mem[i] = -1; + end + end + else + begin + if (sect == 1) + begin + for(i=SecReg_LoAddr;i<=SecReg_HiAddr;i=i+1) + begin + Security_Reg1[i] = -1; + end + end + else if (sect == 2) + begin + for(i=SecReg_LoAddr;i<=SecReg_HiAddr;i=i+1) + begin + Security_Reg2[i] = -1; + end + end + else + begin + for(i=SecReg_LoAddr;i<=SecReg_HiAddr;i=i+1) + begin + Security_Reg3[i] = -1; + end + end + end + end + + if (EDONE == 1) + begin + if (current_state !== PG_SUSP_ERS) + begin + Status_reg1[0] = 1'b0; + end + Status_reg1[1] = 1'b0; + if (ers_screg_flag ) + begin + if (sect == 1) + begin + for(i=SecReg_LoAddr;i<=SecReg_HiAddr;i=i+1) + begin + Security_Reg1[i] = MaxData; + end + end + else if (sect == 2) + for(i=SecReg_LoAddr;i<=SecReg_HiAddr;i=i+1) + begin + Security_Reg2[i] = MaxData; + end + else + for(i=SecReg_LoAddr;i<=SecReg_HiAddr;i=i+1) + begin + Security_Reg3[i] = MaxData; + end + + end + else + begin + for (i=AddrLo_ers;i<=AddrHi_ers;i=i+1) + begin + Mem[i] = MaxData; + end + end + end + + if (Instruct == ERS_PG_SUSP && current_state == SECTOR_ERS) + begin + ESUSP = 1'b1; + ESUSP <= #1000 1'b0; + ERSSUSP_in = 1'b1; + end + if (oe) + begin + if (Instruct == RDSR) + begin + //Read Status Register 1 + sr_read = 1'b1; + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + end // end of SECTOR_ERS + + BULK_ERS: + begin + if (current_state_event && ~EDONE) + begin + for (i=0;i<=AddrRANGE;i=i+1) + begin + Mem[i] = -1; + end + end + if (EDONE == 1) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + for (i=0;i<=AddrRANGE;i=i+1) + begin + Mem[i] = MaxData; + end + end + if (oe) + begin + if (Instruct == RDSR) + begin + //Read Status Register 1 + sr_read = 1'b1; + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + end // end of BULK_ERS + + ERS_SUSP: + begin + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + if (ERSSUSP_out == 1 && ~(Instruct == ERS_PG_RES)) + begin + ERSSUSP_in = 1'b0; + //The BUSY bit in the Status Register will indicate that + //the device is ready for another operation. + Status_reg1[0] = 1'b0; + //The Suspend (SUS) bit in the Status Register2 will + //be set to the logical “1” state to indicate that the + //program operation has been suspended. + Status_reg2[7] = 1'b1; + end + if (ERSRES_out_event && ERSRES_out == 1) + begin + ERSRES_in = 1'b0; + Status_reg1[0] = 1'b1; + end + if (SUS) + begin + if (falling_edge_write) + begin + if (Instruct == ERS_PG_RES) + begin + Status_reg2[7] = 1'b0; + ERSRES_in = 1'b1; + ERES = 1'b1; + ERES <= #1000 1'b0; + end + else if ((Instruct == PP || (Instruct==QPP && QE)) + && WEL) + begin + sect = Address / 16'h1000; + if (sect !== sect_tmp_ers && Sec_Prot[sect]==0) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 1'b0; + PGRES = 1'b0; + Status_reg1[0] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + Status_reg1[0] = 1'b0; + $display("Can't program sector/block"); + $display("Block is protected or suspended"); + end + end + else if (Instruct == PG_SCREG) + begin + sect = Address / 16'h1000; + if ((sect <= 3 && sect >=1) && LB[sect-1]==0) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 1'b0; + PGRES = 1'b0; + Status_reg1[0] = 1'b1; + SA = sect; + wr_cnt = Byte_number; + Addr_screg = Address % 16'h1000; + pg_screg_flag = 1'b1; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + Status_reg1[1] = 1'b0; + end + end + else if (oe) + begin + if (Instruct == RDSR) + begin + //Read Status Register 1 + sr_read = 1'b1; + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + sr_read = 1'b1; + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == READ || Instruct == FAST_READ) + begin + if (sect !== read_addr / 16'h1000) + begin + if (Instruct == READ) + begin + fast_read = 1'b0; + dual_read = 1'b0; + slow_read = 1'b1; + quad_read = 1'b0; + sr_read = 1'b0; + end + else + begin + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + end + if (Mem[read_addr] !== -1) + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + end + else + begin + SOut_zd = 8'bx; + end + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + $display("Can't read suspended sector"); + read_cnt = 0; + end + end + end + else if (Instruct==FAST_DREAD || Instruct==FAST_DREAD_2) + begin + if (sect !== read_addr / 16'h1000) + begin + fast_read = 1'b0; + dual_read = 1'b1; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + if (Mem[read_addr] !== -1) + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + end + else + begin + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + end + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + $display("Can't read suspended sector"); + read_cnt = 0; + end + end + end + else if ((Instruct==FAST_QREAD || Instruct==W_QREAD + || Instruct==FAST_QREAD_4 || Instruct==WOCT_QREAD) + && QE) + begin + if (sect_tmp_ers !== read_addr / 16'h1000) + begin + if ((Instruct==W_QREAD && Address[0]) || + (Instruct==WOCT_QREAD && + ~(Address[3:0]==4'h0))) + begin + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + $display("Word Read can't execute"); + $display("Wrong Read Address"); + end + end + else + begin + fast_read = 1'b0; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b1; + sr_read = 1'b0; + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (wrap_byte[4]==0 && + (Instruct==FAST_QREAD_4 + || Instruct==W_QREAD)) + begin + ADDRHILO_WRAP(AddrLo_wrap, + AddrHi_wrap,Address,w_size); + if (read_addr == AddrHi_wrap) + read_addr = AddrLo_wrap; + else + read_addr = read_addr + 1; + end + else + begin + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + $display("Can't read suspended sector"); + read_cnt = 0; + end + end + end + else if (Instruct==RDID || Instruct==RDID_DUAL || + Instruct==RDID_QUAD) + begin + if (read_addr % 2 == 0) + begin + ident_out2 = {Manuf_ID,Device_ID1}; + end + else + begin + ident_out2 = {Device_ID1,Manuf_ID}; + end + read_id = 1'b1; + if (Instruct == RDID) + begin + fast_read = 1'b1; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + DataDriveOut_SO = ident_out2[15-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 16) + read_cnt = 0; + end + else if (Instruct == RDID_DUAL) + begin + fast_read = 1'b0; + dual_read = 1'b1; + slow_read = 1'b0; + quad_read = 1'b0; + sr_read = 1'b0; + DataDriveOut_SO = ident_out2[15-2*read_cnt]; + DataDriveOut_SI = ident_out2[14-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else // (Instruct == RDID_QUAD) + begin + fast_read = 1'b0; + dual_read = 1'b0; + slow_read = 1'b0; + quad_read = 1'b1; + sr_read = 1'b0; + HOLDNegOut_zd = ident_out2[15-4*read_cnt]; + WPNegOut_zd = ident_out2[14-4*read_cnt]; + SOut_zd = ident_out2[13-4*read_cnt]; + SIOut_zd = ident_out2[12-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + read_cnt = 0; + end + end + else if (Instruct == RD_UNIQ_ID) + begin + // unique ID number is not in data sheet + read_id = 1'b1; + DataDriveOut_SO = unique_id[63-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 64) + read_cnt = 0; + end + else if (Instruct == RDIDJ) + begin + read_id = 1'b1; + ident_out = {Manuf_ID,Device_ID2,Device_ID3}; + DataDriveOut_SO = ident_out[23-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 24) + read_cnt = 0; + end + else if (Instruct == RD_SFDP) + begin + sfdp_addr = read_addr / 12'h100; + if (sfdp_addr == 0) + begin + Addr_tmp_2 = (read_addr % 12'h100); + data_out[7:0] = SFDP_array[Addr_tmp_2]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == SFDP_HiAddr) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + $display("SFDP address is out of range"); + end + end + end + else if (Instruct == RD_SCREG) + begin + Addr_tmp_2 = read_addr / 12'h100; + Addr_tmp_3 = read_addr % 12'h100; + if (Addr_tmp_2 == 16) + begin + // Security Register No.1 + data_out[7:0] = Security_Reg1[Addr_tmp_3]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + end + else if (Addr_tmp_2 == 32) + begin + // Security Register No.2 + data_out[7:0] = Security_Reg2[Addr_tmp_3]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + end + else if (Addr_tmp_2 == 48) + // Security Register No.2 + begin + data_out[7:0] = Security_Reg3[Addr_tmp_3]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + end + else + begin + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + $display("Given Security Register Read "); + $display("address is out of range "); + end + end + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr % 256 == SecReg_HiAddr) + read_addr = (read_addr/256)* + (SecReg_HiAddr+1); + else + read_addr = read_addr + 1; + end + end + end // end of 'oe' + end // end of SUS + end // end of ERS_SUSP + + DP_DOWN: + begin + if (oe) + begin + if (Instruct == RES_RD_ID) + begin + read_id = 1'b1; + data_out[7:0] = Device_ID1; + DataDriveOut_SO = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + if (falling_edge_write) + begin + if (Instruct == RES_RD_ID) + begin + RES_in = 1'b1; + end + else + begin + $display("Device is in Deep Power Down Mode"); + $display("No instructions allowed"); + end + end + end + + endcase + //Output Disable Control + if (CSNeg_ipd ) + begin + SIOut_zd = 1'bZ; + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + DataDriveOut_SO = 1'bZ; + DataDriveOut_SI = 1'bZ; + end + end // end of Functionality + + /////////////////////////////////////////////////////////////////////////// + always @(posedge change_prot_bits) + begin + case (Status_reg1[4:2]) + 3'b000: + begin + if (Status_reg2[6] == 1'b0) + Sec_Prot[4095:0] = {4096{1'b0}}; + else + Sec_Prot[4095:0] = {4096{1'b1}}; + end + + 3'b001: + begin + if (Status_reg2[6] ==1'b0) + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[4095:4032] = {64{1'b1}}; + Sec_Prot[4031:0] = {4032{1'b0}}; + end + 2'b01: + begin + Sec_Prot[4095:64] = {4032{1'b0}}; + Sec_Prot[63:0] = {64{1'b1}}; + end + 2'b10: + begin + Sec_Prot[4095] = 1'b1; + Sec_Prot[4094:0] = {4095{1'b0}}; + end + 2'b11: + begin + Sec_Prot[4095:1] = {4095{1'b0}}; + Sec_Prot[0] = 1'b1; + end + endcase + end + else + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[4095:4032] = {64{1'b0}}; + Sec_Prot[4031:0] = {4032{1'b1}}; + end + 2'b01: + begin + Sec_Prot[4095:64] = {4032{1'b1}}; + Sec_Prot[63:0] = {64{1'b0}}; + end + 2'b10: + begin + Sec_Prot[4095] = 1'b0; + Sec_Prot[4094:0] = {4095{1'b1}}; + end + 2'b11: + begin + Sec_Prot[4095:1] = {4095{1'b1}}; + Sec_Prot[0] = 1'b0; + end + endcase + end + end + + 3'b010: + begin + if (Status_reg2[6] == 1'b0) + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[4095:3968] = {128{1'b1}} ; + Sec_Prot[3967:0] = {3968{1'b0}} ; + end + 2'b01: + begin + Sec_Prot[4095:128] = {3968{1'b0}} ; + Sec_Prot[127:0] = {128{1'b1}} ; + end + 2'b10: + begin + Sec_Prot[4095:4094] = 2'b11; + Sec_Prot[4093:0] = {4094{1'b0}}; + end + 2'b11: + begin + Sec_Prot[4095:2] = {4094{1'b0}}; + Sec_Prot[1:0] = 2'b11; + end + endcase + end + else + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[4095:3968] = {128{1'b0}} ; + Sec_Prot[3967:0] = {3968{1'b1}} ; + end + 2'b01: + begin + Sec_Prot[4095:128] = {3968{1'b1}} ; + Sec_Prot[127:0] = {128{1'b0}} ; + end + 2'b10: + begin + Sec_Prot[4095:4094] = 2'b00; + Sec_Prot[4093:0] = {4094{1'b1}}; + end + 2'b11: + begin + Sec_Prot[4095:2] = {4094{1'b1}}; + Sec_Prot[1:0] = 2'b00; + end + endcase + end + end + + 3'b011: + begin + if (Status_reg2[6] == 1'b0) + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[4095:3840] = {256{1'b1}} ; + Sec_Prot[3839:0] = {3840{1'b0}} ; + end + 2'b01: + begin + Sec_Prot[4095:256] = {3840{1'b0}} ; + Sec_Prot[255:0] = {256{1'b1}} ; + end + 2'b10: + begin + Sec_Prot[4095:4092] = 4'b1111; + Sec_Prot[4091:0] = {4092{1'b0}}; + end + 2'b11: + begin + Sec_Prot[4095:4] = {4092{1'b0}}; + Sec_Prot[3:0] = 4'b1111; + end + endcase + end + else + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[4095:3840] = {256{1'b0}} ; + Sec_Prot[3839:0] = {3840{1'b1}} ; + end + 2'b01: + begin + Sec_Prot[4095:256] = {3840{1'b1}} ; + Sec_Prot[255:0] = {256{1'b0}} ; + end + 2'b10: + begin + Sec_Prot[4095:4092] = 4'b0000; + Sec_Prot[4091:0] = {4092{1'b1}}; + end + 2'b11: + begin + Sec_Prot[4095:4] = {4092{1'b1}}; + Sec_Prot[3:0] = 4'b0000; + end + endcase + end + end + + 3'b100: + begin + if (Status_reg2[6] == 1'b0) + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[4095:3584] = {512{1'b1}} ; + Sec_Prot[3583:0] = {3584{1'b0}} ; + end + 2'b01: + begin + Sec_Prot[4095:512] = {3584{1'b0}} ; + Sec_Prot[511:0] = {512{1'b1}} ; + end + 2'b10: + begin + Sec_Prot[4095:4088] = 8'hFF; + Sec_Prot[4087:0] = {4088{1'b0}}; + end + 2'b11: + begin + Sec_Prot[4095:8] = {4088{1'b0}}; + Sec_Prot[7:0] = 8'hFF; + end + endcase + end + else + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[4095:3584] = {512{1'b0}} ; + Sec_Prot[3583:0] = {3584{1'b1}} ; + end + 2'b01: + begin + Sec_Prot[4095:512] = {3584{1'b1}} ; + Sec_Prot[511:0] = {512{1'b0}} ; + end + 2'b10: + begin + Sec_Prot[4095:4088] = 8'h00; + Sec_Prot[4087:0] = {4088{1'b1}}; + end + 2'b11: + begin + Sec_Prot[4095:8] = {4088{1'b1}}; + Sec_Prot[7:0] = 8'h00; + end + endcase + end + end + + 3'b101: + begin + if (Status_reg2[6] == 1'b0) + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[4095:3072] = {1024{1'b1}} ; + Sec_Prot[3071:0] = {3072{1'b0}} ; + end + 2'b01: + begin + Sec_Prot[4095:1024] = {3072{1'b0}} ; + Sec_Prot[1023:0] = {1024{1'b1}} ; + end + 2'b10: + begin + Sec_Prot[4095:4088] = 8'hFF; + Sec_Prot[4087:0] = {4088{1'b0}}; + end + 2'b11: + begin + Sec_Prot[4095:8] = {4088{1'b0}}; + Sec_Prot[7:0] = 8'hFF; + end + endcase + end + else + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[4095:3072] = {1024{1'b0}} ; + Sec_Prot[3071:0] = {3072{1'b1}} ; + end + 2'b01: + begin + Sec_Prot[4095:1024] = {3072{1'b1}} ; + Sec_Prot[1023:0] = {1024{1'b0}} ; + end + 2'b10: + begin + Sec_Prot[4095:4088] = 8'h00; + Sec_Prot[4087:0] = {4088{1'b1}}; + end + 2'b11: + begin + Sec_Prot[4095:8] = {4088{1'b1}}; + Sec_Prot[7:0] = 8'h00; + end + endcase + end + end + + 3'b110: + begin + if (Status_reg2[6] == 1'b0) + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[4095:2048] = {2048{1'b1}} ; + Sec_Prot[2047:0] = {2048{1'b0}} ; + end + 2'b01: + begin + Sec_Prot[4095:2048] = {2048{1'b0}} ; + Sec_Prot[2047:0] = {2048{1'b1}} ; + end + 2'b10, 2'b11: + begin + $display("This combination of bits "); + $display("is not deffined"); + end + endcase + end + else + begin + case (Status_reg1[6:5]) + 2'b00: + begin + Sec_Prot[4095:2048] = {2048{1'b0}} ; + Sec_Prot[2047:0] = {2048{1'b1}} ; + end + 2'b01: + begin + Sec_Prot[4095:2048] = {2048{1'b1}} ; + Sec_Prot[2047:0] = {2048{1'b0}} ; + end + 2'b10, 2'b11: + begin + $display("This combination of bits "); + $display("is not deffined"); + end + endcase + end + end + + 3'b111: + begin + if (Status_reg2[6]== 1'b0) + Sec_Prot[4095:0] = {4096{1'b1}}; + else + Sec_Prot[4095:0] = {4096{1'b0}}; + end + endcase + end // end of rising_edge_prot_bits + //////////////////////////////////////////////////////////////////////// + always @(SOut_zd or HOLDNeg_in or SIOut_zd) + begin + if (HOLDNeg_in == 0 && ~QE) + begin + hold_mode = 1'b1; + SIOut_z = 1'bZ; + SOut_z = 1'bZ; + end + else + begin + if (hold_mode == 1) + begin + SIOut_z <= #(tpd_HOLDNeg_SO) SIOut_zd; + SOut_z <= #(tpd_HOLDNeg_SO) SOut_zd; + hold_mode = #(tpd_HOLDNeg_SO) 1'b0; + end + else + begin + SIOut_z = SIOut_zd; + SOut_z = SOut_zd; + hold_mode = 1'b0; + end + end + end + + //////////////////////////////////////////////////////////////////////// + // functions & tasks + //////////////////////////////////////////////////////////////////////// + // Procedure ADDRHILO_SEC 4KB, 32KB, 64KB + task ADDRHILO_SEC64; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer sector; + begin + sector = Addr / 20'h10000; + AddrLOW = sector * 20'h10000; + AddrHIGH = sector * 20'h10000 + 20'h0FFFF; + end + endtask + + task ADDRHILO_SEC32; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer sector; + begin + sector = Addr / 16'h8000; + AddrLOW = sector * 16'h8000; + AddrHIGH = sector * 16'h8000 + 16'h7FFF; + end + endtask + + task ADDRHILO_SEC4; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer sector; + begin + sector = Addr / 16'h1000; + AddrLOW = sector * 16'h1000; + AddrHIGH = sector * 16'h1000 + 16'h0FFF; + end + endtask + + // Procedure ADDRHILO_PG + task ADDRHILO_PG; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer page; + begin + page = Addr / 16'h0100; + AddrLOW = page * 16'h0100; + AddrHIGH = page * 16'h0100 + 16'h00FF; + end + endtask + + // Procedure ADDRHILO_WRAP + task ADDRHILO_WRAP; + inout Addr_low_wrap; + inout Addr_hi_wrap; + input Address; + input w_size; + integer Addr_low_wrap; + integer Addr_hi_wrap; + integer Address; + integer w_size; + integer sect_wrap; + begin + sect_wrap = Address / w_size; + Addr_low_wrap = sect_wrap * w_size; + Addr_hi_wrap = sect_wrap * w_size + w_size - 1; + end + endtask + + /////////////////////////////////////////////////////////////////////////// + // edge controll processes + /////////////////////////////////////////////////////////////////////////// + always @(posedge PoweredUp) + begin + rising_edge_PoweredUp = 1; + #1000 rising_edge_PoweredUp = 0; + end + + always @(posedge SCK_ipd) + begin + rising_edge_SCK_ipd = 1'b1; + #1000 rising_edge_SCK_ipd = 1'b0; + end + + always @(negedge SCK_ipd) + begin + falling_edge_SCK_ipd = 1'b1; + #1000 falling_edge_SCK_ipd = 1'b0; + end + + always @(posedge read_out) + begin + rising_edge_read_out = 1'b1; + #1000 rising_edge_read_out = 1'b0; + end + + always @(negedge write) + begin + falling_edge_write = 1'b1; + #1000 falling_edge_write = 1'b0; + end + + always @(posedge CSNeg_ipd) + begin + rising_edge_CSNeg_ipd = 1'b1; + #1000 rising_edge_CSNeg_ipd = 1'b0; + end + + always @(negedge CSNeg_ipd) + begin + falling_edge_CSNeg_ipd = 1'b1; + #1000 falling_edge_CSNeg_ipd = 1'b0; + end + + always @(posedge PDONE) + begin + rising_edge_PDONE = 1'b1; + #1000 rising_edge_PDONE = 1'b0; + end + + always @(posedge WDONE) + begin + rising_edge_WDONE = 1'b1; + #1000 rising_edge_WDONE = 1'b0; + end + + always @(posedge VLTDONE) + begin + rising_edge_VLTDONE = 1'b1; + #1000 rising_edge_VLTDONE = 1'b0; + end + + always @(posedge WSTART) + begin + rising_edge_WSTART = 1'b1; + #1000 rising_edge_WSTART = 1'b0; + end + + always @(posedge VLTSTART) + begin + rising_edge_VLTSTART = 1'b1; + #1000 rising_edge_VLTSTART = 1'b0; + end + + always @(posedge EDONE) + begin + rising_edge_EDONE = 1'b1; + #1000 rising_edge_EDONE = 1'b0; + end + + always @(posedge ESTART) + begin + rising_edge_ESTART = 1'b1; + #1000 rising_edge_ESTART = 1'b0; + end + + always @(posedge PSTART) + begin + rising_edge_PSTART = 1'b1; + #1000 rising_edge_PSTART = 1'b0; + end + + always @(posedge DP_out) + begin + rising_edge_DP_out = 1'b1; + #1 rising_edge_DP_out = 1'b0; + end + + always @(posedge RES_out) + begin + rising_edge_RES_out = 1'b1; + #1000 rising_edge_RES_out = 1'b0; + end + + always @(Instruct) + begin + Instruct_event = 1'b1; + #1000 Instruct_event = 1'b0; + end + + always @(change_addr) + begin + change_addr_event = 1'b1; + #1000 change_addr_event = 1'b0; + end + + always @(next_state) + begin + next_state_event = 1'b1; + #1000 next_state_event = 1'b0; + end + + always @(current_state) + begin + current_state_event = 1'b1; + #1000 current_state_event = 1'b0; + end + + always @(posedge PRGSUSP_out) + begin + PRGSUSP_out_event = 1; + #1000 PRGSUSP_out_event = 0; + end + + always @(posedge PRGRES_out) + begin + PRGRES_out_event = 1; + #1000 PRGRES_out_event = 0; + end + + always @(posedge ESUSP) + begin + ESUSP_event = 1'b1; + #1000 ESUSP_event = 1'b0; + end + + always @(posedge ERSSUSP_out) + begin + ERSSUSP_out_event = 1; + #1000 ERSSUSP_out_event = 0; + end + + always @(posedge ERSRES_out) + begin + ERSRES_out_event = 1; + #1000 ERSRES_out_event = 0; + end + + always @(posedge PGSUSP) + begin + PGSUSP_event = 1'b1; + #1000 PGSUSP_event = 1'b0; + end + + always @(posedge PGRES) + begin + PGRES_event = 1'b1; + #1000 PGRES_event = 1'b0; + end + + always @(posedge ERES) + begin + ERES_event = 1'b1; + #1000 ERES_event = 1'b0; + end + + always @(posedge change_prot_bits) + begin + rising_edge_prot_bits = 1'b1; + #1000 rising_edge_prot_bits = 1'b0; + end + + reg update_time = 1'b0; + always @(posedge read_id) + begin + start_rdid = $time; + update_time = 1'b1; + end + + always @(SO_out) + begin + if (read_id && update_time) + out_time = $time; + SCK_SO_2 = out_time - start_rdid; + update_time = 1'b0; + end + + always @(DataDriveOut_SO,DataDriveOut_SI) + begin + if (SCK_SO_2 > SCK_cycle) + begin + glitch = 1; + SOut_zd <= #SCK_SO_2 DataDriveOut_SO; + SIOut_zd <= #SCK_SO_2 DataDriveOut_SI; + end + else + begin + glitch = 0; + SOut_zd <= DataDriveOut_SO; + SIOut_zd <= DataDriveOut_SI; + end + end + +endmodule \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl128k/model/s25fl128k.vhd b/lib/models/memory/flash/serial/S25fl128k/model/s25fl128k.vhd new file mode 100644 index 0000000..ad7fc72 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128k/model/s25fl128k.vhd @@ -0,0 +1,3787 @@ +------------------------------------------------------------------------------- +-- File Name: s25fl128k.vhd +------------------------------------------------------------------------------- +-- Copyright (C) 2010 Spansion, LLC. +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 R. Prokopovic 10 Oct 08 Inital Release +------------------------------------------------------------------------------- +-- PART DESCRIPTION: +-- +-- Library: FLASH +-- Technology: FLASH MEMORY +-- Part: S25FL128K +-- +-- Description: 128 Megabit Serial Flash Memory +-- +------------------------------------------------------------------------------- +-- Known Bugs: +-- +------------------------------------------------------------------------------- +LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; + USE STD.textio.ALL; + USE IEEE.VITAL_timing.ALL; + USE IEEE.VITAL_primitives.ALL; + +LIBRARY FMF; USE FMF.gen_utils.ALL; + USE FMF.conversions.ALL; +------------------------------------------------------------------------------- +-- ENTITY DECLARATION +------------------------------------------------------------------------------- +ENTITY s25fl128k IS + GENERIC ( + --------------------------------------------------------------------------- + -- TIMING GENERICS: + --------------------------------------------------------------------------- + -- tipd delays: interconnect path delays (delay between components) + -- There should be one for each IN or INOUT pin in the port list + -- They are given default values of zero delay. + tipd_SCK : VitalDelayType01 := VitalZeroDelay01; + tipd_SI : VitalDelayType01 := VitalZeroDelay01; + tipd_SO : VitalDelayType01 := VitalZeroDelay01; + + tipd_CSNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_HOLDNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; + + -- tpd delays: propagation delays (pin-to-pin delay within a component) + tpd_SCK_SO_RDID_EQ_0 : VitalDelayType01Z := UnitDelay01Z;--tCLQV1 + tpd_SCK_SO_RDID_EQ_1 : VitalDelayType01Z := UnitDelay01Z;--tCLQV2 + tpd_CSNeg_SO : VitalDelayType01Z := UnitDelay01Z;--tSHQZ + tpd_HOLDNeg_SO : VitalDelayType01Z := UnitDelay01Z;--tHLQZ + + -- tsetup values: setup times + tsetup_CSNeg_SCK : VitalDelayType := UnitDelay;--tSLCH,tSHCH + tsetup_SI_SCK_normal_noedge_posedge : VitalDelayType + := UnitDelay;--tDVCH + tsetup_HOLDNeg_SCK : VitalDelayType := UnitDelay;--tHLCH,tHHCH + tsetup_WPNeg_CSNeg : VitalDelayType := UnitDelay;--tWHSL + + -- thold values: hold times + thold_CSNeg_SCK : VitalDelayType := UnitDelay;--tSLCH,tSHCH + thold_SI_SCK_normal_noedge_posedge : VitalDelayType + := UnitDelay;--tCHDX + thold_HOLDNeg_SCK : VitalDelayType := UnitDelay;--tCHHL,tCHHH + thold_WPNeg_CSNeg : VitalDelayType := UnitDelay;--tSHWL + + --tpw values: pulse width + tpw_SCK_slow_posedge : VitalDelayType := UnitDelay; -- tCH + tpw_SCK_slow_negedge : VitalDelayType := UnitDelay; -- tCL + tpw_SCK_fast_posedge : VitalDelayType := UnitDelay; -- tCH + tpw_SCK_fast_negedge : VitalDelayType := UnitDelay; -- tCL + tpw_SCK_quad_posedge : VitalDelayType := UnitDelay; -- tCH + tpw_SCK_quad_negedge : VitalDelayType := UnitDelay; -- tCL + tpw_CSNeg_read_posedge : VitalDelayType := UnitDelay; -- tSHSL1 + tpw_CSNeg_pger_posedge : VitalDelayType := UnitDelay; -- tSHSL2 + + -- tperiod min (calculated as 1/max freq) + tperiod_SCK_slow : VitalDelayType := UnitDelay;-- + tperiod_SCK_fast : VitalDelayType := UnitDelay;-- + tperiod_SCK_quad : VitalDelayType := UnitDelay;-- + + -- tdevice values: values for internal delays + -- VCC (min) to CS# Low + tdevice_PU : VitalDelayType := 10 us; + -- CS# High to Power Down Mode -- tDP + tdevice_DP : VitalDelayType := 3 us; + -- CS# High to StandBy mode without Electronic Signature read + tdevice_RES1 : VitalDelayType := 3 us; + -- CS# High to StandBy mode with Electronic Signature read + tdevice_RES2 : VitalDelayType := 1.8 us; + -- CS# High to next Instruction after Suspend + tdevice_PRGSUSP : VitalDelayType := 20 us; + -- CS# High to next Instruction after Suspend + tdevice_ERSSUSP : VitalDelayType := 20 us; + -- CS# High to next Instruction after Suspend + tdevice_SUSP_DLY : VitalDelayType := 20 us; + -- Resume Suspend to Program/Erase time + tdevice_PRGRES : VitalDelayType := 200 ns; + -- Resume Suspend to Program/Erase time + tdevice_ERSRES : VitalDelayType := 200 ns; + -- Page Program Time + tdevice_PP : VitalDelayType := 3 ms; + -- Byte Program Time (First Byte) + tdevice_BP1 : VitalDelayType := 50 us; + -- Additional Byte Program Time (After First Byte) + tdevice_BP2 : VitalDelayType := 12 us; + -- Sector Erase Time (4KB) + tdevice_SE : VitalDelayType := 400 ms; + -- Block Erase Time (32KB) + tdevice_BE1 : VitalDelayType := 800 ms; + -- Block Erase Time (64KB) + tdevice_BE2 : VitalDelayType := 1000 ms; + -- Chip Erase Time + tdevice_CE : VitalDelayType := 40 sec; + -- Write Status Register Time + tdevice_WRR : VitalDelayType := 15 ms; + -- Write Volatile Status Register Time + tdevice_VRR : VitalDelayType := 50 ns; + + --------------------------------------------------------------------------- + -- CONTROL GENERICS: + --------------------------------------------------------------------------- + + -- generic control parameters + InstancePath : STRING := DefaultInstancePath; + TimingChecksOn : BOOLEAN := DefaultTimingChecks; + MsgOn : BOOLEAN := DefaultMsgOn; + XOn : BOOLEAN := DefaultXon; + + -- memory file to be loaded + mem_file_name : STRING := "s25fl128k.mem"; + screg_file_name : STRING := "s25fl128kscreg.mem"; + + UserPreload : BOOLEAN := FALSE; --TRUE; + LongTimming : BOOLEAN := TRUE; + + -- For FMF SDF technology file usage + TimingModel : STRING := DefaultTimingModel + ); + PORT ( + -- Data Inputs/Outputs + SI : INOUT std_ulogic := 'U'; -- serial data input/IO0 + SO : INOUT std_ulogic := 'U'; -- serial data output/IO1 + -- Controls + SCK : IN std_ulogic := 'U'; -- serial clock input + CSNeg : IN std_ulogic := 'U'; -- chip select input + WPNeg : INOUT std_ulogic := 'U'; -- write protect input/IO2 + HOLDNeg : INOUT std_ulogic := 'U' -- hold input/IO3 + ); + + ATTRIBUTE VITAL_LEVEL0 of s25fl128k : ENTITY IS TRUE; +END s25fl128k; + +------------------------------------------------------------------------------- +-- ARCHITECTURE DECLARATION +------------------------------------------------------------------------------- +ARCHITECTURE vhdl_behavioral of s25fl128k IS + ATTRIBUTE VITAL_LEVEL0 OF vhdl_behavioral : ARCHITECTURE IS TRUE; + + --------------------------------------------------------------------------- + -- CONSTANT AND SIGNAL DECLARATION + --------------------------------------------------------------------------- + --Declaration of constants - memory characteristics + -- The constant declared here are used to enable the creation of models + -- of memories within a family with a minimum amount of editing + + CONSTANT PartID : STRING := "s25fl128k"; + CONSTANT MaxData : NATURAL := 16#FF#; + CONSTANT AddrRANGE : NATURAL := 16#FFFFFF#; + CONSTANT PageNum : NATURAL := 16#FFFF#; + CONSTANT SecSize_4 : NATURAL := 16#FFF#; + CONSTANT SecSize_32 : NATURAL := 16#7FFF#; + CONSTANT SecSize_64 : NATURAL := 16#FFFF#; + CONSTANT Blk_4_Num : NATURAL := 4095; + CONSTANT Blk_64_Num : NATURAL := 255; + CONSTANT Blk_32_Num : NATURAL := 511; + CONSTANT SFDP_HiAddr : NATURAL := 16#FF#; + CONSTANT SFDP_LoAddr : NATURAL := 16#00#; + CONSTANT SecReg_HiAddr : NATURAL := 16#FF#; + CONSTANT SecReg_LoAddr : NATURAL := 16#00#; + CONSTANT SCREG_LoAddr : NATURAL := 16#000#; + CONSTANT SCREG_HiAddr : NATURAL := 16#2FF#; + CONSTANT BYTE : NATURAL := 8; + + -- Manufacturer Identification and Device Identification + CONSTANT Manuf_ID : NATURAL := 16#EF#; + CONSTANT Device_ID1 : NATURAL := 16#17#; + CONSTANT Device_ID2 : NATURAL := 16#40#; + CONSTANT Device_ID3 : NATURAL := 16#18#; + CONSTANT Unique_id_1 : NATURAL := 16#ABAB#;--this is 64bit ID number + CONSTANT Unique_id_2 : NATURAL := 16#00#;--this is 64bit ID number + + -- Declaration of signals that will hold the delayed values of ports + SIGNAL SI_ipd : std_ulogic := 'U'; + SIGNAL SO_ipd : std_ulogic := 'U'; + SIGNAL SCK_ipd : std_ulogic := 'U'; + SIGNAL CSNeg_ipd : std_ulogic := 'U'; + SIGNAL WPNeg_ipd : std_ulogic := 'U'; + SIGNAL HOLDNeg_ipd : std_ulogic := 'U'; + SIGNAL HOLDNeg_pullup : std_ulogic := 'U'; + SIGNAL WPNeg_pullup : std_ulogic := 'U'; + + -- internal delays + SIGNAL PP_in : std_ulogic := '0'; + SIGNAL PP_out : std_ulogic := '0'; + SIGNAL BP1_in : std_ulogic := '0'; + SIGNAL BP1_out : std_ulogic := '0'; + SIGNAL BP2_in : std_ulogic := '0'; + SIGNAL BP2_out : std_ulogic := '0'; + SIGNAL SE_in : std_ulogic := '0'; + SIGNAL SE_out : std_ulogic := '0'; + SIGNAL BE1_in : std_ulogic := '0'; + SIGNAL BE1_out : std_ulogic := '0'; + SIGNAL BE2_in : std_ulogic := '0'; + SIGNAL BE2_out : std_ulogic := '0'; + SIGNAL CE_in : std_ulogic := '0'; + SIGNAL CE_out : std_ulogic := '0'; + SIGNAL WRR_in : std_ulogic := '0'; + SIGNAL WRR_out : std_ulogic := '0'; + SIGNAL ERSSUSP_in : std_ulogic := '0'; + SIGNAL ERSSUSP_out : std_ulogic := '0'; + SIGNAL ERSRES_in : std_ulogic := '0'; + SIGNAL ERSRES_out : std_ulogic := '0'; + SIGNAL PRGSUSP_in : std_ulogic := '0'; + SIGNAL PRGSUSP_out : std_ulogic := '0'; + SIGNAL PRGRES_in : std_ulogic := '0'; + SIGNAL PRGRES_out : std_ulogic := '0'; + SIGNAL PU_in : std_ulogic := '0'; + SIGNAL PU_out : std_ulogic := '0'; + SIGNAL RES1_in : std_ulogic := '0'; + SIGNAL RES1_out : std_ulogic := '0'; + SIGNAL RES2_in : std_ulogic := '0'; + SIGNAL RES2_out : std_ulogic := '0'; + SIGNAL DP_in : std_ulogic := '0'; + SIGNAL DP_out : std_ulogic := '0'; + SIGNAL SUSP_FL_IN : std_ulogic := '0'; + SIGNAL SUSP_FL_OUT : std_ulogic := '0'; + +BEGIN + + --------------------------------------------------------------------------- + -- Internal Delays + --------------------------------------------------------------------------- + -- Artificial VITAL primitives to incorporate internal delays + -- Because a tdevice generics is used, there must be a VITAL_primitives + -- assotiated with them + PP :VitalBuf(PP_out, PP_in, (tdevice_PP ,UnitDelay)); + BP1 :VitalBuf(BP1_out, BP1_in, (tdevice_BP1 ,UnitDelay)); + BP2 :VitalBuf(BP2_out, BP2_in, (tdevice_BP2 ,UnitDelay)); + SE :VitalBuf(SE_out, SE_in, (tdevice_SE ,UnitDelay)); + BE1 :VitalBuf(BE1_out, BE1_in, (tdevice_BE1 ,UnitDelay)); + BE2 :VitalBuf(BE2_out, BE2_in, (tdevice_BE2 ,UnitDelay)); + WRR :VitalBuf(WRR_out, WRR_in, (tdevice_WRR ,UnitDelay)); + ERSSUSP :VitalBuf(ERSSUSP_out, ERSSUSP_in, (tdevice_ERSSUSP ,UnitDelay)); + ERSRES :VitalBuf(ERSRES_out, ERSRES_in, (tdevice_ERSRES ,UnitDelay)); + PRGSUSP :VitalBuf(PRGSUSP_out, PRGSUSP_in, (tdevice_PRGSUSP ,UnitDelay)); + PRGRES :VitalBuf(PRGRES_out, PRGRES_in, (tdevice_PRGRES ,UnitDelay)); + PU :VitalBuf(PU_out, PU_in, (tdevice_PU ,UnitDelay)); + RES1 :VitalBuf(RES1_out, RES1_in, (tdevice_RES1 ,UnitDelay)); + CE :VitalBuf(CE_out, CE_in, (tdevice_CE ,UnitDelay)); + DP :VitalBuf(DP_out, DP_in, (tdevice_DP ,UnitDelay)); + RES2 :VitalBuf(RES2_out, RES2_in, (tdevice_RES2 ,UnitDelay)); + SUSP_DLY :VitalBuf(SUSP_FL_OUT, SUSP_FL_IN, (tdevice_SUSP_DLY,UnitDelay)); + + --------------------------------------------------------------------------- + -- Wire Delays + --------------------------------------------------------------------------- + WireDelay : BLOCK + BEGIN + + w_1 : VitalWireDelay (SI_ipd, SI, tipd_SI); + w_2 : VitalWireDelay (SO_ipd, SO, tipd_SO); + w_3 : VitalWireDelay (SCK_ipd, SCK, tipd_SCK); + w_4 : VitalWireDelay (CSNeg_ipd, CSNeg, tipd_CSNeg); + w_6 : VitalWireDelay (WPNeg_ipd, WPNeg, tipd_WPNeg); + w_7 : VitalWireDelay (HOLDNeg_ipd, HOLDNeg, tipd_HOLDNeg); + + END BLOCK; + + --------------------------------------------------------------------------- + -- Main Behavior Block + --------------------------------------------------------------------------- + Behavior: BLOCK + + PORT ( + SIIn : IN std_ulogic := 'U'; + SIOut : OUT std_ulogic := 'U'; + SOIn : IN std_logic := 'U'; + SOut : OUT std_logic := 'U'; + SCK : IN std_ulogic := 'U'; + CSNeg : IN std_ulogic := 'U'; + HOLDNegIn : IN std_ulogic := 'U'; + HOLDNegOut : OUT std_ulogic := 'U'; + WPNegIn : IN std_ulogic := 'U'; + WPNegOut : OUT std_ulogic := 'U' + ); + + PORT MAP ( + SIIn => SI_ipd, + SIOut => SI, + SOIn => SO_ipd, + SOut => SO, + SCK => SCK_ipd, + CSNeg => CSNeg_ipd, + HOLDNegIn => HOLDNeg_ipd, + HOLDNegOut => HOLDNeg, + WPNegIn => WPNeg_ipd, + WPNegOut => WPNeg + ); + + -- State Machine : State_Type + TYPE state_type IS (IDLE, + WRITE_SR, + PAGE_PG, + PG_SUSP, + SECTOR_ERS, + BULK_ERS, + ERS_SUSP, + ERS_SUSP_PG, + PG_SUSP_ERS, + DP_DOWN, + WRITE_SR_V + ); + + -- Instruction Type + TYPE instruction_type IS ( NONE, + WREN , -- 06h + WRENV , -- 50h + WRDI , -- 04h + RDSR , -- 05h + RDSR2 , -- 35h + WRR , -- 01h + READ , -- 03h + FAST_READ , -- 0Bh + FAST_DREAD , -- 3Bh + FAST_QREAD , -- 6Bh + FAST_DREAD_2 , -- BBh + FAST_QREAD_4 , -- EBh + W_QREAD , -- E7h + WOCT_QREAD , -- E3h + SET_BURST_WRAP , -- 77h + CONT_RD_RST , -- FFh or FFFFH + PP , -- 02h + QPP , -- 32h + SE , -- 20h + BE_32 , -- 52h + BE_64 , -- D8h + CE , -- C7h or 60h + ERS_PG_SUSP , -- 75h + ERS_PG_RES , -- 7Ah + DP , -- B9h + RES_RD_ID , -- ABh + RDID , -- 90h + RDID_DUAL , -- 92h + RDID_QUAD , -- 94h + RD_UNIQ_ID , -- 4Bh + RDIDJ , -- 9Fh + RD_SFDP , -- 5Ah + ERS_SCREG , -- 44h + PG_SCREG , -- 42h + RD_SCREG -- 48h + ); + + TYPE WByteType IS ARRAY (0 TO 255) OF INTEGER RANGE -1 TO MaxData; + -- Flash Memory Array + TYPE MemArray IS ARRAY (0 TO AddrRANGE) OF INTEGER RANGE -1 TO MaxData; + -- SFDP Memory Array + TYPE SFDPArray IS ARRAY (SFDP_LoAddr TO SFDP_HiAddr) OF INTEGER + RANGE -1 TO MaxData; + -- Security Register Array + TYPE SCREGArray IS ARRAY (SecReg_LoAddr TO SecReg_HiAddr) OF INTEGER + RANGE -1 TO MaxData; + ----------------------------------------------------------------------- + -- memory declaration + ----------------------------------------------------------------------- + -- Memory + SHARED VARIABLE Mem : MemArray := (OTHERS => MaxData); + -- Security Register 1 + SHARED VARIABLE Security_Reg1 : SCREGArray := (OTHERS => MaxData); + -- Security Register 2 + SHARED VARIABLE Security_Reg2 : SCREGArray := (OTHERS => MaxData); + -- Security Register 3 + SHARED VARIABLE Security_Reg3 : SCREGArray := (OTHERS => MaxData); + --SFDP Array + SHARED VARIABLE SFDP_array : SFDPArray := (OTHERS => 0); + -- Programming Buffer + SIGNAL WByte : WByteType := (OTHERS => MaxData); + + -- states + SIGNAL current_state : state_type; + SIGNAL next_state : state_type; + + SIGNAL Instruct : instruction_type; + + --zero delay signal + SIGNAL SOut_zd : std_logic := 'Z'; + SIGNAL SIOut_zd : std_logic := 'Z'; + SIGNAL HOLDNegOut_zd : std_logic := 'Z'; + SIGNAL WPNegOut_zd : std_logic := 'Z'; + --HOLD delay on output data + SIGNAL SOut_z : std_logic := 'Z'; + SIGNAL SIOut_z : std_logic := 'Z'; + -- powerup + SIGNAL PoweredUp : std_logic := '0'; + + ----------------------------------------------------------------------- + -- Registers + ----------------------------------------------------------------------- + -- Status register 1 + SHARED VARIABLE Status_reg1 : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Status_reg1_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Status Register Protect Bit 0 + ALIAS SRP0 :std_logic IS Status_reg1(7); + -- Sector/Block protect bit + ALIAS SEC :std_logic IS Status_reg1(6); + -- Top Bottom Bit + ALIAS TB :std_logic IS Status_reg1(5); + -- Status Register Block Protection Bits + ALIAS BP2 :std_logic IS Status_reg1(4); + ALIAS BP1 :std_logic IS Status_reg1(3); + ALIAS BP0 :std_logic IS Status_reg1(2); + -- Status Register Write Enable Latch Bit + ALIAS WEL :std_logic IS Status_reg1(1); + -- Status Register Busy Bit + ALIAS BUSY :std_logic IS Status_reg1(0); + + -- Status register 2 + SHARED VARIABLE Status_reg2 : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Status_reg2_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Suspend status bit + ALIAS SUS :std_logic IS Status_reg2(7); + -- Complement protect bit + ALIAS CMP :std_logic IS Status_reg2(6); + -- Security Register Lock bits + ALIAS LB3 :std_logic IS Status_reg2(5); + ALIAS LB2 :std_logic IS Status_reg2(4); + ALIAS LB1 :std_logic IS Status_reg2(3); + -- Quad enable bit + ALIAS QE :std_logic IS Status_reg2(1); + -- Status register protect bit + ALIAS SRP1 :std_logic IS Status_reg2(0); + + -- Sector is protect if Sec_Prot(Blk_4_Num) = '1' + SHARED VARIABLE Sec_Prot : std_logic_vector(Blk_4_Num downto 0) := + (OTHERS => '0'); + + --Command Register + SIGNAL write : std_logic := '0'; + SIGNAL read_out : std_logic := '0'; + + SIGNAL pg_screg_flag : boolean := false; + SIGNAL ers_screg_flag : boolean := false; + SIGNAL slow_read : boolean := false; + SIGNAL dual_read : boolean := false; + SIGNAL fast_rd : boolean := true; + SIGNAL quad_read : boolean := false; + SIGNAL read_id : boolean := false; + SIGNAL sr_read : boolean := false; + + SHARED VARIABLE pp_quad : boolean := false; + SHARED VARIABLE hold_mode : boolean := false; + SHARED VARIABLE res_flag : boolean := false; + SHARED VARIABLE wren_vlt_flag : boolean := false; + + --FSM control signals + SIGNAL PDONE : std_logic := '1'; + SIGNAL PSTART : std_logic := '0'; + SIGNAL PGSUSP : std_logic := '0'; + SIGNAL PGRES : std_logic := '0'; + + SIGNAL WDONE : std_logic := '1'; + SIGNAL WSTART : std_logic := '0'; + SIGNAL VLTSTART : std_logic := '0'; + SIGNAL VLTDONE : std_logic := '1'; + + SIGNAL EDONE : std_logic := '1'; + SIGNAL ESTART : std_logic := '0'; + SIGNAL ESUSP : std_logic := '0'; + SIGNAL ERES : std_logic := '0'; + + SHARED VARIABLE read_cnt : NATURAL := 0; + SHARED VARIABLE read_addr : NATURAL RANGE 0 TO AddrRANGE ; + SHARED VARIABLE wrap_byte : std_logic_vector(7 downto 0); + SIGNAL change_addr : std_logic := '0'; + SIGNAL Address : NATURAL RANGE 0 TO AddrRANGE := 0; + + SIGNAL change_prot_bits : std_logic := '0'; + SHARED VARIABLE BP_bits : std_logic_vector(2 downto 0) := "000"; + SHARED VARIABLE LB_bits : std_logic_vector(2 downto 0) := "000"; + + SIGNAL Byte_number : NATURAL RANGE 0 TO 255 := 0; + + -- Sector and subsector addresses + SIGNAL SA : NATURAL RANGE 0 TO Blk_4_Num := 0; + SHARED VARIABLE sect : NATURAL RANGE 0 TO Blk_4_Num; + SHARED VARIABLE sect_tmp_pg : NATURAL RANGE 0 TO Blk_4_Num; + SHARED VARIABLE sect_tmp_ers: NATURAL RANGE 0 TO Blk_4_Num; + + SHARED VARIABLE w_size : NATURAL RANGE 0 TO 64; + + -- timing check violation + SIGNAL Viol : X01 := '0'; + + PROCEDURE ADDRHILO_SEC64 ( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to AddrRANGE; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to AddrRANGE; + VARIABLE Addr : NATURAL) IS + VARIABLE sector : NATURAL RANGE 0 TO Blk_64_Num; + BEGIN + sector := Addr/16#10000#; + AddrLOW := sector*16#10000#; + AddrHIGH := sector*16#10000# + 16#0FFFF#; + END ADDRHILO_SEC64; + + PROCEDURE ADDRHILO_SEC32 ( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to AddrRANGE; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to AddrRANGE; + VARIABLE Addr : NATURAL) IS + VARIABLE sector : NATURAL RANGE 0 TO Blk_32_Num; + BEGIN + sector := Addr/16#8000#; + AddrLOW := sector*16#8000#; + AddrHIGH := sector*16#8000# + 16#7FFF#; + END ADDRHILO_SEC32; + + PROCEDURE ADDRHILO_SEC4 ( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to AddrRANGE; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to AddrRANGE; + VARIABLE Addr : NATURAL) IS + VARIABLE sector : NATURAL RANGE 0 TO Blk_4_Num; + BEGIN + sector := Addr/16#1000#; + AddrLOW := sector*16#1000#; + AddrHIGH := sector*16#1000# + 16#0FFF#; + END ADDRHILO_SEC4; + + PROCEDURE ADDRHILO_PG( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to AddrRANGE; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to AddrRANGE; + VARIABLE Addr : NATURAL) IS + VARIABLE page : NATURAL RANGE 0 TO PageNum; + BEGIN + page := Addr/16#100#; + AddrLOW := Page*16#100#; + AddrHIGH := Page*16#100# + 16#FF#; + END AddrHILO_PG; + + PROCEDURE ADDRHILO_WRAP( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE Address : NATURAL; + VARIABLE Wrap_size: NATURAL) IS + VARIABLE Addr_tmp : NATURAL; + VARIABLE Sect_wrap: NATURAL; + BEGIN + Addr_tmp := Address; + Sect_wrap := Addr_tmp/Wrap_size; + + AddrLOW := Sect_wrap*Wrap_size; + AddrHIGH := Sect_wrap*Wrap_size + (Wrap_size - 1); + END ADDRHILO_WRAP; + + BEGIN + --------------------------------------------------------------------------- + --Power Up time + --------------------------------------------------------------------------- + PoweredUp <= '1' AFTER tdevice_PU; + + --------------------------------------------------------------------------- + -- VITAL Timing Checks Procedures + --------------------------------------------------------------------------- + VITALTimingCheck: PROCESS(SIIn,SOIn,SCK_ipd,CSNeg_ipd,HOLDNegIn,WPNegIn) + + -- Timing Check Variables + -- Setup/Hold Checks variables + VARIABLE Tviol_CSNeg_SCK : X01 := '0'; + VARIABLE TD_CSNeg_SCK : VitalTimingDataType; + + VARIABLE Tviol_SI_SCK : X01 := '0'; + VARIABLE TD_SI_SCK : VitalTimingDataType; + + VARIABLE Tviol_SOIn_SCK : X01 := '0'; + VARIABLE TD_SOIn_SCK : VitalTimingDataType; + + VARIABLE Tviol_HOLDNeg_SCK : X01 := '0'; + VARIABLE TD_HOLDNeg_SCK : VitalTimingDataType; + + VARIABLE Tviol_HOLDNegIn_SCK : X01 := '0'; + VARIABLE TD_HOLDNegIn_SCK : VitalTimingDataType; + + VARIABLE Tviol_WPNegIn_SCK : X01 := '0'; + VARIABLE TD_WPNegIn_SCK : VitalTimingDataType; + + VARIABLE Tviol_WPNeg_CSNeg_setup : X01 := '0'; + VARIABLE TD_WPNeg_CSNeg_setup : VitalTimingDataType; + + VARIABLE Tviol_WPNeg_CSNeg_hold : X01 := '0'; + VARIABLE TD_WPNeg_CSNeg_hold : VitalTimingDataType; + + --Pulse Width and Period Check Variables + VARIABLE Pviol_SCK_slow : X01 := '0'; + VARIABLE PD_SCK_slow : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_fast : X01 := '0'; + VARIABLE PD_SCK_fast : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_quad : X01 := '0'; + VARIABLE PD_SCK_quad : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_CSNeg_read : X01 := '0'; + VARIABLE PD_CSNeg_read : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_CSNeg_pgers : X01 := '0'; + VARIABLE PD_CSNeg_pgers : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_slow_p : X01 := '0'; + VARIABLE PD_SCK_slow_p : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_fast_p : X01 := '0'; + VARIABLE PD_SCK_fast_p : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_quad_p : X01 := '0'; + VARIABLE PD_SCK_quad_p : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Violation : X01 := '0'; + + BEGIN + --------------------------------------------------------------------------- + -- Timing Check Section + --------------------------------------------------------------------------- + IF (TimingChecksOn) THEN + + -- Setup/Hold Check between CS# and SCK + VitalSetupHoldCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_CSNeg_SCK, + SetupLow => tsetup_CSNeg_SCK, + HoldHigh => thold_CSNeg_SCK, + HoldLow => thold_CSNeg_SCK, + CheckEnabled => true, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_CSNeg_SCK, + Violation => Tviol_CSNeg_SCK + ); + -- Setup/Hold Check between SI and SCK / + VitalSetupHoldCheck ( + TestSignal => SIIn, + TestSignalName => "SI", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_normal_noedge_posedge, + SetupLow => tsetup_SI_SCK_normal_noedge_posedge, + HoldHigh => thold_SI_SCK_normal_noedge_posedge, + HoldLow => thold_SI_SCK_normal_noedge_posedge, + CheckEnabled => SIOut_z /= SIIn AND (NOT dual_read) + AND (NOT quad_read), + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_SI_SCK, + Violation => Tviol_SI_SCK + ); + + VitalSetupHoldCheck ( + TestSignal => SOIn, + TestSignalName => "SO", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_normal_noedge_posedge, + SetupLow => tsetup_SI_SCK_normal_noedge_posedge, + HoldHigh => thold_SI_SCK_normal_noedge_posedge, + HoldLow => thold_SI_SCK_normal_noedge_posedge, + CheckEnabled => SOut_z /= SOIn AND QE = '1' + AND (read_out = '0'), + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_SOIn_SCK, + Violation => Tviol_SOIn_SCK + ); + + VitalSetupHoldCheck ( + TestSignal => HOLDNegIn, + TestSignalName => "HOLD#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_normal_noedge_posedge, + SetupLow => tsetup_SI_SCK_normal_noedge_posedge, + HoldHigh => thold_SI_SCK_normal_noedge_posedge, + HoldLow => thold_SI_SCK_normal_noedge_posedge, + CheckEnabled => HOLDNegOut_zd /= HOLDNegIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_HOLDNegIn_SCK, + Violation => Tviol_HOLDNegIn_SCK + ); + + VitalSetupHoldCheck ( + TestSignal => WPNegIn, + TestSignalName => "WP#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_normal_noedge_posedge, + SetupLow => tsetup_SI_SCK_normal_noedge_posedge, + HoldHigh => thold_SI_SCK_normal_noedge_posedge, + HoldLow => thold_SI_SCK_normal_noedge_posedge, + CheckEnabled => WPNegOut_zd /= WPNegIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WPNegIn_SCK, + Violation => Tviol_WPNegIn_SCK + ); + + -- Setup/Hold Check between HOLD# and SCK / + VitalSetupHoldCheck ( + TestSignal => HOLDNegIn, + TestSignalName => "HOLD#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_HOLDNeg_SCK, + SetupLow => tsetup_HOLDNeg_SCK, + HoldHigh => thold_HOLDNeg_SCK, + HoldLow => thold_HOLDNeg_SCK, + CheckEnabled => QE = '0' AND HOLDNegIn /= 'X', + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_HOLDNeg_SCK, + Violation => Tviol_HOLDNeg_SCK + ); + + -- Setup Check between WP# and CS# \ + VitalSetupHoldCheck ( + TestSignal => WPNegIn, + TestSignalName => "WP#", + RefSignal => CSNeg_ipd, + RefSignalName => "CS#", + SetupHigh => tsetup_WPNeg_CSNeg, + CheckEnabled => QE = '0', + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WPNeg_CSNeg_setup, + Violation => Tviol_WPNeg_CSNeg_setup + ); + + -- Hold Check between WP# and CS# / + VitalSetupHoldCheck ( + TestSignal => WPNegIn, + TestSignalName => "WP#", + RefSignal => CSNeg_ipd, + RefSignalName => "CS#", + HoldHigh => thold_WPNeg_CSNeg, + CheckEnabled => QE = '0', + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WPNeg_CSNeg_hold, + Violation => Tviol_WPNeg_CSNeg_hold + ); + + --Pulse Width and Period Check Variables + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_slow_negedge, + PulseWidthHigh => tpw_SCK_slow_posedge, + PeriodData => PD_SCK_slow, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_slow, + HeaderMsg => InstancePath & PartID, + CheckEnabled => slow_read + ); + + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_fast_negedge, + PulseWidthHigh => tpw_SCK_fast_posedge, + PeriodData => PD_SCK_fast, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_fast, + HeaderMsg => InstancePath & PartID, + CheckEnabled => fast_rd + ); + + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_quad_negedge, + PulseWidthHigh => tpw_SCK_quad_posedge, + PeriodData => PD_SCK_quad, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_quad, + HeaderMsg => InstancePath & PartID, + CheckEnabled => quad_read OR pp_quad + ); + + -- Pulse Width Check CS# for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + PulseWidthHigh => tpw_CSNeg_read_posedge, + PeriodData => PD_CSNeg_read, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_CSNeg_read, + HeaderMsg => InstancePath & PartID, + CheckEnabled => slow_read OR fast_rd OR dual_read OR + quad_read + ); + + -- Pulse Width Check CS# for Program/Erase, serial mode + VitalPeriodPulseCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + PulseWidthHigh => tpw_CSNeg_pger_posedge, + PeriodData => PD_CSNeg_pgers, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_CSNeg_pgers, + HeaderMsg => InstancePath & PartID, + CheckEnabled => true); + + -- Period Check SCK for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_slow, + PeriodData => PD_SCK_slow_p, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_slow_p, + HeaderMsg => InstancePath & PartID, + CheckEnabled => slow_read + ); + + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_fast, + PeriodData => PD_SCK_fast_p, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_fast_p, + HeaderMsg => InstancePath & PartID, + CheckEnabled => fast_rd OR dual_read + ); + + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_quad, + PeriodData => PD_SCK_quad_p, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_quad_p, + HeaderMsg => InstancePath & PartID, + CheckEnabled => pp_quad OR quad_read + ); + + Violation := Tviol_CSNeg_SCK OR + Tviol_SI_SCK OR + Tviol_HOLDNeg_SCK OR + Tviol_WPNeg_CSNeg_setup OR + Tviol_WPNeg_CSNeg_hold OR + Tviol_HOLDNegIn_SCK OR + Tviol_WPNegIn_SCK OR + Tviol_SOIn_SCK OR + Pviol_SCK_slow OR + Pviol_SCK_fast OR + Pviol_CSNeg_read OR + Pviol_CSNeg_pgers OR + Pviol_SCK_slow_p OR + Pviol_SCK_fast_p OR + Pviol_SCK_quad_p OR + Pviol_SCK_quad; + + Viol <= Violation; + + ASSERT Violation = '0' + REPORT InstancePath & partID & ": simulation may be" & + " inaccurate due to timing violations" + SEVERITY WARNING; + + END IF; + END PROCESS VITALTimingCheck; + + --------------------------------------------------------------------------- + -- sequential process for FSM state transition + --------------------------------------------------------------------------- + StateTransition : PROCESS(next_state,PoweredUp) + + BEGIN + IF PoweredUp = '1' THEN + IF next_state'EVENT THEN + current_state <= next_state; + END IF; + END IF; + END PROCESS StateTransition; + + --------------------------------------------------------------------------- + -- Write cycle decode + --------------------------------------------------------------------------- + BusCycleDecode : PROCESS(SCK_ipd, CSNeg_ipd) + + TYPE bus_cycle_type IS (STAND_BY, + OPCODE_BYTE, + ADDRESS_BYTES, + DUMMY_BYTES, + MODE_BYTE, + DATA_BYTES + ); + + TYPE quad_data_type IS ARRAY (0 TO 511) OF INTEGER RANGE 0 TO 15; + + VARIABLE bus_cycle_state : bus_cycle_type; + + VARIABLE opcode_cnt : NATURAL := 0; + VARIABLE addr_cnt : NATURAL := 0; + VARIABLE mode_cnt : NATURAL := 0; + VARIABLE wrap_cnt : NATURAL := 0; + VARIABLE dummy_cnt : NATURAL := 0; + VARIABLE data_cnt : NATURAL := 0; + VARIABLE bit_cnt : NATURAL := 0; + + VARIABLE Data_in : std_logic_vector(2047 downto 0) + := (others => '0'); + VARIABLE opcode : std_logic_vector(7 downto 0); + VARIABLE opcode_in : std_logic_vector(7 downto 0); + VARIABLE opcode_double : std_logic_vector(15 downto 0); + VARIABLE opcode_double_in : std_logic_vector(15 downto 0); + VARIABLE addr_bytes : std_logic_vector(23 downto 0); + VARIABLE Address_in : std_logic_vector(23 downto 0); + VARIABLE mode_bits : std_logic_vector(7 downto 0); + VARIABLE mode_in : std_logic_vector(7 downto 0); +-- VARIABLE wrap_byte : std_logic_vector(7 downto 0); + VARIABLE wrap_in : std_logic_vector(7 downto 0); + VARIABLE quad_data_in : quad_data_type; + VARIABLE quad_nybble : std_logic_vector(3 downto 0); + VARIABLE Quad_slv : std_logic_vector(3 downto 0); + VARIABLE Byte_slv : std_logic_vector(7 downto 0); + + BEGIN + + IF falling_edge(CSNeg_ipd) THEN + IF (bus_cycle_state = STAND_BY) THEN + bus_cycle_state := OPCODE_BYTE; + Instruct <= NONE; + write <= '1'; + opcode_cnt := 0; + addr_cnt := 0; + data_cnt := 0; + mode_cnt := 0; + wrap_cnt := 0; + dummy_cnt := 0; + ELSIF (bus_cycle_state = DATA_BYTES AND + mode_bits(5 DOWNTO 4) = "10") THEN + bus_cycle_state := ADDRESS_BYTES; + dummy_cnt := 0; + opcode_cnt := 0; + END IF; + END IF; + + IF rising_edge(SCK_ipd) AND (PoweredUp = '1') THEN + IF (CSNeg_ipd = '0') THEN + CASE (bus_cycle_state) IS + WHEN OPCODE_BYTE => + IF (HOLDNeg_pullup = '1' AND QE='0') OR QE='1' THEN + opcode_in(opcode_cnt) := SIIn; + opcode_cnt := opcode_cnt + 1; + IF opcode_cnt = BYTE THEN + FOR I IN 7 DOWNTO 0 LOOP + opcode(i) := opcode_in(7-i); + END LOOP; + + CASE opcode IS + WHEN "00000110" => -- 06H + Instruct <= WREN; + bus_cycle_state := DATA_BYTES; + WHEN "01010000" => + Instruct <= WRENV; + bus_cycle_state := DATA_BYTES; + WHEN "00000100" => --04h + Instruct <= WRDI; + bus_cycle_state := DATA_BYTES; + WHEN "00000101" => -- 05h + Instruct <= RDSR; + bus_cycle_state := DATA_BYTES; + WHEN "00110101" => -- 35h + Instruct <= RDSR2; + bus_cycle_state := DATA_BYTES; + WHEN "00000001" => -- 01h + Instruct <= WRR; + bus_cycle_state := DATA_BYTES; + WHEN "00000011" => -- 03h + Instruct <= READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00001011" => -- 0Bh + Instruct <= FAST_READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00111011" => -- 3Bh + Instruct <= FAST_DREAD; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01101011" => -- 6Bh + Instruct <= FAST_QREAD; + IF (QE = '1') THEN + bus_cycle_state := ADDRESS_BYTES; + ELSE + bus_cycle_state := STAND_BY; + END IF; + WHEN "10111011" => -- BBh + Instruct <= FAST_DREAD_2; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11101011" => -- EBh + Instruct <= FAST_QREAD_4; + IF (QE = '1') THEN + bus_cycle_state := ADDRESS_BYTES; + ELSE + bus_cycle_state := STAND_BY; + END IF; + WHEN "11100111" => --E7h + Instruct <= W_QREAD; + IF (QE = '1') THEN + bus_cycle_state := ADDRESS_BYTES; + ELSE + bus_cycle_state := STAND_BY; + END IF; + WHEN "11100011" => -- E3h + Instruct <= WOCT_QREAD; + IF (QE = '1') THEN + bus_cycle_state := ADDRESS_BYTES; + ELSE + bus_cycle_state := STAND_BY; + END IF; + WHEN "01110111" => -- 77h + Instruct <= SET_BURST_WRAP; + IF (QE = '1') THEN + bus_cycle_state := DUMMY_BYTES; + ELSE + bus_cycle_state := STAND_BY; + END IF; + WHEN "11111111" => -- FFh + Instruct <= CONT_RD_RST; + bus_cycle_state := MODE_BYTE; + WHEN "00000010" => -- 02H + Instruct <= PP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00110010" => -- 32h + Instruct <= QPP; + IF (QE = '1') THEN + bus_cycle_state := ADDRESS_BYTES; + ELSE + bus_cycle_state := STAND_BY; + END IF; + WHEN "00100000" => -- 20h + Instruct <= SE; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01010010" => -- 52h + Instruct <= BE_32; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11011000" => -- D8h + Instruct <= BE_64; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11000111" | "01100000" => -- C7 or 60h + Instruct <= CE; + bus_cycle_state := DATA_BYTES; + WHEN "01110101" => -- 75h + Instruct <= ERS_PG_SUSP; + bus_cycle_state := DATA_BYTES; + WHEN "01111010" => -- 7Ah + Instruct <= ERS_PG_RES; + bus_cycle_state := DATA_BYTES; + WHEN "10111001" => -- B9h + Instruct <= DP; + bus_cycle_state := DATA_BYTES; + WHEN "10101011" => -- ABh + Instruct <= RES_RD_ID; + bus_cycle_state := DUMMY_BYTES; + WHEN "10010000" => -- 90h + Instruct <= RDID; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10010010" => -- 92h + Instruct <= RDID_DUAL; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10010100" => -- 94h + Instruct <= RDID_QUAD; + IF (QE = '1') THEN + bus_cycle_state := ADDRESS_BYTES; + ELSE + bus_cycle_state := STAND_BY; + END IF; + WHEN "01001011" => -- 4Bh + Instruct <= RD_UNIQ_ID; + bus_cycle_state := DUMMY_BYTES; + WHEN "10011111" => -- 9Fh + Instruct <= RDIDJ; + bus_cycle_state := DATA_BYTES; + WHEN "01011010" => -- 5Ah + Instruct <= RD_SFDP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01000100" => -- 44h + Instruct <= ERS_SCREG; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01000010" => -- 42h + Instruct <= PG_SCREG; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01001000" => -- 48h + Instruct <= RD_SCREG; + bus_cycle_state := ADDRESS_BYTES; + + WHEN OTHERS => + NULL; + + END CASE; + END IF; + ELSE + REPORT "Device is in HOLD mode, opcode" + SEVERITY NOTE; + END IF; + + WHEN ADDRESS_BYTES => + IF (HOLDNeg_pullup = '1' AND QE='0') OR QE='1' THEN + IF (Instruct = READ OR Instruct = FAST_READ OR + Instruct = FAST_DREAD OR Instruct = RDID OR + Instruct = SE OR Instruct = PP OR + Instruct = RD_SCREG OR Instruct = PG_SCREG OR + Instruct = RD_SFDP OR Instruct = BE_32 OR + Instruct = BE_64 OR Instruct = ERS_SCREG OR + ((Instruct = QPP OR Instruct = FAST_QREAD) + AND QE = '1')) THEN + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 3*BYTE THEN + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + + IF (Instruct = PP OR Instruct = QPP + OR Instruct = READ OR Instruct = SE + OR Instruct = BE_32 OR Instruct = BE_64 + OR Instruct = RDID OR Instruct = PG_SCREG + OR Instruct = ERS_SCREG) THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF (Instruct = RDID_DUAL OR + Instruct = FAST_DREAD_2) THEN + IF (SOIn /= 'Z') THEN + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt + 1):= SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF (addr_cnt = (3*BYTE)/2) THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + ELSIF (mode_bits(5 downto 4) = "10") THEN + opcode_double_in(opcode_cnt) := SIIn; + opcode_cnt := opcode_cnt + 1; + IF (opcode_cnt = 2*BYTE) THEN + FOR I IN 15 DOWNTO 0 LOOP + opcode_double(i) := + opcode_double_in(15-i); + END LOOP; + IF (opcode_double="1111111111111111") THEN + Instruct <= CONT_RD_RST; + bus_cycle_state := MODE_BYTE; + END IF; + END IF; + END IF; + ELSIF (QE = '1' AND (Instruct = FAST_QREAD_4 OR + Instruct = W_QREAD OR Instruct = WOCT_QREAD OR + Instruct = RDID_QUAD)) THEN + IF (SOIn /= 'Z') THEN + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF (addr_cnt = (3*BYTE)/4) THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + ELSIF (mode_bits(5 downto 4) = "10") THEN + opcode_in(opcode_cnt) := SIIn; + opcode_cnt := opcode_cnt + 1; + IF (opcode_cnt = BYTE) THEN + FOR I IN 7 DOWNTO 0 LOOP + opcode(i) := + opcode_in(7-i); + END LOOP; + IF (opcode = "11111111") THEN + Instruct <= CONT_RD_RST; + bus_cycle_state := MODE_BYTE; + END IF; + END IF; + END IF; + END IF; + ELSE + REPORT "Device is in HOLD mode, addr" + SEVERITY NOTE; + END IF; + + WHEN MODE_BYTE => + IF (QE = '1' OR (HOLDNeg_pullup = '1' AND QE = '0')) THEN + IF (Instruct = SET_BURST_WRAP AND QE = '1') THEN + wrap_in(4*wrap_cnt) := HOLDNegIn; + wrap_in(4*wrap_cnt+1) := WPNegIn; + wrap_in(4*wrap_cnt+2) := SOIn; + wrap_in(4*wrap_cnt+3) := SIIn; + wrap_cnt := wrap_cnt + 1; + IF (wrap_cnt = BYTE/4) THEN + wrap_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + wrap_byte(i) := wrap_in(7-i); + END LOOP; + bus_cycle_state := DATA_BYTES; + END IF; + CASE (wrap_byte(6 DOWNTO 5)) IS + WHEN "00" => + w_size := 8; + WHEN "01" => + w_size := 16; + WHEN "10" => + w_size := 32; + WHEN "11" => + w_size := 64; + WHEN OTHERS => + NULL; + END CASE; + ELSIF ((Instruct = FAST_QREAD_4 OR + Instruct = WOCT_QREAD OR Instruct = W_QREAD OR + Instruct = RDID_QUAD ) AND QE = '1') THEN + mode_in(4*mode_cnt) := HOLDNegIn; + mode_in(4*mode_cnt+1) := WPNegIn; + mode_in(4*mode_cnt+2) := SOIn; + mode_in(4*mode_cnt+3) := SIIn; + mode_cnt := mode_cnt + 1; + IF (mode_cnt = BYTE/4) THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bits(i) := mode_in(7-i); + END LOOP; + IF (Instruct = WOCT_QREAD) THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF (Instruct = RDID_DUAL OR + Instruct = FAST_DREAD_2) THEN + mode_in(2*mode_cnt) := SOIn; + mode_in(2*mode_cnt+1) := SIIn; + mode_cnt := mode_cnt + 1; + IF (mode_cnt = BYTE/2) THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bits(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSE + REPORT "Device is in HOLD mode, mode" + SEVERITY NOTE; + END IF; + + WHEN DUMMY_BYTES => + IF (QE = '1' OR (HOLDNeg_pullup = '1' AND QE = '0')) THEN + IF ((Instruct = FAST_QREAD_4 OR + Instruct = RDID_QUAD) AND QE = '1') THEN + dummy_cnt := dummy_cnt + 1; + IF (dummy_cnt = BYTE/2) THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct = W_QREAD AND QE = '1') THEN + dummy_cnt := dummy_cnt + 1; + IF (dummy_cnt = BYTE/4) THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct = SET_BURST_WRAP AND QE = '1') THEN + dummy_cnt := dummy_cnt + 1; + IF (dummy_cnt = 3*BYTE/4) THEN + bus_cycle_state := MODE_BYTE; + END IF; + ELSIF (Instruct = FAST_QREAD AND QE = '1') THEN + dummy_cnt := dummy_cnt + 1; + IF (dummy_cnt = BYTE) THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct=FAST_READ OR Instruct=RD_SFDP + OR Instruct = FAST_DREAD OR Instruct=RD_SCREG) THEN + dummy_cnt := dummy_cnt + 1; + IF (dummy_cnt = BYTE) THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct = RD_UNIQ_ID) THEN + dummy_cnt := dummy_cnt + 1; + IF (dummy_cnt = 4*BYTE) THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSE -- for RES_RD_ID + dummy_cnt := dummy_cnt + 1; + IF (dummy_cnt = 3*BYTE) THEN + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSE + REPORT "Device is in HOLD mode, dummy" + SEVERITY NOTE; + END IF; -- end of DUMMY_BYTES + + WHEN DATA_BYTES => + IF (Instruct = PP OR Instruct = WRR OR + Instruct = PG_SCREG) THEN + IF ((HOLDNeg_pullup = '1' AND QE='0') OR QE='1') THEN + IF (data_cnt > 2047) THEN + --In case of serial mode and PP,IF more than + --256 bytes are sent to the device + IF (bit_cnt = 0) THEN + FOR I IN 0 TO (255*BYTE-1) LOOP + Data_in(i) := Data_in(i+8); + END LOOP; + END IF; + Data_in(2040 + bit_cnt) := SIIn; + bit_cnt := bit_cnt + 1; + IF (bit_cnt = 8) THEN + bit_cnt := 0; + END IF; + data_cnt := data_cnt + 1; + ELSE + Data_in(data_cnt) := SIIn; + data_cnt := data_cnt + 1; + bit_cnt := 0; + END IF; + ELSE + REPORT "Device is in HOLD mode, data" + SEVERITY NOTE; + END IF; + ELSIF (Instruct = QPP AND QE ='1') THEN + pp_quad := TRUE; + quad_nybble := HOLDNegIn & WPNegIn & SOIn & SIIn; + IF (data_cnt > 511) THEN + --In case of quad mode and QPP,IF more than + -- 256 bytes are sent to the device + FOR I IN 0 TO 510 LOOP + quad_data_in(i) := quad_data_in(i+1); + END LOOP; + quad_data_in(511) := to_nat(quad_nybble); + data_cnt := data_cnt +1; + ELSE + IF (quad_nybble /= "ZZZZ") THEN + quad_data_in(data_cnt) := + to_nat(quad_nybble); + END IF; + data_cnt := data_cnt +1; + END IF; + END IF; + + WHEN OTHERS => NULL; + END CASE; + END IF; + END IF; + + IF falling_edge(SCK_ipd) AND (bus_cycle_state = DATA_BYTES AND + CSNeg_ipd ='0') THEN + IF (((Instruct = RDSR OR Instruct = RDSR2 OR + Instruct = FAST_READ OR Instruct = FAST_DREAD OR + Instruct = FAST_DREAD_2 OR Instruct = RES_RD_ID OR + Instruct = RDID OR Instruct = RDID_DUAL OR + Instruct = RD_UNIQ_ID OR Instruct = RDIDJ OR + Instruct = RD_SFDP OR Instruct = RD_SCREG OR + Instruct = READ) AND ((HOLDNeg_pullup ='1' AND QE='0') OR QE='1')) + OR ((Instruct = FAST_QREAD OR Instruct = FAST_QREAD_4 OR + Instruct = W_QREAD OR Instruct = RDID_QUAD OR + Instruct = WOCT_QREAD) AND QE='1')) THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + + IF rising_edge(CSNeg_ipd) THEN + IF (bus_cycle_state=MODE_BYTE AND Instruct = CONT_RD_RST) THEN + mode_bits(5 downto 4) := "11"; + mode_bits(7 downto 6) := "00"; + mode_bits(3 downto 0) := "0000"; + bus_cycle_state := STAND_BY; + ELSIF (bus_cycle_state=DATA_BYTES AND + NOT (mode_bits(5 downto 4)="10")) THEN + bus_cycle_state := STAND_BY; + CASE (Instruct) IS + WHEN WREN | WRDI | SET_BURST_WRAP | SE | BE_32 | BE_64 | + CE | ERS_PG_RES | DP | ERS_SCREG => + + IF (data_cnt = 0) THEN + write <= '0'; + END IF; + WHEN WRENV => + write <= '0'; + wren_vlt_flag := TRUE; + + WHEN RES_RD_ID => + write <= '0'; + res_flag := TRUE; + + WHEN WRR => + IF (data_cnt = 8) THEN + --If CS# is driven high after eight + --cycle,only the Status Register is + --written to. + write <= '0'; + FOR i IN 0 TO 7 LOOP + Status_reg1_in(i) <= Data_in(7-i); + END LOOP; + ELSIF (data_cnt = 16) THEN + --After the 16th cycle both the + --Status and Configuration Registers + --are written to. + write <= '0'; + FOR i IN 0 TO 7 LOOP + Status_reg1_in(i) <= Data_in(7-i); + END LOOP; + + FOR j IN 0 TO 7 LOOP + Status_reg2_in(j) <= Data_in(15-j); + END LOOP; + END IF; + + WHEN PP | PG_SCREG => + IF (data_cnt > 0) THEN + IF ((data_cnt mod 8) = 0) THEN + write <= '0'; + FOR I IN 0 TO 255 LOOP + FOR J IN 7 DOWNTO 0 LOOP + Byte_slv(j) := + Data_in((i*8) + (7-j)); + END LOOP; + WByte(i) <= + to_nat(Byte_slv); + END LOOP; + + IF (data_cnt > 256*BYTE) THEN + Byte_number <= 255; + ELSE + Byte_number <= ((data_cnt/8) - 1); + END IF; + END IF; + END IF; + + WHEN QPP => + IF (data_cnt >0) THEN + IF ((data_cnt mod 2) = 0) THEN + write <= '0'; + FOR I IN 0 TO 255 LOOP + FOR J IN 1 DOWNTO 0 LOOP + Quad_slv := + to_slv(quad_data_in((i*2) + + (1-j)),4); + + Byte_slv(4*j+3 DOWNTO 4*j) := + Quad_slv; + END LOOP; + WByte(i) <= to_nat(Byte_slv); + END LOOP; + + IF (data_cnt > 256*BYTE/4) THEN + Byte_number <= 255; + ELSE + Byte_number <= ((data_cnt/2) - 1); + END IF; + END IF; + END IF; + + WHEN others => + null; + + END CASE; + + ELSIF (bus_cycle_state=DATA_BYTES AND + (mode_bits(5 DOWNTO 4)="10")) THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := STAND_BY; + IF (HOLDNeg_pullup ='1' AND (Instruct = RES_RD_ID) AND + (dummy_cnt = 0)) THEN + write <= '0'; + res_flag := FALSE; + END IF; + END IF; + END IF; -- end of rising_edge_CSNeg_ipd + + END PROCESS BusCycleDecode; + + --------------------------------------------------------------------------- + -- Timing control for the Page Program + --------------------------------------------------------------------------- + ProgTime : PROCESS(PSTART, PGSUSP, PGRES) + VARIABLE pob : time; + VARIABLE elapsed : time; + VARIABLE start : time; + VARIABLE duration : time; + BEGIN + IF Instruct = PP OR Instruct = QPP OR Instruct = PG_SCREG THEN + IF LongTimming THEN + pob := tdevice_PP; + ELSE + pob := tdevice_PP / 10; + END IF; + END IF; + IF rising_edge(PSTART) AND PDONE = '1' THEN + elapsed := 0 ns; + PDONE <= '0', '1' AFTER pob; + start := NOW; + ELSIF PGSUSP'EVENT AND PGSUSP = '1' AND PDONE /= '1' THEN + elapsed := NOW - start; + duration := pob - elapsed; + PDONE <= '0'; + ELSIF PGRES'EVENT AND PGRES = '1' AND PDONE /= '1'THEN + start := NOW; + PDONE <= '0', '1' AFTER duration; + END IF; + + END PROCESS ProgTime; + + --------------------------------------------------------------------------- + -- Timing control for the Write Status Register + --------------------------------------------------------------------------- + WriteTime : PROCESS(WSTART) + VARIABLE wob : time; + BEGIN + IF LongTimming THEN + wob := tdevice_WRR; + ELSE + wob := tdevice_WRR / 100; + END IF; + IF rising_edge(WSTART) AND WDONE = '1' THEN + WDONE <= '0', '1' AFTER wob; + END IF; + + END PROCESS WriteTime; + + --------------------------------------------------------------------------- + -- Timing control for the Write Status Register when Write Enable for + -- Volatile Status Register was issued + --------------------------------------------------------------------------- + + WriteTimeVlt : PROCESS(VLTSTART) + VARIABLE wvob : time; + BEGIN + wvob := tdevice_VRR; + IF rising_edge(VLTSTART) AND VLTDONE = '1' THEN + VLTDONE <= '0' , '1' AFTER wvob; + END IF; + END PROCESS WriteTimeVlt; + + --------------------------------------------------------------------------- + -- Timing control for the Erase Operation + --------------------------------------------------------------------------- + ErsTime : PROCESS(ESTART, ESUSP, ERES) + VARIABLE seo : time; + VARIABLE beo32 : time; + VARIABLE beo64 : time; + VARIABLE ceo : time; + VARIABLE elapsed : time; + VARIABLE start : time; + VARIABLE duration : time; + BEGIN + IF LongTimming THEN + seo := tdevice_SE; + beo32 := tdevice_BE1; + beo64 := tdevice_BE2; + ceo := tdevice_CE; + ELSE + seo := tdevice_SE / 100; + beo32 := tdevice_BE1 / 100; + beo64 := tdevice_BE2 / 100; + ceo := tdevice_CE / 100; + END IF; + IF rising_edge(ESTART) AND EDONE = '1' THEN + IF Instruct = CE THEN + duration := ceo; + ELSIF Instruct = BE_64 THEN + duration := beo64; + ELSIF Instruct = BE_32 THEN + duration := beo32; + ELSIF Instruct = BE_64 THEN + duration := beo64; + ELSE -- sector erase 4KB, instruct SE + duration := seo; + END IF; + elapsed := 0 ns; + EDONE <= '0', '1' AFTER duration; + start := NOW; + ELSIF ESUSP'EVENT AND ESUSP = '1' AND EDONE /= '1' THEN + elapsed := NOW - start; + duration := duration - elapsed; + EDONE <= '0'; + ELSIF ERES'EVENT AND ERES = '1' AND EDONE /= '1' THEN + start := NOW; + EDONE <= '0', '1' AFTER duration; + END IF; + + END PROCESS ErsTime; + + CheckCEOnPowerUP :PROCESS(CSNeg_ipd) + BEGIN + IF (PoweredUp = '0' AND falling_edge(CSNeg_ipd)) THEN + REPORT InstancePath & partID & + ": Device is selected during Power Up" + SEVERITY WARNING; + END IF; + END PROCESS; + + --------------------------------------------------------------------------- + -- Main Behavior Process + -- combinational process for next state generation + --------------------------------------------------------------------------- + StateGen :PROCESS(PoweredUp, write, CSNeg_ipd, WDONE, ERSSUSP_out, RES1_out, + ERSRES_out, PRGSUSP_out, EDONE,PRGRES_out, DP_out, PDONE, + VLTDONE,RES2_out) + + BEGIN + + IF rising_edge(PoweredUp) THEN + next_state <= IDLE; + ELSE + CASE current_state IS + WHEN IDLE => + IF falling_edge(write) THEN + IF (Instruct = WRR AND (SRP1='0' AND + (SRP0='0' OR (SRP0='1' AND WPNeg ='1')))) THEN + IF (WEL='1' AND NOT (wren_vlt_flag)) THEN + next_state <= WRITE_SR; + ELSIF (WEL='0' AND wren_vlt_flag) THEN + next_state <= WRITE_SR_V; + END IF; + ELSIF (Instruct = PP AND WEL='1') THEN + sect := Address / 16#1000#; + sect_tmp_pg := sect; + IF (Sec_Prot(sect) = '0') THEN + next_state <= PAGE_PG; + END IF; + ELSIF (Instruct = QPP AND WEL='1' AND QE='1') THEN + sect := Address / 16#1000#; + sect_tmp_pg := sect; + IF (Sec_Prot(sect) = '0') THEN + next_state <= PAGE_PG; + END IF; + ELSIF (Instruct = PG_SCREG AND WEL='1') THEN + sect := Address / 16#1000#; + IF ((sect < 4 AND sect > 0) AND + LB_bits(sect-1)='0') THEN + next_state <= PAGE_PG; + END IF; + ELSIF (Instruct = ERS_SCREG AND WEL='1') THEN + sect := Address / 16#1000#; + IF ((sect <= 3) AND LB_bits(sect-1)='0') THEN + next_state <= SECTOR_ERS; + END IF; + ELSIF ((Instruct = SE OR Instruct = BE_32 OR + Instruct = BE_64) AND WEL='1') THEN + sect := Address / 16#1000#; + sect_tmp_ers := sect; + IF (Sec_Prot(sect) = '0') THEN + next_state <= SECTOR_ERS; + END IF; + ELSIF (Instruct = CE AND WEL='1' AND + ((CMP='0' AND BP2='0' AND BP1='0' AND BP0='0') OR + (CMP='1' AND BP2='1' AND BP1='1' AND BP0='1'))) THEN + next_state <= BULK_ERS; + ELSE + next_state <= IDLE; + END IF; + ELSIF rising_edge(DP_out) THEN + next_state <= DP_DOWN; + END IF; + + WHEN WRITE_SR => + IF rising_edge(WDONE) THEN + next_state <= IDLE; + END IF; -- end of WRITE_SR + + WHEN WRITE_SR_V => + IF rising_edge(VLTDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PAGE_PG => + IF (PRGSUSP_out'event AND PRGSUSP_out = '1') THEN + next_state <= PG_SUSP; + ELSIF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; -- end of PAGE_PG + + WHEN PG_SUSP => + IF (PRGRES_out'event AND PRGRES_out = '1') THEN + next_state <= PAGE_PG; + ELSIF falling_edge(write) THEN + IF (Instruct = SE OR Instruct = BE_32 OR + Instruct = BE_64) THEN + sect := Address / 16#1000#; + IF ((Sec_Prot(sect) = '0') AND + (sect /= sect_tmp_pg)) THEN + next_state <= PG_SUSP_ERS; + END IF; + END IF; + END IF; -- end of PG_SUSP + + WHEN PG_SUSP_ERS => + IF rising_edge(EDONE) THEN + next_state <= PG_SUSP; + ELSE + next_state <= PG_SUSP_ERS; + END IF; + + WHEN BULK_ERS => + IF rising_edge(EDONE) THEN + next_state <= IDLE; + END IF; + + WHEN SECTOR_ERS => + IF (ERSSUSP_out'event AND ERSSUSP_out = '1') THEN + next_state <= ERS_SUSP; + ELSIF rising_edge(EDONE) THEN + next_state <= IDLE; + END IF; + + WHEN ERS_SUSP => + IF (ERSRES_out'event AND ERSRES_out = '1') THEN + next_state <= SECTOR_ERS; + ELSIF falling_edge(write) THEN + IF (Instruct = PP OR (Instruct = QPP AND QE='1')) THEN + sect := Address / 16#1000#; + IF ((Sec_Prot(sect) = '0') AND + (sect /= sect_tmp_ers)) THEN + next_state <= ERS_SUSP_PG; + END IF; + ELSIF (Instruct = PG_SCREG) THEN + sect := Address / 16#1000#; + IF ((sect < 4 AND sect > 0) AND + LB_bits(sect-1)='0') THEN + next_state <= ERS_SUSP_PG; + END IF; + END IF; + END IF; + + WHEN ERS_SUSP_PG => + IF rising_edge(PDONE) THEN + next_state <= ERS_SUSP; + ELSE + next_state <= ERS_SUSP_PG; + END IF; + + WHEN DP_DOWN => + IF rising_edge(RES1_out) OR rising_edge(RES2_out) THEN + next_state <= IDLE; + END IF; + + END CASE; + END IF; + END PROCESS StateGen; + --------------------------------------------------------------------------- + --FSM Output generation and general funcionality + --------------------------------------------------------------------------- + Functional : PROCESS(read_out, Instruct, SCK_ipd, change_addr, write, + Address, PDONE, WDONE, EDONE, ERSSUSP_out, PoweredUp, + CSNeg_ipd, RES1_out, ERSRES_out, PRGSUSP_out,PRGRES_out, + VLTDONE, current_state, DP_out, RES2_out,SUSP_FL_OUT) + + VARIABLE WData : WByteType:= (OTHERS => MaxData); + + VARIABLE oe : boolean := FALSE; + + VARIABLE AddrLo : NATURAL; + VARIABLE AddrHi : NATURAL; + + VARIABLE AddrLo_ers : NATURAL; + VARIABLE AddrHi_ers : NATURAL; + VARIABLE AddrLo_wrap : NATURAL; + VARIABLE AddrHi_wrap : NATURAL; + + VARIABLE Addr : NATURAL; + VARIABLE Addr_w : NATURAL; + VARIABLE Addr_ers : NATURAL; + VARIABLE Addr_tmp : NATURAL; + VARIABLE Addr_tmp_2 : NATURAL; + VARIABLE Addr_tmp_3 : NATURAL; + VARIABLE Addr_screg : NATURAL; + VARIABLE Addr_screg_tmp : NATURAL; + + VARIABLE data_out : std_logic_vector(7 downto 0); + VARIABLE ident_out : std_logic_vector(23 downto 0); + VARIABLE ident_out2 : std_logic_vector(15 downto 0); + VARIABLE uniq_id : std_logic_vector(63 downto 0); + + VARIABLE old_bit : std_logic_vector(7 downto 0); + VARIABLE new_bit : std_logic_vector(7 downto 0); + VARIABLE old_int : INTEGER RANGE -1 to MaxData; + VARIABLE new_int : INTEGER RANGE -1 to MaxData; + + VARIABLE wr_cnt : NATURAL RANGE 0 TO 255; + VARIABLE cnt : NATURAL RANGE 0 TO 256 := 0; + + BEGIN + + oe := rising_edge(read_out) AND PoweredUp = '1'; + + IF Instruct'EVENT THEN + read_cnt := 0; + + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + sr_read <= false; + read_id <= false; + pp_quad := FALSE; + + IF (current_state = IDLE AND DP_in = '1') THEN + REPORT "Command results can be corrupted " + SEVERITY WARNING; + END IF; + END IF; + + IF rising_edge(PoweredUp) THEN + WEL := '0'; + BUSY := '0'; + SUS := '0'; + change_prot_bits <= '1', '0' AFTER 1 ns; + END IF; + + IF change_addr'EVENT THEN + read_addr := Address; + END IF; + + IF RES1_out'EVENT AND RES1_out = '1' THEN + RES1_in <= '0'; + END IF; + + IF RES2_out'EVENT AND RES2_out = '1' THEN + RES2_in <= '0'; + END IF; + + IF SUSP_FL_OUT'EVENT AND SUSP_FL_OUT = '1' THEN + SUSP_FL_IN <= '0'; + END IF; + + CASE current_state IS + + WHEN IDLE => + + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + read_id <= false; + sr_read <= false; + res_flag := FALSE; + pg_screg_flag <= false; + ers_screg_flag <= false; + + IF falling_edge(write) AND DP_in ='0' THEN + read_cnt := 0; + IF (Instruct = WREN) THEN + WEL := '1'; + ELSIF (Instruct = WRDI) THEN + WEL := '0'; + ELSIF (Instruct = WRR) THEN + IF(SRP1='0' AND (SRP0='0' OR + (SRP0='1' AND WPNeg='1'))) THEN + IF WEL='1' AND NOT (wren_vlt_flag) THEN + WSTART <= '1', '0' AFTER 5 ns; + BUSY := '1'; + ELSIF (WEL='0' AND wren_vlt_flag) THEN + VLTSTART <= '1', '0' AFTER 5 ns; + END IF; + ELSE + WEL := '0'; + END IF; + ELSIF ((Instruct = PP OR (Instruct = QPP AND QE='1')) + AND WEL='1' AND PDONE='1') THEN + sect := Address / 16#1000#; + IF (Sec_Prot(sect) = '0') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + BUSY := '1'; + SA <= sect; + Addr := Address; + Addr_tmp:= Address; + wr_cnt := Byte_number; + + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + WEL := '0'; + END IF; + ELSIF (Instruct = PG_SCREG AND WEL='1') THEN + sect := Address / 16#1000#; + IF ((sect <= 3) AND LB_bits(sect-1)='0') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + BUSY := '1'; + SA <= sect; + wr_cnt := Byte_number; + Addr_screg := Address mod 16#1000#; + Addr_screg_tmp := Address mod 16#1000#; + pg_screg_flag <= true; + + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + + ELSE + WEL := '0'; + END IF; + ELSIF ((Instruct = SE OR Instruct = BE_32 OR + Instruct = BE_64) AND WEL='1') THEN + sect := Address / 16#1000#; + IF (Sec_Prot(sect) = '0') THEN + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + BUSY := '1'; + Addr_ers := Address; + ELSE + WEL := '0'; + END IF; + ELSIF (Instruct = CE AND WEL='1') THEN + IF ((CMP='0' AND BP2='0' AND BP1='0' AND BP0='0') OR + (CMP='1' AND BP2='1' AND BP1='1' AND BP0='1')) THEN + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + BUSY := '1'; + ELSE + WEL := '0'; + END IF; + ELSIF (Instruct = ERS_SCREG AND WEL='1') THEN + sect := Address / 16#1000#; + IF ((sect <= 3) AND LB_bits(sect-1)='0') THEN + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + BUSY := '1'; + SA <= sect; + ers_screg_flag <= true; + ELSE + WEL := '0'; + END IF; + ELSIF (Instruct = DP) THEN + RES2_in <= '0'; + RES1_in <= '0'; + DP_in <= '1'; + END IF; + -- end of falling_edge_write + ELSIF (oe AND DP_in='0') THEN + IF (Instruct = RDSR) THEN + --Read Status Register + sr_read <= true; + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RDSR2) THEN + sr_read <= true; + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = READ OR Instruct = FAST_READ) THEN + IF (Instruct = READ) THEN + fast_rd <= false; + dual_read <= false; + slow_read <= true; + quad_read <= false; + sr_read <= false; + ELSE + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + sr_read <= false; + END IF; + IF (Mem(read_addr) /= -1) THEN + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + ELSE + SOut_zd <= 'U'; + END IF; + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + IF (read_addr = AddrRANGE) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSIF (Instruct=FAST_DREAD OR Instruct=FAST_DREAD_2) THEN + fast_rd <= false; + dual_read <= true; + slow_read <= false; + quad_read <= false; + sr_read <= false; + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 4) THEN + read_cnt := 0; + IF (read_addr = AddrRANGE) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSIF ((Instruct=FAST_QREAD OR Instruct=FAST_QREAD_4 OR + Instruct=W_QREAD OR Instruct=WOCT_QREAD) + AND QE='1') THEN + IF ((Instruct=W_QREAD AND (Address mod 2 /= 0) ) OR + (Instruct=WOCT_QREAD AND + (Address mod 16 /= 0))) THEN + read_cnt := read_cnt + 1; + IF (read_cnt = 2) THEN + read_cnt := 0; + REPORT "Word Read can't execute Wrong Address" + SEVERITY NOTE; + END IF; + ELSE + fast_rd <= false; + dual_read <= false; + slow_read <= false; + quad_read <= true; + sr_read <= false; + Addr_w := Address; + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 2) THEN + read_cnt := 0; + IF (wrap_byte(4)='0' AND (Instruct=FAST_QREAD_4 + OR Instruct=W_QREAD)) THEN + ADDRHILO_WRAP(AddrLo_wrap,AddrHi_wrap, + Addr_w,w_size); + IF (read_addr = AddrHi_wrap) THEN + read_addr := AddrLo_wrap; + ELSE + read_addr := read_addr + 1; + END IF; + ELSE + IF (read_addr = AddrRANGE) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + END IF; + ELSIF (Instruct=RDID OR Instruct=RDID_DUAL OR + Instruct=RDID_QUAD) THEN + IF (read_addr mod 2 = 0) THEN + ident_out2 := to_slv(Manuf_ID,8) & + to_slv(Device_ID1,8); + ELSE + ident_out2 := to_slv(Device_ID1,8) & + to_slv(Manuf_ID,8); + END IF; + read_id <= true; + IF (Instruct = RDID) THEN + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + sr_read <= false; + SOut_zd <= ident_out2(15-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 16) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RDID_DUAL) THEN + fast_rd <= false; + dual_read <= true; + slow_read <= false; + quad_read <= false; + sr_read <= false; + SOut_zd <= ident_out2(15-2*read_cnt); + SIOut_zd <= ident_out2(14-2*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + ELSE -- (Instruct = RDID_QUAD) + fast_rd <= false; + dual_read <= false; + slow_read <= false; + quad_read <= true; + sr_read <= false; + HOLDNegOut_zd <= ident_out2(15-4*read_cnt); + WPNegOut_zd <= ident_out2(14-4*read_cnt); + SOut_zd <= ident_out2(13-4*read_cnt); + SIOut_zd <= ident_out2(12-4*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 4) THEN + read_cnt := 0; + END IF; + END IF; + ELSIF (Instruct = RD_UNIQ_ID) THEN + -- unique ID number is not in data sheet + read_id <= true; + uniq_id := to_slv(Unique_id_2,32)& + to_slv(Unique_id_1,32); + SOut_zd <= uniq_id(63-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 64) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RDIDJ) THEN + read_id <= true; + ident_out := to_slv(Manuf_ID,8) & + to_slv(Device_ID2,8) & to_slv(Device_ID3,8); + SOut_zd <= ident_out(23-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 24) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RD_SFDP) THEN + IF (read_addr / 16#100# = 0) THEN + Addr_tmp_2 := (read_addr mod 16#100#); + data_out := to_slv(SFDP_array(Addr_tmp_2),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + IF (read_addr = SFDP_HiAddr) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + REPORT "Given SFDP address is out of range" + SEVERITY NOTE; + END IF; + END IF; + ELSIF (Instruct = RD_SCREG) THEN + Addr_tmp_2 := read_addr / 16#100#; + Addr_tmp_3 := read_addr mod 16#100#; + IF (Addr_tmp_2 = 16) THEN + -- Security Register No.1 + data_out := to_slv(Security_Reg1(Addr_tmp_3),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + ELSIF (Addr_tmp_2 = 32) THEN + -- Security Register No.2 + data_out := to_slv(Security_Reg2(Addr_tmp_3),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + ELSIF (Addr_tmp_2 = 48) THEN + -- Security Register No.2 + data_out := to_slv(Security_Reg3(Addr_tmp_3),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + REPORT "Security Reg address is out of range " + SEVERITY NOTE; + END IF; + END IF; + IF (read_cnt = 8) THEN + read_cnt := 0; + IF (read_addr mod 256 = SecReg_HiAddr) THEN + read_addr := (read_addr/256)*(SecReg_HiAddr+1); + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSIF Instruct = RES_RD_ID THEN + read_id <= true; + data_out := to_slv(Device_ID1,8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + END IF; -- end of oe + ELSIF rising_edge(DP_out) THEN + DP_in <= '0'; + END IF; -- end of IDLE state + + WHEN WRITE_SR => + + IF (WDONE ='1') THEN + BUSY := '0'; + WEL := '0'; + + SRP0 := Status_reg1_in(7); + SEC := Status_reg1_in(6); + TB := Status_reg1_in(5); + BP2 := Status_reg1_in(4); + BP1 := Status_reg1_in(3); + BP0 := Status_reg1_in(2); + BP_bits := BP2 & BP1 & BP0; + CMP := Status_reg2_in(6); + QE := Status_reg2_in(1); + -- SRP1 bit will only change value from '0' to '1' + -- if SRP1 is '1' than Status Register is protected + --and is not possible to write it + SRP1 := Status_reg2_in(0); + + IF LB3 = '0' THEN + LB3 := Status_reg2_in(5); + ELSE + REPORT "LB bit is set to '1', no change allowed" + SEVERITY NOTE; + END IF; + + IF LB2 = '0' THEN + LB2 := Status_reg2_in(4); + ELSE + REPORT "LB bit is set to '1', no change allowed" + SEVERITY NOTE; + END IF; + IF LB1 = '0' THEN + LB1 := Status_reg2_in(3); + ELSE + REPORT "LB bit is set to '1', no change allowed" + SEVERITY NOTE; + END IF; + LB_bits := LB3 & LB2 & LB1; + change_prot_bits <= '1' , '0' AFTER 2 ns; + END IF; -- end of WDONE + + IF (oe AND Instruct = RDSR) THEN + --Read Status Register 1 + sr_read <= true; + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + END IF; -- end of WRITE_SR + + WHEN WRITE_SR_V => + + IF (VLTDONE = '1') THEN + SRP0 := Status_reg1_in(7); + SEC := Status_reg1_in(6); + TB := Status_reg1_in(5); + BP2 := Status_reg1_in(4); + BP1 := Status_reg1_in(3); + BP0 := Status_reg1_in(2); + BP_bits := BP2 & BP1 & BP0; + CMP := Status_reg2_in(6); + QE := Status_reg2_in(1); + -- SRP1 bit will only change value from '0' to '1' + -- if SRP1 is '1' than Status Register is protected + --and is not possible to write it + SRP1 := Status_reg2_in(0); + IF LB3 = '0' THEN + LB3 := Status_reg2_in(5); + ELSIF LB2 = '0' THEN + LB2 := Status_reg2_in(4); + ELSIF LB1 = '0' THEN + LB1 := Status_reg2_in(3); + ELSE + REPORT "LB bit is set to '1', no change allowed" + SEVERITY NOTE; + END IF; + + change_prot_bits <= '1' , '0' AFTER 2 ns; + + wren_vlt_flag := FALSE; + END IF; + + WHEN PAGE_PG | ERS_SUSP_PG => + + IF current_state'event AND PDONE = '0' THEN + + IF (Instruct /= PG_SCREG) THEN + ADDRHILO_PG(AddrLo, AddrHi, Addr); + END IF; + cnt := 0; + + FOR i IN 0 TO wr_cnt LOOP + new_int := WData(i); + IF (Instruct = PG_SCREG) THEN + IF (sect = 1) THEN + old_int := Security_Reg1(Addr_screg + i - cnt); + ELSIF (sect = 2) THEN + old_int := Security_Reg2(Addr_screg + i - cnt); + ELSE + old_int := Security_Reg3(Addr_screg + i - cnt); + END IF; + ELSE + old_int := Mem(Addr + i - cnt); + END IF; + IF (new_int > -1) THEN + new_bit := to_slv(new_int,8); + IF (old_int > -1) THEN + old_bit := to_slv(old_int,8); + FOR j IN 0 TO 7 LOOP + IF old_bit(j) = '0' THEN + new_bit(j) := '0'; + END IF; + END LOOP; + new_int := to_nat(new_bit); + END IF; + WData(i) := new_int; + ELSE + WData(i) := -1; + END IF; + IF (Instruct = PG_SCREG) THEN + IF (sect = 1) THEN + Security_Reg1(Addr_screg + i - cnt) := - 1; + ELSIF (sect = 2) THEN + Security_Reg2(Addr_screg + i - cnt) := - 1; + ELSE + Security_Reg3(Addr_screg + i - cnt) := - 1; + END IF; + ELSE + Mem(Addr + i - cnt) := - 1; + END IF; + IF (Instruct /= PG_SCREG) THEN + IF ((Addr + i) = AddrHi) THEN + Addr := AddrLo; + cnt := i + 1; + END IF; + ELSE + IF Addr_screg + i = SecReg_HiAddr THEN + Addr_screg := SecReg_LoAddr; + cnt := i + 1; + END IF; + END IF; + END LOOP; + cnt := 0; + + END IF; + + IF (PDONE = '1') THEN + IF (current_state /= ERS_SUSP_PG) THEN + BUSY := '0'; + END IF; + WEL := '0'; + + FOR I IN 0 TO wr_cnt LOOP + IF pg_screg_flag THEN + IF (sect = 1) THEN + Security_Reg1(Addr_screg_tmp + i - cnt) :=WData(i); + ELSIF (sect = 2) THEN + Security_Reg2(Addr_screg_tmp + i - cnt) :=WData(i); + ELSE + Security_Reg3(Addr_screg_tmp + i - cnt) :=WData(i); + END IF; + IF ((Addr_screg_tmp + i) = SecReg_HiAddr) THEN + Addr_screg_tmp := SecReg_LoAddr; + cnt := i + 1; + END IF; + ELSE + Mem(Addr_tmp + i - cnt) := WData(i); + IF ((Addr_tmp + i) = AddrHi) THEN + Addr_tmp := AddrLo; + cnt := i + 1; + END IF; + END IF; + END LOOP; + END IF; -- end of PDONE + + IF (Instruct = ERS_PG_SUSP AND current_state = PAGE_PG AND + SUSP_FL_IN = '0') THEN + PGSUSP <= '1', '0' AFTER 1 ns; + PRGSUSP_in <= '1'; + END IF; + + IF (oe AND Instruct = RDSR) THEN + --Read Status Register 1 + sr_read <= true; + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + END IF; + + WHEN PG_SUSP => + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + sr_read <= false; + BUSY := '0'; + IF (PRGSUSP_out = '1' AND (Instruct /= ERS_PG_RES)) THEN + PRGSUSP_in <= '0'; + --The BUSY bit in the Status Register will indicate that + --the device is ready for another operation. +-- BUSY := '0'; + --The SuspEND (SUS) bit in the Status Register2 will + --be set to the logical “1” state to indicate that the + --program operation has been suspENDed. + SUS := '1'; + END IF; + IF (PRGRES_out'event AND PRGRES_out = '1') THEN + PRGRES_in <= '0'; + BUSY := '1'; + END IF; + IF (SUS = '1') THEN + IF falling_edge(write) THEN + IF (Instruct = ERS_PG_RES) THEN + SUS := '0'; + PRGRES_in <= '1'; + SUSP_FL_IN <= '1'; + PGRES <= '1', '0' AFTER 5 ns; + ELSIF ((Instruct = SE OR Instruct = BE_32 OR + Instruct = BE_64) AND WEL='1') THEN + sect := Address / 16#1000#; + IF (sect /= sect_tmp_pg AND + Sec_Prot(sect) = '0') THEN + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + BUSY := '1'; + Addr_ers := Address; + ELSE + BUSY := '0'; + REPORT "Can't erase sector,protected or susp." + SEVERITY NOTE; + END IF; + END IF; + ELSIF (oe) THEN + IF (Instruct = RDSR) THEN + --Read Status Register 1 + sr_read <= true; + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RDSR2) THEN + --Read Status Register 2 + sr_read <= true; + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = READ OR Instruct = FAST_READ) THEN + IF (sect_tmp_pg /= read_addr / 16#1000#) THEN + IF (Instruct = READ) THEN + fast_rd <= false; + dual_read <= false; + slow_read <= true; + quad_read <= false; + sr_read <= false; + ELSE + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + sr_read <= false; + END IF; + IF (Mem(read_addr) /= -1) THEN + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + ELSE + SOut_zd <= 'U'; + END IF; + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + IF (read_addr = AddrRANGE) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + REPORT "Can't read suspended sector" + SEVERITY NOTE; + read_cnt := 0; + END IF; + END IF; + ELSIF (Instruct=FAST_DREAD OR + Instruct=FAST_DREAD_2) THEN + IF sect_tmp_pg /= (read_addr / 16#1000#) THEN + fast_rd <= false; + dual_read <= true; + slow_read <= false; + quad_read <= false; + sr_read <= false; + IF (Mem(read_addr) /= -1) THEN + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + ELSE + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + END if; + read_cnt := read_cnt + 1; + IF (read_cnt = 4) THEN + read_cnt := 0; + IF (read_addr = AddrRANGE) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 4) THEN + REPORT "Can't read suspended sector" + SEVERITY NOTE; + read_cnt := 0; + END IF; + END IF; + ELSIF ((Instruct=FAST_QREAD OR Instruct=W_QREAD + OR Instruct=FAST_QREAD_4 OR Instruct=WOCT_QREAD) + AND QE = '1') THEN + IF sect_tmp_pg /= (read_addr / 16#1000#) THEN + IF ((Instruct=W_QREAD AND + Address mod 2 /= 0) OR + (Instruct=WOCT_QREAD AND + Address mod 16 /= 0)) THEN + read_cnt := read_cnt + 1; + IF (read_cnt = 2) THEN + read_cnt := 0; + REPORT "Word Read - Wrong Read Address" + SEVERITY NOTE; + END IF; + ELSE + fast_rd <= false; + dual_read <= false; + slow_read <= false; + quad_read <= true; + sr_read <= false; + Addr_w := Address; + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 2) THEN + read_cnt := 0; + IF (wrap_byte(4)= '0' AND + (Instruct=FAST_QREAD_4 OR + Instruct=W_QREAD)) THEN + ADDRHILO_WRAP(AddrLo_wrap, + AddrHi_wrap, Addr_w,w_size); + IF (read_addr = AddrHi_wrap) THEN + read_addr := AddrLo_wrap; + ELSE + read_addr := read_addr + 1; + END IF; + ELSE + IF (read_addr = AddrRANGE) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 2) THEN + REPORT "Can't read suspended sector" + SEVERITY NOTE; + read_cnt := 0; + END IF; + END IF; + ELSIF (Instruct=RDID OR Instruct=RDID_DUAL OR + Instruct=RDID_QUAD) THEN + IF (read_addr mod 2 = 0) THEN + ident_out2 := to_slv(Manuf_ID,8) & + to_slv(Device_ID1,8); + ELSE + ident_out2 := to_slv(Device_ID1,8)& + to_slv(Manuf_ID,8); + END IF; + read_id <= true; + IF (Instruct = RDID) THEN + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + sr_read <= false; + SOut_zd <= ident_out2(15-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 16) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RDID_DUAL) THEN + fast_rd <= false; + dual_read <= true; + slow_read <= false; + quad_read <= false; + sr_read <= false; + SOut_zd <= ident_out2(15-2*read_cnt); + SIOut_zd <= ident_out2(14-2*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + ELSE -- (Instruct = RDID_QUAD) + fast_rd <= false; + dual_read <= false; + slow_read <= false; + quad_read <= true; + sr_read <= false; + HOLDNegOut_zd <= ident_out2(15-4*read_cnt); + WPNegOut_zd <= ident_out2(14-4*read_cnt); + SOut_zd <= ident_out2(13-4*read_cnt); + SIOut_zd <= ident_out2(12-4*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 4) THEN + read_cnt := 0; + END IF; + END IF; + ELSIF (Instruct = RD_UNIQ_ID) THEN + -- unique ID number is not in data sheet + read_id <= true; + uniq_id := to_slv(Unique_id_2,32)& + to_slv(Unique_id_1,32); + SOut_zd <= uniq_id(63-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 64) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RDIDJ) THEN + read_id <= true; + ident_out := to_slv(Manuf_ID,8) & + to_slv(Device_ID2,8) & to_slv(Device_ID3,8); + SOut_zd <= ident_out(23-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 24) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RD_SFDP) THEN + IF (read_addr / 16#100# = 0) THEN + Addr_tmp_2 := (read_addr mod 16#100#); + data_out := to_slv(SFDP_array(Addr_tmp_2),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + IF (read_addr = SFDP_HiAddr) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + REPORT "SFDP address is out of range" + SEVERITY NOTE; + END IF; + END IF; + ELSIF (Instruct = RD_SCREG) THEN + Addr_tmp_2 := read_addr / 16#100#; + Addr_tmp_3 := read_addr mod 16#100#; + IF (Addr_tmp_2 = 16) THEN + -- Security Register No.1 + data_out := to_slv(Security_Reg1(Addr_tmp_3),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + ELSIF (Addr_tmp_2 = 32) THEN + -- Security Register No.2 + data_out := to_slv(Security_Reg2(Addr_tmp_3),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + ELSIF (Addr_tmp_2 = 48) THEN + -- Security Register No.2 + data_out := to_slv(Security_Reg3(Addr_tmp_3),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + REPORT "Security Reg addr is out of range " + SEVERITY NOTE; + END if; + END IF; + + IF (read_cnt = 8) THEN + read_cnt := 0; + IF (read_addr mod 256) = SecReg_HiAddr THEN + read_addr:=(read_addr/256)* + (SecReg_HiAddr+1); + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + END IF; + END IF; + + WHEN SECTOR_ERS | PG_SUSP_ERS => + IF (current_state'event AND EDONE = '0') THEN + IF (Instruct = SE) THEN + ADDRHILO_SEC4(AddrLo_ers, AddrHi_ers, Addr_ers); + ELSIF (Instruct = BE_32) THEN + ADDRHILO_SEC32(AddrLo_ers, AddrHi_ers, Addr_ers); + ELSIF (Instruct = BE_64) THEN + ADDRHILO_SEC64(AddrLo_ers, AddrHi_ers, Addr_ers); + END IF; + IF (Instruct /= ERS_SCREG) THEN + + FOR I IN AddrLo_ers TO AddrHi_ers LOOP + Mem(i) := -1; + END LOOP; + ELSE + IF (sect = 1) THEN + FOR I IN SecReg_LoAddr TO SecReg_HiAddr LOOP + Security_Reg1(i) := -1; + END LOOP; + ELSIF (sect = 2) THEN + FOR I IN SecReg_LoAddr TO SecReg_HiAddr LOOP + Security_Reg2(i) := -1; + END LOOP; + ELSE + FOR I IN SecReg_LoAddr TO SecReg_HiAddr LOOP + Security_Reg3(i) := -1; + END LOOP; + END IF; + END IF; + END IF; + IF (EDONE = '1') THEN + IF (current_state /= PG_SUSP_ERS) THEN + BUSY := '0'; + END IF; + WEL := '0'; + IF (ers_screg_flag) THEN + IF (sect = 1) THEN + FOR I IN SecReg_LoAddr TO SecReg_HiAddr LOOP + Security_Reg1(i) := MaxData; + END LOOP; + ELSIF (sect = 2) THEN + FOR I IN SecReg_LoAddr TO SecReg_HiAddr LOOP + Security_Reg2(i) := MaxData; + END LOOP; + ELSE + FOR I IN SecReg_LoAddr TO SecReg_HiAddr LOOP + Security_Reg3(i) := MaxData; + END LOOP; + END IF; + ELSE + FOR I IN AddrLo_ers TO AddrHi_ers LOOP + Mem(i) := MaxData; + END LOOP; + END IF; + END IF; + + IF (Instruct = ERS_PG_SUSP AND current_state = SECTOR_ERS AND + SUSP_FL_IN = '0') THEN + ESUSP <= '1', '0' AFTER 1 ns; + ERSSUSP_in <= '1'; + END IF; + IF (oe AND Instruct = RDSR) THEN + --Read Status Register 1 + sr_read <= true; + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + END IF; + + WHEN BULK_ERS => + IF (current_state'event AND EDONE = '0') THEN + FOR I IN 0 TO AddrRANGE LOOP + Mem(i) := -1; + END LOOP; + END IF; + IF (EDONE = '1') THEN + BUSY := '0'; + WEL := '0'; + FOR I IN 0 TO AddrRANGE LOOP + Mem(i) := MaxData; + END LOOP; + + END IF; + IF (oe AND Instruct = RDSR) THEN + --Read Status Register 1 + sr_read <= true; + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + END IF; + + WHEN ERS_SUSP => + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + sr_read <= false; + pg_screg_flag <= false; + BUSY := '0'; + IF (ERSSUSP_out = '1' AND (Instruct /= ERS_PG_RES)) THEN + ERSSUSP_in <= '0'; + --The BUSY bit in the Status Register will indicate that + --the device is ready for another operation. +-- BUSY := '0'; + --The SuspEND (SUS) bit in the Status Register2 will + --be set to the logical “1” state to indicate that the + --program operation has been suspENDed. + SUS := '1'; + END IF; + IF (ERSRES_out'event AND ERSRES_out = '1') THEN + ERSRES_in <= '0'; + BUSY := '1'; + END IF; + IF (SUS = '1') THEN + IF falling_edge(write) THEN + IF (Instruct = ERS_PG_RES) THEN + SUS := '0'; + ERSRES_in <= '1'; + SUSP_FL_IN <= '1'; + ERES <= '1', '0' AFTER 5 ns; + ELSIF ((Instruct = PP OR (Instruct=QPP AND QE='1')) + AND WEL ='1') THEN + sect := Address / 16#1000#; + IF (sect /= sect_tmp_ers AND + Sec_Prot(sect)='0') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + BUSY := '1'; + SA <= sect; + Addr := Address; + Addr_tmp:= Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + BUSY := '0'; + REPORT "Can't program sector,protected or susp" + SEVERITY NOTE; + END IF; + ELSIF (Instruct = PG_SCREG) THEN + sect := Address / 16#1000#; + IF ((sect <= 3 AND sect >=1) AND + LB_bits(sect-1)='0') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + BUSY := '1'; + SA <= sect; + wr_cnt := Byte_number; + Addr_screg := Address mod 16#1000#; + Addr_screg_tmp := Address mod 16#1000#; + pg_screg_flag <= true; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + WEL := '0'; + END IF; + END IF; + ELSIF (oe) THEN + IF (Instruct = RDSR) THEN + --Read Status Register 1 + sr_read <= true; + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RDSR2) THEN + --Read Status Register 2 + sr_read <= true; + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = READ OR Instruct = FAST_READ) THEN + IF sect /= (read_addr / 16#1000#) THEN + IF (Instruct = READ) THEN + fast_rd <= false; + dual_read <= false; + slow_read <= true; + quad_read <= false; + sr_read <= true; + ELSE + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + sr_read <= false; + END IF; + IF (Mem(read_addr) /= -1) THEN + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + ELSE + SOut_zd <= 'U'; + END IF; + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + IF (read_addr = AddrRANGE) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + REPORT "Can't read suspended sector" + SEVERITY NOTE; + read_cnt := 0; + END IF; + END IF; + ELSIF (Instruct = FAST_DREAD OR + Instruct = FAST_DREAD_2) THEN + IF sect_tmp_ers /= (read_addr / 16#1000#) THEN + fast_rd <= false; + dual_read <= true; + slow_read <= false; + quad_read <= false; + sr_read <= false; + IF (Mem(read_addr) /= -1) THEN + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + ELSE + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + END IF; + read_cnt := read_cnt + 1; + IF (read_cnt = 4) THEN + read_cnt := 0; + IF (read_addr = AddrRANGE) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 4) THEN + REPORT "Can't read suspended sector" + SEVERITY NOTE; + read_cnt := 0; + END IF; + END IF; + ELSIF ((Instruct=FAST_QREAD OR Instruct=W_QREAD + OR Instruct=FAST_QREAD_4 OR Instruct=WOCT_QREAD) + AND QE = '1') THEN + IF sect_tmp_ers /= (read_addr / 16#1000#) THEN + IF ((Instruct=W_QREAD AND + Address mod 2 /= 0) OR + (Instruct=WOCT_QREAD AND + Address mod 16 /=0)) THEN + read_cnt := read_cnt + 1; + IF (read_cnt = 2) THEN + read_cnt := 0; + REPORT "Bad Word Read- Wrong Address" + SEVERITY NOTE; + END IF; + ELSE + fast_rd <= false; + dual_read <= false; + slow_read <= false; + quad_read <= true; + sr_read <= false; + data_out := to_slv(Mem(read_addr),8); + Addr_w := Address; + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 2) THEN + read_cnt := 0; + IF (wrap_byte(4)='0' AND + (Instruct=FAST_QREAD_4 + OR Instruct=W_QREAD)) THEN + ADDRHILO_WRAP(AddrLo_wrap, + AddrHi_wrap,Addr_w,w_size); + IF (read_addr = AddrHi_wrap) THEN + read_addr := AddrLo_wrap; + ELSE + read_addr := read_addr + 1; + END IF; + ELSE + IF (read_addr = AddrRANGE) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 2) THEN + REPORT "Can't read suspended sector" + SEVERITY NOTE; + read_cnt := 0; + END IF; + END IF; + ELSIF (Instruct=RDID OR Instruct=RDID_DUAL OR + Instruct=RDID_QUAD) THEN + IF (read_addr mod 2 = 0) THEN + ident_out2 := to_slv(Manuf_ID,8) & + to_slv(Device_ID1,8); + ELSE + ident_out2 := to_slv(Device_ID1,8) & + to_slv(Manuf_ID,8); + END IF; + read_id <= true; + IF (Instruct = RDID) THEN + fast_rd <= true; + dual_read <= false; + slow_read <= false; + quad_read <= false; + sr_read <= false; + SOut_zd <= ident_out2(15-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 16) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RDID_DUAL) THEN + fast_rd <= false; + dual_read <= true; + slow_read <= false; + quad_read <= false; + sr_read <= false; + SOut_zd <= ident_out2(15-2*read_cnt); + SIOut_zd <= ident_out2(14-2*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + ELSE -- (Instruct = RDID_QUAD) + fast_rd <= false; + dual_read <= false; + slow_read <= false; + quad_read <= true; + sr_read <= false; + HOLDNegOut_zd <= ident_out2(15-4*read_cnt); + WPNegOut_zd <= ident_out2(14-4*read_cnt); + SOut_zd <= ident_out2(13-4*read_cnt); + SIOut_zd <= ident_out2(12-4*read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 4) THEN + read_cnt := 0; + END IF; + END IF; + ELSIF (Instruct = RD_UNIQ_ID) THEN + -- unique ID number is not in data sheet + read_id <= true; + uniq_id := to_slv(Unique_id_2,32)& + to_slv(Unique_id_1,32); + SOut_zd <= uniq_id(63-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 64) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RDIDJ) THEN + read_id <= true; + ident_out := to_slv(Manuf_ID,8) & + to_slv(Device_ID2,8) & to_slv(Device_ID3,8); + SOut_zd <= ident_out(23-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 24) THEN + read_cnt := 0; + END IF; + ELSIF (Instruct = RD_SFDP) THEN + IF (read_addr / 16#100# = 0) THEN + Addr_tmp_2 := (read_addr mod 16#100#); + data_out := to_slv(SFDP_array(Addr_tmp_2),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + IF (read_addr = SFDP_HiAddr) THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + REPORT "Given SFDP address is out of range" + SEVERITY NOTE; + END IF; + END IF; + ELSIF (Instruct = RD_SCREG) THEN + Addr_tmp_2 := read_addr / 16#100#; + Addr_tmp_3 := read_addr mod 16#100#; + IF (Addr_tmp_2 = 16) THEN + -- Security Register No.1 + data_out :=to_slv(Security_Reg1(Addr_tmp_3),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + ELSIF (Addr_tmp_2 = 32) THEN + -- Security Register No.2 + data_out :=to_slv(Security_Reg2(Addr_tmp_3),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + ELSIF (Addr_tmp_2 = 48) THEN + -- Security Register No.2 + data_out :=to_slv(Security_Reg3(Addr_tmp_3),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; +-- END IF; + ELSE + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + REPORT "Security Reg addr is out of range" + SEVERITY NOTE; + END IF; + END IF; + IF (read_cnt = 8) THEN + read_cnt := 0; + IF (read_addr mod 256 = SecReg_HiAddr) THEN + read_addr := (read_addr/256)* + (SecReg_HiAddr+1); + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + END IF; + END IF; + + WHEN DP_DOWN => + IF (oe AND Instruct = RES_RD_ID) THEN + read_id <= true; + data_out := to_slv(Device_ID1,8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF (read_cnt = 8) THEN + read_cnt := 0; + END IF; + END IF; + IF falling_edge(write) THEN + IF (Instruct = RES_RD_ID) THEN + IF res_flag = true THEN + RES2_in <= '1'; + ELSE + RES1_in <= '1'; + END IF; + ELSE + REPORT "Device is in DPD Mode No instructions allowed" + SEVERITY NOTE; + END IF; + END IF; + + END CASE; + + --Output Disable Control + IF (CSNeg_ipd = '1') THEN + SIOut_zd <= 'Z'; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + END IF; + + END PROCESS Functional; + + --------------------------------------------------------------------------- + -- SFDP Process + --------------------------------------------------------------------------- + SFDPPreload: PROCESS + + BEGIN + ----------------------------------------------------------------------- + --SFDP array data + ----------------------------------------------------------------------- + + SFDP_array(16#00#) := 16#53#; + SFDP_array(16#01#) := 16#46#; + SFDP_array(16#02#) := 16#44#; + SFDP_array(16#03#) := 16#50#; + SFDP_array(16#04#) := 16#01#; + SFDP_array(16#05#) := 16#01#; + SFDP_array(16#06#) := 16#00#; + SFDP_array(16#07#) := 16#FF#; + SFDP_array(16#08#) := 16#EF#; + SFDP_array(16#09#) := 16#00#; + SFDP_array(16#0A#) := 16#01#; + SFDP_array(16#0B#) := 16#04#; + SFDP_array(16#0C#) := 16#80#; + SFDP_array(16#0D#) := 16#00#; + SFDP_array(16#0E#) := 16#00#; + SFDP_array(16#0F#) := 16#FF#; + SFDP_array(16#10#) := 16#EF#; + SFDP_array(16#11#) := 16#00#; + SFDP_array(16#12#) := 16#01#; + SFDP_array(16#13#) := 16#00#; + SFDP_array(16#14#) := 16#90#; + SFDP_array(16#15#) := 16#00#; + SFDP_array(16#16#) := 16#00#; + SFDP_array(16#17#) := 16#FF#; + + FOR I IN 24 TO 127 LOOP + SFDP_array(i) := MaxData; + END LOOP; + + SFDP_array(16#80#) := 16#E5#; + SFDP_array(16#81#) := 16#20#; + SFDP_array(16#82#) := 16#F1#; + SFDP_array(16#83#) := 16#FF#; + SFDP_array(16#84#) := 16#FF#; + SFDP_array(16#85#) := 16#FF#; + SFDP_array(16#86#) := 16#FF#; + SFDP_array(16#87#) := 16#07#; + SFDP_array(16#88#) := 16#44#; + SFDP_array(16#89#) := 16#EB#; + SFDP_array(16#8A#) := 16#08#; + SFDP_array(16#8B#) := 16#6B#; + SFDP_array(16#8C#) := 16#08#; + SFDP_array(16#8D#) := 16#3B#; + SFDP_array(16#8E#) := 16#80#; + SFDP_array(16#8F#) := 16#BB#; + + FOR I IN 144 TO 255 LOOP + SFDP_array(i) := MaxData; + END LOOP; + + WAIT; + + END PROCESS SFDPPreload; + + --------------------------------------------------------------------------- + -- Sector Protection Bits + --------------------------------------------------------------------------- + Protect : PROCESS(change_prot_bits) + BEGIN + IF rising_edge(change_prot_bits) THEN + + CASE BP_bits IS + WHEN "000" => + IF (CMP = '0') THEN + Sec_Prot := (others => '0'); + ELSE + Sec_Prot := (others => '1'); + END IF; + WHEN "001" => + IF (CMP = '0') THEN + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(4095 downto 4032) := + (others => '1'); + Sec_Prot(4031 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(63 downto 0) := + (others => '1'); + Sec_Prot(4095 downto 64) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(4095) := '1'; + Sec_Prot(4094 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(0) := '1'; + Sec_Prot(4095 downto 1) := + (others => '0'); + END IF; + ELSE + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(4031 downto 0) := + (others => '1'); + Sec_Prot(4095 downto 4032) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(4095 downto 64) := + (others => '1'); + Sec_Prot(63 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(4094 downto 0) := + (others => '1'); + Sec_Prot(4095) := '0'; + + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(4095 downto 1) := + (others => '1'); + Sec_Prot(0) := '0'; + END IF; + END IF; + WHEN "010" => + IF (CMP = '0') THEN + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(4095 downto 3968) := + (others => '1'); + Sec_Prot(3967 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(127 downto 0) := + (others => '1'); + Sec_Prot(4095 downto 128) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(4095 downto 4094) := + (others => '1'); + Sec_Prot(4093 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(1 downto 0) := + (others => '1'); + Sec_Prot(4095 downto 2) := + (others => '0'); + END IF; + ELSE + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(3967 downto 0) := + (others => '1'); + Sec_Prot(4095 downto 3968) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(4095 downto 128) := + (others => '1'); + Sec_Prot(127 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(4093 downto 0) := + (others => '1'); + Sec_Prot(4095 downto 4094) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(4095 downto 2) := + (others => '1'); + Sec_Prot(1 downto 0) := + (others => '0'); + END IF; + END IF; + + WHEN "011" => + IF (CMP = '0') THEN + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(4095 downto 3840) := + (others => '1'); + Sec_Prot(3839 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(255 downto 0) := + (others => '1'); + Sec_Prot(4095 downto 256) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(4095 downto 4092) := + (others => '1'); + Sec_Prot(4091 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(3 downto 0) := + (others => '1'); + Sec_Prot(4095 downto 4) := + (others => '0'); + END IF; + ELSE + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(3839 downto 0) := + (others => '1'); + Sec_Prot(4095 downto 3840) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(4095 downto 256) := + (others => '1'); + Sec_Prot(255 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(4091 downto 0) := + (others => '1'); + Sec_Prot(4095 downto 4092) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(4095 downto 4) := + (others => '1'); + Sec_Prot(3 downto 0) := + (others => '0'); + END IF; + END IF; + + WHEN "100" => + IF (CMP = '0') THEN + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(4095 downto 3584) := + (others => '1'); + Sec_Prot(3583 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(511 downto 0) := + (others => '1'); + Sec_Prot(4095 downto 512) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(4095 downto 4088) := + (others => '1'); + Sec_Prot(4087 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(7 downto 0) := + (others => '1'); + Sec_Prot(4095 downto 8) := + (others => '0'); + END IF; + ELSE + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(3583 downto 0) := + (others => '1'); + Sec_Prot(4095 downto 3584) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(4095 downto 512) := + (others => '1'); + Sec_Prot(511 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(4087 downto 0) := + (others => '1'); + Sec_Prot(4095 downto 4088) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(4095 downto 8) := + (others => '1'); + Sec_Prot(7 downto 0) := + (others => '0'); + END IF; + END IF; + + WHEN "101" => + IF (CMP = '0') THEN + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(4095 downto 3072) := + (others => '1'); + Sec_Prot(3071 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(1023 downto 0) := + (others => '1'); + Sec_Prot(4095 downto 1024) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(4095 downto 4088) := + (others => '1'); + Sec_Prot(4087 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(7 downto 0) := + (others => '1'); + Sec_Prot(4095 downto 8) := + (others => '0'); + END IF; + ELSE + IF Status_reg1(6 downto 5) = to_slv(16#00#,2) THEN + Sec_Prot(3071 downto 0) := + (others => '1'); + Sec_Prot(4095 downto 3072) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#01#,2) THEN + Sec_Prot(4095 downto 1024) := + (others => '1'); + Sec_Prot(1023 downto 0) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#02#,2) THEN + Sec_Prot(4087 downto 0) := + (others => '1'); + Sec_Prot(4095 downto 4088) := + (others => '0'); + ELSIF Status_reg1(6 downto 5) = to_slv(16#03#,2) THEN + Sec_Prot(4095 downto 8) := + (others => '1'); + Sec_Prot(7 downto 0) := + (others => '0'); + END IF; + END IF; + + WHEN "110" => + IF (CMP = '0') THEN + IF (SEC = '0' AND TB = '0') THEN + Sec_Prot(4095 downto 2048) := (others => '1'); + Sec_Prot(2047 downto 0) := (others => '0'); + ELSIF (SEC = '0' AND TB = '1') THEN + Sec_Prot(2047 downto 0) := (others => '1'); + Sec_Prot(4095 downto 2048) := (others => '0'); + END IF; + ELSE + IF (SEC = '0' AND TB = '0') THEN + Sec_Prot(4095 downto 2048) := (others => '0'); + Sec_Prot(2047 downto 0) := (others => '1'); + ELSIF (SEC = '0' AND TB = '1') THEN + Sec_Prot(4095 downto 2048) := (others => '1'); + Sec_Prot(2047 downto 0) := (others => '0'); + END IF; + END IF; + + WHEN "111" => + IF (CMP = '0') THEN + Sec_Prot(4095 downto 0) := (others => '1'); + ELSE + Sec_Prot(4095 downto 0) := (others => '0'); + END IF; + WHEN OTHERS => + Sec_Prot := (OTHERS => '1'); + END CASE; -- end of CASE BP_bits + END IF; + END PROCESS Protect; + + HOLD_FRAME_ON_PO_ZD : PROCESS(SOut_zd, SIOut_zd, HOLDNegIn) + BEGIN + IF (HOLDNegIn = '0' AND QE /= '1') THEN + hold_mode := TRUE; + SIOut_z <= 'Z'; + SOut_z <= 'Z'; + ELSE + IF hold_mode THEN + SIOut_z <= SIOut_zd AFTER tpd_HOLDNeg_SO(trz0); + SOut_z <= SOut_zd AFTER tpd_HOLDNeg_SO(trz0); + hold_mode := FALSE; + ELSE + SIOut_z <= SIOut_zd; + SOut_z <= SOut_zd; + hold_mode := FALSE; + END IF; + END IF; + END PROCESS HOLD_FRAME_ON_PO_ZD; + + HOLD_PULL_UP : PROCESS(HOLDNegIn) + BEGIN + IF (QE = '0') THEN + IF (HOLDNegIn = 'Z') THEN + HOLDNeg_pullup <= '1'; + ELSE + HOLDNeg_pullup <= HOLDNegIn; + END IF; + END IF; + END PROCESS HOLD_PULL_UP; + + WP_PULL_UP : PROCESS(WPNegIn) + BEGIN + IF (QE = '0') THEN + IF (WPNegIn = 'Z') THEN + WPNeg_pullup <= '1'; + ELSE + WPNeg_pullup <= WPNegIn; + END IF; + END IF; + END PROCESS WP_PULL_UP; + + --------------------------------------------------------------------------- + ---- File Read Section - Preload Control + --------------------------------------------------------------------------- + + MemPreload: PROCESS + -- text file input variables + FILE mem_file : text is mem_file_name; + FILE screg_file : text is screg_file_name; + VARIABLE ind : NATURAL RANGE 0 TO AddrRANGE:= 0; + VARIABLE screg_ind: NATURAL RANGE 16#00# TO 16#2FF#:= 16#00#; + VARIABLE buf : line; + + BEGIN + -- memory preload + IF (mem_file_name (1 to 4)/= "none" AND UserPreload) THEN + ind := 0; + Mem := (OTHERS => MaxData); + WHILE (not ENDFILE (mem_file)) LOOP + READLINE (mem_file, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 7)); --address + ELSE + IF ind <= AddrRANGE THEN + Mem(ind) := h(buf(1 to 2)); + END IF; + IF ind < AddrRANGE THEN + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + ----------------------------------------------------------------------- + -- Security Register Preload + ----------------------------------------------------------------------- + + IF (screg_file_name(1 to 4) /= "none" AND UserPreload) THEN + ind := 0; + Security_Reg1 := (OTHERS => MaxData); + Security_Reg2 := (OTHERS => MaxData); + Security_Reg3 := (OTHERS => MaxData); + WHILE (not ENDFILE (screg_file)) LOOP + READLINE (screg_file, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + screg_ind := h(buf(2 to 4)); --address + ELSE + IF screg_ind <= 16#0FF# THEN + Security_Reg1(screg_ind) := h(buf(1 to 2)); + ELSIF screg_ind>=16#100# AND screg_ind<=16#1FF# THEN + Security_Reg2(screg_ind-16#100#) := h(buf(1 to 2)); + ELSIF screg_ind>=16#200# AND screg_ind<=16#2FF# THEN + Security_Reg3(screg_ind-16#200#) := h(buf(1 to 2)); + END IF; + IF (screg_ind mod 16#100#) < 16#FF# THEN + screg_ind := screg_ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + WAIT; + END PROCESS MemPreload; + + --------------------------------------------------------------------------- + -- Path Delay Section + --------------------------------------------------------------------------- + + S_Out_PathDelay_Gen : PROCESS(SOut_z) + + VARIABLE SO_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => SOut, + OutSignalName => "SO", + OutTemp => SOut_z, + Mode => VitalTransport, + GlitchData => SO_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_0), + PathCondition => SOut_z /= 'Z' AND NOT(read_id)), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_1), + PathCondition => SOut_z /= 'Z' AND read_id), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1'), + 3 => (InputChangeTime => HOLDNegIn'LAST_EVENT, + PathDelay => tpd_HOLDNeg_SO, + PathCondition => QE = '0') + ) + ); + END PROCESS; + + SI_Out_PathDelay : PROCESS(SIOut_z) + + VARIABLE SI_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => SIOut, + OutSignalName => "SI", + OutTemp => SIOut_z, + Mode => VitalTransport, + GlitchData => SI_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_0), + PathCondition => SIOut_z /= 'Z' AND NOT(read_id)), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_1), + PathCondition => SIOut_z /= 'Z' AND read_id), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND SIOut_zd = 'Z'), + 3 => (InputChangeTime => HOLDNegIn'LAST_EVENT, + PathDelay => tpd_HOLDNeg_SO, + PathCondition => SIOut_z /= 'Z' AND QE = '0') + ) + ); + END PROCESS; + + HOLD_Out_PathDelay : PROCESS(HOLDNegOut_zd) + + VARIABLE HOLD_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => HOLDNegOut, + OutSignalName => "HOLDNeg", + OutTemp => HOLDNegOut_zd, + GlitchData => HOLD_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_0), + PathCondition => HOLDNegOut_zd /= 'Z' --AND quad_read + AND QE = '1' AND NOT(read_id)), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_1), + PathCondition => HOLDNegOut_zd /= 'Z' --AND quad_read + AND QE = '1' AND read_id), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND --quad_read AND + HOLDNegOut_zd = 'Z' AND QE = '1') + ) + ); + END PROCESS; + + WP_Out_PathDelay : PROCESS(WPNegOut_zd) + + VARIABLE WP_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => WPNegOut, + OutSignalName => "WPNeg", + OutTemp => WPNegOut_zd, + GlitchData => WP_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_0), + PathCondition => WPNegOut_zd /= 'Z' --AND quad_read + AND QE = '1' AND NOT(read_id)), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_RDID_EQ_1), + PathCondition => WPNegOut_zd /= 'Z' -- AND quad_read + AND QE = '1' AND read_id), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND --quad_read AND + WPNegOut_zd = 'Z' AND QE = '1') + ) + ); + END PROCESS; + + END BLOCK behavior; +END vhdl_behavioral; \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl128k/model/s25fl128k_ver.ftm b/lib/models/memory/flash/serial/S25fl128k/model/s25fl128k_ver.ftm new file mode 100644 index 0000000..581567c --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128k/model/s25fl128k_ver.ftm @@ -0,0 +1,65 @@ + +FMF Timing for s25fl128k Parts + + +version: | author: | mod date: | changes made: + V1.0 R. Prokopovic 10 Oct 08 Initial release + +1ns +s25fl128k + +S25FL128KOXMFI000 Spansion, S25FL128K, JULY 22,2010 +S25FL128KOXMFI001 Spansion, S25FL128K, JULY 22,2010 +S25FL128KOXMFI003 Spansion, S25FL128K, JULY 22,2010 +The values listed are for VCC=2.7V to 3.6V, +Industrial Ta=-40 to +85 Celsius + +(DELAY(ABSOLUTE + (COND ~read_id (IOPATH SCK SO (5:6:7) (5:6:7) () (5:6:7) () (5:6:7))) + (COND (~glitch || quad_read) && read_id (IOPATH SCK SO (5.5:7:8.5) (5.5:7:8.5) () (5.5:7:8.5) () (5.5:7:8.5))) + (COND CSNeg (IOPATH CSNeg SO () () (5:6:7) () (5:6:7) ())) + (COND ~quad_read (IOPATH HOLDNeg SO () () (8:10:12) (5:6:7) (8:10:12) (5:6:7))) + (COND (dual_read || quad_read) && ~read_id (IOPATH SCK SI (5:6:7) (5:6:7) () (5:6:7) () (5:6:7))) + (COND dual_read && read_id && ~glitch (IOPATH SCK SI (5.5:7:8.5) (5.5:7:8.5) () (5.5:7:8.5) () (5.5:7:8.5))) + (COND quad_read && read_id (IOPATH SCK SI (5.5:7:8.5) (5.5:7:8.5) () (5.5:7:8.5) () (5.5:7:8.5))) + (COND CSNeg && ~deg_sin (IOPATH CSNeg SI () () (5:6:7) () (5:6:7) ())) + (COND ~quad_read && dual_read (IOPATH HOLDNeg SI () () (8:10:12) (5:6:7) (8:10:12) (5:6:7))) + (COND quad_read && ~read_id (IOPATH SCK WPNeg (5:6:7) (5:6:7) () (5:6:7) () (5:6:7))) + (COND quad_read && read_id (IOPATH SCK WPNeg (5.5:7:8.5) (5.5:7:8.5) () (5.5:7:8.5) () (5.5:7:8.5))) + (COND quad_read && ~read_id (IOPATH SCK HOLDNeg (5:6:7) (5:6:7) () (5:6:7) () (5:6:7))) + (COND quad_read && read_id (IOPATH SCK HOLDNeg (5.5:7:8.5) (5.5:7:8.5) () (5.5:7:8.5) () (5.5:7:8.5))) + (COND CSNeg && QE (IOPATH CSNeg SI () () (5:6:7) () (5:6:7) ())) + (COND CSNeg && QE (IOPATH CSNeg WPNeg () () (5:6:7) () (5:6:7) ())) + (COND CSNeg && QE (IOPATH CSNeg HOLDNeg () () (5:6:7) () (5:6:7) ())) +)) +(TIMINGCHECK + (SETUP CSNeg (posedge SCK) (5)) + (SETUP SI (COND deg_sin(posedge SCK)) (2)) + (SETUP SO (COND quad_pg(posedge SCK)) (2)) + (SETUP WPNeg (COND quad_pg(posedge SCK)) (2)) + (SETUP HOLDNeg (COND quad_pg(posedge SCK)) (2)) + (SETUP HOLDNeg (COND hold_cond(posedge SCK)) (5)) + (SETUP WPNeg CSNeg (20)) + + (HOLD CSNeg SCK (5)) + (HOLD SI (COND deg_sin (posedge SCK)) (5)) + (HOLD SO (COND quad_pg (posedge SCK)) (5)) + (HOLD WPNeg (COND quad_pg (posedge SCK)) (5)) + (HOLD HOLDNeg (COND quad_pg (posedge SCK)) (5)) + (HOLD HOLDNeg (COND hold_cond(posedge SCK)) (5)) + (HOLD WPNeg (COND wr_prot (posedge CSNeg)) (100)) + + (WIDTH (COND rd_slow (posedge SCK)) (8)) + (WIDTH (COND rd_slow (negedge SCK)) (8)) + (WIDTH (COND rd_fast (posedge SCK)) (4)) + (WIDTH (COND rd_fast (negedge SCK)) (4)) + (WIDTH (COND quad_spi (posedge SCK)) (6)) + (WIDTH (COND quad_spi (negedge SCK)) (6)) + (WIDTH (COND any_read (posedge CSNeg)) (10)) + (WIDTH (COND pg_ers (posedge CSNeg)) (50)) + (PERIOD (COND rd_slow SCK) (16)) + (PERIOD (COND rd_fast SCK) (8)) + (PERIOD (COND quad_spi SCK) (12)) +) + + \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl128k/model/s25fl128k_vhd.ftm b/lib/models/memory/flash/serial/S25fl128k/model/s25fl128k_vhd.ftm new file mode 100644 index 0000000..14c4dec --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128k/model/s25fl128k_vhd.ftm @@ -0,0 +1,81 @@ + +FMF Timing for s25fl128k Parts + + +version: | author: | mod date: | changes made: + V1.0 R. Prokopovic 10 Oct 05 Initial release + +1ns +s25fl128k + +S25FL128KOXMFI000 Spansion, S25FL128K, JULY 22,2010 +S25FL128KOXMFI001 Spansion, S25FL128K, JULY 22,2010 +S25FL128KOXMFI003 Spansion, S25FL128K, JULY 22,2010 +The values listed are for VCC=2.7V to 3.6V, +Industrial Ta=-40 to +85 Celsius + +(DELAY(ABSOLUTE + (COND RDID == 0 (IOPATH SCK SO (5:6:7) (5:6:7) () (5:6:7) () (5:6:7))) + (COND RDID == 1 (IOPATH SCK SO (5.5:7:8.5) (5.5:7:8.5) () (5.5:7:8.5) () (5.5:7:8.5))) + (IOPATH CSNeg SO () () (5:6:7) () (5:6:7) ()) + (IOPATH HOLDNeg SO () () (8:10:12) (5:6:7) (8:10:12) (5:6:7)) + )) + (TIMINGCHECK + (SETUP CSNeg SCK (5)) + (SETUP (COND normal SI) (posedge SCK) (2)) + (SETUP HOLDNeg SCK (5)) + (SETUP WPNeg CSNeg (20)) + + (HOLD CSNeg SCK (5)) + (HOLD (COND normal SI) (posedge SCK) (5)) + (HOLD HOLDNeg SCK (5)) + (HOLD WPNeg CSNeg (100)) + + (WIDTH (COND slow (posedge SCK)) (8)) + (WIDTH (COND slow (negedge SCK)) (8)) + (WIDTH (COND fast (posedge SCK)) (4)) + (WIDTH (COND fast (negedge SCK)) (4)) + (WIDTH (COND quad (posedge SCK)) (6)) + (WIDTH (COND quad (negedge SCK)) (6)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pger (posedge CSNeg)) (50)) + (PERIOD (COND slow SCK) (16)) + (PERIOD (COND fast SCK) (8)) + (PERIOD (COND quad SCK) (12)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP) (DELAY (ABSOLUTE (DEVICE(400000:700000:3000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BP1) (DELAY (ABSOLUTE (DEVICE(15000:30000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BP2) (DELAY (ABSOLUTE (DEVICE(1000:2500:12000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE) (DELAY (ABSOLUTE (DEVICE(10000000:30000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE1) (DELAY (ABSOLUTE (DEVICE(5e7:12e7:8e8) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE2) (DELAY (ABSOLUTE (DEVICE(5e7:15e7:1e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/CE) (DELAY (ABSOLUTE (DEVICE(15e9:25e9:40e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(10000:10000:10000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/DP) (DELAY (ABSOLUTE (DEVICE(3000:3000:3000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/RES1) (DELAY (ABSOLUTE (DEVICE(3000:3000:3000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/RES2) (DELAY (ABSOLUTE (DEVICE(1800:1800:1800) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/ERSSUSP) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PRGSUSP) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PRGRES) (DELAY (ABSOLUTE (DEVICE(200:200:200) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/ERSRES) (DELAY (ABSOLUTE (DEVICE(200:200:200) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WRR) (DELAY (ABSOLUTE(DEVICE(15000000:15000000:15000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SUSP_DLY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl128k/utilities/CreateSDF/mk_sdf.cmd b/lib/models/memory/flash/serial/S25fl128k/utilities/CreateSDF/mk_sdf.cmd new file mode 100644 index 0000000..f6d6cc7 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128k/utilities/CreateSDF/mk_sdf.cmd @@ -0,0 +1,10 @@ +SET sdffile_suffix .sdf +SET use_global_timing_dir false +SET timingfile_dir /user/USERNAME/CreateSDF +SET timingfile_suffix .ftm +SET time_scale 1ns +SET local_path . +SET vendor MODELSIM_HOME +SET diagnostics on +SET vhdl_file testbench.vhd +SET lwb false diff --git a/lib/models/memory/flash/serial/S25fl128k/utilities/CreateSDF/mk_sdf_204.pl b/lib/models/memory/flash/serial/S25fl128k/utilities/CreateSDF/mk_sdf_204.pl new file mode 100644 index 0000000..5f2f2b8 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128k/utilities/CreateSDF/mk_sdf_204.pl @@ -0,0 +1,462 @@ +#!/usr/local/bin/perl +# +# mk_sdf : Perl replacement for C mk_sdf +# +# Copyright (C) 2000, 1999 Free Model Foundry; http:/vhdl.org/fmf/ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# Author : R. Munden +# Date : 20001115 +# Version : 2.0.4 +# +# Revision history: +# 2.0: 19990702 +# o Intial release of perl version +# 2.0.1: 19990722 +# o fixed problem with . in path for TimingModels +# 2.0.2: 20000616 +# o changed instance search to work with Mentor +# 2.0.3: 20001115 +# o changed to parse ":" without leading space +# o fixed problem with . in path for TimingModels again +# 2.0.4: 20030405 +# o chaged SDF version to 3.0 +# +################################################################# +# +# command line arguments: + +# ARGV[0] - name of VHDL netlist + +# global variables: + +# %component_list - list of instance names by component name +# %instance_isin - list architectures by instances contained therein +# %instance_comp - list of component names by instance name +# %comp_lib - library each component (by name) is configured to +# @instance_list - array of all instance names in design in order found + +$version = "2.0.4"; +$design_name = ''; +$timing_dir = ''; +$diags = "off"; + +%keywords = (architecture => 1, + component => 1, + timingmodel => 1); + +# INPUT files +$CMD = "mk_sdf.cmd"; +$VHD = ''; # name of VHDL netlist + +# OUTPUT files +$RFV = "/tmp/short.vhd"; # reformatted VHDL +$sdf_file = ''; # name of SDF file + +&read_cmd_file; +&get_names; +&reformat; + +open INPUT, $RFV; +@lines = ; +close INPUT; + +$current_architecture = ""; + +foreach $line (@lines) +{ + @words = split / /, $line; + foreach $word (@words) + { + $keywords{$word} == "1" and do { &$word(@words);}; + if ($component_list{$word}) + { + $line =~ /(.+) : $word/ and do { + if ($1 !~ /for/) { # instantiation found + $component_list{$word} = $component_list{$word} . $1; + push (@instance_list, $1); + $instance_name = $1; + } + }; + $instance_comp{$1} = $word; + $instance_isin{$1} = $current_architecture; + if ( $diags ne off ) { + print "reading instance $instance_name: $word in $current_architecture\n"; + } + $line =~ /for all : $word use entity (.+)/ and do + { + @config = split(/\./, $1); + $comp_lib{$word} = $config[0];}; + } + } +} +if ( $diags ne off ) { + print "finished with netlist\n\n"; +} + +&begin_sdf; +&build_paths; +&close_sdf; +`rm $RFV`; + +print "$time\n"; + +sub architecture +{ + $current_architecture = $_[3]; + push (@architectures, $current_architecture); +} + +sub component +{ + if ($_[0] ne "end") + { + $name = $_[1]; + $arch_list{$current_architecture} = + $arch_list{$current_architecture} . " " . $name; + unless ($component_list{$name}) { $component_list{$name} = " ";} + } +} + +sub timingmodel +{ + $line =~ /timingmodel => \"(.+)\"/ and do { + $model = $1; + $model_name{$instance_name} = $model; + }; +} + +sub begin_sdf +{ + if ( $diags ne off ) { + print "writing SDF boilerplate\n"; + } + $time = localtime; + if (open(SDF, ">$sdf_file") !=1) { die "can't open $sdf_file\n";} + print "Opening $sdf_file\n"; + print SDF "(DELAYFILE\n"; + print SDF " (SDFVERSION \"3.0\")\n"; + print SDF " (DESIGN \"$design_name\")\n"; + print SDF " (DATE \"$time\")\n"; + print SDF " (VENDOR \"Free Model Foundry\")\n"; + print SDF " (PROGRAM \"SDF timing utility(tm)\")\n"; + print SDF " (VERSION \"$version\")\n"; + print SDF " (DIVIDER /)\n"; + print SDF " (VOLTAGE)\n"; + print SDF " (PROCESS)\n"; + print SDF " (TEMPERATURE)\n"; + print SDF " (TIMESCALE 1ns)\n"; +} + +sub build_paths +{ + foreach $instance_list (@instance_list) + { + @instance = $instance_list; + foreach $instance (@instance) + { + if ( $diags ne off ) { + print "working on $instance\n"; + } + if ($gtd =~ /true/i) { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; +# $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}./$timing_dir"; + } else { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; + } + $timing_file = "$path/$instance_comp{$instance}_vhd.ftm"; + $timing_file =~ s/\s//; + if ( $diags ne off ) { + print "$instance should be in $timing_file\n"; + } + if (-e $timing_file) { + if ($model_name{$instance} ne "") { + print SDF " (CELL\n"; + print SDF " (CELLTYPE \"$instance_comp{$instance}\")\n"; + $inst = $instance; + $full_inst = $instance; + while ($component_list{$instance_isin{$inst}}) { + $full_inst = "$component_list{$instance_isin{$inst}}/$full_inst"; + $full_inst =~ s/\s+//; + $inst = $component_list{$instance_isin{$inst}}; + $inst =~ s/\s+//; +# print SDF " (INSTANCE $component_list{$instance_isin{$instance}}/$instance)\n"; + } + print SDF " (INSTANCE $full_inst)\n"; + &add_timing; + } + } else { + if ( $diags ne off ) { + print "$timing_file not found!\n"; + } + } + } + } +} + +sub add_timing +{ + $timing_found = "false"; + $part_found = "false"; +# unless ($lib_path{$comp_lib{$instance_comp{$instance}}}) + unless ($timing_file) + { + print "path to $timing_file not found\n"; + exit; + } + if ($gtd =~ /true/i) { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; +# $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}./$timing_dir"; + } else { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; + } + $timing_file = "$path/$instance_comp{$instance}_vhd.ftm"; + if (open(TF, "<$timing_file") !=1) { warn "can't open $timing_file\n"; } + if ( $diags ne off ) { + print "reading $timing_file\n"; + } + $section_found = "false"; + while () + { + next unless (/$model_name{$instance}/i || ($part_found eq "true")); + $part_found = "true"; + if ( $diags ne off ) { + print "found entry for $model_name{$instance}\n"; + } + next unless (//i || ($timing_found eq "true")); + $timing_found = "true"; + next if (//i); + if (/<\/timing>/i) + { + print SDF " )\n"; + $timing_found = "false"; + $part_found = "false"; + $section_found = "true"; + last; + } else { + if (/%LABEL%/) + { + if ($component_list{$instance_isin{$instance}}) + { + $_ =~ s/%LABEL%/$component_list{$instance_isin{$instance}}\/$instance/; + } else { + $_ =~ s/%LABEL%/$instance/; + } + } + print SDF $_; + } + } + unless ($section_found eq "true") { + print "$model_name not found\n"; + } +} + +sub close_sdf +{ + print SDF ")\n"; + print "closing $sdf_file\n"; + close(SDF); +} + +# read mk_sdf.cmd + +sub read_cmd_file { + + if (open(CMD, $CMD) !=1) { die "can't open $CMD\n"; } + while () { + chop; + @fields = ''; + @fields = split; + unless ($fields[0] =~ /#/) { + if ($fields[0] =~ /SET/) { + if ($fields[1] =~ /vhdl_file/) {$VHD = $fields[2]} + if ($fields[1] =~ /sdffile_suffix/) {$suffix = $fields[2]} + if ($fields[1] =~ /use_global_timing_dir/) {$gtd = $fields[2]} + if ($fields[1] =~ /timingfile_dir/) {$timing_dir = $fields[2]} + if ($fields[1] =~ /vendor/) {$vendor = $fields[2]} + if ($fields[1] =~ /diagnostics/) {$diags = $fields[2]} + } + } + } + if ( $diags ne off ) { + print "\nmk_sdf diagnostics on\n\n"; + print "vhdl_file $VHD\n"; + print "sdffile_suffix $suffix\n"; + print "use_global_timing_dir $gtd\n"; + print "timingfile_dir $timing_dir\n"; + print "vendor $vendor\n\n"; + } +} +# + +# get name of netlist + +sub get_names +{ + + if ($ARGV[0] ne "") { $VHD = "$ARGV[0]"; } + + if ($ARGV[1] eq "") + { + @name = split(/\./,$VHD); + $design_name = $name[0]; + } else { + $design_name = "$ARGV[1]"; + } + $sdf_file = $design_name . $suffix; + if ($gtd =~ /false/i) + { + if ($vendor =~ /modeltech/i) { &read_mti; } + if ($vendor =~ /cadence/i) { &read_cds; } + } + if ( $diags ne off ) { + print "design name is $design_name\n\n"; + } +} +# +################################################################ +# + +# reformat netlist + +sub reformat +{ + $entfound = false; + + if (open(VHD, $VHD) !=1) { die "can't open $VHD\n"; } + if (open(OUT, ">$RFV") !=1) { die "can't open $OUT\n"; } + + while () { + if (/^--|library|package/i) { next } + if (/--/) { # strip embeded comments + @line = split("--"); + $_ = $line[0]; + } + s/:/ : /g; + s/;/ ;/g; + s/\s+/ /g; # reduces spaces and tabs + s/^\s//g; # no leading spaces + if (/entity/i) { + $entfound = "true"; + } + chomp; + if ( $entfound eq true ) { + print OUT lc($_); + if (/;|is|begin/i) { print OUT "\n"; } + } + } + + close OUT; + if ( $diags ne off ) { + print "reformatted netlist written to $RFV\n\n"; + } + +} + +# read ModelTech's modelsim.ini file + +sub read_mti +{ + $lib_found = "false"; + if ($ENV{MODELPATH}) + { + $ini_file = "$ENV{MODELPATH}/../modelsim.ini"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + if ($lib_found eq "true") + { + chomp; + if (/\[.+\]/) { last; } + s/\s+//; + @lib_line = split(/=/); + $lib_line[1] =~ s/\/work//; + $lib_path{$lib_line[0]} = $lib_line[1]; + } elsif (/\[Library\]/i) + { + $lib_found = "true"; + next; + } + } + } else { + print "\$MODELPATH environment variable not found\n"; + } + $lib_found = "false"; + if (-e "modelsim.ini") + { + $ini_file = "modelsim.ini"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + if ($lib_found eq "true") + { + chomp; + if (/\[.+\]/) { last; } + s/\s+//; + @lib_line = split(/=/); + $lib_line[1] =~ s/\/work//; + $lib_path{$lib_line[0]} = $lib_line[1]; + } elsif (/\[Library\]/i) + { + $lib_found = "true"; + next; + } + } + } else { + print "local modelsim.ini file not found, may not be needed\n"; + } +} + +# read Cadence's cds.lib file + +sub read_cds +{ + if ($ENV{CDS_VHDL}) + { + $ini_file = "$ENV{CDS_VHDL}/files/cds.lib"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + chomp; + s/\s+/ /; + if (/define/i) + { + @lib_line = split; + $lib_path{$lib_line[1]} = $lib_line[2]; + } + } + } else { + print "\$CDS_VHDL environment variable not found\n"; + } + if (-e "cds.lib") + { + $ini_file = "cds.lib"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + chomp; + s/\s+/ /; + if (/define/i) + { + @lib_line = split; + $lib_path{$lib_line[1]} = $lib_line[2]; + } + } + } else { + print "local cds.lib file not found, may not be needed\n"; + } +} diff --git a/lib/models/memory/flash/serial/S25fl128k/utilities/CreateSDF/my_mem_vhd.ftm b/lib/models/memory/flash/serial/S25fl128k/utilities/CreateSDF/my_mem_vhd.ftm new file mode 100644 index 0000000..2fc35c2 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128k/utilities/CreateSDF/my_mem_vhd.ftm @@ -0,0 +1,205 @@ + +FMF Timing for testbench Parts + + +version: | author: | mod date: | changes made: + V1.0 VHD2FTM 03 July 11 Initial release + +1ns +am29lv640m + +MY_MEM +AM29LV640MH90R +AM29LV640ML90R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (90:90:90) (90:90:90)) + (IOPATH A0 DQ1 (25:25:25) (25:25:25)) + (IOPATH CENeg DQ0 (85:85:85) (85:85:85) (11:11:11) (85:85:85) (11:11:11) (85:85:85)) + (IOPATH OENeg DQ0 (20:20:20) (20:20:20) (11:11:11) (20:20:20) (11:11:11) (20:20:20)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (90)) + (IOPATH WENeg RY (0) (90)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (90:90:90)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH101 +AM29LV640ML101 +AM29LV640MH101R +AM29LV640ML101R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (100:100:100) (100:100:100)) + (IOPATH A0 DQ1 (30:30:30) (30:30:30)) + (IOPATH CENeg DQ0 (95:95:95) (95:95:95) (11:11:11) (95:95:95) (11:11:11) (95:95:95)) + (IOPATH OENeg DQ0 (25:25:25) (25:25:25) (11:11:11) (25:25:25) (11:11:11) (25:25:25)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (100)) + (IOPATH WENeg RY (0) (100)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (100:100:100)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH112 +AM29LV640ML112 +AM29LV640MH112R +AM29LV640ML112R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (110:110:110) (110:110:110)) + (IOPATH A0 DQ1 (40:40:40) (40:40:40)) + (IOPATH CENeg DQ0 (105:105:105) (105:105:105) (11:11:11) (105:105:105) (11:11:11) (105:105:105)) + (IOPATH OENeg DQ0 (35:35:35) (35:35:35) (11:11:11) (35:35:35) (11:11:11) (35:35:35)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (110)) + (IOPATH WENeg RY (0) (110)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (110:110:110)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH120 +AM29LV640ML120 +AM29LV640MH120R +AM29LV640ML120R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (120:120:120) (120:120:120)) + (IOPATH A0 DQ1 (40:40:40) (40:40:40)) + (IOPATH CENeg DQ0 (115:115:115) (115:115:115) (11:11:11) (115:115:115) (11:11:11) (115:115:115)) + (IOPATH OENeg DQ0 (35:35:35) (35:35:35) (11:11:11) (35:35:35) (11:11:11) (35:35:35)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (120)) + (IOPATH WENeg RY (0) (120)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (120:120:120)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + diff --git a/lib/models/memory/flash/serial/S25fl128k/utilities/CreateSDF/testbench.sdf b/lib/models/memory/flash/serial/S25fl128k/utilities/CreateSDF/testbench.sdf new file mode 100644 index 0000000..02495dd --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128k/utilities/CreateSDF/testbench.sdf @@ -0,0 +1,58 @@ +(DELAYFILE + (SDFVERSION "3.0") + (DESIGN "testbench") + (DATE "Wed Jan 28 15:15:41 2004") + (VENDOR "Free Model Foundry") + (PROGRAM "SDF timing utility(tm)") + (VERSION "2.0.4") + (DIVIDER /) + (VOLTAGE) + (PROCESS) + (TEMPERATURE) + (TIMESCALE 1ns) + (CELL + (CELLTYPE "my_mem") + (INSTANCE dut) + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (90:90:90) (90:90:90)) + (IOPATH A0 DQ1 (25:25:25) (25:25:25)) + (IOPATH CENeg DQ0 (85:85:85) (85:85:85) (11:11:11) (85:85:85) (11:11:11) (85:85:85)) + (IOPATH OENeg DQ0 (20:20:20) (20:20:20) (11:11:11) (20:20:20) (11:11:11) (20:20:20)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (90)) + (IOPATH WENeg RY (0) (90)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (90:90:90)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + ) +) diff --git a/lib/models/memory/flash/serial/S25fl128k/utilities/CreateSDF/testbench.vhd b/lib/models/memory/flash/serial/S25fl128k/utilities/CreateSDF/testbench.vhd new file mode 100644 index 0000000..c7d852a --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128k/utilities/CreateSDF/testbench.vhd @@ -0,0 +1,1606 @@ +------------------------------------------------------------------------------ +-- File name : testbench_640.vhd +------------------------------------------------------------------------------- +-- Copyright (C) 2003 AMD. +-- +-- MODIFICATION HISTORY : +-- +-- version: | author: | mod date: | changes made: +-- V0.1 M.Marinkovic 11 July 03 Initial +-- v0.2 M.Marinkovic 28 Aug 03 Changed protected sector selection +-- +------------------------------------------------------------------------------- +-- PART DESCRIPTION: +-- +-- Description: +-- Generic test enviroment for verification of AMD flash memory +-- VITAL models.my_mem +-- +------------------------------------------------------------------------------- +-- Note: VHDL code formating not done +-- For High/Low sector protection selection change: +-- TimingModel constant and TimingModel generic value +-- +------------------------------------------------------------------------------- +LIBRARY IEEE; + USE IEEE.std_logic_1164.ALL; +--USE IEEE.VITAL_timing.ALL; +--USE IEEE.VITAL_primitives.ALL; + USE STD.textio.ALL; + +LIBRARY VITAL2000; + USE VITAL2000.vital_timing.ALL; + USE VITAL2000.vital_primitives.ALL; + +LIBRARY FMF; + USE FMF.gen_utils.ALL; + USE FMF.conversions.ALL; + + +LIBRARY work; + USE work.amd_tc_pkg.ALL; + +------------------------------------------------------------------------------- +-- ENTITY DECLARATION +------------------------------------------------------------------------------- +ENTITY testbench_640 IS +END testbench_640; + + +------------------------------------------------------------------------------- +-- ARCHITECTURE DECLARATION +------------------------------------------------------------------------------- +ARCHITECTURE vhdl_behavioral of testbench_640 IS + COMPONENT my_mem + GENERIC ( + -- tipd delays: interconnect path delays + tipd_A0 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A1 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A2 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A3 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A4 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A5 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A6 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A7 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A8 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A9 : VitalDelayType01 := VitalZeroDelay01; --address + tipd_A10 : VitalDelayType01 := VitalZeroDelay01; --lines + tipd_A11 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A12 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A13 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A14 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A15 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A16 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A17 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A18 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A19 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A20 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A21 : VitalDelayType01 := VitalZeroDelay01; -- + + tipd_DQ0 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ1 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ2 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ3 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ4 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ5 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ6 : VitalDelayType01 := VitalZeroDelay01; -- data + tipd_DQ7 : VitalDelayType01 := VitalZeroDelay01; -- lines + tipd_DQ8 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ9 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ10 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ11 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ12 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ13 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ14 : VitalDelayType01 := VitalZeroDelay01; -- + + tipd_DQ15 : VitalDelayType01 := VitalZeroDelay01; -- DQ15/A-1 + + tipd_CENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_OENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_RESETNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; --WP#/ACC + tipd_BYTENeg : VitalDelayType01 := VitalZeroDelay01; + + -- tpd delays + tpd_A0_DQ0 : VitalDelayType01 := UnitDelay01;--tACC + tpd_A0_DQ1 : VitalDelayType01 := UnitDelay01;--tPACC + tpd_CENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(tCE,tCE,tDF,-,tDF,-) + tpd_OENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(tOE,tOE,tDF,-,tDF,-) + tpd_RESETNeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(-,-,0,-,0,-) + tpd_CENeg_RY : VitalDelayType01 := UnitDelay01; --tBUSY + tpd_WENeg_RY : VitalDelayType01 := UnitDelay01; --tBUSY + + --tsetup values + tsetup_A0_CENeg : VitalDelayType := UnitDelay; --tAS edge \ + tsetup_A0_OENeg : VitalDelayType := UnitDelay; --tASO edge \ + tsetup_DQ0_CENeg : VitalDelayType := UnitDelay; --tDS edge / + + --thold values + thold_CENeg_RESETNeg: VitalDelayType := UnitDelay; --tRH edge / + thold_OENeg_WENeg : VitalDelayType := UnitDelay; --tOEH edge / + thold_A0_CENeg : VitalDelayType := UnitDelay; --tAH edge \ + thold_A0_OENeg : VitalDelayType := UnitDelay; --tAHT edge \ + thold_DQ0_CENeg : VitalDelayType := UnitDelay; --tDH edge / + thold_WENeg_OENeg : VitalDelayType := UnitDelay; --tGHWL edge / + + --tpw values: pulse width + tpw_RESETNeg_negedge: VitalDelayType := UnitDelay; --tRP + tpw_OENeg_posedge : VitalDelayType := UnitDelay; --tOEPH + tpw_WENeg_negedge : VitalDelayType := UnitDelay; --tWP + tpw_WENeg_posedge : VitalDelayType := UnitDelay; --tWPH + tpw_CENeg_negedge : VitalDelayType := UnitDelay; --tCP + tpw_CENeg_posedge : VitalDelayType := UnitDelay; --tCEPH + tpw_A0_negedge : VitalDelayType := UnitDelay; --tWC tRC + + + -- tdevice values: values for internal delays + --Effective Write Buffer Program Operation tWHWH1 + tdevice_WBPB : VitalDelayType := 11 us; + --Program Operation + tdevice_POB : VitalDelayType := 100 us; + --Sector Erase Operation tWHWH2 + tdevice_SEO : VitalDelayType := 500 ms; + --Timing Limit Exceeded + tdevice_HANG : VitalDelayType := 400 ms; --? + --program/erase suspend timeout + tdevice_START_T1 : VitalDelayType := 5 us; + --sector erase command sequence timeout + tdevice_CTMOUT : VitalDelayType := 50 us; + --device ready after Hardware reset(during embeded algorithm) + tdevice_READY : VitalDelayType := 20 us; --tReady + + -- generic control parameters + InstancePath : STRING := DefaultInstancePath; + TimingChecksOn : BOOLEAN := DefaultTimingChecks; + MsgOn : BOOLEAN := DefaultMsgOn; + XOn : BOOLEAN := DefaultXon; + -- memory file to be loaded + mem_file_name : STRING ;--:= "am29lv640m.mem"; + prot_file_name : STRING ;--:= "am29lv640m_prot.mem"; + secsi_file_name : STRING ;--:= "am29lv_secsi.mem"; + + UserPreload : BOOLEAN ;--:= TRUE; + LongTimming : BOOLEAN ;--:= TRUE; + + -- For FMF SDF technology file usage + TimingModel : STRING --:= "AM29LV640MH90R" + ); + PORT ( + A21 : IN std_logic := 'U'; -- + A20 : IN std_logic := 'U'; -- + A19 : IN std_logic := 'U'; -- + A18 : IN std_logic := 'U'; -- + A17 : IN std_logic := 'U'; -- + A16 : IN std_logic := 'U'; -- + A15 : IN std_logic := 'U'; -- + A14 : IN std_logic := 'U'; -- + A13 : IN std_logic := 'U'; --address + A12 : IN std_logic := 'U'; --lines + A11 : IN std_logic := 'U'; -- + A10 : IN std_logic := 'U'; -- + A9 : IN std_logic := 'U'; -- + A8 : IN std_logic := 'U'; -- + A7 : IN std_logic := 'U'; -- + A6 : IN std_logic := 'U'; -- + A5 : IN std_logic := 'U'; -- + A4 : IN std_logic := 'U'; -- + A3 : IN std_logic := 'U'; -- + A2 : IN std_logic := 'U'; -- + A1 : IN std_logic := 'U'; -- + A0 : IN std_logic := 'U'; -- + + DQ15 : INOUT std_logic := 'U'; -- DQ15/A-1 + DQ14 : INOUT std_logic := 'U'; -- + DQ13 : INOUT std_logic := 'U'; -- + DQ12 : INOUT std_logic := 'U'; -- + DQ11 : INOUT std_logic := 'U'; -- + DQ10 : INOUT std_logic := 'U'; -- + DQ9 : INOUT std_logic := 'U'; -- data + DQ8 : INOUT std_logic := 'U'; -- lines + DQ7 : INOUT std_logic := 'U'; -- + DQ6 : INOUT std_logic := 'U'; -- + DQ5 : INOUT std_logic := 'U'; -- + DQ4 : INOUT std_logic := 'U'; -- + DQ3 : INOUT std_logic := 'U'; -- + DQ2 : INOUT std_logic := 'U'; -- + DQ1 : INOUT std_logic := 'U'; -- + DQ0 : INOUT std_logic := 'U'; -- + + CENeg : IN std_logic := 'U'; + OENeg : IN std_logic := 'U'; + WENeg : IN std_logic := 'U'; + RESETNeg : IN std_logic := 'U'; + WPNeg : IN std_logic := 'U'; --WP#/ACC + BYTENeg : IN std_logic := 'U'; + RY : OUT std_logic := 'U' --RY/BY# + ); + END COMPONENT; + + FOR ALL: my_mem USE ENTITY WORK.my_mem(VHDL_BEHAVIORAL); + + --------------------------------------------------------------------------- + --memory configuration + --------------------------------------------------------------------------- + CONSTANT MaxData : NATURAL := 16#FF#; --255; + CONSTANT SecSize : NATURAL := 16#FFFF#; --65535 + CONSTANT SecSiSize : NATURAL := 255; + CONSTANT SecNum : NATURAL := 127; + CONSTANT HiAddrBit : NATURAL := 21; + --Address of the Protected Sector +-- CONSTANT ProtSecNum : NATURAL := SecNum; + + --------------------------------------------------------------------------- + --model configuration + --------------------------------------------------------------------------- + CONSTANT mem_file : STRING := "am29lv640m.mem"; + CONSTANT prot_file : STRING := "am29lv640m_prot.mem"; + CONSTANT secsi_file : STRING := "am29lv_secsi.mem"; + + CONSTANT UserPreload : boolean := TRUE; + CONSTANT DebugInfo : boolean := FALSE; + CONSTANT LongTimming : boolean := TRUE; + CONSTANT TimingModel : STRING := "MY_MEM"; + -- "AM29LV640MH90R";--High sect prot. + -- "AM29LV128ML93R";--Low sect. prot. + --------------------------------------------------------------------------- + SIGNAL ProtSecNum : NATURAL := SecNum ; + + --Flash Memory Array + TYPE SecType IS ARRAY (0 TO SecSize) OF + INTEGER RANGE -1 TO MaxData; + TYPE MemArray IS ARRAY (0 TO SecNum) OF + SecType; + + --Common Flash Interface Query codes + TYPE CFItype IS ARRAY (16#10# TO 16#50#) OF + NATURAL RANGE 0 TO 16#FF#; + + --SecSi Sector + TYPE SecSiType IS ARRAY ( 0 TO SecSiSize) OF + INTEGER RANGE -1 TO MaxData; + + --------------------------------------------------------------------------- + -- memory declaration + --------------------------------------------------------------------------- + -- -- Mem(SecAddr)(Address).... + SHARED VARIABLE Mem : MemArray := (OTHERS => (OTHERS=> MaxData)); + SHARED VARIABLE CFI_array : CFItype :=(OTHERS=>0); + SHARED VARIABLE SecSi : SecSiType :=(OTHERS=>0); + + --command sequence + SHARED VARIABLE cmd_seq : cmd_seq_type; + + SIGNAL status : status_type := none; + SIGNAL sts_check : std_logic_vector(7 downto 0); + + + SIGNAL check_err : std_logic := '0'; + SIGNAL ErrorInTest : std_logic := '0'; -- + ---------------------------------------------------------------------------- + --Personality module: + -- + -- instanciates the DUT module and adapts generic test signals to it + -- TBD: block port + ---------------------------------------------------------------------------- + --DUT port + SIGNAL T_DQ : std_logic_vector(15 downto 0) := (OTHERS=>'U'); + SIGNAL T_A : std_logic_vector(HiAddrBit downto 0) := (OTHERS=>'U'); + SIGNAL T_RESETNeg : std_logic := 'U'; + SIGNAL T_CENeg : std_logic := 'U'; + SIGNAL T_WENeg : std_logic := 'U'; + SIGNAL T_OENeg : std_logic := 'U'; + SIGNAL T_WPNeg : std_logic := 'U'; + SIGNAL T_BYTENeg : std_logic := 'U'; + SIGNAL T_RY : std_logic := 'U'; + + --------------------------------------------------------------------------- + -- + --------------------------------------------------------------------------- + --SecSi ProtectionStatus + SHARED VARIABLE FactoryProt : std_logic := '1'; + --Sector Protection Status + SHARED VARIABLE Sec_Prot : std_logic_vector (SecNum downto 0) := + (OTHERS => '0'); + SHARED VARIABLE Sect : NATURAL RANGE 0 TO SecNum := 0; + SHARED VARIABLE Addr : NATURAL RANGE 0 TO SecSize := 0; + SHARED VARIABLE WriteData : NATURAL RANGE 0 TO MaxData := 0; + + + --CONSTANT + --timming parameters + CONSTANT RESETNeg_pw : time := 500 ns; --tRP + + SIGNAL pwron : std_logic := '0'; + + SIGNAL Tseries : NATURAL; + SIGNAL Tcase : NATURAL; + + SHARED VARIABLE ts_cnt : NATURAL RANGE 1 TO 30:=1; -- testseries counter + SHARED VARIABLE tc_cnt : NATURAL RANGE 0 TO 10:=0; -- testcase counter + + + BEGIN + DUT : my_mem + GENERIC MAP ( + -- tipd delays: interconnect path delays + tipd_A0 => VitalZeroDelay01, -- + tipd_A1 => VitalZeroDelay01, -- + tipd_A2 => VitalZeroDelay01, -- + tipd_A3 => VitalZeroDelay01, -- + tipd_A4 => VitalZeroDelay01, -- + tipd_A5 => VitalZeroDelay01, -- + tipd_A6 => VitalZeroDelay01, -- + tipd_A7 => VitalZeroDelay01, -- + tipd_A8 => VitalZeroDelay01, -- + tipd_A9 => VitalZeroDelay01, --address + tipd_A10 => VitalZeroDelay01, --lines + tipd_A11 => VitalZeroDelay01, -- + tipd_A12 => VitalZeroDelay01, -- + tipd_A13 => VitalZeroDelay01, -- + tipd_A14 => VitalZeroDelay01, -- + tipd_A15 => VitalZeroDelay01, -- + tipd_A16 => VitalZeroDelay01, -- + tipd_A17 => VitalZeroDelay01, -- + tipd_A18 => VitalZeroDelay01, -- + tipd_A19 => VitalZeroDelay01, -- + tipd_A20 => VitalZeroDelay01, -- + tipd_A21 => VitalZeroDelay01, -- + + tipd_DQ0 => VitalZeroDelay01, -- + tipd_DQ1 => VitalZeroDelay01, -- + tipd_DQ2 => VitalZeroDelay01, -- + tipd_DQ3 => VitalZeroDelay01, -- + tipd_DQ4 => VitalZeroDelay01, -- + tipd_DQ5 => VitalZeroDelay01, -- + tipd_DQ6 => VitalZeroDelay01, -- data + tipd_DQ7 => VitalZeroDelay01, -- lines + tipd_DQ8 => VitalZeroDelay01, -- + tipd_DQ9 => VitalZeroDelay01, -- + tipd_DQ10 => VitalZeroDelay01, -- + tipd_DQ11 => VitalZeroDelay01, -- + tipd_DQ12 => VitalZeroDelay01, -- + tipd_DQ13 => VitalZeroDelay01, -- + tipd_DQ14 => VitalZeroDelay01, -- + + tipd_DQ15 => VitalZeroDelay01, -- DQ15/A-1 + + tipd_CENeg => VitalZeroDelay01, + tipd_OENeg => VitalZeroDelay01, + tipd_WENeg => VitalZeroDelay01, + tipd_RESETNeg => VitalZeroDelay01, + tipd_WPNeg => VitalZeroDelay01,--WP#/ACC + tipd_BYTENeg => VitalZeroDelay01, + + -- tpd delays + tpd_A0_DQ0 => UnitDelay01,--tACC + tpd_A0_DQ1 => UnitDelay01,--tPACC + tpd_CENeg_DQ0 => UnitDelay01Z, + --(tCE,tCE,tDF,-,tDF + tpd_OENeg_DQ0 => UnitDelay01Z, + --(tOE,tOE,tDF,-,tDF + tpd_RESETNeg_DQ0 => UnitDelay01Z, + --(-,-,0,-,0,-) + tpd_CENeg_RY => UnitDelay01, --tBUSY + tpd_WENeg_RY => UnitDelay01, --tBUSY + + --tsetup values + tsetup_A0_CENeg => UnitDelay, --tAS edge \ + tsetup_A0_OENeg => UnitDelay, --tASO edge \ + tsetup_DQ0_CENeg => UnitDelay, --tDS edge / + + --thold values + thold_CENeg_RESETNeg=> UnitDelay, --tRH edge / + thold_OENeg_WENeg => UnitDelay, --tOEH edge / + thold_A0_CENeg => UnitDelay, --tAH edge \ + thold_A0_OENeg => UnitDelay, --tAHT edge \ + thold_DQ0_CENeg => UnitDelay, --tDH edge / + thold_WENeg_OENeg => UnitDelay, --tGHVL edge / + + --tpw values: pulse width + tpw_RESETNeg_negedge=> UnitDelay, --tRP + tpw_OENeg_posedge => UnitDelay, --tOEPH + tpw_WENeg_negedge => UnitDelay, --tWP + tpw_WENeg_posedge => UnitDelay, --tWPH + tpw_CENeg_negedge => UnitDelay, --tCP + tpw_CENeg_posedge => UnitDelay, --tCEPH + tpw_A0_negedge => UnitDelay, --tWC tRC + -- tdevice values: values for internal delays + --Effective Write Buffer Program Operation tWHWH1 + tdevice_WBPB => 11 us, + --Program Operation + tdevice_POB => 100 us, + --Sector Erase Operation tWHWH2 + tdevice_SEO => 500 ms, + --Timing Limit Exceeded + tdevice_HANG => 400 ms, --? + --program/erase suspend timeout + tdevice_START_T1 => 5 us, + --sector erase command sequence timeout + tdevice_CTMOUT => 50 us, + --device ready after Hardware reset(during embeded algorithm) + tdevice_READY => 20 us, --tReady + + -- generic control parameters + InstancePath => DefaultInstancePath, + TimingChecksOn => TRUE,--DefaultTimingChecks, + MsgOn => DefaultMsgOn, + XOn => DefaultXon, + -- memory file to be loaded + mem_file_name => mem_file, + prot_file_name => prot_file , + secsi_file_name => secsi_file, + + UserPreload => UserPreload, + LongTimming => LongTimming, + -- For FMF SDF technology file usage + TimingModel => "AM29LV640MH90R" -- TimingModel + ) + PORT MAP( + A21 => T_A(21), -- + A20 => T_A(20), -- + A19 => T_A(19), -- + A18 => T_A(18), -- + A17 => T_A(17), -- + A16 => T_A(16), -- + A15 => T_A(15), -- + A14 => T_A(14), -- + A13 => T_A(13), --address + A12 => T_A(12), --lines + A11 => T_A(11), -- + A10 => T_A(10), -- + A9 => T_A(9), -- + A8 => T_A(8), -- + A7 => T_A(7), -- + A6 => T_A(6), -- + A5 => T_A(5),-- + A4 => T_A(4),-- + A3 => T_A(3), -- + A2 => T_A(2), -- + A1 => T_A(1), -- + A0 => T_A(0), -- + + DQ15 => T_DQ(15), -- DQ15/A-1 + DQ14 => T_DQ(14), -- + DQ13 => T_DQ(13), -- + DQ12 => T_DQ(12), -- + DQ11 => T_DQ(11), -- + DQ10 => T_DQ(10), -- + DQ9 => T_DQ(9), -- data + DQ8 => T_DQ(8), -- lines + DQ7 => T_DQ(7), -- + DQ6 => T_DQ(6), -- + DQ5 => T_DQ(5), -- + DQ4 => T_DQ(4), -- + DQ3 => T_DQ(3), -- + DQ2 => T_DQ(2), -- + DQ1 => T_DQ(1), -- + DQ0 => T_DQ(0), -- + + CENeg => T_CENeg, + OENeg => T_OENeg, + WENeg => T_WENeg, + RESETNeg => T_RESETNeg, + WPNeg => T_WPNeg, --WP#/ACC + BYTENeg => T_BYTENeg, + RY => T_RY --RY/BY# + ); + + --------------------------------------------------------------------------- + --protected sector + --------------------------------------------------------------------------- + ProtSecNum <= SecNum WHEN TimingModel(11) = 'H' ELSE + 0 ;-- WHEN TimingModel = "AM29LV128ML93R" + + pwron <= '0', '1' after 1 ns; + +--At the end of the simulation, if ErrorInTest='0' there were no errors +err_ctrl : PROCESS ( check_err ) + BEGIN + IF check_err = '1' THEN + ErrorInTest <= '1'; + END IF; + END PROCESS err_ctrl; + +tb :PROCESS + + -------------------------------------------------------------------------- + --= PROCEDURE to select TC + -- can be modified to read TC list from file, or to generate random list + -------------------------------------------------------------------------- + PROCEDURE Pick_TC + (Model : IN STRING := "AM29LV640MH90R" ) + IS + BEGIN + IF TC_cnt < tc(TS_cnt) THEN + TC_cnt := TC_cnt+1; + ELSE + TC_cnt:=1; + IF TS_cnt<30 THEN + TS_cnt := TS_cnt+1; + ELSE + -- end test + IF ErrorInTest='0' THEN + REPORT "Test Ended without errors" + SEVERITY note; + ELSE + REPORT "There were errors in test" + SEVERITY note; + END IF; + WAIT; + END IF; + END IF; + END PROCEDURE Pick_TC; + + --------------------------------------------------------------------------- + --bus commands, device specific implementation + --------------------------------------------------------------------------- + TYPE bus_type IS (bus_idle, + bus_standby, --CE# deasseretd, others are don't care + bus_enable, --CE# asserted, others deasserted + bus_output_disable, + bus_reset, + bus_write, + bus_read); + + --bus drive for specific command sequence cycle + PROCEDURE bus_cycle( + bus_cmd :IN bus_type := bus_idle; + byte :IN boolean ; + data :IN INTEGER RANGE -2 TO MaxData := -2; -- -1 for all Z + dataHi :IN INTEGER RANGE -2 TO MaxData := -2; -- -2 for ignore + sector :IN INTEGER RANGE -1 TO SecNum := -1; -- -1 for ignore addr + address :IN NATURAL RANGE 0 TO SecSize := 0; + disable :IN boolean := false; + violate :IN boolean := false; + tm :IN TIME := 10 ns) + IS + + VARIABLE tmp : std_logic_vector(15 downto 0); + BEGIN + + IF data=-1 THEN -- HiZ + T_DQ(7 downto 0) <= (OTHERS => 'Z'); + END IF; + + IF (NOT byte)THEN --word access + IF dataHi=-1 THEN -- HiZ + T_DQ(15 downto 8) <= (OTHERS => 'Z'); + END IF; + T_BYTENeg <= '1'; + ELSE --byte access + T_BYTENeg <= '0'; + T_DQ(14 downto 8) <= (OTHERS => 'Z'); + END IF; + + IF sector > -1 THEN + T_A(HiAddrBit downto 15) <= to_slv(sector, HiAddrbit-14); + tmp := to_slv(address, 16); + IF byte THEN + T_A(14 downto 0) <= tmp(15 downto 1); + T_DQ(15) <= tmp(0); + ELSE + T_A(14 downto 0) <= tmp(14 downto 0); + END IF; + + END IF; + + wait for 1 ns; + + CASE bus_cmd IS + WHEN bus_output_disable => + T_OENeg <= '1'; + WAIT FOR 20 ns; + + WHEN bus_idle => + T_RESETNeg <= '1'; + T_WENeg <= '1'; + T_CENeg <= '1'; + T_OENeg <= '1'; + IF disable THEN + T_WPNeg <= '0'; + ELSE + T_WPNeg <= '1'; + END IF; + WAIT FOR 30 ns; + + WHEN bus_standby => + T_CENeg <= '1'; + WAIT FOR 30 ns; + + WHEN bus_reset => + T_RESETNeg <= '0', '1' AFTER tm ; + -- WAIT FOR 500 ns should follow this bus cmd for reset to + --complete + WAIT FOR 30 ns; + + WHEN bus_enable => + T_WENeg <= '1' AFTER 50 ns; --- + T_CENeg <= '0' AFTER 50 ns; --- + T_OENeg <= '1' AFTER 30 ns; --- + + WAIT FOR tm ; + + WHEN bus_write => + T_OENeg <= '1' ;-- AFTER 5 ns; + T_CENeg <= '0' AFTER 10 ns ; + T_WENeg <= '0' AFTER 20 ns; + + IF data>-1 THEN + T_DQ(7 downto 0) <= to_slv(data,8); + END IF; + IF NOT byte THEN + IF dataHi>-1 THEN + T_DQ(15 downto 8) <= to_slv(dataHi,8); + END IF; + END IF; + + IF violate THEN + T_WENeg <= '1'; + WAIT FOR 50 ns; + T_WENeg <= '0', '1' AFTER tm; + WAIT FOR 50 ns; + ELSE + WAIT FOR 100 ns; + END IF; + + WHEN bus_read => + + T_CENeg <= '0' ; + T_WENeg <= '1'AFTER 10 ns; + IF NOT disable THEN + T_OENeg <= '0' AFTER 15 ns; + ELSE + T_OENeg <= '1'; + END IF; + + IF NOT byte THEN + T_DQ(15 downto 8) <= (OTHERS => 'Z'); + END IF; + T_DQ(7 downto 0) <= (OTHERS => 'Z'); + + WAIT FOR 100 ns; + + -- T_OENeg <= '1' ; ----------- + + END CASE; + + + END PROCEDURE; + + + --------------------------------------------------------------------------- + --procedure to decode commands into specific bus command sequence + --------------------------------------------------------------------------- + PROCEDURE cmd_dc + ( command : IN cmd_rec ) + IS + VARIABLE D_hi : NATURAL ;--RANGE 0 to MaxData; + VARIABLE D_lo : NATURAL RANGE 0 to MaxData; + VARIABLE Addr : NATURAL RANGE 0 to SecSize :=0; + VARIABLE Addrfix : NATURAL RANGE 0 to SecSize/2:=0; + VARIABLE Sect : INTEGER RANGE -1 to SecNum :=0; + VARIABLE slv_1, slv_2 : std_logic_vector(7 downto 0); + VARIABLE byte : boolean; + VARIABLE i : NATURAL; + BEGIN + CASE command.cmd IS + WHEN idle => + bus_cycle(bus_cmd => bus_idle, + byte => command.byte, + disable => command.aux=disable); + + WHEN h_reset => + bus_cycle(bus_cmd => bus_reset, + byte => command.byte, + tm => command.wtime); + + WHEN rd => + bus_cycle(bus_cmd => bus_enable, + byte => command.byte, + data => -1, + sector => command.sect, + address => command.addr, + tm => 90 ns); + + bus_cycle(bus_cmd => bus_read, + byte => command.byte, + data => -1, + dataHi => -1, + sector => command.sect, + address => command.addr, + disable => command.aux=disable); + + bus_cycle(bus_cmd => bus_output_disable, + byte => command.byte); + + WHEN rd_page => + bus_cycle(bus_cmd => bus_enable, + byte => command.byte, + data => -1, + sector => 0, + address => 0, + tm => 90 ns); + + Addr := command.addr; + Sect := command.sect; + byte := command.byte; + ---- 08July---- + WAIT FOR 10 ns; + -------------- + i := 0; + WHILE i < command.d_hi LOOP + + IF command.wtime > 0 ns THEN + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + --byte toggle mode + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + byte := false; + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + Addrfix := Addr /2; + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + --word read; + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addrfix); + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + byte := true; + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 30 ns); + + --first byte read + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addr); + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + i := i +3; + wait for 10 ns; ------- + ELSE + byte := command.byte; + END IF; + --second byte read in byte toggle mode + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addr); + + + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + i := i +1; + WAIT FOR 10 ns; + END LOOP; + bus_cycle(bus_cmd => bus_output_disable, + byte => command.byte); + + + + WHEN w_cycle => + + D_lo := 16#AA# ; --first command data + Addr := 16#AAA#; --first command byte address + D_hi := 16#55#; --second command data + Addrfix := 16#555#; --second command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + Addrfix := 16#2AA#; --second command byte address + END IF; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_lo, + dataHi => 0, + sector => 0, + address => Addr, + violate => command.aux=violate, + tm => command.wtime); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_hi, + dataHi => 0, + sector => 0, + address => Addrfix); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_reset | w_prog | w_erase | w_unlock | + w_autoselect | w_enter_sec => + Addr := 16#AAA#; + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + + CASE command.cmd IS + WHEN w_reset => + d_lo := 16#F0#; + WHEN w_prog => + d_lo := 16#A0#; + WHEN w_erase => + d_lo := 16#80#; + WHEN w_unlock => + d_lo := 16#20#; + WHEN w_autoselect => + d_lo := 16#90#; + WHEN w_enter_sec => + d_lo := 16#88#; + WHEN OTHERS => + d_lo := 0; + END CASE; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => d_lo, + dataHi => 0, + sector => 0, + address => Addr); + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + + WHEN w_unlock_reset => + Addr := 16#AAA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#90#, + dataHi => 0, + sector => 0, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#F0#, + dataHi => 0, + sector => 0, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + WHEN w_chip_ers => + Addr := 16#AAA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#10#, + dataHi => 0, + sector => 0, + Address => Addr); + FOR i IN 0 TO SecNum LOOP + IF Sec_Prot(i)/='1' THEN + mem(i) := (OTHERS=>16#FF#); + END IF; + END LOOP; + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_cfi => + Addr := 16#AA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#55#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#98#, + dataHi => 0, + sector => 0, + Address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + + WHEN w_suspend => + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#B0#, + dataHi => 0, + sector => -1); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + WHEN w_resume => + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#30#, + dataHi => 0, + sector => -1); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_data => + + D_hi := command.d_hi MOD 16#100#; + D_lo := command.d_lo ; + Addr := command.addr; + Sect := command.sect; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_lo, + dataHi => D_hi, + sector => Sect, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + IF NOT command.byte THEN + Addr := Addr*2; + END IF; + + --write value(s) in default mem + IF status = erase_active AND Sec_Prot(Sect)/='1'THEN + --sector should be erased + mem(Sect) := (OTHERS=>16#FF#); + + ELSIF status = erase_na AND Sec_Prot(Sect)/='1'THEN + --sector erase terminated = data integrity violated + mem(Sect) := (OTHERS=>-1); + + ELSIF status = readX AND Sec_Prot(Sect)/='1' THEN + mem(Sect)(Addr) := -1; + IF NOT command.byte THEN + mem(Sect)(Addr+1) := -1; + END IF; + + -- Write to Secure Silicon Sector Region + ELSIF status = rd_SecSi AND FactoryProt/='1' THEN + slv_1 := to_slv(d_lo,8); + IF SecSi(Addr)>-1 THEN + slv_2 := to_slv(SecSi(Addr),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + SecSi(Addr) := to_nat(slv_1); + IF NOT command.byte THEN + slv_1 := to_slv(d_hi,8); + IF SecSi(Addr+1)>-1 THEN + slv_2 := to_slv(SecSi(Addr+1),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + SecSi(Addr+1) := to_nat(slv_1); + END IF; + + ELSIF status=buff_wr_busy THEN + --Write to Buffer command cycle + null; + + ELSIF status=erase_na THEN + --sector erase command sequence violation + null; + + -- Write to Flash Memory Array + ELSIF status /= err AND Sec_Prot(Sect)/='1'THEN + slv_1 := to_slv(d_lo,8); + IF mem(Sect)(Addr)>-1 THEN + slv_2 := to_slv(mem(Sect)(Addr),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + mem(Sect)(Addr) := to_nat(slv_1); + IF NOT command.byte THEN + slv_1 := to_slv(d_hi,8); + IF mem(Sect)(Addr+1)>-1 THEN + slv_2 := to_slv(mem(Sect)(Addr+1),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + mem(Sect)(Addr+1) := to_nat(slv_1); + END IF; + END IF; + + + WHEN wt => + WAIT FOR command.wtime; + + WHEN wt_rdy => + IF T_RY/='1' THEN + WAIT UNTIL rising_edge(T_RY) FOR command.wtime; + END IF; + + WHEN wt_bsy => + IF T_RY='1' THEN + WAIT UNTIL falling_edge(T_RY) FOR command.wtime; + END IF; + + WHEN OTHERS => null; + END CASE; + END PROCEDURE; + + + VARIABLE cmd_cnt : NATURAL; + VARIABLE command : cmd_rec; -- + +BEGIN + Pick_TC (Model => "AM29LV640MH90R" ); + + Tseries <= ts_cnt ; + Tcase <= tc_cnt ; + + Generate_TC + (Model => "AM29LV640MH90R" , + Series => ts_cnt, + TestCase => tc_cnt, + command_seq => cmd_seq); + + + cmd_cnt := 1; + WHILE cmd_seq(cmd_cnt).cmd/=done LOOP + command:= cmd_seq(cmd_cnt); + IF command.sect = -1 THEN + command.sect := ProtSecNum; + END IF; + status <= command.status; + sts_check<= to_slv(command.d_lo,8); --used only for toggle/status check + cmd_dc(command); + cmd_cnt :=cmd_cnt +1; + + END LOOP; + +END PROCESS tb; + +--process to monitor WP# +PROCESS(T_WPNeg) +VARIABLE reg : std_logic; +BEGIN + IF falling_edge(T_WPNeg) THEN + reg := Sec_Prot(ProtSecNum); + Sec_Prot(ProtSecNum) := '1'; + ELSIF rising_edge(T_WPNeg) THEN + Sec_Prot(ProtSecNum) := reg; + END IF; +END PROCESS; + +-------------------------------------------------------------------------------- +-- Checker process, +-- Bus transition extractor: when bus cycle is read samples addr and data +-- Transition checker : verifies correct read data using default memory +-------------------------------------------------------------------------------- +checker: PROCESS + VARIABLE RAddr : NATURAL; + VARIABLE RSect : NATURAL; + VARIABLE longread : boolean; + VARIABLE shortread : boolean; + VARIABLE toggle : boolean:=false; + VARIABLE toggle_sts : std_logic_vector(7 downto 0); + +BEGIN +-- Transition extractor + IF (T_CENeg='0'AND T_OENeg='0'AND T_WENeg='1') THEN + IF T_BYTENeg='1' THEN + RAddr := to_nat(T_A(14 downto 0)&'0'); + ELSE + RAddr := to_nat(T_A(14 downto 0)&T_DQ(15)); + END IF; + RSect := to_nat(T_A(HiAddrBit downto 15)); + + shortread:= false; + longread := false; + + --DUT specific timing + IF (T_CENeg'EVENT OR T_WENeg'EVENT OR T_A(HiAddrBit downto 2)'EVENT)AND -- + (status=read OR status=rd_cfi OR status=rd_secsi) THEN --OR status=readX) + longread := true; + CASE TimingModel IS + WHEN "AM29LV640MH90R" | + "AM29LV640ML90R" => WAIT FOR 95 ns; +-- WHEN "AM29LV640MH101" | +-- "AM29LV640ML101" => WAIT FOR 105 ns; +-- WHEN "AM29LV640MH101R" | +-- "AM29LV640ML101R" => WAIT FOR 105 ns; +-- WHEN "AM29LV640MH112" | +-- "AM29LV640ML112" => WAIT FOR 115 ns; +-- WHEN "AM29LV640MH112R" | +-- "AM29LV640ML112R" => WAIT FOR 115 ns; +-- WHEN "AM29LV640MH120" | +-- "AM29LV640ML120" => WAIT FOR 125 ns; +-- WHEN "AM29LV640MH120R" | +-- "AM29LV640ML120R" => WAIT FOR 125 ns; + WHEN OTHERS => + REPORT "Timing model NOT supported : "&TimingModel + SEVERITY error; + END CASE; + + ELSIF T_A(1 downto 0)'EVENT OR + (T_DQ(15)'EVENT AND T_BYTENeg='0')OR + (T_BYTENeg'EVENT) OR + T_OENeg'EVENT OR + (status/=read AND status/=rd_cfi AND + status/=rd_secsi) THEN --AND status/=readX) + shortread:=true; + CASE TimingModel IS + WHEN "AM29LV640MH90R" | + "AM29LV640ML90R" => WAIT FOR 30 ns; +-- WHEN "AM29LV640MH101" | +-- "AM29LV640ML101" => WAIT FOR 40 ns; +-- WHEN "AM29LV640MH101R" | +-- "AM29LV640ML101R" => WAIT FOR 40 ns; +-- WHEN "AM29LV640MH112" | +-- "AM29LV640ML112" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH112R" | +-- "AM29LV640ML112R" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH120" | +-- "AM29LV640ML120" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH120R" | +-- "AM29LV640ML120R" => WAIT FOR 45 ns; + WHEN OTHERS => + REPORT "Timing model NOT supported : "&TimingModel + SEVERITY error; + END CASE; + + END IF; + + + + --Checker + IF longread OR shortread THEN + + CASE status IS + WHEN none => + toggle := false; + + -- read memory array data + WHEN read => + toggle := false; + Check_read ( + DQ => T_DQ, + D_lo => mem(RSect)(RAddr), + D_hi => mem(RSect)(RAddr+1), + Byte => T_BYTENeg, + check_err=> check_err); + + -- read secure silicon region + WHEN rd_secsi => + toggle := false; + Check_SecSi ( + DQ => T_DQ, + D_lo => SecSi(RAddr), + D_hi => SecSi(RAddr+1), + Byte => T_BYTENeg, + check_err=>check_err); + + + --read CFI query codes + WHEN rd_cfi => + RAddr := to_nat(T_A(14 downto 0)); --x16 addressing + toggle := false; + Check_CFI ( + DQ => T_DQ, + D_lo => CFI_array(RAddr) , + D_hi => 0 , + Byte => T_BYTENeg, + check_err=>check_err); + + + + -- read Autoselect codes + WHEN rd_AS => + RAddr := to_nat(T_A(14 downto 0)); --x16 addressing + toggle := false; + Check_AS ( + DQ => T_DQ, + addr => RAddr, + ProtSecNum=>ProtSecNum, + secProt => Sec_Prot(RSect), + FactoryProt=>FactoryProt , + Byte => T_BYTENeg, + AS_E => to_slv(16#0C#,8), + AS_F => to_slv(1,8), + + check_err=>check_err); + + + WHEN rd_HiZ => + toggle:=false; + Check_Z ( + DQ => T_DQ, + check_err=>check_err); + + + + WHEN readX => + toggle:=false; + Check_X ( + DQ => T_DQ, + check_err=>check_err); + + + WHEN erase_na | erase_active => + IF toggle THEN + Check_Erase ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN ers_susp_e => + IF toggle THEN + Check_Ers_Susp ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + +-- + + WHEN ers_susp_prog_na | ers_susp_prog => + IF toggle THEN + Check_Ers_Susp_Prog ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + +-- + + WHEN prog_na | prog_active => + IF toggle THEN + Check_Progr ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN buff_wr_busy | buff_wr_N_busy => + IF toggle THEN + Check_Buff_Busy ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN buff_abort => + IF toggle THEN + Check_Abort ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + WHEN OTHERS => null; + END CASE; + + -- get firs data for toggle check + CASE status IS + WHEN prog_active | prog_na | + erase_active | erase_na | + ers_susp_e | + ers_susp_prog | ers_susp_prog_na | + buff_wr_busy | buff_wr_N_busy | + buff_abort | get_toggle => + + IF (NOT toggle) OR (status=get_toggle) THEN + toggle:=true; + toggle_sts := T_DQ(7 downto 0); + END IF; + + WHEN OTHERS => null; + END CASE; + + + END IF; + + END IF; + + WAIT ON T_A, T_CENeg, T_OENeg, T_WENeg, T_DQ(15), T_BYTENeg; + +END PROCESS checker; + + +default: PROCESS + -- text file input variables + FILE mem_f : text is mem_file; + FILE prot_f : text is prot_file; + FILE secsi_f : text is secsi_file; + + VARIABLE S_ind : NATURAL RANGE 0 TO SecNum:= 0; + VARIABLE ind : NATURAL RANGE 0 TO SecSize:= 0; + VARIABLE buf : line; + +BEGIN + --Preload Control + ----------------------------------------------------------------------- + -- File Read Section + ----------------------------------------------------------------------- + IF UserPreload THEN + --- Sector protection preload + IF (prot_file /= "none" ) THEN + ind := 0; + FactoryProt := '0'; + Sec_Prot := (OTHERS => '0'); + WHILE (not ENDFILE (prot_f)) LOOP + READLINE (prot_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 3)); --address + ELSE + IF ind > SecNum THEN + --SecSi Factory protect preload + IF buf(1)='1' THEN + FactoryProt := '1'; + END IF; + ELSE + -- Standard Sector prload + IF buf(1)='1' THEN + Sec_Prot(ind):= '1'; + END IF; + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + -- Secure Silicon Sector Region preload + IF (SecSi_file /= "none" ) THEN + SecSi := (OTHERS => MaxData); + ind := 0; + WHILE (not ENDFILE (SecSi_f)) LOOP + READLINE (SecSi_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 3)); --address + ELSE + IF ind <= SecSiSize THEN + SecSi(ind) := h(buf(1 TO 2)); + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + --- Memory Preload + IF (mem_file /= "none" ) THEN + ind := 0; + Mem := (OTHERS => (OTHERS => MaxData)); + -- load sector 0 + WHILE (not ENDFILE (mem_f)) LOOP + READLINE (mem_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 5)); --address + ELSE + IF ind <= SecSize THEN + Mem(0)(ind) := h(buf(1 to 2)); + ind := ind + 1; + END IF; + END IF; + END LOOP; + -- load other sectors + FOR i IN 1 TO SecNum LOOP + Mem(i) := Mem(0); + END LOOP; + END IF; + + END IF; + ----------------------------------------------------------------------- + --CFI array data / AM29LV640MH90R !!! DEVICE SPECIFIC + ----------------------------------------------------------------------- + --CFI query identification string + -- !!!!!! WORD ADDRESSES (x16) - for x8 addressing double addr + --CFI query identification string + CFI_array(16#10#) := 16#51#; + CFI_array(16#11#) := 16#52#; + CFI_array(16#12#) := 16#59#; + CFI_array(16#13#) := 16#02#; + CFI_array(16#14#) := 16#00#; + CFI_array(16#15#) := 16#40#; + CFI_array(16#16#) := 16#00#; + CFI_array(16#17#) := 16#00#; + CFI_array(16#18#) := 16#00#; + CFI_array(16#19#) := 16#00#; + CFI_array(16#1A#) := 16#00#; + --system interface string + CFI_array(16#1B#) := 16#27#; + CFI_array(16#1C#) := 16#36#; + CFI_array(16#1D#) := 16#00#; + CFI_array(16#1E#) := 16#00#; + CFI_array(16#1F#) := 16#07#; + CFI_array(16#20#) := 16#07#; + CFI_array(16#21#) := 16#0A#; + CFI_array(16#22#) := 16#00#; + CFI_array(16#23#) := 16#01#; + CFI_array(16#24#) := 16#05#; + CFI_array(16#25#) := 16#04#; + CFI_array(16#26#) := 16#00#; + --device geometry definition + CFI_array(16#27#) := 16#17#; + CFI_array(16#28#) := 16#02#; + CFI_array(16#29#) := 16#00#; + CFI_array(16#2A#) := 16#05#; + CFI_array(16#2B#) := 16#00#; + CFI_array(16#2C#) := 16#01#; + CFI_array(16#2D#) := 16#7F#; + CFI_array(16#2E#) := 16#00#; + CFI_array(16#2F#) := 16#00#; + CFI_array(16#30#) := 16#01#; + CFI_array(16#31#) := 16#00#; + CFI_array(16#32#) := 16#00#; + CFI_array(16#33#) := 16#00#; + CFI_array(16#34#) := 16#00#; + CFI_array(16#35#) := 16#00#; + CFI_array(16#36#) := 16#00#; + CFI_array(16#37#) := 16#00#; + CFI_array(16#38#) := 16#00#; + CFI_array(16#39#) := 16#00#; + CFI_array(16#3A#) := 16#00#; + CFI_array(16#3B#) := 16#00#; + CFI_array(16#3C#) := 16#00#; + --primary vendor-specific extended query + CFI_array(16#40#) := 16#50#; + CFI_array(16#41#) := 16#52#; + CFI_array(16#42#) := 16#49#; + CFI_array(16#43#) := 16#31#; + CFI_array(16#44#) := 16#33#; + CFI_array(16#45#) := 16#08#; + CFI_array(16#46#) := 16#02#; + CFI_array(16#47#) := 16#01#; + CFI_array(16#48#) := 16#01#; + CFI_array(16#49#) := 16#04#; + CFI_array(16#4A#) := 16#00#; + CFI_array(16#4B#) := 16#00#; + CFI_array(16#4C#) := 16#01#; + CFI_array(16#4D#) := 16#B5#; + CFI_array(16#4E#) := 16#C5#; + IF TimingModel(11) = 'L' THEN + CFI_array(16#4F#) := 16#04#; + ELSE + CFI_array(16#4F#) := 16#05#; --uniform sectors top protect + END IF; + CFI_array(16#50#) := 16#01#; + + WAIT; + +END PROCESS default; + + + +END vhdl_behavioral; + diff --git a/lib/models/memory/flash/serial/S25fl128k/utilities/conversions.vhd b/lib/models/memory/flash/serial/S25fl128k/utilities/conversions.vhd new file mode 100644 index 0000000..e5fc0d6 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128k/utilities/conversions.vhd @@ -0,0 +1,1035 @@ +-------------------------------------------------------------------------------- +-- File Name: conversions_p.vhd +-------------------------------------------------------------------------------- +-- Copyright (C) 1997, 1998, 2001 Free Model Foundry; http://eda.org/fmf/ +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License version 2 as +-- published by the Free Software Foundation. +-- +-- This package was written by SEVA Technologies, Inc. and donated to the FMF. +-- www.seva.com +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 R. Steele 97 DEC 05 Added header and formatting to SEVA file +-- V1.1 R. Munden 98 NOV 28 Corrected some comments +-- Corrected function b +-- V1.2 R. Munden 01 MAY 27 Corrected function to_nat for weak values +-- and combined into a single file +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; + +-------------------------------------------------------------------------------- +-- CONVERSION FUNCTION SELECTION TABLES +-------------------------------------------------------------------------------- +-- +-- FROM TO: std_logic_vector std_logic natural time string +-- -----------------|---------------|---------|---------|---------|----------- +-- std_logic_vector | N/A | N/A | to_nat | combine | see below +-- std_logic | N/A | N/A | to_nat | combine | see below +-- natural | to_slv | to_sl | N/A | to_time | see below +-- time | N/A | N/A | to_nat | N/A | to_time_str +-- hex string | h | N/A | h | combine | N/A +-- decimal string | d | N/A | d | combine | N/A +-- octal string | o | N/A | o | combine | N/A +-- binary string | b | N/A | b | combine | N/A +-- -----------------|---------------|---------|---------|---------|----------- +-- +-- FROM TO: hex string decimal string octal string binary string +-- -----------------|------------|-------------|------------|---------------- +-- std_logic_vector | to_hex_str | to_int_str | to_oct_str | to_bin_str +-- std_logic | N/A | N/A | N/A | to_bin_str +-- natural | to_hex_str | to_int_str | to_oct_str | to_bin_str +-- -----------------|------------|-------------|------------|---------------- +-- +-------------------------------------------------------------------------------- + +PACKAGE conversions IS + + ---------------------------------------------------------------------------- + -- the conversions in this package are not guaranteed to be synthesizable. + -- + -- others functions available + -- fill creates a variable length string of the fill character + -- + -- + -- + -- input parameters of type natural or integer can be in the form: + -- normal -> 8, 99, 4_237 + -- base#value# -> 2#0101#, 16#fa4C#, 8#6_734# + -- with exponents(x10) -> 8e4, 16#2e#E4 + -- + -- input parameters of type string can be in the form: + -- "99", "4_237", "0101", "1010_1010" + -- + -- for bit/bit_vector <-> std_logic/std_logic_vector conversions use + -- package std_logic_1164 + -- to_bit(std_logic) + -- to_bitvector(std_logic_vector) + -- to_stdlogic(bit) + -- to_stdlogicvector(bit_vector) + -- + -- for "synthesizable" signed/unsigned/std_logic_vector/integer + -- conversions use + -- package std_logic_arith + -- conv_integer(signed/unsigned) + -- conv_unsigned(integer/signed,size) + -- conv_signed(integer/unsigned,size) + -- conv_std_logic_vector(integer/signed/unsigned,size) + -- + -- for "synthesizable" std_logic_vector -> integer conversions use + -- package std_logic_unsigned/std_logic_signed + -- + -- conv_integer(std_logic_vector) + -- + -- type1'(expression of type2) + -- + -- most conversions have 4 parmeters: + -- x : value to be converted + -- rtn_len : size of the return value + -- justify : justify value 'left' or 'right', default is right + -- basespec : print the base of the value - 'yes'/'no', default is yes + -- + -- Typical ways to call these functions: + -- simple, all defaults used + -- to_bin_str(x) + -- x will be converted to a string of minimum size with a + -- base specification appended for clarity + -- if x is 10101 then return is b"10101" + -- + -- to control size of return string + -- to_hex_str(x, + -- 6) + -- length of string returned will be 6 characters + -- value will be right justified in the field + -- if x is 10101 then return is ....h"15" + -- where '.' represents a blank + -- if 'rtn_len' parm defaults or is set to 0 then + -- return string will always be minimum size + -- + -- to left justify and suppress base specification + -- to_int_str(x, + -- 6, + -- justify => left, + -- basespec => yes) + -- length of return string will be 6 characters + -- the base specification will be suppressed + -- if x is 10101 then return is 21.... + -- where '.' represents a blank + -- + -- other usage notes + -- + -- if rtn_len less than or equal to x'length then ignore + -- rtn_len and return string of x'length + -- the 'justify' parm is effectively ignored in this case + -- + -- if rtn_len greater than x'length then return string + -- of rtn_len with blanks based on 'justify' parm + -- + -- these routines do not handle negative numbers + ---------------------------------------------------------------------------- + + type justify_side is (left, right); + type b_spec is (no , yes); + + -- std_logic_vector to binary string + function to_bin_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- std_logic to binary string + function to_bin_str(x : std_logic; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to binary string + function to_bin_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to hex string + function to_hex_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to hex string + function to_hex_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to octal string + function to_oct_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to octal string + function to_oct_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- natural to integer string + function to_int_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to integer string + function to_int_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- time to string + function to_time_str (x : time) + return string; + + -- add characters to a string + function fill (fill_char : character := '*'; + rtn_len : integer := 1) + return string; + -- usage: + -- fill + -- returns * + -- fill(' ',10) + -- returns .......... when '.' represents a blank + -- fill(lf) or fill(ht) + -- returns line feed character or tab character respectively + + -- std_logic_vector to natural + function to_nat (x : std_logic_vector) + return natural; + + -- std_logic to natural + function to_nat (x : std_logic) + return natural; + + -- time to natural + function to_nat (x : time) + return natural; + + -- hex string to std_logic_vector + function h (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or a,A to f,F + -- or x,X,z,Z,u,U,-,w,W, result will be 0 + + -- decimal string to std_logic_vector + function d (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- octal string to std_logic_vector + function o (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 7 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- binary string to std_logic_vector + function b (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 1 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- hex string to natural + function h (x : string) + return natural; + -- if x is other than characters 0 to 9 or a,A to f,F, result will be 0 + + -- decimal string to natural + function d (x : string) + return natural; + -- if x is other than characters 0 to 9, result will be 0 + + -- octal string to natural + function o (x : string) + return natural; + -- if x is other than characters 0 to 7, result will be 0 + + -- binary string to natural + function b (x : string) + return natural; + -- if x is other than characters 0 to 1, result will be 0 + + -- natural to std_logic_vector + function to_slv (x : natural; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than sizeof(x), result will be truncated on the left + -- see note above regarding possible formats for x + + -- natural to std_logic + function to_sl (x : natural) + return std_logic; + + -- natural to time + function to_time (x : natural) + return time; + -- see note above regarding possible formats for x + +END conversions; +-- +-------------------------------------------------------------------------------- +-- + +PACKAGE BODY conversions IS + + -- private declarations for this package + type basetype is (binary, octal, decimal, hex); + + function max(x,y: integer) return integer is + begin + if x > y then return x; else return y; end if; + end max; + + function min(x,y: integer) return integer is + begin + if x < y then return x; else return y; end if; + end min; + + -- consider function sizeof for string/slv/???, return natural + + -- function size(len: natural) return natural is + -- begin + -- if len=0 then + -- return 31; + -- else return len; + -- end if; + -- end size; + + function nextmultof (x : positive; + size : positive) return positive is + begin + case x mod size is + when 0 => return size * x/size; + when others => return size * (x/size + 1); + end case; + end nextmultof; + + function rtn_base (base : basetype) return character is + begin + case base is + when binary => return 'b'; + when octal => return 'o'; + when decimal => return 'd'; + when hex => return 'h'; + end case; + end rtn_base; + + function format (r : string; + base : basetype; + rtn_len : natural ; + justify : justify_side; + basespec : b_spec) return string is + variable int_rtn_len : integer; + begin + if basespec=yes then + int_rtn_len := rtn_len - 3; + else + int_rtn_len := rtn_len; + end if; + if int_rtn_len <= r'length then + case basespec is + when no => return r ; + when yes => return rtn_base(base) & '"' & r & '"'; + end case; + else + case justify is + when left => + case basespec is + when no => + return r & fill(' ',int_rtn_len - r'length); + when yes => + return rtn_base(base) & '"' & r & '"' & + fill(' ',int_rtn_len - r'length); + end case; + when right => + case basespec is + when no => + return fill(' ',int_rtn_len - r'length) & r ; + when yes => + return fill(' ',int_rtn_len - r'length) & + rtn_base(base) & '"' & r & '"'; + end case; + end case; + end if; + end format; + + -- convert numeric string of any base to natural + function cnvt_base (x : string; + inbase : natural range 2 to 16) return natural is + -- assumes x is an unsigned number string of base 'inbase' + -- values larger than natural'high are not supported + variable r,t : natural := 0; + variable place : positive := 1; + begin + for i in x'reverse_range loop + case x(i) is + when '0' => t := 0; + when '1' => t := 1; + when '2' => t := 2; + when '3' => t := 3; + when '4' => t := 4; + when '5' => t := 5; + when '6' => t := 6; + when '7' => t := 7; + when '8' => t := 8; + when '9' => t := 9; + when 'a'|'A' => t := 10; + when 'b'|'B' => t := 11; + when 'c'|'C' => t := 12; + when 'd'|'D' => t := 13; + when 'e'|'E' => t := 14; + when 'f'|'F' => t := 15; + when '_' => t := 0; -- ignore these characters + place := place / inbase; + when others => + assert false + report lf & + "CNVT_BASE found input value larger than base: " & lf & + "Input value: " & x(i) & + " Base: " & to_int_str(inbase) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + if t / inbase > 1 then -- invalid value for base + assert false + report lf & + "CNVT_BASE found input value larger than base: " & lf & + "Input value: " & x(i) & + " Base: " & to_int_str(inbase) & lf & + "converting input to integer 0" + severity warning; + return 0; + else + r := r + (t * place); + place := place * inbase; + end if; + end loop; + return r; + end cnvt_base; + + function extend (x : std_logic; + len : positive) return std_logic_vector is + variable v : std_logic_vector(1 to len) := (others => x); + begin + return v; + end extend; + + + -- implementation of public declarations + + function to_bin_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + + variable int : std_logic_vector(1 to x'length):=x; + variable r : string(1 to x'length):=(others=>'$'); + begin + for i in int'range loop + r(i to i) := to_bin_str(int(i),basespec=>no); + end loop; + return format (r,binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_bin_str(x : std_logic; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable r : string(1 to 1); + begin + case x is + when '0' => r(1) := '0'; + when '1' => r(1) := '1'; + when 'U' => r(1) := 'U'; + when 'X' => r(1) := 'X'; + when 'Z' => r(1) := 'Z'; + when 'W' => r(1) := 'W'; + when 'H' => r(1) := 'H'; + when 'L' => r(1) := 'L'; + when '-' => r(1) := '-'; + end case; + return format (r,binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_bin_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 2 to 32 := 32; + variable r : string(2 to 32):=(others=>'$'); + begin + if int = 0 then + return format ("0",binary,rtn_len,justify,basespec); + end if; + + while int > 0 loop + case int rem 2 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when others => + assert false report lf & "TO_BIN_STR, shouldn't happen" + severity failure; + return "$"; + null; + end case; + int := int / 2; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 32),binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_hex_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + -- will return x'length/4 + variable nxt : positive := nextmultof(x'length,4); + variable int : std_logic_vector(1 to nxt):= (others => '0'); + variable ptr : positive range 1 to (nxt/4)+1 := 1; + variable r : string(1 to nxt/4):=(others=>'$'); + subtype slv4 is std_logic_vector(1 to 4); + begin + int(nxt-x'length+1 to nxt) := x; + if nxt-x'length > 0 and x(x'left) /= '1' then + int(1 to nxt-x'length) := extend(x(x'left),nxt-x'length); + end if; + for i in int'range loop + next when i rem 4 /= 1; + case slv4'(int(i to i+3)) is + when "0000" => r(ptr) := '0'; + when "0001" => r(ptr) := '1'; + when "0010" => r(ptr) := '2'; + when "0011" => r(ptr) := '3'; + when "0100" => r(ptr) := '4'; + when "0101" => r(ptr) := '5'; + when "0110" => r(ptr) := '6'; + when "0111" => r(ptr) := '7'; + when "1000" => r(ptr) := '8'; + when "1001" => r(ptr) := '9'; + when "1010" => r(ptr) := 'A'; + when "1011" => r(ptr) := 'B'; + when "1100" => r(ptr) := 'C'; + when "1101" => r(ptr) := 'D'; + when "1110" => r(ptr) := 'E'; + when "1111" => r(ptr) := 'F'; + when "ZZZZ" => r(ptr) := 'Z'; + when "WWWW" => r(ptr) := 'W'; + when "LLLL" => r(ptr) := 'L'; + when "HHHH" => r(ptr) := 'H'; + when "UUUU" => r(ptr) := 'U'; + when "XXXX" => r(ptr) := 'X'; + when "----" => r(ptr) := '-'; + when others => + assert false + report lf & + "TO_HEX_STR found illegal value: " & + to_bin_str(int(i to i+3)) & lf & + "converting input to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr + 1; + end loop; + return format (r,hex,rtn_len,justify,basespec); + end to_hex_str; + + function to_hex_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 20 := 20; + variable r : string(1 to 20):=(others=>'$'); + begin + if x=0 then return format ("0",hex,rtn_len,justify,basespec); end if; + while int > 0 loop + case int rem 16 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when 8 => r(ptr) := '8'; + when 9 => r(ptr) := '9'; + when 10 => r(ptr) := 'A'; + when 11 => r(ptr) := 'B'; + when 12 => r(ptr) := 'C'; + when 13 => r(ptr) := 'D'; + when 14 => r(ptr) := 'E'; + when 15 => r(ptr) := 'F'; + when others => + assert false report lf & "TO_HEX_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 16; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 20),hex,rtn_len,justify,basespec); + end to_hex_str; + + function to_oct_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + -- will return x'length/3 + variable nxt : positive := nextmultof(x'length,3); + variable int : std_logic_vector(1 to nxt):= (others => '0'); + variable ptr : positive range 1 to (nxt/3)+1 := 1; + variable r : string(1 to nxt/3):=(others=>'$'); + subtype slv3 is std_logic_vector(1 to 3); + begin + int(nxt-x'length+1 to nxt) := x; + if nxt-x'length > 0 and x(x'left) /= '1' then + int(1 to nxt-x'length) := extend(x(x'left),nxt-x'length); + end if; + for i in int'range loop + next when i rem 3 /= 1; + case slv3'(int(i to i+2)) is + when "000" => r(ptr) := '0'; + when "001" => r(ptr) := '1'; + when "010" => r(ptr) := '2'; + when "011" => r(ptr) := '3'; + when "100" => r(ptr) := '4'; + when "101" => r(ptr) := '5'; + when "110" => r(ptr) := '6'; + when "111" => r(ptr) := '7'; + when "ZZZ" => r(ptr) := 'Z'; + when "WWW" => r(ptr) := 'W'; + when "LLL" => r(ptr) := 'L'; + when "HHH" => r(ptr) := 'H'; + when "UUU" => r(ptr) := 'U'; + when "XXX" => r(ptr) := 'X'; + when "---" => r(ptr) := '-'; + when others => + assert false + report lf & + "TO_OCT_STR found illegal value: " & + to_bin_str(int(i to i+2)) & lf & + "converting input to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr + 1; + end loop; + return format (r,octal,rtn_len,justify,basespec); + end to_oct_str; + + function to_oct_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 20 := 20; + variable r : string(1 to 20):=(others=>'$'); + begin + if x=0 then return format ("0",octal,rtn_len,justify,basespec); end if; + while int > 0 loop + case int rem 8 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when others => + assert false report lf & "TO_OCT_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 8; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 20),octal,rtn_len,justify,basespec); + end to_oct_str; + + function to_int_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 32 := 32; + variable r : string(1 to 32):=(others=>'$'); + begin + if x=0 then return format ("0",hex,rtn_len,justify,basespec); + else + while int > 0 loop + case int rem 10 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when 8 => r(ptr) := '8'; + when 9 => r(ptr) := '9'; + when others => + assert false report lf & "TO_INT_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 10; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 32),decimal,rtn_len,justify,basespec); + end if; + end to_int_str; + + function to_int_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string is + begin + return to_int_str(to_nat(x),rtn_len,justify,basespec); + end to_int_str; + + + function to_time_str (x : time) + return string is + begin + return to_int_str(to_nat(x),basespec=>no) & " ns"; + end to_time_str; + + function fill (fill_char : character := '*'; + rtn_len : integer := 1) + return string is + variable r : string(1 to max(rtn_len,1)) := (others => fill_char); + variable len : integer; + begin + if rtn_len < 2 then -- always returns at least 1 fill char + len := 1; + else + len := rtn_len; + end if; + return r(1 to len); + end fill; + + function to_nat(x : std_logic_vector) return natural is + -- assumes x is an unsigned number, lsb on right, + -- more than 31 bits are truncated on left + variable t : std_logic_vector(1 to x'length) := x; + variable int : std_logic_vector(1 to 31) := (others => '0'); + variable r : natural := 0; + variable place : positive := 1; + begin + if x'length < 32 then + int(max(32-x'length,1) to 31) := t(1 to x'length); + else -- x'length >= 32 + int(1 to 31) := t(x'length-30 to x'length); + end if; + for i in int'reverse_range loop + case int(i) is + when '1' | 'H' => r := r + place; + when '0' | 'L' => null; + when others => + assert false + report lf & + "TO_NAT found illegal value: " & to_bin_str(int(i)) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + exit when i=1; + place := place * 2; + end loop; + return r; + end to_nat; + + function to_nat (x : std_logic) + return natural is + begin + case x is + when '0' => return 0 ; + when '1' => return 1 ; + when others => + assert false + report lf & + "TO_NAT found illegal value: " & to_bin_str(x) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + end to_nat; + + function to_nat (x : time) + return natural is + begin + return x / 1 ns; + end to_nat; + + function h(x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or a,A to f,F or + -- x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length*4,rtn_len); + variable ptr : integer range -3 to size := size; + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr-3 to ptr) := "0000"; + when '1' => r(ptr-3 to ptr) := "0001"; + when '2' => r(ptr-3 to ptr) := "0010"; + when '3' => r(ptr-3 to ptr) := "0011"; + when '4' => r(ptr-3 to ptr) := "0100"; + when '5' => r(ptr-3 to ptr) := "0101"; + when '6' => r(ptr-3 to ptr) := "0110"; + when '7' => r(ptr-3 to ptr) := "0111"; + when '8' => r(ptr-3 to ptr) := "1000"; + when '9' => r(ptr-3 to ptr) := "1001"; + when 'a'|'A' => r(ptr-3 to ptr) := "1010"; + when 'b'|'B' => r(ptr-3 to ptr) := "1011"; + when 'c'|'C' => r(ptr-3 to ptr) := "1100"; + when 'd'|'D' => r(ptr-3 to ptr) := "1101"; + when 'e'|'E' => r(ptr-3 to ptr) := "1110"; + when 'f'|'F' => r(ptr-3 to ptr) := "1111"; + when 'U' => r(ptr-3 to ptr) := "UUUU"; + when 'X' => r(ptr-3 to ptr) := "XXXX"; + when 'Z' => r(ptr-3 to ptr) := "ZZZZ"; + when 'W' => r(ptr-3 to ptr) := "WWWW"; + when 'H' => r(ptr-3 to ptr) := "HHHH"; + when 'L' => r(ptr-3 to ptr) := "LLLL"; + when '-' => r(ptr-3 to ptr) := "----"; + when '_' => ptr := ptr + 4; + when others => + assert false + report lf & + "O conversion found illegal input character: " & + int(i) & lf & "converting character to '----'" + severity warning; + r(ptr-3 to ptr) := "----"; + end case; + ptr := ptr - 4; + end loop; + return r(size-rtn_len+1 to size); + end h; + + function d (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than binary length of x, result will be truncated on + -- the left + -- if x is other than characters 0 to 9, result will be 0 + begin + return to_slv(cnvt_base(x,10),rtn_len); + end d; + + function o (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length*3, result will be truncated on the left + -- if x is other than characters 0 to 7 or or x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length*3,rtn_len); + variable ptr : integer range -2 to size := size; + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr-2 to ptr) := "000"; + when '1' => r(ptr-2 to ptr) := "001"; + when '2' => r(ptr-2 to ptr) := "010"; + when '3' => r(ptr-2 to ptr) := "011"; + when '4' => r(ptr-2 to ptr) := "100"; + when '5' => r(ptr-2 to ptr) := "101"; + when '6' => r(ptr-2 to ptr) := "110"; + when '7' => r(ptr-2 to ptr) := "111"; + when 'U' => r(ptr-2 to ptr) := "UUU"; + when 'X' => r(ptr-2 to ptr) := "XXX"; + when 'Z' => r(ptr-2 to ptr) := "ZZZ"; + when 'W' => r(ptr-2 to ptr) := "WWW"; + when 'H' => r(ptr-2 to ptr) := "HHH"; + when 'L' => r(ptr-2 to ptr) := "LLL"; + when '-' => r(ptr-2 to ptr) := "---"; + when '_' => ptr := ptr + 3; + when others => + assert false + report lf & + "O conversion found illegal input character: " & + int(i) & lf & "converting character to '---'" + severity warning; + r(ptr-2 to ptr) := "---"; + end case; + ptr := ptr - 3; + end loop; + return r(size-rtn_len+1 to size); + end o; + + function b (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length, result will be truncated on the left + -- if x is other than characters 0 to 1 or x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length,rtn_len); + variable ptr : integer range 0 to size+1 := size; -- csa + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr) := '0'; + when '1' => r(ptr) := '1'; + when 'U' => r(ptr) := 'U'; + when 'X' => r(ptr) := 'X'; + when 'Z' => r(ptr) := 'Z'; + when 'W' => r(ptr) := 'W'; + when 'H' => r(ptr) := 'H'; + when 'L' => r(ptr) := 'L'; + when '-' => r(ptr) := '-'; + when '_' => ptr := ptr + 1; + when others => + assert false + report lf & + "B conversion found illegal input character: " & + int(i) & lf & "converting character to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr - 1; + end loop; + return r(size-rtn_len+1 to size); + end b; + + function h (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 9 + -- a,A to f,F + -- blanks, underscore + begin + return cnvt_base(x,16); + end h; + + function d (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 9 + -- blanks, underscore + begin + return cnvt_base(x,10); + end d; + + function o (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 7 + -- blanks, underscore + begin + return cnvt_base(x,8); + end o; + + function b (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 1 + -- blanks, underscore + begin + return cnvt_base(x,2); + end b; + + function to_slv(x : natural; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than sizeof(x), result will be truncated on the left + variable int : natural := x; + variable ptr : positive := 32; + variable r : std_logic_vector(1 to 32) := (others=>'0'); + begin + while int > 0 loop + case int rem 2 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when others => + assert false report lf & "TO_SLV, shouldn't happen" + severity failure; + return "0"; + end case; + int := int / 2; + ptr := ptr - 1; + end loop; + return r(33-rtn_len to 32); + end to_slv; + + function to_sl(x : natural) + return std_logic is + variable r : std_logic := '0'; + begin + case x is + when 0 => null; + when 1 => r := '1'; + when others => + assert false + report lf & + "TO_SL found illegal input character: " & + to_int_str(x) & lf & "converting character to '-'" + severity warning; + return '-'; + end case; + return r; + end to_sl; + + function to_time (x: natural) return time is + begin + return x * 1 ns; + end to_time; + +END conversions; diff --git a/lib/models/memory/flash/serial/S25fl128k/utilities/gen_utils.vhd b/lib/models/memory/flash/serial/S25fl128k/utilities/gen_utils.vhd new file mode 100644 index 0000000..65c0e77 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128k/utilities/gen_utils.vhd @@ -0,0 +1,144 @@ +-------------------------------------------------------------------------------- +-- File name: gen_utils.vhd +-------------------------------------------------------------------------------- +-- Copyright (C) 1996, 1998, 2001 Free Model Foundry; http://eda.org/fmf/ +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License version 2 as +-- published by the Free Software Foundation. +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 R. Steele 96 SEP 26 Initial release +-- V1.1 REV3 97 Feb 27 Added Xon and MsgOn generics +-- V1.2 R. Steele 97 APR 16 Changed wired-or to wired-and +-- V1.3 R. Steele 97 APR 16 Added diff. receiver table +-- V1.4 R. Munden 98 APR 13 Added GenParity and CheckParity +-- V1.5 R. Munden 01 NOV 24 Added UnitDelay01ZX +-- +-------------------------------------------------------------------------------- +LIBRARY IEEE; USE IEEE.std_Logic_1164.ALL; + USE IEEE.VITAL_primitives.ALL; + USE IEEE.VITAL_timing.ALL; + +PACKAGE gen_utils IS + + ---------------------------------------------------------------------------- + -- Result map for Wired-and output values (open collector) + ---------------------------------------------------------------------------- + CONSTANT STD_wired_and_rmap : VitalResultMapType := ('U','X','0','Z'); + + ---------------------------------------------------------------------------- + -- Table for computing a single signal from a differential receiver input + -- pair. + ---------------------------------------------------------------------------- + CONSTANT diff_rec_tab : VitalStateTableType := ( + + ------INPUTS--|-PREV-|-OUTPUT---- + -- A ANeg | Aint | Aint' -- + --------------|------|----------- + ( 'X', '-', '-', 'X'), -- A unknown + ( '-', 'X', '-', 'X'), -- A unknown + ( '1', '-', 'X', '1'), -- Recover from 'X' + ( '0', '-', 'X', '0'), -- Recover from 'X' + ( '/', '0', '0', '1'), -- valid diff. rising edge + ( '1', '\', '0', '1'), -- valid diff. rising edge + ( '\', '1', '1', '0'), -- valid diff. falling edge + ( '0', '/', '1', '0'), -- valid diff. falling edge + ( '-', '-', '-', 'S') -- default + ); -- end of VitalStateTableType definition + + + ---------------------------------------------------------------------------- + -- Default Constants + ---------------------------------------------------------------------------- + CONSTANT UnitDelay : VitalDelayType := 1 ns; + CONSTANT UnitDelay01 : VitalDelayType01 := (1 ns, 1 ns); + CONSTANT UnitDelay01Z : VitalDelayType01Z := (others => 1 ns); + CONSTANT UnitDelay01ZX : VitalDelayType01ZX := (others => 1 ns); + + CONSTANT DefaultInstancePath : STRING := "*"; + CONSTANT DefaultTimingChecks : BOOLEAN := FALSE; + CONSTANT DefaultTimingModel : STRING := "UNIT"; + CONSTANT DefaultXon : BOOLEAN := TRUE; + CONSTANT DefaultMsgOn : BOOLEAN := TRUE; + + -- Older VITAL generic being phased out + CONSTANT DefaultXGeneration : BOOLEAN := TRUE; + + ------------------------------------------------------------------- + -- Generate Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION GenParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic_vector; + + ------------------------------------------------------------------- + -- Check Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION CheckParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic; -- '0' - Parity Error + +END gen_utils; + +PACKAGE BODY gen_utils IS + + function XOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 403 + variable result: STD_LOGIC; + begin + result := '0'; + for i in ARG'range loop + result := result xor ARG(i); + end loop; + return result; + end; + ------------------------------------------------------------------- + -- Generate Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION GenParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic_vector + IS + VARIABLE I: NATURAL; + VARIABLE Result: std_logic_vector (Data'Length - 1 DOWNTO 0); + BEGIN + I := 0; + WHILE (I < SIZE) LOOP + Result(I+7 DOWNTO I) := Data(I+7 downto I); + Result(I+8) := XOR_REDUCE( Data(I+7 downto I) ) XOR ODDEVEN; + I := I + 9; + END LOOP; + RETURN Result; + END GenParity; + + ------------------------------------------------------------------- + -- Check Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION CheckParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic -- '0' - Parity Error + IS + VARIABLE I: NATURAL; + VARIABLE Result: std_logic; + BEGIN + I := 0; Result := '1'; + WHILE (I < SIZE) LOOP + Result := Result AND + NOT (XOR_REDUCE( Data(I+8 downto I) ) XOR ODDEVEN); + I := I + 9; + END LOOP; + RETURN Result; + END CheckParity; + +END gen_utils; diff --git a/lib/models/memory/flash/serial/S25fl128s/Model_Manual_English.pdf b/lib/models/memory/flash/serial/S25fl128s/Model_Manual_English.pdf new file mode 100644 index 0000000..954c3f6 Binary files /dev/null and b/lib/models/memory/flash/serial/S25fl128s/Model_Manual_English.pdf differ diff --git a/lib/models/memory/flash/serial/S25fl128s/Model_Manual_Japanese.pdf b/lib/models/memory/flash/serial/S25fl128s/Model_Manual_Japanese.pdf new file mode 100644 index 0000000..de2f909 Binary files /dev/null and b/lib/models/memory/flash/serial/S25fl128s/Model_Manual_Japanese.pdf differ diff --git a/lib/models/memory/flash/serial/S25fl128s/model/model_release_history.txt b/lib/models/memory/flash/serial/S25fl128s/model/model_release_history.txt new file mode 100644 index 0000000..9ec8ed8 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128s/model/model_release_history.txt @@ -0,0 +1,438 @@ +########################################## +Date (DD/MM/YYYY) - 11.11.2009 + +Model name - S25FL128S + +Vendor - Spansion (www.spansion.com) + +Publication ID - S25FL128 256 512 01GS MRS Rev0 98 + +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Ranko Prokopovic + r-prokopovic@hdl-dh.com + Hana Dimitrijevic + h-dimitrijevic@hdl-dh.com + Branislav Colakovic + b-colakovic@hdl-dh.com +########################################## +########################################## +INITIAL RELEASE + +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2009-11-11-3.tar.gz +# Release Date (DD/MM/YYYY) => 11/11/2009 +# Release Version => 1.0 + +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Ranko Prokopovic + r-prokopovic@hdl-dh.com + Hana Dimitrijevic + h-dimitrijevic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2009-11-12-1.tar.gz +# Release Date (DD/MM/YYYY) => 12/11/2009 +# Release Version => 1.1 + +# Correction of s25fl128s.v file : +# State transition from Program Suspend to Autoboot state when +# RESET command is initiated, is delayed with additional 500 ps. +# (For compatibility with Modelsim 6.4b Version) + +# Files modified +-s25fl128s.v +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Ranko Prokopovic + r-prokopovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2009-11-20-1.tar.gz +# Release Date (DD/MM/YYYY) => 20/11/2009 +# Release Version => 1.2 + +# Corrections: +# 1.Negative tests which show how model behaves when reset pulse +# width is less than specified and when write and erase operations are interrupted . +# with reset signal are interrupted with reset signal are added. +# 2.Implementation of Continuous Read Mode +# 3.After 8 clock cycles for instruction, first address bit is latched on the next +# rising edge of clock. + +# Files modified +-s25fl128s.vhd +-testbench_s25fl128s_vhdl.vhd +-spansion_tc_pkg.vhd +-s25fl128s.ftm +-s25fl128s_vhdl.sdf +-s25fl128s.v +-testbench_s25fl128s_verilog.vhd +-s25fl128s.ftmv +-s25fl128s_verilog.sdf +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Ranko Prokopovic + r-prokopovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2009-11-23-1.tar.gz +# Release Date (DD/MM/YYYY) => 23/11/2009 +# Release Version => 1.3 + +# Corrections: +# 1.Correction of Bulk Erase Time +# + +# Files modified +-s25fl128s.v +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2010-02-24-1.tar.gz +# Release Date (DD/MM/YYYY) => 24/02/2010 +# Release Version => 1.4 + +# Corrections: +# 1.Array variable WByte in sensitivity list is replaced with signal WB_flag to enable +# compilation in NCSim +# 2.addr_cnt for second read in high performance read continuous mode can change its +# value only when CSNeg = '0' + +# Files modified +-s25fl128s.v +-s25fl128s.vhd +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2010-04-15-1.tar.gz +# Release Date (DD/MM/YYYY) => 15/04/2010 +# Release Version => 1.5 + +# Corrections: +# 1.HOLD mode corrected +# 2.Condition for PP operation corrected + +# Files modified +-s25fl128s.v +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2010-05-19-1.tar.gz +# Release Date (DD/MM/YYYY) => 19/05/2010 +# Release Version => 1.6 + +# Corrections: +# 1.SRWD bit assignment is corrected +# 2.Condition for WRR command in write_cycle_decode section is corrected +# 3.Blocking assignments for signals WSTART and PSTART are replaced with +# nonblocking assignments +# 4.Conditions in Page Program section are fixed +# + +# Files modified +-s25fl128s.v +-s25fl128s.vhd +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2010-05-26-1.tar.gz +# Release Date (DD/MM/YYYY) => 26/05/2010 +# Release Version => 1.7 + +# Corrections: +# 1. Timing control sections for Program and Erase operation are changed +# 2. Conditions in Page Program section are fixed +# + +# Files modified +-s25fl128s.v +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2010-06-03-2.tar.gz +# Release Date (DD/MM/YYYY) => 03/06/2010 +# Release Version => 1.8 + +# Corrections: +# 1. bus_cycle_state section for PGSP command is fixed +# + +# Files modified +-s25fl128s.v +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2010-07-29-1.tar.gz +# Release Date (DD/MM/YYYY) => 29/07/2010 +# Release Version => 1.9 + +# Corrections: +# 1. During the QUAD mode HOLD# input is not monitored for its normal function +# 2. Internal pull-up resistors for HOLD# and WP# inputs are implemented + +# Files modified +-s25fl128s.v +-s25fl128s.vhd +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2010-08-24-1.tar.gz +# Release Date (DD/MM/YYYY) => 24/08/2010 +# Release Version => 2.0 + +# Corrections: +# 1. All redundant signals are removed from BusCycle process + +# Files modified +-s25fl128s.v +-s25fl128s.vhd +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Ranko Prokopovic + r-prokopovic@hdl-dh.com + Branislav Colakovic + b-colakovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2010-10-19-2.tar.gz +# Release Date (DD/MM/YYYY) => 19/10/2010 +# Release Version => 2.1 + +# Corrections: +# 1. Path delay correction: path delay is longer than clock cycle. +# 2. Write bank register: WIP bit of status register 1 is not affected by this +# instruction. +# 3. All other functionality is updated according to new datasheet version 1.5 + +# Files modified +-s25fl128s.v +-testbench_s25fl128s_verilog.vhd +-s25fl128s.ftmv +-s25fl128s_verilog.sdf +-spansion_tc_pkg.vhd +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Ranko Prokopovic + r-prokopovic@hdl-dh.com + Branislav Colakovic + b-colakovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2010-10-21-1.tar.gz +# Release Date (DD/MM/YYYY) => 21/10/2010 +# Release Version => 2.2 + +# Corrections: +# 1. VHDL model, which is alligned with datasheet version 1.5, added to the release +# 2. Names of documentation files are updated + +# Files modified +-s25fl128s.vhd +-testbench_s25fl128s_vhdl.vhd +-s25fl128s.ftm +-s25fl128s_vhdl.sdf +-spansion_flash_testbench_struct.pdf +-spansion_flash_test_cases_list.pdf +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Ranko Prokopovic + r-prokopovic@hdl-dh.com + Branislav Colakovic + b-colakovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2010-11-05-1.tar.gz +# Release Date (DD/MM/YYYY) => 05/11/2010 +# Release Version => 2.3 + +# Corrections: +# 1. Hybrid configuration added + +# Files modified +-s25fl128s.v +-s25fl128s.vhd +-testbench_s25fl128s_verilog.vhd +-testbench_s25fl128s_vhdl.vhd +-spansion_tc_pkg.vhd +-s25fl128s.ftmv +-s25fl128s.ftm +-s25fl128s_verilog.sdf +-s25fl128s_vhdl.sdf +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Ranko Prokopovic + r-prokopovic@hdl-dh.com + Branislav Colakovic + b-colakovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2010-11-12-1.tar.gz +# Release Date (DD/MM/YYYY) => 12/11/2010 +# Release Version => 2.4 + +# Corrections: +# 1. QUAD Program operation during Erase Suspend is added +# 2. Warning for Resume to Suspend time is added +# 3. During Erase Suspend, after Program operation is completed, WEL bit is cleared +# 4. Implemetation of Software Reset is Changed + +# Files modified +-spansion_tc_pkg.vhd +-s25fl128s.v +-s25fl128s.vhd +########################################## +########################################## +VITAL model author - Snezana Petrovic + s-petrovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2011-04-08-2.tar.gz +# Release Date (DD/MM/YYYY) => 08/04/2011 +# Release Version => 2.5 + +# Corrections: +- corrected timing for internal signal rising_edge_CSNeg_ipd + +# Files modified +-s25fl128s.v +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2011-05-11-1.tar.gz +# Release Date (DD/MM/YYYY) => 11/05/2011 +# Release Version => 2.6 + +# Corrections: +- Condition for CS# High Time(Program/Erase) is fixed + +# Files modified +-s25fl128s.vhd +-testbench_s25fl128s_vhdl.vhd +-spansion_tc_pkg.vhd +-s25fl128s.v +-testbench_s25fl128s_verilog.vhd +-s25fl128s.ftmv +-s25fl128s_verilog.sdf +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2011-07-01-1.tar.gz +# Release Date (DD/MM/YYYY) => 01/07/2011 +# Release Version => 2.7 + +# Corrections: +- Latest Datasheet Aligned + +# Files modified +-s25fl128s.v +-s25fl128s.vhd +-testbench_s25fl128s_verilog.vhd +-testbench_s25fl128s_vhdl.vhd +-spansion_tc_pkg.vhd +-s25fl128s.ftmv +-s25fl128s.ftm +-s25fl128s_verilog.sdf +-s25fl128s_vhdl.sdf +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Branislav Colakovic + b-colakovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2011-07-14-2.tar.gz +# Release Date (DD/MM/YYYY) => 14/07/2011 +# Release Version => 2.8 + +# Corrections: +- Optimization issue is fixed + +# Files modified +-s25fl128s.v +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2011-07-22-1.tar.gz +# Release Date (DD/MM/YYYY) => 22/07/2011 +# Release Version => 2.9 + +# Corrections: +- Timing check issue is fixed + +# Files modified +-s25fl128s.v +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2011-11-16-1.tar.gz +# Release Date (DD/MM/YYYY) => 16/11/2011 +# Release Version => 3.0 + +# Corrections: +- Time tHO is changed to 1 ns (customer's request) +- Setting of Device protection mode is modified (customer's request) +- BRWR instruction is corrected + +# Files modified +-s25fl128s.v +-s25fl128s.vhd +-testbench_s25fl128s_verilog.vhd +-testbench_s25fl128s_vhdl.vhd +-s25fl128s.ftmv +-s25fl128s.ftm +-s25fl128s_verilog.sdf +-s25fl128s_vhdl.sdf +########################################## +########################################## +VITAL model author - Snezana Petrovic + s-petrovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2012-08-28-1.tar.gz +# Release Date (DD/MM/YYYY) => 28/08/2012 +# Release Version => 3.1 + +# Corrections: +- QPP instruction is allowed on previously programmed page + +# Files modified +-s25fl128s.v +-s25fl128s.vhd +-testbench_s25fl128s_verilog.vhd +-testbench_s25fl128s_vhdl.vhd +-spansion_tc_pkg.vhd +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl128s-2012-08-30-1.tar.gz +# Release Date (DD/MM/YYYY) => 30/08/2012 +# Release Version => 3.2 + +# Corrections: +- Wrong code corrected + +# Files modified +-s25fl128s.v +########################################## \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl128s/model/s25fl128s.v b/lib/models/memory/flash/serial/S25fl128s/model/s25fl128s.v new file mode 100644 index 0000000..e11b4a4 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128s/model/s25fl128s.v @@ -0,0 +1,7978 @@ +/////////////////////////////////////////////////////////////////////////////// +// File name : s25fl128s.v +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2012 Spansion, LLC. +// +// MODIFICATION HISTORY : +// +// version: | author: | mod date: | changes made: +// V1.0 V.Mancev 23 Nov 09 Initial +// R.Prokopovic +// V1.1 V.Mancev 24 Feb 10 addr_cnt for second read in +// high performance read continuous +// mode can change its value only +// when CSNeg = '0' +// V1.2 V.Mancev 23 Mar 10 During read operations read_out +// signal changes its value in +// shorter interval +// V1.3 V.Mancev 13 Apr 10 HOLD mode corrected +// Condition for PP operation +// corrected +// V1.4 V.Mancev 19 May 10 SRWD bit assignment is corrected +// Condition for WRR command in +// write_cycle _decode section is +// corrected +// Blocking assignments for signals +// WSTART and PSTART are replaced +// with nonblocking assignments +// Conditions in Page Program +// section are fixed +// V1.5 V.Mancev 26 May 10 Conditions in programming +// sections are fixed +// Timing control sections for +// Program and Erase operation are +// changed +// V1.6 V.Mancev 03 June 10 bus_cycle_state section for +// PGSP command is fixed +// V1.7 V.Mancev 29 July 10 During the QUAD mode HOLD# input +// is not monitored for its normal +// function +// V1.8 B.Colakovic 24 Aug 10 All redundant signals are removed +// from BusCycle process +// V1.9 V. Mancev 08 Oct 10 Latest datasheet aligned +// B.Colakovic +// R. Prokopovic +// V1.10 V. Mancev 01 Nov 10 Read Configuration register added +// B.Colakovic for any state. Hybrid configuration +// R. Prokopovic added +// V1.11 S.Petrovic 08 Apr 11 Corrected timing in always block +// that generates +// rising_edge_CSNeg_ipd +// V1.12 V. Mancev 11 May 11 Condition for CS# High Time +// (Program/Erase) is fixed +// V1.13 V. Mancev 01 July 11 Latest datasheet aligned +// V1.14 B.Colakovic 14 July 11 Optimization issue is fixed +// V1.15 V.Mancev 22 July 11 Timing check issue is fixed +// V1.16 V. Mancev 16 Nov 11 Time tHO is changed to 1 ns +// (customer's request) +// BRWR instruction is corrected +// V1.17 S.Petrovic 28 Aug 12 QPP Instruction is allowed on +// previously programmed page +// V1.18 S.Petrovic 30 Aug 12 Wrong code corrected +// +/////////////////////////////////////////////////////////////////////////////// +// PART DESCRIPTION: +// +// Library: FLASH +// Technology: FLASH MEMORY +// Part: S25FL128S +// +// Description: 128 Megabit Serial Flash Memory +// +////////////////////////////////////////////////////////////////////////////// +// Comments : +// For correct simulation, simulator resolution should be set to 1 ps +// A device ordering (trim) option determines whether a feature is enabled +// or not, or provide relevant parameters: +// -15th character in TimingModel determines if enhanced high +// performance option is available +// (0,2,3,R,A,B,C,D) EHPLC +// (Y,Z,S,T,K,L) Security EHPLC +// (4,6,7,8,9,Q) HPLC +// -15th character in TimingModel determines if RESET# input +// is available +// (R,A,B,C,D,Q.6,7,K,L,S,T,M,N,U,V) RESET# is available +// (0,2,3,4,8,9,Y.Z.W,X) RESET# is tied to the inactive +// state,inside the package. +// -16th character in TimingModel determines Sector and Page Size: +// (0) Sector Size = 64 kB; Page Size = 256 bytes +// Hybrid Top/Bottom sector size architecture +// (1) Sector Size = 256 kB; Page Size = 512 bytes +// Uniform sector size architecture +////////////////////////////////////////////////////////////////////////////// +// Known Bugs: +// +////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// MODULE DECLARATION // +////////////////////////////////////////////////////////////////////////////// +`timescale 1 ps/1 ps + +module s25fl128s + ( + // Data Inputs/Outputs + SI , + SO , + // Controls + SCK , + CSNeg , + RSTNeg , + WPNeg , + HOLDNeg + +); + +/////////////////////////////////////////////////////////////////////////////// +// Port / Part Pin Declarations +/////////////////////////////////////////////////////////////////////////////// + + inout SI ; + inout SO ; + + input SCK ; + input CSNeg ; + input RSTNeg ; + inout HOLDNeg ; + inout WPNeg ; + + // interconnect path delay signals + wire SCK_ipd ; + wire SI_ipd ; + wire SO_ipd ; + + wire SI_in ; + assign SI_in = SI_ipd ; + + wire SI_out ; + assign SI_out = SI ; + + wire SO_in ; + assign SO_in = SO_ipd ; + + wire SO_out ; + assign SO_out = SO ; + + wire CSNeg_ipd ; + wire HOLDNeg_ipd ; + wire WPNeg_ipd ; + wire RSTNeg_ipd ; + + wire HOLDNeg_in ; + //Internal pull-up + assign HOLDNeg_in = (HOLDNeg_ipd === 1'bx) ? 1'b1 : HOLDNeg_ipd; + + wire HOLDNeg_out ; + assign HOLDNeg_out = HOLDNeg ; + + wire WPNeg_in ; + //Internal pull-up + assign WPNeg_in = (WPNeg_ipd === 1'bx) ? 1'b1 : WPNeg_ipd; + + wire WPNeg_out ; + assign WPNeg_out = WPNeg ; + + wire RSTNeg_in ; + //Internal pull-up + assign RSTNeg_in = (RSTNeg_ipd === 1'bx) ? 1'b1 : RSTNeg_ipd; + + // internal delays + reg PP_in ; + reg PP_out ; + reg BP_in ; + reg BP_out ; + reg SE_in ; + reg SE_out ; + reg BE_in ; + reg BE_out ; + reg WRR_in ; + reg WRR_out ; + reg ERSSUSP_in ; + reg ERSSUSP_out ; + reg PRGSUSP_in ; + reg PRGSUSP_out ; + reg PU_in ; + reg PU_out ; + reg RST_in ; + reg RST_out ; + reg PPBERASE_in ; + reg PPBERASE_out; + reg PASSULCK_in ; + reg PASSULCK_out; + reg PASSACC_in ; + reg PASSACC_out; + + // event control registers + reg PRGSUSP_out_event; + reg ERSSUSP_out_event; + reg Reseted_event; + reg SCK_ipd_event; + reg next_state_event; + + reg rising_edge_PoweredUp; + reg rising_edge_Reseted; + reg rising_edge_PASSULCK_in; + reg rising_edge_RES_out; + reg rising_edge_PSTART; + reg rising_edge_WSTART; + reg rising_edge_ESTART; + reg rising_edge_RSTNeg; + reg rising_edge_RST; + reg falling_edge_RSTNeg; + reg falling_edge_RST; + reg rising_edge_RST_out; + reg rising_edge_CSNeg_ipd = 1'b0; + reg falling_edge_CSNeg_ipd = 1'b0; + reg rising_edge_SCK_ipd = 1'b0; + reg falling_edge_SCK_ipd = 1'b0; + + reg RST ; + + reg SOut_zd = 1'bZ ; + reg SOut_z = 1'bZ ; + + wire SI_z ; + wire SO_z ; + + reg SIOut_zd = 1'bZ ; + reg SIOut_z = 1'bZ ; + + reg WPNegOut_zd = 1'bZ ; + reg HOLDNegOut_zd = 1'bZ ; + + assign SI_z = SIOut_z; + assign SO_z = SOut_z; + + parameter UserPreload = 1; + parameter mem_file_name = "none";//"s25fl128s.mem"; + parameter otp_file_name = "s25fl128sOTP.mem";//"none"; + + parameter TimingModel = "DefaultTimingModel"; + + parameter PartID = "s25fl128s"; + parameter MaxData = 255; + parameter MemSize = 24'hFFFFFF; + parameter SecSize256 = 20'h3FFFF; + parameter SecSize64 = 16'hFFFF; + parameter SecSize4 = 12'hFFF; + parameter SecNum64 = 285; + parameter SecNum256 = 63; + parameter PageNum64 = 20'h1FFFF; + parameter PageNum256 = 16'h7FFF; + parameter AddrRANGE = 24'hFFFFFF; + parameter HiAddrBit = 31; + parameter OTPSize = 1023; + parameter OTPLoAddr = 12'h000; + parameter OTPHiAddr = 12'h3FF; + parameter BYTE = 8; + + // Manufacturer Identification + parameter Manuf_ID = 8'h01; + parameter DeviceID = 8'h17; + // Electronic Signature + parameter ESignature = 8'h17; + // Device ID + //Manufacturer Identification && Memory Type && Memory Capacity + parameter Jedec_ID = 8'h01; + parameter DeviceID1 = 8'h20; + parameter DeviceID2 = 8'h18; + parameter ExtendedBytes = 8'h4D; + parameter ExtendedID64 = 8'h01; + parameter ExtendedID256 = 8'h00; + parameter DieRev = 8'h03; + parameter MaskRev = 8'h00; + + integer PageSize; + integer PageNum; + integer SecSize; + integer b_act = 0; + + integer ASP_ProtSE = 0; + integer Sec_ProtSE = 0; + + integer EHP; //Enhanced High Performance Mode active + + integer BAR_ACC = 0; //Bank Register Access active + + //varaibles to resolve architecture used + reg [24*8-1:0] tmp_timing;//stores copy of TimingModel + reg [7:0] tmp_char1;//Define EHPLC or HPLC Mode + reg [7:0] tmp_char2;//stores "0" or "1" character defining sector/page size + integer found = 1'b0; + + // If speedsimulation is needed uncomment following line + + `define SPEEDSIM; + + // powerup + reg PoweredUp; + + // Memory Array Configuration + reg BottomBoot = 1'b0; + reg TopBoot = 1'b0; + reg UniformSec = 1'b0; + + // FSM control signals + reg PDONE ; + reg PSTART ; + reg PGSUSP ; + reg PGRES ; + + reg RES_TO_SUSP_MIN_TIME; + reg RES_TO_SUSP_TYP_TIME; + + reg WDONE ; + reg WSTART ; + + reg EDONE ; + reg ESTART ; + reg ESUSP ; + reg ERES ; + reg ERS_SUSP_PG_SUSP_ACT; + + reg Reseted ; + + reg PARAM_REGION = 1'b0; + + // Lock Bit is enabled for customer programming + reg WRLOCKENABLE = 1'b1; + // Flag that mark if ASP Register is allready programmed + reg ASPOTPFLAG = 1'b0; + + //Flag for Password unlock command + reg PASS_UNLOCKED = 1'b0; + reg [63:0] PASS_TEMP = 64'hFFFFFFFFFFFFFFFF; + + reg QUADRD = 1'b0; + reg INITIAL_CONFIG = 1'b0; + reg CHECK_FREQ = 1'b0; + + // Programming buffer + integer WByte[0:511]; + // CFI array + integer CFI_array[8'h00:8'h50]; + // OTP Memory Array + integer OTPMem[OTPLoAddr:OTPHiAddr]; + // Flash Memory Array + integer Mem[0:AddrRANGE]; + + // Registers + // VDLR Register + reg[7:0] VDLR_reg = 8'h00; + reg[7:0] VDLR_reg_in = 8'h00; + // NVDLR Register + reg[7:0] NVDLR_reg = 8'h00; + reg[7:0] NVDLR_reg_in = 8'h00; + reg dlp_act = 1'b0; + + // Status Register 1 + reg[7:0] Status_reg1 = 8'h00; + reg[7:0] Status_reg1_in = 8'h00; + + wire SRWD ; + wire P_ERR; + wire E_ERR; + wire [2:0]BP; + wire WEL; + wire WIP; + assign SRWD = Status_reg1[7]; + assign P_ERR = Status_reg1[6]; + assign E_ERR = Status_reg1[5]; + assign BP = Status_reg1[4:2]; + assign WEL = Status_reg1[1]; + assign WIP = Status_reg1[0]; + + // Status Register 2 + reg[7:0] Status_reg2 = 8'h00; + reg[7:0] Status_reg2_in = 8'h00; + + wire ES ; + wire PS ; + assign ES = Status_reg2[1]; + assign PS = Status_reg2[0]; + + // Configuration Register 1 + reg[7:0] Config_reg1 = 8'h00; + reg[7:0] Config_reg1_in = 8'h00; + + wire LC1 ; + wire LC0 ; + wire TBPROT ; + wire LOCK ; + wire BPNV ; + wire TBPARM ; + wire QUAD ; + wire FREEZE ; + assign LC1 = Config_reg1[7]; + assign LC0 = Config_reg1[6]; + assign TBPROT = Config_reg1[5]; + assign LOCK = Config_reg1[4]; + assign BPNV = Config_reg1[3]; + assign TBPARM = Config_reg1[2]; + assign QUAD = Config_reg1[1]; + assign FREEZE = Config_reg1[0]; + + // Autoboot Register + reg[31:0] AutoBoot_reg = 32'h00000000; + reg[31:0] AutoBoot_reg_in = 32'h00000000; + + wire ABE; + assign ABE = AutoBoot_reg[0]; + + // Bank Address Register + reg [7:0] Bank_Addr_reg = 8'h00; + reg [7:0] Bank_Addr_reg_in = 8'h00; + + wire EXTADD; + assign EXTADD = Bank_Addr_reg[7]; + + // ASP Register + reg[15:0] ASP_reg ; + reg[15:0] ASP_reg_in; + + wire RPME ; + wire PPBOTP ; + wire PWDMLB ; + wire PSTMLB ; + assign RPME = ASP_reg[5]; + assign PPBOTP = ASP_reg[3]; + assign PWDMLB = ASP_reg[2]; + assign PSTMLB = ASP_reg[1]; + + // Password register + reg[63:0] Password_reg = 64'hFFFFFFFFFFFFFFFF; + reg[63:0] Password_reg_in = 64'hFFFFFFFFFFFFFFFF; + + // PPB Lock Register + reg[7:0] PPBL = 8'h00; + reg[7:0] PPBL_in = 8'h00; + + wire PPB_LOCK ; + assign PPB_LOCK = PPBL[0]; + + // PPB Access Register + reg[7:0] PPBAR = 8'hFF; + reg[7:0] PPBAR_in = 8'hFF; + + reg[SecNum64:0] PPB_bits = {286{1'b1}}; + + // DYB Access Register + reg[7:0] DYBAR = 8'hFF; + reg[7:0] DYBAR_in = 8'hFF; + + reg[SecNum64:0] DYB_bits = {286{1'b1}}; + + //The Lock Protection Registers for OTP Memory space + reg[7:0] LOCK_BYTE1; + reg[7:0] LOCK_BYTE2; + reg[7:0] LOCK_BYTE3; + reg[7:0] LOCK_BYTE4; + + // Command Register + reg write; + reg cfg_write; + reg read_out; + reg dual = 1'b0; + reg rd_fast = 1'b1; + reg rd_slow = 1'b0; + reg ddr = 1'b0; + reg ddr_fast = 1'b0; + reg hold_mode = 1'b0; + reg any_read = 1'b0; + reg quad_pg = 1'b0; + + wire rd ; + wire fast_rd ; + wire ddrd ; + wire fast_ddr ; + + wire quadpg ; + assign quadpg = quad_pg; + + wire RD_EQU_1; + assign RD_EQU_1 = any_read; + + wire RD_EQU_0; + assign RD_EQU_0 = ~any_read; + + reg change_TBPARM = 0; + + reg change_BP = 0; + reg [2:0] BP_bits = 3'b0; + + reg DOUBLE = 1'b0; //Double Data Rate (DDR) flag + + reg RdPswdProtMode = 1'b0;//Read Password Protection Mode Active flag + reg RdPswdProtEnable = 1'b0;//Read Password Protection Mode Support flag + + integer Byte_number = 0; + + reg oe = 1'b0; + reg oe_z = 1'b0; + + reg [647:0] CFI_array_tmp ; + reg [7:0] CFI_tmp; + + integer start_delay; + reg start_autoboot; + integer ABSD; + + reg change_addr ; + integer Address = 0; + integer SectorSuspend = 0; + + //Sector and subsector addresses + integer SA = 0; + + // Sector is protect if Sec_Prot(SecNum) = '1' + reg [SecNum64:0] Sec_Prot = {286{1'b0}}; + + // timing check violation + reg Viol = 1'b0; + + integer WOTPByte; + integer AddrLo; + integer AddrHi; + + reg[7:0] old_bit, new_bit; + integer old_int, new_int; + reg[63:0] old_pass; + reg[63:0] new_pass; + integer wr_cnt; + integer cnt; + + integer read_cnt = 0; + integer byte_cnt = 1; + integer read_addr = 0; + integer read_addr_tmp = 0; + integer Sec_addr = 0; + integer SecAddr = 0; + integer Page_addr = 0; + integer pgm_page = 0; + + reg[7:0] data_out; + reg[647:0] ident_out; + + time SCK_cycle = 0; + time prev_SCK; + time start_ddr; + time out_time; + time SCK_SO_DDR; +/////////////////////////////////////////////////////////////////////////////// +//Interconnect Path Delay Section +/////////////////////////////////////////////////////////////////////////////// + buf (SCK_ipd, SCK); + buf (SI_ipd, SI); + + buf (SO_ipd, SO); + buf (CSNeg_ipd, CSNeg); + buf (HOLDNeg_ipd, HOLDNeg); + buf (WPNeg_ipd, WPNeg); + buf (RSTNeg_ipd, RSTNeg); + +/////////////////////////////////////////////////////////////////////////////// +// Propagation delay Section +/////////////////////////////////////////////////////////////////////////////// + nmos (SI, SI_z , 1); + + nmos (SO, SO_z , 1); + nmos (HOLDNeg, HOLDNegOut_zd , 1); + nmos (WPNeg, WPNegOut_zd , 1); + + wire deg_pin; + wire deg_sin; + wire deg_holdin; + //VHDL VITAL CheckEnable equivalents + wire quad_rd; + assign quad_rd = deg_holdin && ~QUAD && (SIOut_z != 1'bz); + wire wr_prot; + assign wr_prot = SRWD && WEL && ~QUAD; + wire dual_rd; + assign dual_rd = dual ; + wire ddro; + assign ddro = ddr && ~dual ; + wire ddr_rd; + assign ddr_rd = PoweredUp && ddr; + wire sdr_rd; + assign sdr_rd = PoweredUp && ~ddr; + +specify + // tipd delays: interconnect path delays , mapped to input port delays. + // In Verilog is not necessary to declare any tipd_ delay variables, + // they can be taken from SDF file + // With all the other delays real delays would be taken from SDF file + + // tpd delays + specparam tpd_SCK_SO_normal =1; + specparam tpd_CSNeg_SO =1; + specparam tpd_HOLDNeg_SO =1; + specparam tpd_RSTNeg_SO =1; + //DDR operation values + specparam tpd_SCK_SO_DDR =1; + + //tsetup values: setup times + specparam tsetup_CSNeg_SCK =1; + specparam tsetup_SI_SCK_normal =1; + specparam tsetup_WPNeg_CSNeg =1; + specparam tsetup_HOLDNeg_SCK =1; + specparam tsetup_RSTNeg_CSNeg =1; + // DDR operation values + specparam tsetup_SI_SCK_DDR =1; + specparam tsetup_SI_SCK_DDR_fast =1; + specparam tsetup_CSNeg_SCK_DDR =1; + + //thold values: hold times + specparam thold_CSNeg_SCK =1; + specparam thold_SI_SCK_normal =1; + specparam thold_WPNeg_CSNeg =1; + specparam thold_HOLDNeg_SCK =1; + specparam thold_CSNeg_RSTNeg =1; + // DDR operation values + specparam thold_SI_SCK_DDR =1; + specparam thold_SI_SCK_DDR_fast =1; + specparam thold_CSNeg_SCK_DDR =1; + + // tpw values: pulse width + specparam tpw_SCK_serial_posedge =1; + specparam tpw_SCK_dual_posedge =1; + specparam tpw_SCK_fast_posedge =1; + specparam tpw_SCK_quadpg_posedge =1; + specparam tpw_SCK_serial_negedge =1; + specparam tpw_SCK_dual_negedge =1; + specparam tpw_SCK_fast_negedge =1; + specparam tpw_SCK_quadpg_negedge =1; + specparam tpw_CSNeg_read_posedge =1; + specparam tpw_CSNeg_pgers_posedge =1; + specparam tpw_RSTNeg_negedge =1; + specparam tpw_RSTNeg_posedge =1; + // DDR operation values + specparam tpw_SCK_DDR_posedge =1; + specparam tpw_SCK_DDR_negedge =1; + + // tperiod min (calculated as 1/max freq) + specparam tperiod_SCK_serial_rd =1;// 50 MHz + specparam tperiod_SCK_fast_rd =1;//133 MHz + specparam tperiod_SCK_dual_rd =1;//104 MHz + specparam tperiod_SCK_quadpg =1;// 80 MHz + // DDR operation values + specparam tperiod_SCK_DDR_rd =1;// 66 MHz + + `ifdef SPEEDSIM + // Page Program Operation + specparam tdevice_PP_256 = 55e7;//tPP + // Page Program Operation + specparam tdevice_PP_512 = 75e7;//tPP + // Typical Byte Programming Time + specparam tdevice_BP = 4e8;//tBP + // Sector Erase Operation + specparam tdevice_SE64 = 650e7;//tSE + // Sector Erase Operation + specparam tdevice_SE256 = 1875e7;//tSE + // Bulk Erase Operation + specparam tdevice_BE = 165e9;//tBE + // WRR Cycle Time + specparam tdevice_WRR = 2e9;//tW + // Erase Suspend/Erase Resume Time + specparam tdevice_ERSSUSP = 40e6;//tESL + // Program Suspend/Program Resume Time + specparam tdevice_PRGSUSP = 40e6;// + // VCC (min) to CS# Low + specparam tdevice_PU = 3e8;//tPU + // PPB Erase Time + specparam tdevice_PPBERASE = 15e9;// + // Password Unlock Time + specparam tdevice_PASSULCK = 1e6;// + // Password Unlock to Password Unlock Time + specparam tdevice_PASSACC = 100e6; + `else + // Page Program Operation + specparam tdevice_PP_256 = 55e7;//tPP + // Page Program Operation + specparam tdevice_PP_512 = 75e7;//tPP + // Typical Byte Programming Time + specparam tdevice_BP = 4e8;//tBP + // Sector Erase Operation + specparam tdevice_SE64 = 650e9;//tSE + // Sector Erase Operation + specparam tdevice_SE256 = 1875e9;//tSE + // Bulk Erase Operation + specparam tdevice_BE = 165e12;//tBE + // WRR Cycle Time + specparam tdevice_WRR = 2e11;//tW + // Erase Suspend/Erase Resume Time + specparam tdevice_ERSSUSP = 40e6;//tESL + // Program Suspend/Program Resume Time + specparam tdevice_PRGSUSP = 40e6;// + // VCC (min) to CS# Low + specparam tdevice_PU = 3e8;//tPU + // PPB Erase Time + specparam tdevice_PPBERASE = 15e9;// + // Password Unlock Time + specparam tdevice_PASSULCK = 1e6;// + // Password Unlock to Password Unlock Time + specparam tdevice_PASSACC = 100e6; + `endif // SPEEDSIM + +/////////////////////////////////////////////////////////////////////////////// +// Input Port Delays don't require Verilog description +/////////////////////////////////////////////////////////////////////////////// +// Path delays // +/////////////////////////////////////////////////////////////////////////////// + if (~ddr) (SCK => SO) = tpd_SCK_SO_normal; + if (ddr || rd_fast) (SCK => SO) = tpd_SCK_SO_DDR; + + if (~ddr && dual) (SCK => SI) = tpd_SCK_SO_normal; + if ( ddr && dual) (SCK => SI) = tpd_SCK_SO_DDR; + + if (~ddr && QUAD)(SCK => HOLDNeg) = tpd_SCK_SO_normal; + if ( ddr && QUAD)(SCK => HOLDNeg) = tpd_SCK_SO_DDR; + if (~ddr && QUAD)(SCK => WPNeg) = tpd_SCK_SO_normal; + if ( ddr && QUAD)(SCK => WPNeg) = tpd_SCK_SO_DDR; + + if (CSNeg) (CSNeg => SO) = tpd_CSNeg_SO; + if (CSNeg && dual) (CSNeg => SI) = tpd_CSNeg_SO; + + if (CSNeg && QUAD) (CSNeg => HOLDNeg) = tpd_CSNeg_SO; + if (CSNeg && QUAD) (CSNeg => WPNeg) = tpd_CSNeg_SO; + + if (~QUAD) (HOLDNeg => SO) = tpd_HOLDNeg_SO; + if (~QUAD && dual) (HOLDNeg => SI) = tpd_HOLDNeg_SO; + + (RSTNeg => SO) = tpd_RSTNeg_SO; +/////////////////////////////////////////////////////////////////////////////// +// Timing Violation // +/////////////////////////////////////////////////////////////////////////////// + $setup ( CSNeg , posedge SCK &&& sdr_rd, + tsetup_CSNeg_SCK, Viol); + $setup ( CSNeg , posedge SCK &&& ddr_rd, + tsetup_CSNeg_SCK_DDR, Viol); + $setup ( SI , posedge SCK &&& deg_sin, + tsetup_SI_SCK_normal, Viol); + $setup ( WPNeg , negedge CSNeg &&& wr_prot, + tsetup_WPNeg_CSNeg, Viol); + $setup ( HOLDNeg , posedge SCK &&& quad_rd, + tsetup_HOLDNeg_SCK, Viol); + $setup ( SI , posedge SCK &&& ddro, + tsetup_SI_SCK_DDR, Viol); + $setup ( SI , negedge SCK &&& ddro, + tsetup_SI_SCK_DDR, Viol); + + $setup ( RSTNeg , negedge CSNeg, + tsetup_RSTNeg_CSNeg, Viol); + + $hold ( posedge SCK &&& sdr_rd , CSNeg, + thold_CSNeg_SCK, Viol); + $hold ( posedge SCK &&& ddr_rd , CSNeg, + thold_CSNeg_SCK_DDR, Viol); + $hold ( posedge SCK &&& deg_sin , SI , + thold_SI_SCK_normal, Viol); + $hold ( posedge CSNeg &&& wr_prot , WPNeg , + thold_WPNeg_CSNeg, Viol); + $hold ( posedge SCK &&& quad_rd , HOLDNeg , + thold_HOLDNeg_SCK, Viol); + $hold ( posedge SCK &&& ddro , SI, + thold_SI_SCK_DDR, Viol); + $hold ( negedge SCK &&& ddro , SI, + thold_SI_SCK_DDR, Viol); + + $hold ( negedge RSTNeg , CSNeg, + thold_CSNeg_RSTNeg, Viol); + + $width ( posedge SCK &&& rd , tpw_SCK_serial_posedge); + $width ( negedge SCK &&& rd , tpw_SCK_serial_negedge); + $width ( posedge SCK &&& dual_rd , tpw_SCK_dual_posedge); + $width ( negedge SCK &&& dual_rd , tpw_SCK_dual_negedge); + $width ( posedge SCK &&& fast_rd , tpw_SCK_fast_posedge); + $width ( negedge SCK &&& fast_rd , tpw_SCK_fast_negedge); + $width ( posedge SCK &&& ddrd , tpw_SCK_DDR_posedge); + $width ( negedge SCK &&& ddrd , tpw_SCK_DDR_negedge); + $width ( posedge SCK &&& quadpg , tpw_SCK_quadpg_posedge); + $width ( negedge SCK &&& quadpg , tpw_SCK_quadpg_negedge); + + $width ( posedge CSNeg &&& RD_EQU_1, tpw_CSNeg_read_posedge); + $width ( posedge CSNeg &&& RD_EQU_0, tpw_CSNeg_pgers_posedge); + $width ( negedge RSTNeg , tpw_RSTNeg_negedge); + $width ( posedge RSTNeg , tpw_RSTNeg_posedge); + + $period ( posedge SCK &&& rd , tperiod_SCK_serial_rd); + $period ( posedge SCK &&& fast_rd , tperiod_SCK_fast_rd); + $period ( posedge SCK &&& dual_rd , tperiod_SCK_dual_rd); + $period ( posedge SCK &&& quadpg , tperiod_SCK_quadpg); + $period ( posedge SCK &&& ddrd , tperiod_SCK_DDR_rd); + +endspecify + +/////////////////////////////////////////////////////////////////////////////// +// Main Behavior Block // +/////////////////////////////////////////////////////////////////////////////// +// FSM states + parameter IDLE = 5'd0; + parameter RESET_STATE = 5'd1; + parameter AUTOBOOT = 5'd2; + parameter WRITE_SR = 5'd3; + parameter PAGE_PG = 5'd4; + parameter OTP_PG = 5'd5; + parameter PG_SUSP = 5'd6; + parameter SECTOR_ERS = 5'd7; + parameter BULK_ERS = 5'd8; + parameter ERS_SUSP = 5'd9; + parameter ERS_SUSP_PG = 5'd10; + parameter ERS_SUSP_PG_SUSP= 5'd11; + parameter PASS_PG = 5'd12; + parameter PASS_UNLOCK = 5'd13; + parameter PPB_PG = 5'd14; + parameter PPB_ERS = 5'd15; + parameter AUTOBOOT_PG = 5'd16; + parameter ASP_PG = 5'd17; + parameter PLB_PG = 5'd18; + parameter DYB_PG = 5'd19; + parameter NVDLR_PG = 5'd20; + + reg [4:0] current_state; + reg [4:0] next_state; + +// Instruction type + parameter NONE = 7'd0; + parameter WRR = 7'd1; + parameter PP = 7'd2; + parameter READ = 7'd3; + parameter WRDI = 7'd4; + parameter RDSR = 7'd5; + parameter WREN = 7'd6; + parameter RDSR2 = 7'd7; + parameter FSTRD = 7'd8; + parameter FSTRD4 = 7'd9; + parameter DDRFR = 7'd10; + parameter DDRFR4 = 7'd11; + parameter PP4 = 7'd12; + parameter RD4 = 7'd13; + parameter ABRD = 7'd14; + parameter ABWR = 7'd15; + parameter BRRD = 7'd16; + parameter BRWR = 7'd17; + parameter P4E = 7'd19; + parameter P4E4 = 7'd20; + parameter ASPRD = 7'd21; + parameter ASPP = 7'd22; + parameter CLSR = 7'd23; + parameter QPP = 7'd24; + parameter QPP4 = 7'd25; + parameter RDCR = 7'd26; + parameter DOR = 7'd27; + parameter DOR4 = 7'd28; + parameter DLPRD = 7'd29; + parameter OTPP = 7'd30; + parameter PNVDLR = 7'd31; + parameter OTPR = 7'd32; + parameter WVDLR = 7'd33; + parameter BE = 7'd34; + parameter QOR = 7'd35; + parameter QOR4 = 7'd36; + parameter ERSP = 7'd37; + parameter ERRS = 7'd38; + parameter PGSP = 7'd39; + parameter PGRS = 7'd40; + parameter REMS = 7'd41; + parameter RDID = 7'd42; + parameter MPM = 7'd43; + parameter PLBWR = 7'd44; + parameter PLBRD = 7'd45; + parameter RES = 7'd46; + parameter DIOR = 7'd47; + parameter DIOR4 = 7'd48; + parameter DDRDIOR = 7'd49; + parameter DDRDIOR4 = 7'd50; + parameter SE = 7'd51; + parameter SE4 = 7'd52; + parameter DYBRD = 7'd53; + parameter DYBWR = 7'd54; + parameter PPBRD = 7'd55; + parameter PPBP = 7'd56; + parameter PPBERS = 7'd57; + parameter PASSRD = 7'd58; + parameter PASSP = 7'd59; + parameter PASSU = 7'd60; + parameter QIOR = 7'd61; + parameter QIOR4 = 7'd62; + parameter DDRQIOR = 7'd63; + parameter DDRQIOR4 = 7'd64; + parameter RESET = 7'd65; + parameter MBR = 7'd66; + parameter BRAC = 7'd67; + + reg [6:0] Instruct; + +//Bus cycle state + parameter STAND_BY = 3'd0; + parameter OPCODE_BYTE = 3'd1; + parameter ADDRESS_BYTES = 3'd2; + parameter DUMMY_BYTES = 3'd3; + parameter MODE_BYTE = 3'd4; + parameter DATA_BYTES = 3'd5; + + reg [2:0] bus_cycle_state; + + reg deq_pin; + always @(SO_in, SO_z) + begin + if (SO_in==SO_z) + deq_pin=1'b0; + else + deq_pin=1'b1; + end + // check when data is generated from model to avoid setuphold check in + // this occasion + assign deg_pin=deq_pin; + + reg deq_sin; + always @(SI_in, SIOut_z) + begin + if (SI_in==SIOut_z) + deq_sin=1'b0; + else + deq_sin=1'b1; + end + // check when data is generated from model to avoid setuphold check in + // this occasion + assign deg_sin=deq_sin + && (ddr == 1'b0) && (Instruct !== DDRFR) + && (Instruct !== DDRFR4) && (Instruct !== DDRDIOR) + && (Instruct !== DDRDIOR4) && (Instruct !== DDRQIOR) + && (Instruct !== DDRQIOR4) && (SIOut_z != 1'bz); + + reg deq_holdin; + always @(HOLDNeg_ipd, HOLDNegOut_zd) + begin + if (HOLDNeg_ipd==HOLDNegOut_zd) + deq_holdin=1'b0; + else + deq_holdin=1'b1; + end + // check when data is generated from model to avoid setuphold check in + // this occasion + assign deg_holdin=deq_holdin; + + //Power Up time; + initial + begin + PoweredUp = 1'b0; + #tdevice_PU PoweredUp = 1'b1; + end + + initial + begin : Init + write = 1'b0; + cfg_write = 1'b0; + read_out = 1'b0; + Address = 0; + change_addr = 1'b0; + cnt = 0; + RST = 1'b0; + RST_in = 1'b0; + RST_out = 1'b1; + PDONE = 1'b1; + PSTART = 1'b0; + PGSUSP = 1'b0; + PGRES = 1'b0; + PRGSUSP_in = 1'b0; + ERSSUSP_in = 1'b0; + RES_TO_SUSP_MIN_TIME = 1'b0; + RES_TO_SUSP_TYP_TIME = 1'b0; + + EDONE = 1'b1; + ESTART = 1'b0; + ESUSP = 1'b0; + ERES = 1'b0; + + WDONE = 1'b1; + WSTART = 1'b0; + + Reseted = 1'b0; + + Instruct = NONE; + bus_cycle_state = STAND_BY; + current_state = IDLE; + next_state = IDLE; + end + + // initialize memory and load preload files if any + initial + begin: InitMemory + integer i; + + for (i=0;i<=AddrRANGE;i=i+1) + begin + Mem[i] = MaxData; + end + + if ((UserPreload) && !(mem_file_name == "none")) + begin + // Memory Preload + //s25fl128s.mem, memory preload file + // @aaaaaa - stands for address + // dd -
is byte to be written at Mem(aaaaaa++) + // (aaaaaa is incremented at every load) + $readmemh(mem_file_name,Mem); + end + + for (i=OTPLoAddr;i<=OTPHiAddr;i=i+1) + begin + OTPMem[i] = MaxData; + end + + if (UserPreload && !(otp_file_name == "none")) + begin + //s25fl128s_otp memory file + // / - comment + // @aaaaaa - stands for address within last defined + // sector + // dd -
is byte to be written at OTPMem(aaa++) + // (aa is incremented at every load) + // only first 1-4 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + $readmemh(otp_file_name,OTPMem); + end + + LOCK_BYTE1[7:0] = OTPMem[16]; + LOCK_BYTE2[7:0] = OTPMem[17]; + LOCK_BYTE3[7:0] = OTPMem[18]; + LOCK_BYTE4[7:0] = OTPMem[19]; + end + + // initialize memory and load preload files if any + initial + begin: InitTimingModel + integer i; + integer j; + //UNIFORM OR HYBRID arch model is used + //assumptions: + //1. TimingModel has format as S25FL128SXXXXXXXX_X_XXpF + //it is important that 16-th character from first one is "0" or "1" + //2. TimingModel does not have more then 24 characters + tmp_timing = TimingModel;//copy of TimingModel + + i = 23; + while ((i >= 0) && (found != 1'b1))//search for first non null character + begin //i keeps position of first non null character + j = 7; + while ((j >= 0) && (found != 1'b1)) + begin + if (tmp_timing[i*8+j] != 1'd0) + found = 1'b1; + else + j = j-1; + end + i = i - 1; + end + i = i +1; + if (found)//if non null character is found + begin + for (j=0;j<=7;j=j+1) + begin + //EHPLC/HPLC character is 15 + tmp_char1[j] = TimingModel[(i-14)*8+j]; + //256B/512B Page character is 16 + tmp_char2[j] = TimingModel[(i-15)*8+j]; + end + end + if (tmp_char1 == "0" || tmp_char1 == "2" || tmp_char1 == "3" || + tmp_char1 == "R" || tmp_char1 == "A" || tmp_char1 == "B" || + tmp_char1 == "C" || tmp_char1 == "D" || tmp_char1 == "Y" || + tmp_char1 == "Z" || tmp_char1 == "S" || tmp_char1 == "T" || + tmp_char1 == "K" || tmp_char1 == "L") + begin + EHP = 1; + if(tmp_char1 == "Z" || tmp_char1 == "S" || tmp_char1 == "T" || + tmp_char1 == "K" || tmp_char1 == "L" || tmp_char1 == "Y") + begin + RdPswdProtEnable = 1; + end + end + else if (tmp_char1 == "4" || tmp_char1 == "6" || tmp_char1 == "7" || + tmp_char1 == "8" || tmp_char1 == "9" || tmp_char1 == "Q") + begin + EHP = 0; + end + + if (tmp_char1 == "0" || tmp_char1 == "2" || tmp_char1 == "3" || + tmp_char1 == "R" || tmp_char1 == "A" || tmp_char1 == "B" || + tmp_char1 == "C" || tmp_char1 == "D" || tmp_char1 == "4" || + tmp_char1 == "6" || tmp_char1 == "7" || tmp_char1 == "8" || + tmp_char1 == "9" || tmp_char1 == "Q") + begin + ASP_reg = 16'hFE7F; + ASP_reg_in = 16'hFE7F; + end + else if (tmp_char1 == "Y" || tmp_char1 == "Z" || tmp_char1 == "S" || + tmp_char1 == "T" || tmp_char1 == "K" || tmp_char1 == "L") + begin + ASP_reg = 16'hFE4F; + ASP_reg_in = 16'hFE4F; + end + + if (tmp_char2 == "0") + begin + PageSize = 255; + PageNum = PageNum64; + SecSize = SecSize64; + end + else if (tmp_char2 == "1") + begin + PageSize = 511; + PageNum = PageNum256; + SecSize = SecSize256; + end + end + + //CFI + initial + begin: InitCFI + integer i; + integer j; + /////////////////////////////////////////////////////////////////////// + // ID-CFI array data + /////////////////////////////////////////////////////////////////////// + // Manufacturer and Device ID + CFI_array[8'h00] = Jedec_ID; + CFI_array[8'h01] = DeviceID1; + CFI_array[8'h02] = DeviceID2; + CFI_array[8'h03] = 8'h00; + if (tmp_char2 == "0") + // Uniform 64kB sectors + CFI_array[8'h04] = ExtendedID64; + else if (tmp_char2 == "1") + // Uniform 256kB sectors + CFI_array[8'h04] = ExtendedID256; + CFI_array[8'h05] = 8'h80; + CFI_array[8'h06] = 8'h00; + CFI_array[8'h07] = 8'h00; + CFI_array[8'h08] = 8'h00; + CFI_array[8'h09] = 8'h00; + CFI_array[8'h0A] = 8'h00; + CFI_array[8'h0B] = 8'h00; + CFI_array[8'h0C] = 8'h00; + CFI_array[8'h0D] = 8'h00; + CFI_array[8'h0E] = 8'h00; + CFI_array[8'h0F] = 8'h00; + // CFI Query Identification String + CFI_array[8'h10] = 8'h51; + CFI_array[8'h11] = 8'h52; + CFI_array[8'h12] = 8'h59; + CFI_array[8'h13] = 8'h02; + CFI_array[8'h14] = 8'h00; + CFI_array[8'h15] = 8'h40; + CFI_array[8'h16] = 8'h00; + CFI_array[8'h17] = 8'h53; + CFI_array[8'h18] = 8'h46; + CFI_array[8'h19] = 8'h51; + CFI_array[8'h1A] = 8'h00; + //CFI system interface string + CFI_array[8'h1B] = 8'h27; + CFI_array[8'h1C] = 8'h36; + CFI_array[8'h1D] = 8'h00; + CFI_array[8'h1E] = 8'h00; + CFI_array[8'h1F] = 8'h06; + if (tmp_char2 == "0") + begin + // 64kB sector and 256B page + CFI_array[8'h20] = 8'h08; + CFI_array[8'h21] = 8'h08; + end + else if (tmp_char2 == "1") + begin + // 256kB sector and 512B page + CFI_array[8'h20] = 8'h09; + CFI_array[8'h21] = 8'h09; + end + CFI_array[8'h22] = 8'h0F; + CFI_array[8'h23] = 8'h02; + CFI_array[8'h24] = 8'h02; + CFI_array[8'h25] = 8'h03; + CFI_array[8'h26] = 8'h03; + // Device Geometry Definition(Uniform Sector Devices) + CFI_array[8'h27] = 8'h18; + CFI_array[8'h28] = 8'h02; + CFI_array[8'h29] = 8'h01; + + if (tmp_char2 == "0") + // 64kB sectors + CFI_array[8'h2A] = 8'h08; + else if (tmp_char2 == "1") + CFI_array[8'h2A] = 8'h09; + + CFI_array[8'h2B] = 8'h00; + if (tmp_char2 == "1") + begin + CFI_array[8'h2C] = 8'h01; + CFI_array[8'h2D] = 8'h3F; + CFI_array[8'h2E] = 8'h00; + CFI_array[8'h2F] = 8'h00; + CFI_array[8'h30] = 8'h04; + CFI_array[8'h31] = 8'hFF; + CFI_array[8'h32] = 8'hFF; + CFI_array[8'h33] = 8'hFF; + CFI_array[8'h34] = 8'hFF; + end + else + begin + CFI_array[8'h2C] = 8'h02; + if (TBPARM) + begin + // 4KB physical sectors at top + CFI_array[8'h2D] = 8'hFD; + CFI_array[8'h2E] = 8'h00; + CFI_array[8'h2F] = 8'h00; + CFI_array[8'h30] = 8'h01; + CFI_array[8'h31] = 8'h1F; + CFI_array[8'h32] = 8'h00; + CFI_array[8'h33] = 8'h10; + CFI_array[8'h34] = 8'h00; + end + else + begin + // 4KB physical sectors at bottom + CFI_array[8'h2D] = 8'h1F; + CFI_array[8'h2E] = 8'h00; + CFI_array[8'h2F] = 8'h10; + CFI_array[8'h30] = 8'h00; + CFI_array[8'h31] = 8'hFD; + CFI_array[8'h32] = 8'h00; + CFI_array[8'h33] = 8'h00; + CFI_array[8'h34] = 8'h01; + end + end + CFI_array[8'h35] = 8'hFF; + CFI_array[8'h36] = 8'hFF; + CFI_array[8'h37] = 8'hFF; + CFI_array[8'h38] = 8'hFF; + CFI_array[8'h39] = 8'hFF; + CFI_array[8'h3A] = 8'hFF; + CFI_array[8'h3B] = 8'hFF; + CFI_array[8'h3C] = 8'hFF; + CFI_array[8'h3D] = 8'hFF; + CFI_array[8'h3E] = 8'hFF; + CFI_array[8'h3F] = 8'hFF; + // CFI Primary Vendor-Specific Extended Query + CFI_array[8'h40] = 8'h50; + CFI_array[8'h41] = 8'h52; + CFI_array[8'h42] = 8'h49; + CFI_array[8'h43] = 8'h31; + CFI_array[8'h44] = 8'h33; + CFI_array[8'h45] = 8'h21; + CFI_array[8'h46] = 8'h02; + CFI_array[8'h47] = 8'h01; + CFI_array[8'h48] = 8'h00; + CFI_array[8'h49] = 8'h08; + CFI_array[8'h4A] = 8'h00; + CFI_array[8'h4B] = 8'h01; + CFI_array[8'h4C] = 8'h00; + CFI_array[8'h4D] = 8'h00; + CFI_array[8'h4E] = 8'h00; + CFI_array[8'h4F] = 8'h07; + CFI_array[8'h50] = 8'h01; + + begin + for(i=80;i>=0;i=i-1) + begin + CFI_tmp = CFI_array[8'h00-i+80]; + for(j=7;j>=0;j=j-1) + begin + CFI_array_tmp[8*i+j] = CFI_tmp[j]; + end + end + end + + end + + always @(next_state_event or PoweredUp or RST or RST_out) + begin: StateTransition + if (PoweredUp) + begin + if ((RSTNeg_in) && RST_out == 1'b1) + current_state = #(1000) next_state; + else if ((~RSTNeg_in || rising_edge_RSTNeg) && falling_edge_RST) + begin + // no state transition while RESET# low + current_state = RESET_STATE; + RST_in = 1'b1; + #1000 RST_in = 1'b0; + end + end + end + + always @(posedge RST_in) + begin:Threset + RST_out = 1'b0; + #(35000000-200000) RST_out = 1'b1; + end + + always @(negedge CSNeg_ipd) + begin:CheckCEOnPowerUP + if (~PoweredUp) + $display ("Device is selected during Power Up"); + end + + /////////////////////////////////////////////////////////////////////////// + //// Internal Delays + /////////////////////////////////////////////////////////////////////////// + + always @(posedge PRGSUSP_in) + begin:PRGSuspend + PRGSUSP_out = 1'b0; + #tdevice_PRGSUSP PRGSUSP_out = 1'b1; + end + + always @(posedge PPBERASE_in) + begin:PPBErs + PPBERASE_out = 1'b0; + #tdevice_PPBERASE PPBERASE_out = 1'b1; + end + + always @(posedge ERSSUSP_in) + begin:ERSSuspend + ERSSUSP_out = 1'b0; + #tdevice_ERSSUSP ERSSUSP_out = 1'b1; + end + + always @(posedge PASSULCK_in) + begin:PASSULock + PASSULCK_out = 1'b0; + #tdevice_PASSULCK PASSULCK_out = 1'b1; + end + + always @(posedge PASSACC_in) + begin:PASSAcc + PASSACC_out = 1'b0; + #tdevice_PASSACC PASSACC_out = 1'b1; + end + +/////////////////////////////////////////////////////////////////////////////// +// write cycle decode +/////////////////////////////////////////////////////////////////////////////// + integer opcode_cnt = 0; + integer addr_cnt = 0; + integer mode_cnt = 0; + integer dummy_cnt = 0; + integer data_cnt = 0; + integer bit_cnt = 0; + + reg [4095:0] Data_in = 4096'b0; + reg [7:0] opcode; + reg [7:0] opcode_in; + reg [7:0] opcode_tmp; + reg [31:0] addr_bytes; + reg [31:0] hiaddr_bytes; + reg [31:0] Address_in; + reg [7:0] mode_bytes; + reg [7:0] mode_in; + integer Latency_code; + integer quad_data_in [0:1023]; + reg [3:0] quad_nybble = 4'b0; + reg [3:0] Quad_slv; + reg [7:0] Byte_slv; + + always @(rising_edge_CSNeg_ipd or falling_edge_CSNeg_ipd or + rising_edge_SCK_ipd or falling_edge_SCK_ipd) + begin: Buscycle + integer i; + integer j; + integer k; + time CLK_PER; + time LAST_CLK; + + if (falling_edge_CSNeg_ipd) + begin + if (bus_cycle_state==STAND_BY) + begin + Instruct = NONE; + write = 1'b1; + cfg_write = 0; + opcode_cnt = 0; + addr_cnt = 0; + mode_cnt = 0; + dummy_cnt = 0; + data_cnt = 0; + opcode_tmp = 0; + DOUBLE = 1'b0; + QUADRD = 1'b0; + CLK_PER = 1'b0; + LAST_CLK = 1'b0; + if (current_state == AUTOBOOT) + begin + bus_cycle_state = DATA_BYTES; + end + else + begin + bus_cycle_state = OPCODE_BYTE; + end + end + end + + if (rising_edge_SCK_ipd) // Instructions, addresses or data present + begin // at SI are latched on the rising edge of SCK + + CLK_PER = $time - LAST_CLK; + LAST_CLK = $time; + if (CHECK_FREQ) + begin + if ((CLK_PER < 20000 && Latency_code == 3) || + (CLK_PER < 12500 && Latency_code == 0) || + (CLK_PER < 11100 && Latency_code == 1) || + (CLK_PER < 9600 && Latency_code == 2)) + begin + $display ("More wait states are required for"); + $display ("this clock frequency value"); + end + CHECK_FREQ = 0; + end + + if (~CSNeg_ipd) + begin + case (bus_cycle_state) + OPCODE_BYTE: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + opcode_in[opcode_cnt] = SI_in; + opcode_cnt = opcode_cnt + 1; + Latency_code = Config_reg1[7:6]; + if (opcode_cnt == BYTE) + begin + for(i=7;i>=0;i=i-1) + begin + opcode[i] = opcode_in[7-i]; + end + case (opcode) + 8'b00000110 : // 06h + begin + Instruct = WREN; + bus_cycle_state = DATA_BYTES; + end + 8'b00000100 : // 04h + begin + Instruct = WRDI; + bus_cycle_state = DATA_BYTES; + end + 8'b00000001 : // 01h + begin + Instruct = WRR; + bus_cycle_state = DATA_BYTES; + end + 8'b00000011 : // 03h + begin + Instruct = READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00010011 : // 13h + begin + Instruct = RD4; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01001011 : // 4Bh + begin + Instruct = OTPR; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00000101 : // 05h + begin + Instruct = RDSR; + bus_cycle_state = DATA_BYTES; + end + 8'b00000111 : // 07h + begin + Instruct = RDSR2; + bus_cycle_state = DATA_BYTES; + end + 8'b00110101 : // 35h + begin + Instruct = RDCR; + bus_cycle_state = DATA_BYTES; + end + 8'b10010000 : // 90h + begin + Instruct = REMS; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10011111 : // 9Fh + begin + Instruct = RDID; + bus_cycle_state = DATA_BYTES; + end + 8'b10101011 : // ABh + begin + Instruct = RES; + bus_cycle_state = DUMMY_BYTES; + end + 8'b00001011 : // 0Bh + begin + Instruct = FSTRD; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00001100 : // 0Ch + begin + Instruct = FSTRD4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00001101 : // 0Dh + begin + Instruct = DDRFR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00001110 : // 0Eh + begin + Instruct = DDRFR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00111011 : // 3Bh + begin + Instruct = DOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00111100 : // 3Ch + begin + Instruct = DOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b10111011 : // BBh + begin + Instruct = DIOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b10111100 : // BCh + begin + Instruct = DIOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b10111101 : // BDh + begin + Instruct = DDRDIOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b10111110 : // BEh + begin + Instruct = DDRDIOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b01101011 : // 6Bh + begin + Instruct = QOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b01101100 : // 6Ch + begin + Instruct = QOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b11101011 : // EBh + begin + Instruct = QIOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b11101100 : // ECh + begin + Instruct = QIOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b11101101 : // EDh + begin + Instruct = DDRQIOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b11101110 : // EEh + begin + Instruct = DDRQIOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00000010 : // 02h + begin + Instruct = PP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00010010 : // 12h + begin + Instruct = PP4; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00110010: // 32h + begin + Instruct = QPP; + bus_cycle_state = ADDRESS_BYTES; + quad_pg = 1'b1; + end + 8'b00111000: // 38h + begin + Instruct = QPP; + bus_cycle_state = ADDRESS_BYTES; + quad_pg = 1'b1; + end + 8'b00110100 : // 34h + begin + Instruct = QPP4; + bus_cycle_state = ADDRESS_BYTES; + quad_pg = 1'b1; + end + 8'b01000010 : // 42h + begin + Instruct = OTPP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10000101 : // 85h + begin + Instruct = PGSP; + bus_cycle_state = DATA_BYTES; + end + 8'b10001010 : // 8Ah + begin + Instruct = PGRS; + bus_cycle_state = DATA_BYTES; + end + 8'b11000111 : // C7h + begin + Instruct = BE; + bus_cycle_state = DATA_BYTES; + end + 8'b01100000 : // 60h + begin + Instruct = BE; + bus_cycle_state = DATA_BYTES; + end + 8'b11011000 : // D8h + begin + Instruct = SE; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11011100 : // DCh + begin + Instruct = SE4; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01110101 : // 75h + begin + Instruct = ERSP; + bus_cycle_state = DATA_BYTES; + end + 8'b01111010 : // 7Ah + begin + Instruct = ERRS; + bus_cycle_state = DATA_BYTES; + end + 8'b00010100 : // 14h + begin + Instruct = ABRD; + bus_cycle_state = DATA_BYTES; + end + 8'b00010101 : // 15h + begin + Instruct = ABWR; + bus_cycle_state = DATA_BYTES; + end + 8'b00010110 : // 16h + begin + Instruct = BRRD; + bus_cycle_state = DATA_BYTES; + end + 8'b00010111 : // 17h + begin + Instruct = BRWR; + bus_cycle_state = DATA_BYTES; + end + 8'b00101011 : // 2Bh + begin + Instruct = ASPRD; + bus_cycle_state = DATA_BYTES; + end + 8'b00101111 : // 2Fh + begin + Instruct = ASPP; + bus_cycle_state = DATA_BYTES; + end + 8'b11100000 : // E0h + begin + Instruct = DYBRD; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11100001 : // E1h + begin + Instruct = DYBWR; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11100010 : // E2h + begin + Instruct = PPBRD; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11100011 : // E3h + begin + Instruct = PPBP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11100100 : // E4h + begin + Instruct = PPBERS; + bus_cycle_state = DATA_BYTES; + end + 8'b10100110 : // A6h + begin + Instruct = PLBWR; + bus_cycle_state = DATA_BYTES; + end + 8'b10100111 : // A7h + begin + Instruct = PLBRD; + bus_cycle_state = DATA_BYTES; + end + 8'b11100111 : // E7h + begin + Instruct = PASSRD; + bus_cycle_state = DATA_BYTES; + end + 8'b11101000 : // E8h + begin + Instruct = PASSP; + bus_cycle_state = DATA_BYTES; + end + 8'b11101001 : // E9h + begin + Instruct = PASSU; + bus_cycle_state = DATA_BYTES; + end + 8'b11110000 : // F0h + begin + Instruct = RESET; + bus_cycle_state = DATA_BYTES; + end + 8'b00110000 : // 30h + begin + Instruct = CLSR; + bus_cycle_state = DATA_BYTES; + end + 8'b00100000 : // 20h + begin + Instruct = P4E; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00100001 : // 21h + begin + Instruct = P4E4; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01000001 : // 41h + begin + Instruct = DLPRD; + bus_cycle_state = DATA_BYTES; + end + 8'b01000011 : // 43h + begin + Instruct = PNVDLR; + bus_cycle_state = DATA_BYTES; + end + 8'b01001010 : // 4Ah + begin + Instruct = WVDLR; + bus_cycle_state = DATA_BYTES; + end + 8'b10111001 : // B9h + begin + Instruct = BRAC; + bus_cycle_state = DATA_BYTES; + end + 8'b11111111 : // FFh + begin + Instruct = MBR; + bus_cycle_state = MODE_BYTE; + end + endcase + end + end + end //end of OPCODE BYTE + + ADDRESS_BYTES : + begin + if ((Instruct == DDRFR) || (Instruct == DDRFR4) || + (Instruct == DDRDIOR) || (Instruct == DDRDIOR4) || + (Instruct == DDRQIOR) || (Instruct == DDRQIOR4)) + DOUBLE = 1'b1; + else + DOUBLE = 1'b0; + if ((Instruct == QOR) || (Instruct == QOR4) || + (Instruct == QIOR) || (Instruct == QIOR4) || + (Instruct == DDRQIOR) || (Instruct == DDRQIOR4)) + QUADRD = 1'b1; + else + QUADRD = 1'b0; + if (DOUBLE == 1'b0) + begin + if (((((Instruct == FSTRD) && (~EXTADD)) || + ((Instruct == DOR) && (~EXTADD)) || + (Instruct == OTPR)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + ((Instruct == QOR) && QUAD && (~EXTADD))) + begin + //Instruction + 3 Bytes Address + Dummy Byte + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE) + begin + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:24] = 8'b00000000; + Address = addr_bytes ; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (Instruct==FSTRD || Instruct==DOR || + Instruct == QOR) + begin + if (Latency_code == 3) + bus_cycle_state = DATA_BYTES; + else + bus_cycle_state = DUMMY_BYTES; + end + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((((Instruct==FSTRD4) || + (Instruct==DOR4) || + ((Instruct==FSTRD) && EXTADD) || + ((Instruct==DOR) && EXTADD)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + ((Instruct==QOR4) && QUAD) || + ((Instruct==QOR) && QUAD && EXTADD)) + begin + //Instruction + 4 Bytes Address + Dummy Byte + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 4*BYTE) + begin + for(i=31;i>=0;i=i-1) + begin + hiaddr_bytes[31-i] = Address_in[i]; + end + Address = hiaddr_bytes[23:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (Latency_code == 3) + bus_cycle_state = DATA_BYTES; + else + begin + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + + end + end + end + end + else if ((Instruct==DIOR) && (~EXTADD) && + ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + //DUAL I/O High Performance Read(3 Bytes Addr) + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt + 1] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE/2) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i]=Address_in[i]; + end + addr_bytes[31:24] = 8'b00000000; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if (((Instruct==DIOR4) || + ((Instruct==DIOR) && EXTADD)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) + begin //DUAL I/O High Performance Read(4Bytes Addr) + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt + 1] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 4*BYTE/2) + begin + addr_cnt = 0; + for(i=31;i>=0;i=i-1) + begin + addr_bytes[31-i] = Address_in[i]; + end + Address = addr_bytes[23:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((Instruct == QIOR) && (~EXTADD)) + begin + //QUAD I/O High Performance Read (3Bytes Address) + if (QUAD) + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE/4) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:24] = 8'b00000000; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + else + bus_cycle_state = STAND_BY; + end + else if ((Instruct==QIOR4) || ((Instruct==QIOR) + && EXTADD)) + begin + //QUAD I/O High Performance Read (4Bytes Addr) + if (QUAD) + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt +1; + if (addr_cnt == 4*BYTE/4) + begin + addr_cnt =0; + for(i=31;i>=0;i=i-1) + begin + hiaddr_bytes[31-i] = Address_in[i]; + end + Address = hiaddr_bytes[23:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + else + bus_cycle_state = STAND_BY; + end + else if ((((Instruct==RD4) || (Instruct==PP4) || + (Instruct==SE4) ||(Instruct==PPBRD) || + (Instruct==DYBRD) ||(Instruct==DYBWR) || + (Instruct==PPBP) || (Instruct==P4E4) || + ((Instruct==READ) && EXTADD) || + ((Instruct==PP) && EXTADD) || + ((Instruct==P4E) && EXTADD) || + ((Instruct==SE) && EXTADD)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + (QUAD && (Instruct==QPP4 || + ((Instruct==QPP) && EXTADD)))) + begin + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 4*BYTE) + begin + for(i=31;i>=0;i=i-1) + begin + hiaddr_bytes[31-i] = Address_in[i]; + end + Address = hiaddr_bytes[23:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = DATA_BYTES; + end + end + else if (((HOLDNeg_in && ~QUAD) || QUAD) && + (~EXTADD)) + begin + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE) + begin + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:24] = 8'b00000000; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = DATA_BYTES; + end + end + end + else + begin + if ((Instruct==DDRFR) && (~EXTADD)) + //Fast DDR Read Mode + begin + Address_in[addr_cnt] = SI_in; + if ((addr_cnt/2) <= 16) + begin + opcode_tmp[addr_cnt/2] = SI_in; + end + addr_cnt = addr_cnt + 1; + read_cnt = 0; + end + else if ((Instruct==DDRFR4) || + ((Instruct==DDRFR) && EXTADD)) + begin + Address_in[addr_cnt] = SI_in; + if ((addr_cnt/2) <= 16) + begin + opcode_tmp[addr_cnt/2] = SI_in; + end + addr_cnt = addr_cnt + 1; + read_cnt = 0; + end + else if ((Instruct == DDRDIOR) && (~EXTADD)) + begin //Dual I/O DDR Read Mode + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt+1]= SI_in; + if ((addr_cnt/2) <= 16) + begin + opcode_tmp[addr_cnt/2] = SI_in; + end + addr_cnt = addr_cnt + 1; + read_cnt = 0; + end + else if ((Instruct==DDRDIOR4) || + ((Instruct==DDRDIOR) && EXTADD)) + begin //Dual I/O DDR Read Mode + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt+1] = SI_in; + if ((addr_cnt/2) <= 16) + begin + opcode_tmp[addr_cnt/2] = SI_in; + end + addr_cnt = addr_cnt + 1; + read_cnt = 0; + end + else if ((Instruct==DDRQIOR) && (~EXTADD) && QUAD) + begin //Quad I/O DDR Read Mode + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + opcode_tmp[addr_cnt/2] = SI_in; + addr_cnt = addr_cnt +1; + read_cnt = 0; + end + else if (QUAD && ((Instruct==DDRQIOR4) || + ((Instruct==DDRQIOR) && EXTADD))) + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + opcode_tmp[addr_cnt/2] = SI_in; + addr_cnt = addr_cnt +1; + read_cnt = 0; + end + end + end + + MODE_BYTE : + begin + if (((Instruct==DIOR) || (Instruct == DIOR4)) + && ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + mode_in[2*mode_cnt] = SO_in; + mode_in[2*mode_cnt+1] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/2) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + if (Latency_code == 0 || Latency_code == 3) + bus_cycle_state = DATA_BYTES; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if (((Instruct==QIOR) || (Instruct == QIOR4)) + && QUAD) + begin + mode_in[4*mode_cnt] = HOLDNeg_in; + mode_in[4*mode_cnt+1] = WPNeg_in; + mode_in[4*mode_cnt+2] = SO_in; + mode_in[4*mode_cnt+3] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/4) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((Instruct == DDRFR) || (Instruct == DDRFR4)) + mode_in[2*mode_cnt] = SI_in; + else if ((Instruct==DDRDIOR) || (Instruct==DDRDIOR4)) + begin + mode_in[4*mode_cnt] = SO_in; + mode_in[4*mode_cnt+1] = SI_in; + end + else if (((Instruct==DDRQIOR) || (Instruct == DDRQIOR4)) + && QUAD) + begin + mode_in[0] = HOLDNeg_in; + mode_in[1] = WPNeg_in; + mode_in[2] = SO_in; + mode_in[3] = SI_in; + end + dummy_cnt = 0; + end + + DUMMY_BYTES : + begin + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + if ((((Instruct==FSTRD) || (Instruct==FSTRD4) || + (Instruct==DOR) || (Instruct==DOR4) || + (Instruct==OTPR)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + (((Instruct==QOR)||(Instruct==QOR4)) && QUAD)) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == BYTE) + begin + bus_cycle_state = DATA_BYTES; + end + end + + else if ((Instruct==DDRFR) || (Instruct==DDRFR4)) + begin + dummy_cnt = dummy_cnt + 1; + if (EHP) + begin + if (((Latency_code == 3) && (dummy_cnt==1)) || + ((Latency_code == 0) && (dummy_cnt==2)) || + ((Latency_code == 1) && (dummy_cnt==4)) || + ((Latency_code == 2) && (dummy_cnt==5))) + begin + bus_cycle_state = DATA_BYTES; + end + end + else + begin + if (((Latency_code == 3) && (dummy_cnt==4)) || + ((Latency_code == 0) && (dummy_cnt==5)) || + ((Latency_code == 1) && (dummy_cnt==6)) || + ((Latency_code == 2) && (dummy_cnt==7))) + begin + bus_cycle_state = DATA_BYTES; + end + end + end + else if (Instruct==RES) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == 3*BYTE) + bus_cycle_state = DATA_BYTES; + end + else if ((Instruct == DIOR) || (Instruct == DIOR4) + && ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + dummy_cnt = dummy_cnt + 1; + if (EHP) + begin + if (((Latency_code == 1) && (dummy_cnt==1)) || + ((Latency_code == 2) && (dummy_cnt==2))) + bus_cycle_state = DATA_BYTES; + end + else + begin + if (((Latency_code == 3) && (dummy_cnt==4)) || + ((Latency_code == 0) && (dummy_cnt==4)) || + ((Latency_code == 1) && (dummy_cnt==5)) || + ((Latency_code == 2) && (dummy_cnt==6))) + bus_cycle_state = DATA_BYTES; + end + end + else if ((Instruct==DDRDIOR) || (Instruct==DDRDIOR4)) + begin + dummy_cnt = dummy_cnt + 1; + if (EHP) + begin + if (((Latency_code == 3) && (dummy_cnt==2)) || + ((Latency_code == 0) && (dummy_cnt==4)) || + ((Latency_code == 1) && (dummy_cnt==5)) || + ((Latency_code == 2) && (dummy_cnt==6))) + begin + bus_cycle_state = DATA_BYTES; + end + end + else + begin + if (((Latency_code == 3) && (dummy_cnt==4)) || + ((Latency_code == 0) && (dummy_cnt==6)) || + ((Latency_code == 1) && (dummy_cnt==7)) || + ((Latency_code == 2) && (dummy_cnt==8))) + begin + bus_cycle_state = DATA_BYTES; + end + end + end + else if (((Instruct == QIOR) || (Instruct == QIOR4)) + && QUAD) + begin + dummy_cnt = dummy_cnt + 1; + if (((Latency_code == 3) && (dummy_cnt==1)) || + ((Latency_code == 0) && (dummy_cnt==4)) || + ((Latency_code == 1) && (dummy_cnt==4)) || + ((Latency_code == 2) && (dummy_cnt==5))) + begin + bus_cycle_state = DATA_BYTES; + end + end + else if (((Instruct==DDRQIOR) || (Instruct==DDRQIOR4)) + && QUAD) + begin + dummy_cnt = dummy_cnt + 1; + + if (((Latency_code == 3) && (dummy_cnt==3)) || + ((Latency_code == 0) && (dummy_cnt==6)) || + ((Latency_code == 1) && (dummy_cnt==7)) || + ((Latency_code == 2) && (dummy_cnt==8))) + begin + bus_cycle_state = DATA_BYTES; + end + end + end + + DATA_BYTES : + begin + + if (DOUBLE == 1'b1 && (hold_mode==0)) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + + if ((QUAD) && ((Instruct==QPP) || (Instruct == QPP4))) + begin + quad_nybble = {HOLDNeg_in, WPNeg_in, SO_in, SI_in}; + if (data_cnt > ((PageSize+1)*2-1)) + begin + //In case of quad mode and QPP, + //if more than 512 bytes are sent to the device + for(i=0;i<=(PageSize*2-1);i=i+1) + begin + quad_data_in[i] = quad_data_in[i+1]; + end + quad_data_in[(PageSize+1)*2-1] = quad_nybble; + data_cnt = data_cnt +1; + end + else + begin + if (quad_nybble !== 4'bZZZZ) + begin + quad_data_in[data_cnt] = quad_nybble; + end + data_cnt = data_cnt +1; + end + end + else if ((~QUADRD) && ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + if (data_cnt > ((PageSize+1)*8-1)) + begin + //In case of serial mode and PP, + //if more than PageSize are sent to the device + //previously latched data are discarded and last + //256/512 data bytes are guaranteed to be programmed + //correctly within the same page. + if (bit_cnt == 0) + begin + for(i=0;i<=(PageSize*BYTE-1);i=i+1) + begin + Data_in[i] = Data_in[i+8]; + end + end + Data_in[PageSize*BYTE + bit_cnt] = SI_in; + bit_cnt = bit_cnt + 1; + if (bit_cnt == 8) + begin + bit_cnt = 0; + end + data_cnt = data_cnt + 1; + end + else + begin + Data_in[data_cnt] = SI_in; + data_cnt = data_cnt + 1; + bit_cnt = 0; + end + end + end + endcase + end + end + + if (falling_edge_SCK_ipd) + begin + if (~CSNeg_ipd) + begin + case (bus_cycle_state) + ADDRESS_BYTES : + begin + if (DOUBLE == 1'b1) + begin + if ((Instruct==DDRFR) && (~EXTADD)) + //Fast DDR Read Mode + begin + Address_in[addr_cnt] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 3*BYTE) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:24] = 8'b00000000; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((Instruct==DDRFR4) || + ((Instruct==DDRFR) && EXTADD)) + begin + Address_in[addr_cnt] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 4*BYTE) + begin + addr_cnt = 0; + for(i=31;i>=0;i=i-1) + begin + addr_bytes[31-i] = Address_in[i]; + end + Address = addr_bytes[23:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + begin + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + end + else if ((Instruct == DDRDIOR) && (~EXTADD)) + begin //Dual I/O DDR Read Mode + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt+1]= SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 3*BYTE/2) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:24] = 8'b00000000; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((Instruct==DDRDIOR4) || + ((Instruct==DDRDIOR) && EXTADD)) + begin //Dual I/O DDR Read Mode + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt+1] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 4*BYTE/2) + begin + addr_cnt = 0; + for(i=31;i>=0;i=i-1) + begin + addr_bytes[31-i] = Address_in[i]; + end + Address = addr_bytes[23:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + begin + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + end + else if ((Instruct==DDRQIOR) && (~EXTADD) && QUAD) + begin //Quad I/O DDR Read Mode + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 3*BYTE/4) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:24] = 8'b00000000; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + else if (QUAD && ((Instruct==DDRQIOR4) || + ((Instruct==DDRQIOR) && EXTADD))) + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 4*BYTE/4) + begin + addr_cnt = 0; + for(i=31;i>=0;i=i-1) + begin + addr_bytes[31-i] = Address_in[i]; + end + Address = addr_bytes[23:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + end + end + + MODE_BYTE : + begin + if ((Instruct == DDRFR) || (Instruct == DDRFR4)) + begin + mode_in[2*mode_cnt+1] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/2) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + else if ((Instruct==DDRDIOR) || (Instruct==DDRDIOR4)) + begin + mode_in[4*mode_cnt+2] = SO_in; + mode_in[4*mode_cnt+3] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/4) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + else if ((Instruct==DDRQIOR) || (Instruct==DDRQIOR4)) + begin + mode_in[4] = HOLDNeg_in; + mode_in[5] = WPNeg_in; + mode_in[6] = SO_in; + mode_in[7] = SI_in; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + + DATA_BYTES: + begin + if (hold_mode==0) + begin + if (DOUBLE == 1'b1 ) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + + end + else + begin + if ((Instruct==READ) || (Instruct==RD4) || + (Instruct==FSTRD)|| (Instruct==FSTRD4)|| + (Instruct==RDSR) || (Instruct==RDSR2) || + (Instruct==RDCR) || (Instruct==OTPR) || + (Instruct==DOR) || (Instruct==DOR4) || + (Instruct==DIOR)|| (Instruct==DIOR4)|| + (Instruct==ABRD) || (Instruct==BRRD) || + (Instruct==ASPRD)|| (Instruct==DYBRD) || + (Instruct==PPBRD)|| + (Instruct==PASSRD)|| (Instruct==RDID)|| + (Instruct==RES) || (Instruct==REMS) || + (Instruct==PLBRD)|| (Instruct==DLPRD) || + (current_state == AUTOBOOT && + start_delay == 0) || + (((Instruct==QOR) || (Instruct==QIOR) || + (Instruct==QOR4) || + (Instruct==QIOR4)) && QUAD)) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + end + + DUMMY_BYTES: + begin + if (hold_mode==0) + begin + if (DOUBLE == 1'b1 && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + + endcase + end + end + + if (rising_edge_CSNeg_ipd) + begin + if ((bus_cycle_state != DATA_BYTES) && + (bus_cycle_state != DUMMY_BYTES)) + begin + if (bus_cycle_state == ADDRESS_BYTES && opcode_tmp == 8'hFF) + begin + Instruct = MBR; + end + bus_cycle_state = STAND_BY; + end + else + begin + if (bus_cycle_state == DATA_BYTES) + begin + if (((mode_bytes[7:4] == 4'b1010) && + (Instruct==DIOR || Instruct==DIOR4 || + Instruct==QIOR || Instruct==QIOR4)) || + ((mode_bytes[7:4] == ~mode_bytes[3:0]) && + (Instruct == DDRFR || Instruct == DDRFR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4))) + bus_cycle_state = ADDRESS_BYTES; + else + bus_cycle_state = STAND_BY; + + case (Instruct) + WREN, + WRDI, + BE, + SE, + SE4, + P4E, + P4E4, + CLSR, + BRAC, + RESET, + PPBERS, + PPBP, + PLBWR, + PGSP, + PGRS, + ERSP, + ERRS: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 0) + write = 1'b0; + end + end + + WRR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + //If CS# is driven high after eight + //cycle,only the Status Register is + //written to. + begin + write = 1'b0; + for(i=0;i<=7;i=i+1) + begin + Status_reg1_in[i]= + Data_in[7-i]; + end + end + else if (data_cnt == 16) + //After the 16th cycle both the + //Status and Configuration Registers + //are written to. + begin + write = 1'b0; + cfg_write = 1'b1; + for(i=0;i<=7;i=i+1) + begin + Status_reg1_in[i]= + Data_in[7-i]; + Config_reg1_in[i]= + Data_in[15-i]; + end + end + end + end + + PP, + PP4, + OTPP: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt > 0) + begin + if ((data_cnt % 8) == 0) + begin + write = 1'b0; + for(i=0;i<=PageSize;i=i+1) + begin + for(j=7;j>=0;j=j-1) + begin + if ((Data_in[(i*8)+(7-j)]) + !== 1'bX) + begin + Byte_slv[j] = + Data_in[(i*8)+(7-j)]; + end + end + WByte[i] = Byte_slv; + end + + if (data_cnt > (PageSize+1)*BYTE) + Byte_number = PageSize; + else + Byte_number = + ((data_cnt/8) - 1); + end + end + end + end + + QPP, + QPP4: + begin + if (data_cnt >0) + begin + if ((data_cnt % 2) == 0) + begin + write = 1'b0; + quad_pg = 1'b0; + for(i=0;i<=PageSize;i=i+1) + begin + for(j=1;j>=0;j=j-1) + begin + Quad_slv = + quad_data_in[(i*2)+(1-j)]; + if (j==1) + Byte_slv[7:4] = Quad_slv; + else if (j==0) + Byte_slv[3:0] = Quad_slv; + end + WByte[i] = Byte_slv; + end + if (data_cnt > (PageSize+1)*2) + Byte_number = PageSize; + else + Byte_number = ((data_cnt/2)-1); + end + end + end + + ABWR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 32) + begin + write = 1'b0; + for(j=0;j<=31;j=j+1) + begin + AutoBoot_reg_in[j] = Data_in[31-j]; + end + end + end + end + + BRWR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + begin + write = 1'b0; + for(j=0;j<=7;j=j+1) + begin + Bank_Addr_reg_in[j] = Data_in[7-j]; + end + end + end + end + + ASPP: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 16) + begin + write = 1'b0; + for(j=0;j<=15;j=j+1) + begin + ASP_reg_in[j] = Data_in[15-j]; + end + end + end + end + + DYBWR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + begin + write = 1'b0; + for(j=0;j<=7;j=j+1) + begin + DYBAR_in[j] = Data_in[7-j]; + end + end + end + end + + PNVDLR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + begin + write = 1'b0; + for(j=0;j<=7;j=j+1) + begin + NVDLR_reg_in[j] = Data_in[7-j]; + end + end + end + end + + WVDLR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + begin + write = 1'b0; + for(j=0;j<=7;j=j+1) + begin + VDLR_reg_in[j] = Data_in[7-j]; + end + end + end + end + + PASSP: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 64) + begin + write = 1'b0; + for(j=1;j<=8;j=j+1) + begin + for(k=1;k<=8;k=k+1) + begin + Password_reg_in[j*8-k] = + Data_in[8*(j-1)+k-1]; + end + end + end + end + end + + PASSU: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 64) + begin + write = 1'b0; + for(j=1;j<=8;j=j+1) + begin + for(k=1;k<=8;k=k+1) + begin + PASS_TEMP[j*8-k] = + Data_in[8*(j-1)+k-1]; + end + end + end + end + end + endcase + end + end + end + end + +/////////////////////////////////////////////////////////////////////////////// +// Timing control for the Page Program +/////////////////////////////////////////////////////////////////////////////// + time pob; + time elapsed_pgm; + time start_pgm; + time duration_pgm; + event pdone_event; + + always @(rising_edge_PSTART) + begin + if ((Instruct == PP) || (Instruct == PP4) || (Instruct == OTPP) || + (Instruct == QPP) || (Instruct == QPP4)) + if (PageSize == 255) + begin + pob = tdevice_PP_256; + end + else + begin + pob = tdevice_PP_512; + end + else + pob = tdevice_BP; + if ((rising_edge_PSTART) && PDONE) + begin + elapsed_pgm = 0; + duration_pgm = pob; + PDONE = 1'b0; + ->pdone_event; + start_pgm = $time; + end + end + + always @(posedge PGSUSP) + begin + if (PGSUSP && (~PDONE)) + begin + disable pdone_process; + elapsed_pgm = $time - start_pgm; + duration_pgm = pob - elapsed_pgm; + PDONE = 1'b0; + end + end + + always @(posedge PGRES) + begin + start_pgm = $time; + ->pdone_event; + end + + always @(pdone_event) + begin:pdone_process + PDONE = 1'b0; + #duration_pgm PDONE = 1'b1; + end + +/////////////////////////////////////////////////////////////////////////////// +// Timing control for the Write Status Register +/////////////////////////////////////////////////////////////////////////////// + time wob; + always @(posedge WSTART) + begin:wdone_process + wob = tdevice_WRR; + if (WSTART && WDONE) + begin + WDONE = 1'b0; + #wob WDONE = 1'b1; + end + end + +/////////////////////////////////////////////////////////////////////////////// +// Reset Timing +/////////////////////////////////////////////////////////////////////////////// + + time startlo; + time starthi; + time durationlo; + time durationhi; + + always @(negedge RSTNeg_in or Instruct) + begin + if (~RSTNeg_in) + begin + RST = 1'b1; + #200000 RST = 1'b0; // 200 ns + end + else if (Instruct == RESET) + begin + Reseted = 1'b0; + #10000 Reseted = 1'b1; // 10 ns + end + end + + always @(RST_in or rising_edge_Reseted) // Reset done,program terminated + begin + if ((RST_in && ~RST) || (rising_edge_Reseted)) + disable pdone_process; + disable edone_process; + disable wdone_process; + PDONE = 1'b1; + EDONE = 1'b1; + WDONE = 1'b1; + end + +/////////////////////////////////////////////////////////////////////////////// +// Timing control for the Bulk Erase +/////////////////////////////////////////////////////////////////////////////// + time seo; + time beo; + event edone_event; + time elapsed_ers; + time start_ers; + time duration_ers; + + always @(rising_edge_ESTART) + begin + if (UniformSec) + begin + seo = tdevice_SE256; + end + else + begin + seo = tdevice_SE64; + end + beo = tdevice_BE; + if ((rising_edge_ESTART) && EDONE) + begin + if (Instruct == BE) + begin + duration_ers = beo; + end + else + begin + duration_ers = seo; + end + elapsed_ers = 0; + EDONE = 1'b0; + ->edone_event; + start_ers = $time; + end + end + + always @(posedge ESUSP) + begin + if (ESUSP && (~EDONE)) + begin + disable edone_process; + elapsed_ers = $time - start_ers; + duration_ers = seo - elapsed_ers; + EDONE = 1'b0; + end + end + + always @(posedge ERES) + begin + if (ERES && (~EDONE)) + begin + start_ers = $time; + ->edone_event; + end + end + + always @(edone_event) + begin : edone_process + EDONE = 1'b0; + #duration_ers EDONE = 1'b1; + end + + /////////////////////////////////////////////////////////////////// + // Process for clock frequency determination + /////////////////////////////////////////////////////////////////// + always @(posedge SCK_ipd) + begin : clock_period + if (SCK_ipd) + begin + SCK_cycle = $time - prev_SCK; + prev_SCK = $time; + end + end + +// ///////////////////////////////////////////////////////////////////////// +// // Main Behavior Process +// // combinational process for next state generation +// ///////////////////////////////////////////////////////////////////////// + + reg rising_edge_PDONE = 1'b0; + reg rising_edge_EDONE = 1'b0; + reg rising_edge_WDONE = 1'b0; + reg falling_edge_write = 1'b0; + reg falling_edge_PPBERASE_in = 1'b0; + reg falling_edge_PASSULCK_in = 1'b0; + + integer i; + integer j; + + always @(rising_edge_PoweredUp or falling_edge_write or + falling_edge_RSTNeg or rising_edge_PDONE or rising_edge_WDONE or + rising_edge_EDONE or ERSSUSP_out_event or rising_edge_RSTNeg or + PRGSUSP_out_event or rising_edge_CSNeg_ipd or rising_edge_RST_out + or falling_edge_PPBERASE_in or falling_edge_PASSULCK_in) + begin: StateGen1 + + integer sect; + + if (rising_edge_PoweredUp) + begin + if (ABE == 1 && RPME !== 0 ) + begin + next_state = AUTOBOOT; + read_cnt = 0; + byte_cnt = 1; + read_addr = {AutoBoot_reg[31:9], 9'b0}; + start_delay = AutoBoot_reg[8:1]; + start_autoboot = 0; + ABSD = AutoBoot_reg[8:1]; + end + else + next_state = IDLE; + end + else + begin + if (RST_out == 1'b0) + next_state = current_state; + else if (falling_edge_write && Instruct == RESET) + begin + if (ABE == 1 && RPME !== 0) + begin + read_cnt = 0; + byte_cnt = 1; + read_addr = {AutoBoot_reg[31:9], 9'b0}; + start_delay = AutoBoot_reg[8:1]; + ABSD = AutoBoot_reg[8:1]; + start_autoboot = 0; + next_state = AUTOBOOT; + end + else + next_state = IDLE; + end + else + begin + case (current_state) + RESET_STATE : + begin + if (rising_edge_RST_out) + begin + if (ABE == 1 && RPME!== 0) + begin + next_state = AUTOBOOT; + read_cnt = 0; + byte_cnt = 1; + read_addr = {AutoBoot_reg[31:9],9'b0}; + start_delay = AutoBoot_reg[8:1]; + start_autoboot = 0; + ABSD = AutoBoot_reg[8:1]; + end + else + next_state = IDLE; + end + end + + IDLE : + begin + if (falling_edge_write && RdPswdProtMode == 0) + begin + if (Instruct == WRR && WEL == 1 && BAR_ACC == 0 + && (((~(SRWD == 1 && ~WPNeg_in))&& ~QUAD) || QUAD)) + // can not execute if HPM is entered or + // if WEL bit is zero + if (((TBPROT==1 && Config_reg1_in[5]==1'b0) || + (TBPARM==1 && Config_reg1_in[2]==1'b0) || + (BPNV ==1 && Config_reg1_in[3]==1'b0)) && + cfg_write) + begin + $display ("WARNING: Changing value of "); + $display ("Configuration Register OTP "); + $display ("bit from 1 to 0 is not"); + $display ("allowed!!!"); + end + else + begin + next_state = WRITE_SR; + end + else if (Instruct == WRR && BAR_ACC == 1) + begin + // Write to the lower address bits of the BAR + if (P_ERR == 0 && E_ERR == 0) + begin + $display ("WARNING: Changing values of "); + $display ("Bank Address Register"); + $display ("RFU bits are not allowed!!!"); + end + end + else if ((Instruct == PP || Instruct == QPP || + Instruct == PP4 || Instruct == QPP4) && + WEL == 1) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + if (Sec_Prot[sect]== 0 && PPB_bits[sect]== 1 && + DYB_bits[sect]== 1) + begin + next_state = PAGE_PG; + end + end + else if (Instruct==OTPP && WEL==1 && FREEZE==0) + begin + if (((((Address>=16'h0010 && Address<=16'h0013) + ||(Address>=16'h0020 && Address<=16'h00FF)) + && LOCK_BYTE1[Address/32] == 1) || + ((Address>=16'h0100 && Address<=16'h01FF) + && LOCK_BYTE2[(Address-16'h0100)/32]==1) || + ((Address>=16'h0200 && Address<=16'h02FF) + && LOCK_BYTE3[(Address-16'h0200)/32]==1) || + ((Address>=16'h0300 && Address<=16'h03FF) + && LOCK_BYTE4[(Address-16'h0300)/32] == 1)) + && (Address + Byte_number <= OTPHiAddr)) + next_state = OTP_PG; + end + else if ((Instruct == SE || Instruct == SE4) + && WEL == 1) + begin + ReturnSectorID(sect,Address); + if (UniformSec || (TopBoot && sect < 254) || + (BottomBoot && sect > 31)) + begin + if (Sec_Prot[sect]== 0 && PPB_bits[sect]== 1 + && DYB_bits[sect]== 1) + next_state = SECTOR_ERS; + end + else if ((TopBoot && sect >= 254) || + (BottomBoot && sect <= 31)) + begin + if (Sec_ProtSE == 32 && ASP_ProtSE == 32) + //Sector erase command is applied to a + //64 KB range that includes 4 KB sectors. + next_state = SECTOR_ERS; + end + end + else if ((Instruct == P4E || Instruct == P4E4) + && WEL == 1) + begin + if (UniformSec || (TopBoot && sect < 254) || + (BottomBoot && sect > 31)) + begin + $display("The instruction is applied to"); + $display("a sector that is larger than"); + $display("4 KB."); + $display("Instruction is ignored!!!"); + end + else + begin + if (Sec_Prot[sect]== 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + next_state = SECTOR_ERS; + end + end + else if (Instruct == BE && WEL == 1 && + (Status_reg1[4]== 0 && Status_reg1[3]== 0 && + Status_reg1[2]== 0)) + next_state = BULK_ERS; + else if (Instruct == ABWR && WEL == 1) + //Autoboot Register Write Command + next_state = AUTOBOOT_PG; + else if (Instruct == BRWR) + //Bank Register Write Command + next_state = IDLE; + else if (Instruct == ASPP && WEL == 1) + begin + //ASP Register Program Command + if (~(ASPOTPFLAG)) + next_state = ASP_PG; + end + else if (Instruct == PLBWR && WEL == 1 && + RdPswdProtEnable == 0) + next_state = PLB_PG; + else if (Instruct == PASSP && WEL == 1) + begin + if (~(PWDMLB== 0 && PSTMLB== 1)) + next_state = PASS_PG; + end + else if (Instruct == PASSU && WEL && ~WIP) + next_state = PASS_UNLOCK; + else if (Instruct == PPBP && WEL == 1) + next_state <= PPB_PG; + else if (Instruct == PPBERS && WEL && PPBOTP) + next_state <= PPB_ERS; + else if (Instruct == DYBWR && WEL == 1) + next_state = DYB_PG; + else if (Instruct == PNVDLR && WEL == 1) + next_state = NVDLR_PG; + else + next_state = IDLE; + end + if (falling_edge_write && RdPswdProtMode == 1 && ~WIP) + begin + if (Instruct == PASSU) + next_state = PASS_UNLOCK; + end + end + + AUTOBOOT : + begin + if (rising_edge_CSNeg_ipd) + next_state = IDLE; + end + + WRITE_SR : + begin + if (rising_edge_WDONE) + next_state = IDLE; + end + + PAGE_PG : + begin + if (PRGSUSP_out_event && PRGSUSP_out == 1) + next_state = PG_SUSP; + else if (rising_edge_PDONE) + next_state = IDLE; + end + + PG_SUSP : + begin + if (falling_edge_write) + begin + if (Instruct == BRWR) + //Bank Register Write Command + next_state = PG_SUSP; + else if (Instruct == PGRS) + next_state = PAGE_PG; + end + end + + OTP_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + BULK_ERS : + begin + if (rising_edge_EDONE) + next_state = IDLE; + end + + SECTOR_ERS : + begin + if (ERSSUSP_out_event && ERSSUSP_out == 1) + next_state = ERS_SUSP; + else if (rising_edge_EDONE) + next_state = IDLE; + end + + ERS_SUSP : + begin + if (falling_edge_write) + begin + if ((Instruct == PP || Instruct == QPP || + Instruct == PP4 || Instruct == QPP4) && + WEL == 1) + begin + if ((PARAM_REGION && + SectorSuspend != Address/(SecSize+1)) || + (~PARAM_REGION && SectorSuspend != + Address/(SecSize+1)+30*b_act)) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + if (PPB_bits[sect]== 1 && + DYB_bits[sect]== 1) + begin + next_state = ERS_SUSP_PG; + end + end + end + else if (Instruct == BRWR) + begin + //Bank Register Write Command + next_state = ERS_SUSP; + end + else if (Instruct == DYBWR && WEL == 1) + next_state = DYB_PG; + else if (Instruct == ERRS) + next_state = SECTOR_ERS; + end + end + + ERS_SUSP_PG : + begin + if (rising_edge_PDONE) + next_state = ERS_SUSP; + else if (PRGSUSP_out_event && PRGSUSP_out == 1) + next_state = ERS_SUSP_PG_SUSP; + end + + ERS_SUSP_PG_SUSP : + begin + if (rising_edge_PDONE) + next_state = ERS_SUSP; + if (falling_edge_write) + begin + if (Instruct == BRWR) + begin + next_state = ERS_SUSP_PG_SUSP; + end + else if (Instruct == PGRS) + begin + next_state = ERS_SUSP_PG; + end + end + end + + PASS_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + PASS_UNLOCK : + begin + if (falling_edge_PASSULCK_in) + next_state = IDLE; + end + + PPB_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + PPB_ERS : + begin + if (falling_edge_PPBERASE_in) + next_state = IDLE; + end + + AUTOBOOT_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + PLB_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + DYB_PG : + begin + if (rising_edge_PDONE) + if (ES) + next_state = ERS_SUSP; + else + next_state = IDLE; + end + + ASP_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + NVDLR_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + endcase + end + end + end + + /////////////////////////////////////////////////////////////////////////// + //FSM Output generation and general functionality + /////////////////////////////////////////////////////////////////////////// + reg rising_edge_read_out = 1'b0; + reg Instruct_event = 1'b0; + reg change_addr_event = 1'b0; + reg current_state_event = 1'b0; + reg rising_edge_DP_out = 1'b0; + + integer WData [0:511]; + integer WOTPData; + integer Addr; + integer Addr_tmp; + + always @(Instruct_event) + begin + read_cnt = 0; + byte_cnt = 1; + rd_fast = 1'b1; + dual = 1'b0; + rd_slow = 1'b0; + any_read = 1'b0; + end + + always @(rising_edge_read_out) + begin + if (rising_edge_read_out == 1'b1) + begin + if (PoweredUp == 1'b1) + begin + oe_z = 1'b1; + #1000 oe_z = 1'b0; + oe = 1'b1; + #1000 oe = 1'b0; + end + end + end + + always @(change_addr_event) + begin + if (change_addr_event) + begin + read_addr = Address; + end + end + + always @(posedge PASSACC_out) + begin + Status_reg1[0] = 1'b0; //WIP + PASSACC_in = 1'b0; + end + + always @(Instruct or posedge start_autoboot or oe or current_state_event or + falling_edge_write or posedge PDONE or posedge WDONE or oe_z or + posedge EDONE or ERSSUSP_out or rising_edge_Reseted or + rising_edge_PoweredUp or rising_edge_CSNeg_ipd or PRGSUSP_out or + Address) + begin: Functionality + integer i,j; + integer sect; + + if (rising_edge_PoweredUp) + begin + //the default condition after power-up + //The Bank Address Register is loaded to all zeroes + Bank_Addr_reg = 8'h0; + //The Configuration Register FREEZE bit is cleared. + Config_reg1[0] = 0; + //The WEL bit is cleared. + Status_reg1[1] = 0; + //When BPNV is set to '1'. the BP2-0 bits in Status Register are + //volatile and will be reset binary 111 after power-on reset + if (BPNV == 1 && LOCK == 0 && FREEZE == 0 ) + begin + Status_reg1[4] = 1'b0;// BP2 + Status_reg1[3] = 1'b0;// BP1 + Status_reg1[2] = 1'b0;// BP0 + BP_bits = {Status_reg1[4],Status_reg1[3],Status_reg1[2]}; + change_BP = 1'b1; + #1000 change_BP = 1'b0; + end + + //As shipped from the factory, all devices default ASP to the + //Persistent Protection mode, with all sectors unprotected, + //when power is applied. The device programmer or host system must + //then choose which sector protection method to use. + //For Persistent Protection mode, PPBLOCK defaults to "1" + PPBL[0] = 1'b1; + + //All the DYB power-up in the unprotected state + DYB_bits = {286{1'b1}}; + end + + if (Instruct == RESET) + begin + //EXTADD is cleared to “0” + Bank_Addr_reg[7] = 1'b0; + //P_ERR bit is cleared + Status_reg1[6] = 1'b0; + //E_ERR bit is cleared + Status_reg1[5] = 1'b0; + //The WEL bit is cleared. + Status_reg1[1] = 1'b0; + //The WIP bit is cleared. + Status_reg1[0] = 1'b0; + //The ES bit is cleared. + Status_reg2[1] = 1'b0; + //The PS bit is cleared. + Status_reg2[0] = 1'b0; + //When BPNV is set to '1'. the BP2-0 bits in Status + //Register are volatile and will be reseted after + //reset command + if (BPNV == 1 && LOCK== 0 && FREEZE == 0) + begin + Status_reg1[4] = 1'b1; + Status_reg1[3] = 1'b1; + Status_reg1[2] = 1'b1; + + BP_bits = {Status_reg1[4],Status_reg1[3], + Status_reg1[2]}; + change_BP = 1'b1; + #1000 change_BP = 1'b0; + end + end + + case (current_state) + IDLE : + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + ASP_ProtSE = 0; + Sec_ProtSE = 0; + + if (BottomBoot) + begin + for (j=31;j>=0;j=j-1) + begin + if (PPB_bits[j] == 1 && DYB_bits[j] == 1) + begin + ASP_ProtSE = ASP_ProtSE + 1; + end + if (Sec_Prot[j] == 0) + begin + Sec_ProtSE = Sec_ProtSE + 1; + end + end + end + else if (TopBoot) + begin + for (j=285;j>=254;j=j-1) + begin + if (PPB_bits[j] == 1 && DYB_bits[j] == 1) + begin + ASP_ProtSE = ASP_ProtSE + 1; + end + if (Sec_Prot[j] == 0) + begin + Sec_ProtSE = Sec_ProtSE + 1; + end + end + end + + if (falling_edge_write && RdPswdProtMode == 1) + begin + if(Instruct == PASSU) + begin + if (~WIP) + begin + PASSULCK_in = 1; + Status_reg1[0] = 1'b1; //WIP + end + else + begin + $display ("The PASSU command cannot be accepted"); + $display (" any faster than once every 100us"); + end + end + else if (Instruct == CLSR) + begin + //The Clear Status Register Command resets bit SR1[5] + //(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + Status_reg1[5] = 0; + Status_reg1[6] = 0; + end + end + + if (falling_edge_write && RdPswdProtMode == 0) + begin + read_cnt = 0; + byte_cnt = 1; + if (Instruct == WREN) + Status_reg1[1] = 1'b1; + else if (Instruct == WRDI) + Status_reg1[1] = 0; + else if ((Instruct == WRR) && WEL == 1 && WDONE == 1 && + BAR_ACC == 0) + begin + if (((~(SRWD == 1 && ~WPNeg_in))&& ~QUAD) || QUAD) + begin + if (((TBPROT==1 && Config_reg1_in[5]==1'b0) || + (TBPARM==1 && Config_reg1_in[2]==1'b0) || + (BPNV ==1 && Config_reg1_in[3]==1'b0)) && + cfg_write) + begin + // P_ERR bit is set to 1 + Status_reg1[6] = 1'b1; + end + else + begin + // can not execute if Hardware Protection Mode + // is entered or if WEL bit is zero + WSTART = 1'b1; + WSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + end + else + Status_reg1[1] = 0; + end + else if ((Instruct == PP || Instruct == PP4) && WEL ==1 && + PDONE == 1 ) + begin + ReturnSectorID(sect,Address); + if (Sec_Prot[sect] == 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 0; + PGRES = 0; + INITIAL_CONFIG = 1; + Status_reg1[0] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + //P_ERR bit will be set when the user attempts to + //to program within a protected main memory sector + Status_reg1[6] = 1'b1; //P_ERR + Status_reg1[1] = 1'b0; //WEL + end + end + else if ((Instruct == QPP || Instruct == QPP4) && WEL ==1 && + PDONE == 1 ) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + if (Sec_Prot[sect] == 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 0; + PGRES = 0; + INITIAL_CONFIG = 1; + Status_reg1[0] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + //P_ERR bit will be set when the user attempts to + //to program within a protected main memory sector + Status_reg1[6] = 1'b1; //P_ERR + Status_reg1[1] = 1'b0; //WEL + end + end + else if (Instruct == OTPP && WEL == 1) + begin + // As long as the FREEZE bit remains cleared to a logic + // '0' the OTP address space is programmable. + if (FREEZE == 0) + begin + if (((((Address>= 16'h0010 && Address<= 16'h0013) || + (Address >= 16'h0020 && Address <= 16'h00FF)) + && LOCK_BYTE1[Address/32] == 1) || + ((Address >= 16'h0100 && Address <= 16'h01FF) + && LOCK_BYTE2[(Address-16'h0100)/32] == 1) || + ((Address >= 16'h0200 && Address <= 16'h02FF) + && LOCK_BYTE3[(Address-16'h0200)/32] == 1) || + ((Address >= 16'h0300 && Address <= 16'h03FF) + && LOCK_BYTE4[(Address-16'h0300)/32] == 1)) && + (Address + Byte_number <= OTPHiAddr)) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else if ((Address < 8'h10 || (Address > 8'h13 && + Address < 8'h20) || Address > 12'h3FF )) + begin + Status_reg1[6] = 1'b1;//P_ERR + Status_reg1[1] = 1'b0;//WEL + if (Address < 8'h20) + begin + $display ("Given address is "); + $display ("in reserved address range"); + end + else if (Address > 12'h3FF) + begin + $display ("Given address is "); + $display ("out of OTP address range"); + end + end + else + begin + //P_ERR bit will be set when the user attempts to + // to program within locked OTP region + Status_reg1[6] = 1'b1;//P_ERR + Status_reg1[1] = 1'b0;//WEL + end + end + else + begin + //P_ERR bit will be set when the user attempts to + //to program within locked OTP region + Status_reg1[6] = 1'b1;//P_ERR + Status_reg1[1] = 1'b0;//WEL + end + end + else if ((Instruct == SE || Instruct == SE4) && WEL == 1) + begin + ReturnSectorID(sect,Address); + if (UniformSec || (TopBoot && sect < 254) || + (BottomBoot && sect > 31)) + begin + SectorSuspend = sect; + PARAM_REGION = 0; + if (Sec_Prot[sect] == 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + ESTART = 1'b1; + ESTART <= #5 1'b0; + ESUSP = 0; + ERES = 0; + INITIAL_CONFIG = 1; + Status_reg1[0] = 1'b1; + Addr = Address; + end + else + begin + //E_ERR bit will be set when the user attempts to + //erase an individual protected main memory sector + Status_reg1[5] = 1'b1;//E_ERR + Status_reg1[1] = 1'b0;//WEL + end + end + else if ((TopBoot && sect >= 254) || + (BottomBoot && sect <= 31)) + begin + if (Sec_ProtSE == 32 && ASP_ProtSE == 32) + //Sector erase command is applied to a 64 KB range + //that includes 4 KB sectors + begin + if (TopBoot) + begin + SectorSuspend = 254 + (285 - sect)/16; + end + else + begin + SectorSuspend = sect/16; + end + PARAM_REGION = 1; + ESTART = 1'b1; + ESTART <= #5 1'b0; + ESUSP = 0; + ERES = 0; + INITIAL_CONFIG = 1; + Status_reg1[0] = 1'b1; + Addr = Address; + end + else + begin + //E_ERR bit will be set when the user attempts to + //erase an individual protected main memory sector + Status_reg1[5] = 1'b1;//E_ERR + Status_reg1[1] = 1'b0;//WEL + end + end + end + else if ((Instruct == P4E || Instruct == P4E4) && WEL == 1) + begin + ReturnSectorID(sect,Address); + if (UniformSec || (TopBoot && sect < 254) || + (BottomBoot && sect > 31)) + begin + Status_reg1[1] = 1'b0;//WEL + end + else + begin + if (Sec_Prot[sect] == 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + //A P4E instruction applied to a sector + //that has been Write Protected through the + //Block Protect Bits or ASP will not be + //executed and will set the E_ERR status + begin + ESTART = 1'b1; + ESTART <= #5 1'b0; + ESUSP = 0; + ERES = 0; + INITIAL_CONFIG = 1; + Status_reg1[0] = 1'b1; + Addr = Address; + end + else + begin + //E_ERR bit will be set when the user attempts to + //erase an individual protected main memory sector + Status_reg1[5] = 1'b1;//E_ERR + Status_reg1[1] = 1'b0;//WEL + end + end + end + else if (Instruct == BE && WEL == 1) + begin + if (Status_reg1[4]== 0 && Status_reg1[3]== 0 && + Status_reg1[2]== 0) + begin + ESTART = 1'b1; + ESTART <= #5 1'b0; + ESUSP = 0; + ERES = 0; + INITIAL_CONFIG = 1; + Status_reg1[0] = 1'b1; + end + else + begin + //The Bulk Erase command will not set E_ERR if a + //protected sector is found during the command + //execution. + Status_reg1[1] = 1'b0;//WEL + end + end + else if (Instruct == PASSP && WEL == 1) + begin + if (~(PWDMLB== 0 && PSTMLB== 1)) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else + begin + $display ("Password programming is not allowed"); + $display (" in Password Protection Mode."); + end + end + else if (Instruct == PASSU && WEL) + begin + if (~WIP) + begin + PASSULCK_in = 1; + Status_reg1[0] = 1'b1; //WIP + end + else + begin + $display ("The PASSU command cannot be accepted"); + $display (" any faster than once every 100us"); + end + end + else if (Instruct == BRWR) + begin + Bank_Addr_reg[7] = Bank_Addr_reg_in[7]; + end + else if (Instruct == ASPP && WEL == 1) + begin + if (~(ASPOTPFLAG)) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + $display ("Once the Protection Mode is selected,"); + $display ("no further changes to the ASP "); + $display ("register is allowed."); + end + end + else if (Instruct == ABWR && WEL == 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == PPBP && WEL == 1) + begin + ReturnSectorID(sect,Address); + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == PPBERS && WEL == 1) + begin + if (PPBOTP) + begin + PPBERASE_in = 1'b1; + Status_reg1[0] = 1'b1; + end + else + begin + Status_reg1[5] = 1'b1; + end + end + else if (Instruct == PLBWR && WEL == 1 && + RdPswdProtEnable == 0) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == DYBWR && WEL == 1) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == PNVDLR && WEL == 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == WVDLR && WEL == 1) + begin + VDLR_reg = VDLR_reg_in; + Status_reg1[1] = 1'b0; + end + else if (Instruct == CLSR) + begin + //The Clear Status Register Command resets bit SR1[5] + //(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + Status_reg1[5] = 0; + Status_reg1[6] = 0; + end + + if (Instruct == BRAC && P_ERR == 0 && E_ERR == 0) + begin + BAR_ACC = 1; + end + else + begin + BAR_ACC = 0; + end + end + else if (oe_z) + begin + if (Instruct == READ || Instruct == RD4 || + Instruct == RES || + (Instruct == DLPRD && RdPswdProtMode == 0)) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else if (Instruct == DDRDIOR || Instruct == DDRDIOR4 || + ((Instruct == DDRQIOR || Instruct == DDRQIOR4) + && QUAD)) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + ((Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4) + && QUAD)) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + else if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == READ || Instruct == RD4 || + Instruct == FSTRD || Instruct == FSTRD4 || + Instruct == DDRFR || Instruct == DDRFR4 ) + begin + //Read Memory array + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + if (bus_cycle_state == DUMMY_BYTES + && VDLR_reg != 8'b00000000) + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) is enabled + // Optional DLP + if (VDLR_reg != 8'b00000000 && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + read_addr_tmp = read_addr; + SecAddr = read_addr/(SecSize+1) ; + Sec_addr = read_addr - SecAddr*(SecSize+1); + SecAddr = ReturnSectorIDRdPswdMd(TBPROT); + read_addr = Sec_addr + SecAddr*(SecSize+1); + if (RdPswdProtMode == 0) + begin + read_addr = read_addr_tmp; + end + if (Mem[read_addr] !== -1) + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + end + else + begin + SOut_zd = 8'bx; + end + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 ) + begin + //Read Memory array + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + if (VDLR_reg != 8'b00000000 && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + read_addr_tmp = read_addr; + SecAddr = read_addr/(SecSize+1) ; + Sec_addr = read_addr - SecAddr*(SecSize+1); + SecAddr = ReturnSectorIDRdPswdMd(TBPROT); + read_addr = Sec_addr + SecAddr*(SecSize+1); + if (RdPswdProtMode == 0) + read_addr = read_addr_tmp; + + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if ((Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4 ) + && QUAD) + begin + //Read Memory array + if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (bus_cycle_state == DUMMY_BYTES) + begin + if ((Instruct == DDRQIOR || Instruct == DDRQIOR4) + && QUAD) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) is enabled + // Optional DLP + if (VDLR_reg != 8'b00000000 && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + HOLDNegOut_zd = data_out[7-read_cnt]; + WPNegOut_zd = data_out[7-read_cnt]; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + read_addr_tmp = read_addr; + SecAddr = read_addr/(SecSize+1) ; + Sec_addr = read_addr - SecAddr*(SecSize+1); + SecAddr = ReturnSectorIDRdPswdMd(TBPROT); + read_addr = Sec_addr + SecAddr*(SecSize+1); + if (RdPswdProtMode == 0) + read_addr = read_addr_tmp; + + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == OTPR) + begin + if(read_addr>=OTPLoAddr && read_addr<=OTPHiAddr + && RdPswdProtMode == 0) + begin + //Read OTP Memory array + rd_fast = 1'b1; + rd_slow = 1'b0; + data_out[7:0] = OTPMem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + else if ((read_addr > OTPHiAddr)||(RdPswdProtMode==1)) + begin + //OTP Read operation will not wrap to the + //starting address after the OTP address is at + //its maximum or Read Password Protection Mode + //is selected instead, the data beyond the + //maximum OTP address will be undefined. + SOut_zd = 1'bX; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (Instruct == REMS) + begin + //Read Manufacturer and Device ID + if (read_addr % 2 == 0) + begin + data_out[7:0] = Manuf_ID; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + else + begin + data_out[7:0] = DeviceID; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = 0; + end + end + end + else if (Instruct == RDID) + begin + ident_out = CFI_array_tmp; + if(read_cnt < 648) + begin + SOut_zd = ident_out[647-read_cnt]; + read_cnt = read_cnt + 1; + end + else + begin + //Continued shifting of output beyond the end of + //the defined ID-CFI address space will + //provide undefined data. + SOut_zd = 1'bX; + end + end + else if (Instruct == RES) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + data_out = ESignature; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == DLPRD && RdPswdProtMode == 0) + begin + //Read DLP + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = VDLR_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == ABRD && RdPswdProtMode == 0) + begin + //Read AutoBoot register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = AutoBoot_reg[31-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 32) + read_cnt = 0; + end + else if (Instruct == BRRD && RdPswdProtMode == 0) + begin + //Read Bank Address Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = Bank_Addr_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == ASPRD && RdPswdProtMode == 0) + begin + //Read ASP Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = ASP_reg[15-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 16) + read_cnt = 0; + end + else if (Instruct == PASSRD && RdPswdProtMode == 0) + begin + //Read Password Register + if (~(PWDMLB == 0 && PSTMLB == 1)) + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = + Password_reg[(8*byte_cnt-1)-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + byte_cnt = byte_cnt + 1; + if (byte_cnt == 9) + byte_cnt = 1; + end + end + end + else if (Instruct == PLBRD) + begin + //Read PPB Lock Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = PPBL[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == DYBRD) + begin + //Read DYB Access Register + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + DYBAR[7:0] = 8'bXXXXXXXX; + + if (RdPswdProtMode == 0) + begin + if (DYB_bits[sect] == 1) + DYBAR[7:0] = 8'hFF; + else + begin + DYBAR[7:0] = 8'h0; + end + end + SOut_zd = DYBAR[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == PPBRD) + begin + //Read PPB Access Register + ReturnSectorID(sect,Address); + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + PPBAR[7:0] = 8'bXXXXXXXX; + if (RdPswdProtMode == 0) + begin + if (PPB_bits[sect] == 1) + PPBAR[7:0] = 8'hFF; + else + begin + PPBAR[7:0] = 8'h0; + end + end + SOut_zd = PPBAR[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + end + + AUTOBOOT: + begin + if (start_autoboot == 1) + begin + if (oe) + begin + any_read = 1'b1; + if (QUAD == 1) + begin + if (ABSD > 0) //If ABSD > 0, + begin //max SCK frequency is 104MHz + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else // If ABSD = 0, max SCK frequency is 50 MHz + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + else + begin + if (ABSD > 0) //If ABSD > 0, + begin //max SCK frequency is 133MHz + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + else // If ABSD = 0, max SCK frequency is 50 MHz + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + end + else if (oe_z) + begin + if (QUAD == 1) + begin + if (ABSD > 0) //If ABSD > 0, + begin //max SCK frequency is 104MHz + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else // If ABSD = 0, max SCK frequency is 50 MHz + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + end + else + begin + if (ABSD > 0) //If ABSD > 0, + begin //max SCK frequency is 133MHz + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + else // If ABSD = 0, max SCK frequency is 50 MHz + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + end + end + + WRITE_SR: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (WDONE == 1) + begin + Status_reg1[0] = 1'b0; //WIP + Status_reg1[1] = 1'b0; //WEL + //SRWD bit + Status_reg1[7] = Status_reg1_in[7]; //MSB first + + if (LOCK == 0) + begin + if (FREEZE == 0) + //The Freeze Bit, when set to 1, locks the current + //state of the BP2-0 bits in Status Register, + //the TBPROT and TBPARM bits in the Config Register + //As long as the FREEZE bit remains cleared to logic + //'0', the other bits of the Configuration register + //including FREEZE are writeable. + begin + Status_reg1[4] = Status_reg1_in[4];//BP2 + Status_reg1[3] = Status_reg1_in[3];//BP1 + Status_reg1[2] = Status_reg1_in[2];//BP0 + + BP_bits = {Status_reg1[4],Status_reg1[3], + Status_reg1[2]}; + if (TBPROT == 1'b0 && INITIAL_CONFIG == 1'b0) + begin + Config_reg1[5] = Config_reg1_in[5];//TBPROT + end + if (TBPARM == 1'b0 && INITIAL_CONFIG == 1'b0 && + tmp_char2 == "0") + begin + Config_reg1[2] = Config_reg1_in[2];//TBPARM + change_TBPARM = 1'b1; + #1000 change_TBPARM = 1'b0; + end + change_BP = 1'b1; + #1000 change_BP = 1'b0; + end + end + + Config_reg1[7] = Config_reg1_in[7];//LC1 + Config_reg1[6] = Config_reg1_in[6];//LC0 + Config_reg1[1] = Config_reg1_in[1];//QUAD + + if (FREEZE == 1'b0) + begin + Config_reg1[0] = Config_reg1_in[0];//FREEZE + end + + if (WRLOCKENABLE== 1'b1 && LOCK == 1'b0) + begin + Config_reg1[4] = Config_reg1_in[4];//LOCK + WRLOCKENABLE = 1'b0; + end + if (BPNV == 1'b0) + begin + Config_reg1[3] = Config_reg1_in[3];//BPNV + end + end + end + + PAGE_PG : + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == PAGE_PG) + begin + if (~PDONE) + begin + ADDRHILO_PG(AddrLo, AddrHi, Addr); + cnt = 0; + + for (i=0;i<=wr_cnt;i=i+1) + begin + new_int = WData[i]; + old_int = Mem[Addr + i - cnt]; + if (new_int > -1) + begin + new_bit = new_int; + if (old_int > -1) + begin + old_bit = old_int; + for(j=0;j<=7;j=j+1) + begin + if (~old_bit[j]) + new_bit[j]=1'b0; + end + new_int=new_bit; + end + WData[i]= new_int; + end + else + begin + WData[i] = -1; + end + + Mem[Addr + i - cnt] = - 1; + if ((Addr + i) == AddrHi) + begin + + Addr = AddrLo; + cnt = i + 1; + end + end + end + cnt = 0; + end + + if (PDONE) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + quad_pg = 0; + for (i=0;i<=wr_cnt;i=i+1) + begin + Mem[Addr_tmp + i - cnt] = WData[i]; + if ((Addr_tmp + i) == AddrHi) + begin + Addr_tmp = AddrLo; + cnt = i + 1; + end + end + end + + if (Instruct) + begin + if (Instruct == PGSP && ~PRGSUSP_in) + begin + if (~RES_TO_SUSP_MIN_TIME) + begin + PGSUSP = 1'b1; + PGSUSP <= #5 1'b0; + PRGSUSP_in = 1'b1; + if (RES_TO_SUSP_TYP_TIME) + begin + $display("Typical periods are needed for ", + "Program to progress to completion"); + end + end + else + begin + $display("Minimum for tPRS is not satisfied! ", + "PGSP command is ignored"); + end + end + end + end + + PG_SUSP: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + + if (PRGSUSP_out && PRGSUSP_in) + begin + PRGSUSP_in = 1'b0; + //The RDY/BSY bit in the Status Register will indicate that + //the device is ready for another operation. + Status_reg1[0] = 1'b0; + //The Program Suspend (PS) bit in the Status Register will + //be set to the logical “1” state to indicate that the + //program operation has been suspended. + Status_reg2[0] = 1'b1; + PDONE = 1'b1; + end + + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == BRRD) + begin + //Read Bank Address Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = Bank_Addr_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + //Read Array Operations + else if (Instruct == READ || Instruct == RD4 || + Instruct == FSTRD || Instruct == FSTRD4 || + Instruct == DDRFR || Instruct == DDRFR4 ) + begin + //Read Memory array + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + if (pgm_page != read_addr / (PageSize+1)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + + end + end + else + begin + SOut_zd = 8'bxxxxxxxx; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 ) + begin + //Read Memory array + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (pgm_page != read_addr / (PageSize+1)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4 ) + begin + //Read Memory array + if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (pgm_page != read_addr / (PageSize+1)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if ((Instruct == DDRQIOR + || Instruct == DDRQIOR4) && QUAD) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + HOLDNegOut_zd= data_out[7-read_cnt]; + WPNegOut_zd = data_out[7-read_cnt]; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + HOLDNegOut_zd = 1'bx; + WPNegOut_zd = 1'bx; + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + end + else if (oe_z) + begin + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (falling_edge_write) + begin + if (Instruct == BRWR) + begin + Bank_Addr_reg[7] = Bank_Addr_reg_in[7]; + end + else if (Instruct == WRR && BAR_ACC == 1) + begin + // Write to the lower address bits of the BAR + if (P_ERR == 0 && E_ERR == 0) + begin + $display ("WARNING: Changing values of "); + $display ("Bank Address Register"); + $display ("RFU bits are not allowed!!!"); + end + end + else if (Instruct == PGRS) + begin + Status_reg2[0] = 1'b0; + Status_reg1[0] = 1'b1; + PGRES = 1'b1; + PGRES <= #5 1'b0; + RES_TO_SUSP_MIN_TIME = 1'b1; + RES_TO_SUSP_MIN_TIME <= #60000 1'b0;//60 ns + RES_TO_SUSP_TYP_TIME = 1'b1; + RES_TO_SUSP_TYP_TIME <= #100000000 1'b0;//100us + end + + if (Instruct == BRAC && P_ERR == 0 && E_ERR == 0 && + RdPswdProtMode == 0) + begin + BAR_ACC = 1; + end + else + begin + BAR_ACC = 0; + end + end + end + + ERS_SUSP_PG_SUSP: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + + if (PRGSUSP_out && PRGSUSP_in) + begin + PRGSUSP_in = 1'b0; + //The RDY/BSY bit in the Status Register will indicate that + //the device is ready for another operation. + Status_reg1[0] = 1'b0; + //The Program Suspend (PS) bit in the Status Register will + //be set to the logical “1” state to indicate that the + //program operation has been suspended. + Status_reg2[0] = 1'b1; + end + + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == BRRD) + begin + //Read Bank Address Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = Bank_Addr_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + //Read Array Operations + else if (Instruct == READ || Instruct == RD4 || + Instruct == FSTRD || Instruct == FSTRD4 || + Instruct == DDRFR || Instruct == DDRFR4 ) + begin + //Read Memory array + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + if ((SectorSuspend != read_addr/(SecSize+1)) && + (pgm_page != read_addr / (PageSize+1))) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + + end + end + else + begin + SOut_zd = 8'bxxxxxxxx; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 ) + begin + //Read Memory array + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if ((SectorSuspend != read_addr/(SecSize+1)) && + (pgm_page != read_addr / (PageSize+1))) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4 ) + begin + //Read Memory array + if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if ((SectorSuspend != read_addr/(SecSize+1)) && + (pgm_page != read_addr / (PageSize+1))) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if ((Instruct == DDRQIOR + || Instruct == DDRQIOR4) && QUAD) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + HOLDNegOut_zd =data_out[7-read_cnt]; + WPNegOut_zd = data_out[7-read_cnt]; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + HOLDNegOut_zd = 1'bx; + WPNegOut_zd = 1'bx; + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + end + else if (oe_z) + begin + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (falling_edge_write) + begin + if (Instruct == BRWR) + begin + Bank_Addr_reg[7] = Bank_Addr_reg_in[7]; + end + else if (Instruct == WRR && BAR_ACC == 1) + begin + // Write to the lower address bits of the BAR + if (P_ERR == 0 && E_ERR == 0) + begin + $display ("WARNING: Changing values of "); + $display ("Bank Address Register"); + $display ("RFU bits are not allowed!!!"); + end + end + else if (Instruct == PGRS) + begin + Status_reg2[0] = 1'b0; + Status_reg1[0] = 1'b1; + PGRES = 1'b1; + PGRES <= #5 1'b0; + RES_TO_SUSP_MIN_TIME = 1'b1; + RES_TO_SUSP_MIN_TIME <= #60000 1'b0;//60 ns + RES_TO_SUSP_TYP_TIME = 1'b1; + RES_TO_SUSP_TYP_TIME <= #100000000 1'b0;//100us + end + + if (Instruct == BRAC && P_ERR == 0 && E_ERR == 0 && + RdPswdProtMode == 0) + begin + BAR_ACC = 1; + end + else + begin + BAR_ACC = 0; + end + end + end + + OTP_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == OTP_PG) + begin + if (~PDONE) + begin + if (Address + wr_cnt <= OTPHiAddr) + begin + for (i=0;i<=wr_cnt;i=i+1) + begin + new_int = WData[i]; + old_int = OTPMem[Addr + i]; + if (new_int > -1) + begin + new_bit = new_int; + if (old_int > -1) + begin + old_bit = old_int; + for(j=0;j<=7;j=j+1) + begin + if (~old_bit[j]) + new_bit[j] = 1'b0; + end + new_int = new_bit; + end + WData[i] = new_int; + end + else + begin + WData[i] = -1; + end + OTPMem[Addr + i] = -1; + end + end + else + begin + $display ("Programming will reach over "); + $display ("address limit of OTP array"); + end + end + end + + if (PDONE) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + for (i=0;i<=wr_cnt;i=i+1) + begin + OTPMem[Addr + i] = WData[i]; + end + LOCK_BYTE1 = OTPMem[16]; + LOCK_BYTE2 = OTPMem[17]; + LOCK_BYTE3 = OTPMem[18]; + LOCK_BYTE4 = OTPMem[19]; + end + end + + SECTOR_ERS: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == SECTOR_ERS) + begin + if (~EDONE) + begin + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = -1; + end + end + end + + if (EDONE == 1) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = MaxData; + end + end + else if (Instruct == ERSP && ~ERSSUSP_in) + begin + ESUSP = 1'b1; + ESUSP <= #5 1'b0; + ERSSUSP_in = 1'b1; + if (RES_TO_SUSP_TYP_TIME) + begin + $display("Typical periods are needed for ", + "Program to progress to completion"); + end + end + end + + BULK_ERS: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == BULK_ERS) + begin + if (~EDONE) + begin + for (i=0;i<=AddrRANGE;i=i+1) + begin + ReturnSectorID(sect,i); + if (PPB_bits[sect] == 1 && DYB_bits[sect] == 1) + begin + Mem[i] = -1; + end + end + end + end + + if (EDONE == 1) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + for (i=0;i<=AddrRANGE;i=i+1) + begin + ReturnSectorID(sect,i); + if (PPB_bits[sect] == 1 && DYB_bits[sect] == 1) + begin + Mem[i] = MaxData; + end + end + end + end + + ERS_SUSP: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (ERSSUSP_out == 1) + begin + ERSSUSP_in = 0; + //The Erase Suspend (ES) bit in the Status Register will + //be set to the logical “1” state to indicate that the + //erase operation has been suspended. + Status_reg2[1] = 1'b1; + //The WIP bit in the Status Register will indicate that + //the device is ready for another operation. + Status_reg1[0] = 1'b0; + end + + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == DYBRD) + begin + //Read DYB Access Register + ReturnSectorID(sect,Address); + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (DYB_bits[sect] == 1) + DYBAR[7:0] = 8'hFF; + else + begin + DYBAR[7:0] = 8'h0; + end + SOut_zd = DYBAR[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == BRRD) + begin + //Read Bank Address Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = Bank_Addr_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == PPBRD) + begin + //Read PPB Access Register + ReturnSectorID(sect,Address); + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + PPBAR[7:0] = 8'bXXXXXXXX; + if (RdPswdProtMode == 0) + begin + if (PPB_bits[sect] == 1) + PPBAR[7:0] = 8'hFF; + else + begin + PPBAR[7:0] = 8'h0; + end + end + SOut_zd = PPBAR[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == READ || Instruct == RD4 || + Instruct == FSTRD || Instruct == FSTRD4 || + Instruct == DDRFR || Instruct == DDRFR4 ) + begin + //Read Memory array + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + if ((PARAM_REGION && + SectorSuspend != read_addr/(SecSize+1)) || + (~PARAM_REGION && + SectorSuspend != read_addr/(SecSize+1)+30*b_act)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + SOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 ) + begin + //Read Memory array + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if ((PARAM_REGION && + SectorSuspend != read_addr/(SecSize+1)) || + (~PARAM_REGION && + SectorSuspend != read_addr/(SecSize+1)+30*b_act)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4 ) + begin + //Read Memory array + if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if ((PARAM_REGION && + SectorSuspend != read_addr/(SecSize+1)) || + (~PARAM_REGION && + SectorSuspend != read_addr/(SecSize+1)+30*b_act)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if ((Instruct == DDRQIOR + || Instruct == DDRQIOR4) && QUAD) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + HOLDNegOut_zd= data_out[7-read_cnt]; + WPNegOut_zd = data_out[7-read_cnt]; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + HOLDNegOut_zd = 1'bx; + WPNegOut_zd = 1'bx; + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + end + else if (oe_z) + begin + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (falling_edge_write) + begin + if ((Instruct == PP || Instruct == PP4) && WEL == 1) + begin + if ((PARAM_REGION && + SectorSuspend != Address/(SecSize+1)) || + (~PARAM_REGION && + SectorSuspend != Address/(SecSize+1)+30*b_act)) + begin + ReturnSectorID(sect,Address); + if (Sec_Prot[sect] == 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 0; + PGRES = 0; + Status_reg1[0] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + end + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + end + end + else if ((Instruct == QPP || Instruct == QPP4) && WEL == 1) + begin + if ((PARAM_REGION && + SectorSuspend != Address/(SecSize+1)) || + (~PARAM_REGION && + SectorSuspend != Address/(SecSize+1)+30*b_act)) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + + if (Sec_Prot[sect] == 0 + && PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 0; + PGRES = 0; + Status_reg1[0] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + end + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + end + end + else if (Instruct == WREN) + Status_reg1[1] = 1'b1; + else if (Instruct == CLSR) + begin + //The Clear Status Register Command resets bit SR1[5] + //(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + Status_reg1[5] = 0; + Status_reg1[6] = 0; + end + else if (Instruct == BRWR) + begin + Bank_Addr_reg[7] = Bank_Addr_reg_in[7]; + end + else if (Instruct == WRR && BAR_ACC == 1) + begin + // Write to the lower address bits of the BAR + if (P_ERR == 0 && E_ERR == 0) + begin + $display ("WARNING: Changing values of "); + $display ("Bank Address Register"); + $display ("RFU bits are not allowed!!!"); + end + end + else if (Instruct == DYBWR && WEL == 1) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == ERRS) + begin + Status_reg2[1] = 1'b0; + Status_reg1[0] = 1'b1; + if (BottomBoot) + begin + if (PARAM_REGION) + begin + Addr = SectorSuspend*(SecSize+1); + end + else + begin + Addr = (SectorSuspend-30)*(SecSize+1); + end + end + else + begin + Addr = SectorSuspend*(SecSize+1); + end + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + ERES = 1'b1; + ERES <= #5 1'b0; + RES_TO_SUSP_TYP_TIME = 1'b1; + RES_TO_SUSP_TYP_TIME <= #100000000 1'b0;//100us + end + + if (Instruct == BRAC && P_ERR == 0 && E_ERR == 0 && + RdPswdProtMode == 0) + begin + BAR_ACC = 1; + end + else + begin + BAR_ACC = 0; + end + end + end + + ERS_SUSP_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == ERS_SUSP_PG) + begin + if (~PDONE) + begin + ADDRHILO_PG(AddrLo, AddrHi, Addr); + cnt = 0; + for (i=0;i<=wr_cnt;i=i+1) + begin + new_int = WData[i]; + old_int = Mem[Addr + i - cnt]; + if (new_int > -1) + begin + new_bit = new_int; + if (old_int > -1) + begin + old_bit = old_int; + for(j=0;j<=7;j=j+1) + begin + if (~old_bit[j]) + new_bit[j] = 1'b0; + end + new_int = new_bit; + end + WData[i] = new_int; + end + else + begin + WData[i] = -1; + end + + if ((Addr + i) == AddrHi) + begin + Addr = AddrLo; + cnt = i + 1; + end + end + end + cnt =0; + end + + if(PDONE == 1) + begin + Status_reg1[0] = 1'b0;//WIP + Status_reg1[1] = 1'b0;//WEL + for (i=0;i<=wr_cnt;i=i+1) + begin + Mem[Addr_tmp + i - cnt] = WData[i]; + if ((Addr_tmp + i) == AddrHi ) + begin + Addr_tmp = AddrLo; + cnt = i + 1; + end + end + end + + if (Instruct) + begin + if (Instruct == PGSP && ~PRGSUSP_in) + begin + if (~RES_TO_SUSP_MIN_TIME) + begin + PGSUSP = 1'b1; + PGSUSP <= #5 1'b0; + PRGSUSP_in = 1'b1; + if (RES_TO_SUSP_TYP_TIME) + begin + $display("Typical periods are needed for ", + "Program to progress to completion"); + end + end + else + begin + $display("Minimum for tPRS is not satisfied! ", + "PGSP command is ignored"); + end + end + end + end + + PASS_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + new_pass = Password_reg_in; + old_pass = Password_reg; + for (i=0;i<=63;i=i+1) + begin + if (old_pass[j] == 0) + new_pass[j] = 0; + end + + if (PDONE == 1) + begin + Password_reg = new_pass; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + PASS_UNLOCK: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PASS_TEMP == Password_reg) + begin + PASS_UNLOCKED = 1'b1; + end + else + begin + PASS_UNLOCKED = 1'b0; + end + if (PASSULCK_out == 1'b1) + begin + if ((PASS_UNLOCKED == 1'b1) && (~PWDMLB)) + begin + PPBL[0] = 1'b1; + Status_reg1[0] = 1'b0; //WIP + end + else + begin + Status_reg1[6] = 1'b1; + $display ("Incorrect Password"); + PASSACC_in = 1'b1; + end + Status_reg1[1] = 1'b0; + PASSULCK_in = 1'b0; + end + end + + PPB_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + if (PPB_LOCK !== 0) + begin + PPB_bits[sect]= 1'b0; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + else + begin + Status_reg1[5] = 1'b0; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + end + + PPB_ERS: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PPBERASE_out == 1'b1) + begin + if ((PPB_LOCK !== 0) && PPBOTP) + begin + PPB_bits = {286{1'b1}}; + end + else + begin + Status_reg1[5] = 1'b1; + end + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + PPBERASE_in = 1'b0; + end + end + + AUTOBOOT_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + AutoBoot_reg = AutoBoot_reg_in; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + PLB_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + PPBL[0] = 1'b0; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + DYB_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + DYBAR = DYBAR_in; + if (DYBAR == 8'hFF) + begin + DYB_bits[sect]= 1'b1; + end + else if (DYBAR == 8'h00) + begin + DYB_bits[sect]= 1'b0; + end + else + begin + Status_reg1[6] = 1'b1; + end + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + ASP_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + + if (RPME == 1'b0 && ASP_reg_in[5] == 1'b1) + begin + Status_reg1[6] = 1'b1; //P_ERR + $display("RPME bit is allready programmed"); + end + else + begin + ASP_reg[5] = ASP_reg_in[5];//RPME + end + + if (PPBOTP == 1'b0 && ASP_reg_in[3] == 1'b1) + begin + Status_reg1[6] = 1'b1; //P_ERR + $display("PPBOTP bit is allready programmed"); + end + else + begin + ASP_reg[3] = ASP_reg_in[3];//PPBOTP + end + + if (PWDMLB == 1'b1 && PSTMLB == 1'b1) + begin + if (ASP_reg_in[2] == 1'b0 && ASP_reg_in[1] == 1'b0) + begin + $display("ASPR[2:1] = 00 Illegal condition"); + Status_reg1[6] = 1'b1; //P_ERR + end + else + begin + if (ASP_reg_in[2]!==1'b1 || ASP_reg_in[1]!==1'b1) + begin + ASPOTPFLAG = 1'b1; + end + ASP_reg[2] = ASP_reg_in[2];//PWDMLB + ASP_reg[1] = ASP_reg_in[1];//PSTMLB + end + end + + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + NVDLR_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + if (NVDLR_reg == 0) + begin + NVDLR_reg = NVDLR_reg_in; + VDLR_reg = NVDLR_reg_in; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + else + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; //P_ERR + $display("NVDLR bits allready programmed"); + end + end + end + + RESET_STATE: + begin + //the default condition hardware reset + //The Bank Address Register is loaded to all zeroes + Bank_Addr_reg = 8'h0; + if (BPNV && ~LOCK && ~FREEZE) + begin + Status_reg1[2] = 1'b1;// BP0 + Status_reg1[3] = 1'b1;// BP1 + Status_reg1[4] = 1'b1;// BP2 + BP_bits = 3'b111; + change_BP = 1'b1; + #1000 change_BP = 1'b0; + end + //Resets the volatile bits in the Status register 1 + Status_reg1[6] = 1'b0; + Status_reg1[5] = 1'b0; + Status_reg1[1] = 1'b0; + Status_reg1[0] = 1'b0; + //Resets the volatile bits in the Status register 2 + Status_reg2[1] = 1'b0; + Status_reg2[0] = 1'b0; + //Resets the volatile bits in the Configuration register 1 + Config_reg1[0] = 1'b0; + //On reset cycles the data pattern reverts back + //to what is in the NVDLR + VDLR_reg = NVDLR_reg; + dlp_act = 1'b0; + //Loads the Program Buffer with all ones + for(i=0;i<=511;i=i+1) + begin + WData[i] = MaxData; + end + if (~PWDMLB) + PPBL[0] = 1'b0; + else + PPBL[0] = 1'b1; + end + + endcase + + //Output Disable Control + if (CSNeg_ipd ) + begin + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + end + end + + assign fast_rd = rd_fast; + assign rd = rd_slow; + assign ddrd = ddr; + assign fast_ddr = ddr_fast; + + always @(change_TBPARM, posedge PoweredUp) + begin + if (tmp_char2 == "0") + begin + if (TBPARM == 0) + begin + BottomBoot = 1; + b_act = 1; + end + else + begin + TopBoot = 1; + BottomBoot = 0; + b_act = 0; + end + end + else if (tmp_char2 == "1") + begin + UniformSec = 1; + end + end + + always @(posedge change_BP) + begin + case (Status_reg1[4:2]) + + 3'b000: + Sec_Prot[285:0] = {286{1'b0}}; + + 3'b001: + begin + if (tmp_char2 == "1") + begin + if (~TBPROT) + begin + Sec_Prot[SecNum256:(SecNum256+1)*63/64] = 1'b1; + Sec_Prot[(SecNum256+1)*63/64-1 : 0] = {63{1'b0}}; + end + else + begin + Sec_Prot[(SecNum256+1)/64-1 : 0] = 1'b1; + Sec_Prot[SecNum256 : (SecNum256+1)/64] = {63{1'b0}}; + end + end + else if (tmp_char2 == "0" && TBPARM == 1) + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64:(SecNum64-29)*63/64] = {34{1'b1}}; + Sec_Prot[(SecNum64-29)*63/64-1 : 0] = {252{1'b0}}; + end + else + begin + Sec_Prot[(SecNum64-29)/64-1 : 0] = {4{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/64] = {282{1'b0}}; + end + end + else + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64:(SecNum64-29)*63/64+30] = {4{1'b1}}; + Sec_Prot[(SecNum64-29)*63/64+29 : 0] = {282{1'b0}}; + end + else + begin + Sec_Prot[(SecNum64-29)/64+29 : 0] = {34{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/64+30] = {252{1'b0}}; + end + end + end + + 3'b010: + begin + if (tmp_char2 == "1") + begin + if (~TBPROT) + begin + Sec_Prot[SecNum256 : (SecNum256+1)*31/32] = {2{1'b1}}; + Sec_Prot[(SecNum256+1)*31/32-1 : 0] = {62{1'b0}}; + end + else + begin + Sec_Prot[(SecNum256+1)/32-1 : 0] = {2{1'b1}}; + Sec_Prot[SecNum256 : (SecNum256+1)/32] = {62{1'b0}}; + end + end + else if (tmp_char2 == "0" && TBPARM == 1) + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64 : (SecNum64-29)*31/32] = {38{1'b1}}; + Sec_Prot[(SecNum64-29)*31/32-1 : 0] = {248{1'b0}}; + end + else + begin + Sec_Prot[(SecNum64-29)/32-1 : 0] = {8{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/32] = {278{1'b0}}; + end + end + else + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64:(SecNum64-29)*31/32+30] = {8{1'b1}}; + Sec_Prot[(SecNum64-29)*31/32+29 : 0] = {278{1'b0}}; + end + else + begin + Sec_Prot[(SecNum64-29)/32+29 : 0] = {38{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/32+30] = {248{1'b0}}; + end + end + end + + 3'b011: + begin + if (tmp_char2 == "1") + begin + if (~TBPROT) + begin + Sec_Prot[SecNum256 : (SecNum256+1)*15/16] = 4'b1111; + Sec_Prot[(SecNum256+1)*15/16-1 : 0] = {60{1'b0}}; + end + else + begin + Sec_Prot[(SecNum256+1)/16-1 : 0] = 4'b1111; + Sec_Prot[SecNum256 : (SecNum256+1)/16] = {60{1'b0}}; + end + end + else if (tmp_char2 == "0" && TBPARM == 1) + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64 : (SecNum64-29)*15/16] = {46{1'b1}}; + Sec_Prot[(SecNum64-29)*15/16-1 : 0] = {240{1'b0}}; + end + else + begin + Sec_Prot[(SecNum64-29)/16-1 : 0] = {16{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/16] = {270{1'b0}}; + end + end + else + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64 : (SecNum64-29)*15/16+30] ={16{1'b1}}; + Sec_Prot[(SecNum64-29)*15/16+29 : 0] = {270{1'b0}}; + end + else + begin + Sec_Prot[(SecNum64-29)/16+29 : 0] ={46{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/16+30] = {240{1'b0}}; + end + end + end + + 3'b100: + begin + if (tmp_char2 == "1") + begin + if (~TBPROT) + begin + Sec_Prot[SecNum256 : (SecNum256+1)*7/8] = {8{1'b1}}; + Sec_Prot[(SecNum256+1)*7/8-1 : 0] = {278{1'b0}}; + end + else + begin + Sec_Prot[(SecNum256+1)/8-1 : 0] = {8{1'b1}}; + Sec_Prot[SecNum256 : (SecNum256+1)/8] = {278{1'b0}}; + end + end + else if (tmp_char2 == "0" && TBPARM == 1) + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64 : (SecNum64-29)*7/8] = {62{1'b1}}; + Sec_Prot[(SecNum64-29)*7/8-1 : 0] = {224{1'b0}}; + end + else + begin + Sec_Prot[(SecNum64-29)/8-1 : 0] = {32{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/8] = {254{1'b0}}; + end + end + else + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64 : (SecNum64-29)*7/8+30] ={32{1'b1}}; + Sec_Prot[(SecNum64-29)*7/8+29 : 0] = {254{1'b0}}; + end + else + begin + Sec_Prot[(SecNum64-29)/8+29 : 0] = {62{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/8+30] = {224{1'b0}}; + end + end + end + + 3'b101: + begin + if (tmp_char2 == "1") + begin + if (~TBPROT) + begin + Sec_Prot[SecNum256 : (SecNum256+1)*3/4] = {16{1'b1}}; + Sec_Prot[(SecNum256+1)*3/4-1 : 0] = {270{1'b0}}; + end + else + begin + Sec_Prot[(SecNum256+1)/4-1 : 0] = {16{1'b1}}; + Sec_Prot[SecNum256 : (SecNum256+1)/4] = {270{1'b0}}; + end + end + else if (tmp_char2 == "0" && TBPARM == 1) + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64 : (SecNum64-29)*3/4] = {94{1'b1}}; + Sec_Prot[(SecNum64-29)*3/4-1 : 0] = {192{1'b0}}; + end + else + begin + Sec_Prot[(SecNum64-29)/4-1 : 0] = {64{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/4] = {222{1'b0}}; + end + end + else + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64 : (SecNum64-29)*3/4+30] = {64{1'b1}}; + Sec_Prot[(SecNum64-29)*3/4+29 : 0] = {222{1'b0}}; + end + else + begin + Sec_Prot[(SecNum64-29)/4+29 : 0] = {94{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/4+30] = {192{1'b0}}; + end + end + end + + 3'b110: + begin + if (tmp_char2 == "1") + begin + if (~TBPROT) + begin + Sec_Prot[SecNum256 : (SecNum256+1)/2] = {32{1'b1}}; + Sec_Prot[(SecNum256+1)/2-1 : 0] = {32{1'b0}}; + end + else + begin + Sec_Prot[(SecNum256+1)/2-1 : 0] = {32{1'b1}}; + Sec_Prot[SecNum256 : (SecNum256+1)/2] = {32{1'b0}}; + end + end + else if (tmp_char2 == "0" && TBPARM == 1) + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64 : (SecNum64-29)/2] = {158{1'b1}}; + Sec_Prot[(SecNum64-29)/2-1 : 0] = {128{1'b0}}; + end + else + begin + Sec_Prot[(SecNum64-29)/2-1 : 0] = {128{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/2] = {158{1'b0}}; + end + end + else + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64 : (SecNum64-29)/2+30] = {128{1'b1}}; + Sec_Prot[(SecNum64-29)/2+29 : 0] = {158{1'b0}}; + end + else + begin + Sec_Prot[(SecNum64-29)/2+29 : 0] = {158{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/2+30] = {128{1'b0}}; + end + end + end + + 3'b111: + begin + Sec_Prot[SecNum64:0] = {286{1'b1}}; + end + endcase + end + + always @(SOut_zd or HOLDNeg_in or SIOut_zd) + begin + if (HOLDNeg_in == 0 && ~QUAD) + begin + hold_mode = 1'b1; + SIOut_z = 1'bZ; + SOut_z = 1'bZ; + end + else + begin + if (hold_mode == 1) + begin + SIOut_z <= #(tpd_HOLDNeg_SO) SIOut_zd; + SOut_z <= #(tpd_HOLDNeg_SO) SOut_zd; + hold_mode = #(tpd_HOLDNeg_SO) 1'b0; + end + else + begin + SIOut_z = SIOut_zd; + SOut_z = SOut_zd; + hold_mode = 1'b0; + end + end + end + + //////////////////////////////////////////////////////////////////////// + // autoboot control logic + //////////////////////////////////////////////////////////////////////// + always @(rising_edge_SCK_ipd or current_state_event) + begin + if(current_state == AUTOBOOT) + begin + if (rising_edge_SCK_ipd) + begin + if (start_delay > 0) + start_delay = start_delay - 1; + end + + if (start_delay == 0) + begin + start_autoboot = 1; + end + end + end + + //////////////////////////////////////////////////////////////////////// + // functions & tasks + //////////////////////////////////////////////////////////////////////// + // Procedure FDDR_DPL + task Return_DLP; + input integer Instruct; + input integer EHP; + input integer Latency_code; + input integer dummy_cnt; + inout dlp_act; + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + if (EHP) + begin + if (Latency_code == 1) + dlp_act = 1'b1; + else if (Latency_code == 2 && dummy_cnt >= 1) + dlp_act = 1'b1; + else if(Latency_code == 3 || Latency_code == 0) + begin + dlp_act = 1'b0; + $display("Warning at", $time); + $display("Inappropriate latency is set during DPL mode"); + end + end + else + begin + if (Latency_code == 3) + dlp_act = 1'b1; + else if (Latency_code == 0 && dummy_cnt >= 1) + dlp_act = 1'b1; + else if(Latency_code == 1 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if(Latency_code == 2 && dummy_cnt >= 3) + dlp_act = 1'b1; + end + end + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + if (EHP) + begin + if (Latency_code == 1 && dummy_cnt >= 1) + dlp_act = 1'b1; + else if (Latency_code == 2 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if( Latency_code == 3 || Latency_code == 0) + begin + dlp_act = 1'b0; + $display("Warning at", $time); + $display("Inappropriate latency is set during DPL mode"); + end + end + else + begin + if (Latency_code == 3) + dlp_act = 1'b0; + else if (Latency_code == 0 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if (Latency_code == 1 && dummy_cnt >= 3) + dlp_act = 1'b1; + else if(Latency_code == 2 && dummy_cnt >= 4) + dlp_act = 1'b1; + end + end + if ((Instruct == DDRQIOR || Instruct == DDRQIOR4) && QUAD) + begin + if (EHP) + begin + if (Latency_code == 0 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if (Latency_code == 1 && dummy_cnt >= 3) + dlp_act = 1'b1; + else if (Latency_code == 2 && dummy_cnt >= 4) + dlp_act = 1'b1; + else if( Latency_code == 3) + begin + dlp_act = 1'b0; + $display("Warning at", $time); + $display("Inappropriate latency is"); + $display("set during DPL mode"); + end + end + else + begin + if (Latency_code == 0 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if (Latency_code == 1 && dummy_cnt >= 3) + dlp_act = 1'b1; + else if (Latency_code == 2 && dummy_cnt >= 4) + dlp_act = 1'b1; + else if( Latency_code == 3) + begin + dlp_act = 1'b0; + $display("Warning at", $time); + $display("Inappropriate latency is"); + $display("set during DPL mode"); + end + end + end + end + endtask + + function integer ReturnSectorIDRdPswdMd; + input reg TBPROT; + begin + if(TBPROT == 0) + begin + ReturnSectorIDRdPswdMd = 0; + end + else + begin + if (UniformSec) + begin + ReturnSectorIDRdPswdMd = SecNum256; + end + else + begin + ReturnSectorIDRdPswdMd = 255; + end + end + end + endfunction + + // Procedure ADDRHILO_SEC + task ADDRHILO_SEC; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer sector; + begin + if (tmp_char2 == "0") + begin + if (TBPARM == 0) + begin + if (Addr/(SecSize64+1) <= 1 && + (Instruct == P4E || Instruct == P4E4)) //4KB Sectors + begin + sector = Addr/(SecSize4+1); + AddrLOW = sector*(SecSize4+1); + AddrHIGH = sector*(SecSize4+1) + SecSize4; + end + else + begin + sector = Addr/(SecSize64+1); + AddrLOW = sector*(SecSize64+1); + AddrHIGH = sector*(SecSize64+1) + SecSize64; + end + end + else + begin + if (Addr/(SecSize64+1) >= 254 && + (Instruct == P4E || Instruct == P4E4)) //4KB Sectors + begin + sector = 254 + (Addr-(SecSize64+1)*254)/(SecSize4+1); + AddrLOW = 254*(SecSize64+1)+(sector-254)*(SecSize4+1); + AddrHIGH = 254*(SecSize64+1)+(sector-254)*(SecSize4+1) + + SecSize4; + end + else + begin + sector = Addr/(SecSize64+1); + AddrLOW = sector*(SecSize64+1); + AddrHIGH = sector*(SecSize64+1) + SecSize64; + end + end + end + else if (tmp_char2 == "1") + begin + sector = Addr/(SecSize256+1); + AddrLOW = sector*(SecSize256+1); + AddrHIGH = sector*(SecSize256+1) + SecSize256; + end + end + endtask + + // Procedure ADDRHILO_PG + task ADDRHILO_PG; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer page; + begin + page = Addr / (PageSize + 1); + AddrLOW = page * (PageSize + 1); + AddrHIGH = page * (PageSize + 1) + PageSize ; + end + endtask + + // Procedure ReturnSectorID + task ReturnSectorID; + inout sect; + input Address; + integer sect; + integer Address; + integer conv; + begin + if (tmp_char2 == "0") + begin + conv = Address / (SecSize64+1); + if (BottomBoot) + begin + if (conv <= 1) //4KB Sectors + begin + sect = Address/(SecSize4+1); + end + else + begin + sect = conv + 30; + end + end + else if (TopBoot) + begin + if (conv >= 254) //4KB Sectors + begin + sect = 254 + (Address-(SecSize64+1)*254)/(SecSize4+1); + end + else + begin + sect = conv; + end + end + end + else + begin + sect = Address/(SecSize256+1); + end + end + endtask + + always @(PPBL[0], ASP_reg) + begin + if (PPBL[0] == 0 && PWDMLB == 0 && RPME == 0 && RdPswdProtEnable) + begin + RdPswdProtMode = 1; + AutoBoot_reg[0] = 0;//AUTOBOOT is disabled when Read Password + end //Protection is enabled + else + begin + RdPswdProtMode = 0; + end + end + + /////////////////////////////////////////////////////////////////////////// + // edge controll processes + /////////////////////////////////////////////////////////////////////////// + + always @(posedge PoweredUp) + begin + rising_edge_PoweredUp = 1; + #1000 rising_edge_PoweredUp = 0; + end + + always @(posedge SCK_ipd) + begin + rising_edge_SCK_ipd = 1'b1; + #1000 rising_edge_SCK_ipd = 1'b0; + end + + always @(negedge SCK_ipd) + begin + falling_edge_SCK_ipd = 1'b1; + #1000 falling_edge_SCK_ipd = 1'b0; + end + + always @(posedge read_out) + begin + rising_edge_read_out = 1'b1; + #1000 rising_edge_read_out = 1'b0; + end + + always @(negedge write) + begin + falling_edge_write = 1; + #1000 falling_edge_write = 0; + end + + always @(posedge PRGSUSP_out) + begin + PRGSUSP_out_event = 1; + #1000 PRGSUSP_out_event = 0; + end + + always @(posedge ERSSUSP_out) + begin + ERSSUSP_out_event = 1; + #1000 ERSSUSP_out_event = 0; + end + + always @(posedge CSNeg_ipd) + begin + rising_edge_CSNeg_ipd = 1'b1; + #1000 rising_edge_CSNeg_ipd = 1'b0; + end + + always @(negedge CSNeg_ipd) + begin + falling_edge_CSNeg_ipd = 1'b1; + #1000 falling_edge_CSNeg_ipd = 1'b0; + end + + always @(negedge RSTNeg_in) + begin + falling_edge_RSTNeg = 1'b1; + #50000 falling_edge_RSTNeg = 1'b0; + end + + always @(posedge RSTNeg_in) + begin + rising_edge_RSTNeg = 1'b1; + #10000 rising_edge_RSTNeg = 1'b0; + end + + always @(negedge RST) + begin + falling_edge_RST = 1'b1; + #10000 falling_edge_RST = 1'b0; + end + + always @(posedge RST) + begin + rising_edge_RST = 1'b1; + #1000 rising_edge_RST = 1'b0; + end + + always @(posedge PDONE) + begin + rising_edge_PDONE = 1'b1; + #1000 rising_edge_PDONE = 1'b0; + end + + always @(posedge WDONE) + begin + rising_edge_WDONE = 1'b1; + #1000 rising_edge_WDONE = 1'b0; + end + + always @(posedge WSTART) + begin + rising_edge_WSTART = 1'b1; + #1000 rising_edge_WSTART = 1'b0; + end + + always @(posedge EDONE) + begin + rising_edge_EDONE = 1'b1; + #1000 rising_edge_EDONE = 1'b0; + end + + always @(posedge ESTART) + begin + rising_edge_ESTART = 1'b1; + #1000 rising_edge_ESTART = 1'b0; + end + + always @(posedge PSTART) + begin + rising_edge_PSTART = 1'b1; + #1000 rising_edge_PSTART = 1'b0; + end + + always @(posedge Reseted) + begin + rising_edge_Reseted = 1'b1; + #1000 rising_edge_Reseted = 1'b0; + end + + always @(negedge PASSULCK_in) + begin + falling_edge_PASSULCK_in = 1'b1; + #1000 falling_edge_PASSULCK_in = 1'b0; + end + + always @(negedge PPBERASE_in) + begin + falling_edge_PPBERASE_in = 1'b1; + #1000 falling_edge_PPBERASE_in = 1'b0; + end + + always @(Instruct) + begin + Instruct_event = 1'b1; + #1000 Instruct_event = 1'b0; + end + + always @(change_addr) + begin + change_addr_event = 1'b1; + #1000 change_addr_event = 1'b0; + end + + always @(next_state) + begin + next_state_event = 1'b1; + #1000 next_state_event = 1'b0; + end + + always @(current_state) + begin + current_state_event = 1'b1; + #1000 current_state_event = 1'b0; + end + + always @(posedge RST_out) + begin + rising_edge_RST_out = 1'b1; + #1000 rising_edge_RST_out = 1'b0; + end + +endmodule \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl128s/model/s25fl128s.vhd b/lib/models/memory/flash/serial/S25fl128s/model/s25fl128s.vhd new file mode 100644 index 0000000..2657e30 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128s/model/s25fl128s.vhd @@ -0,0 +1,7180 @@ +------------------------------------------------------------------------------- +-- File Name: s25fl128s.vhd +------------------------------------------------------------------------------- +-- Copyright (C) 2012 Spansion, LLC. +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 V.Mancev 09 Nov 25 Inital Release +-- V1.1 V.Mancev 10 Feb 24 addr_cnt for second read in +-- high performance read continuous +-- mode can change its value only +-- when CSNeg = '0' +-- V1.2 V.Mancev 10 July 29 During the QUAD mode HOLD# input +-- is not monitored for its normal +-- function +-- V1.3 B.Colakovic 10 Aug 24 All redundant signals are removed from +-- BusCycle process +-- V1.4 R.Prokopovic 10 Oct 21 Latest datasheet aligned +-- V.Mancev +-- V1.5 R.Prokopovic 10 Oct 22 Read Configuration register added for any +-- V.Mancev state. Hybrid configuration added +-- V1.6 R.Prokopovic 10 Nov 12 QUAD Program operation during Erase +-- V.Mancev Suspend is added. Warning for Resume to +-- Suspend time is added. During Erase +-- Suspend, after Program operation is +-- completed, WEL bit is cleared. +-- Implemetation of Software Reset is +-- changed. +-- V1.7 V. Mancev 11 May 11 Condition for CS# High Time +-- (Program/Erase) is fixed +-- V1.8 V. Mancev 11 July 01 Latest datasheet aligned +-- V1.9 V. Mancev 11 Nov 16 Time tHO is changed to 1 ns +-- (customer's request) +-- BRWR instruction is corrected +-- V1.10 S.Petrovic 12 Aug 28 QPP Instruction is allowed on +-- previously programmed page +-- +------------------------------------------------------------------------------- +-- PART DESCRIPTION: +-- +-- Library: FLASH +-- Technology: FLASH MEMORY +-- Part: S25FL128S +-- +-- Description: 128 Megabit Serial Flash Memory +-- +------------------------------------------------------------------------------- +-- Comments : +-- For correct simulation, simulator resolution should be set to 1 ps +-- A device ordering (trim) option determines whether a feature is enabled +-- or not, or provide relevant parameters: +-- -15th character in TimingModel determines if enhanced high +-- performance option is available +-- (0,2,3,R,A,B,C,D) EHPLC +-- (Y,Z,S,T,K,L) Security EHPLC +-- (4,6,7,8,9,Q) HPLC +-- -15th character in TimingModel determines if RESET# input +-- is available +-- (R,A,B,C,D,Q.6,7,K,L,S,T,M,N,U,V) RESET# is available +-- (0,2,3,4,8,9,Y.Z.W,X) RESET# is tied to the inactive +-- state,inside the package. +-- -16th character in TimingModel determines Sector and Page Size: +-- (0) Sector Size = 64 kB; Page Size = 256 bytes +-- Hybrid Top/Bottom sector size architecture +-- (1) Sector Size = 256 kB; Page Size = 512 bytes +-- Uniform sector size architecture +-- +------------------------------------------------------------------------------- +-- Known Bugs: +-- +------------------------------------------------------------------------------- +LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; + USE STD.textio.ALL; + USE IEEE.VITAL_timing.ALL; + USE IEEE.VITAL_primitives.ALL; + +LIBRARY FMF; USE FMF.gen_utils.ALL; + USE FMF.conversions.ALL; +------------------------------------------------------------------------------- +-- ENTITY DECLARATION +------------------------------------------------------------------------------- +ENTITY s25fl128s IS + GENERIC ( + --------------------------------------------------------------------------- + -- TIMING GENERICS: + --------------------------------------------------------------------------- + -- tipd delays: interconnect path delays (delay between components) + -- There should be one for each IN or INOUT pin in the port list + -- They are given default values of zero delay. + tipd_SCK : VitalDelayType01 := VitalZeroDelay01; + tipd_SI : VitalDelayType01 := VitalZeroDelay01; + tipd_SO : VitalDelayType01 := VitalZeroDelay01; + + tipd_CSNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_HOLDNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_RSTNeg : VitalDelayType01 := VitalZeroDelay01; + + -- tpd delays: propagation delays (pin-to-pin delay within a component) + tpd_SCK_SO_normal : VitalDelayType01Z := UnitDelay01Z; -- tV, tHO + tpd_CSNeg_SO : VitalDelayType01Z := UnitDelay01Z; -- tDIS + tpd_HOLDNeg_SO : VitalDelayType01Z := UnitDelay01Z;-- + tpd_RSTNeg_SO : VitalDelayType01Z := UnitDelay01Z;-- + -- DDR operation values + tpd_SCK_SO_DDR : VitalDelayType01Z := UnitDelay01Z;--tV(66MHz) + + -- tsetup values: setup times + -- setup time is minimum time before the referent signal edge the + -- input should be stable + tsetup_CSNeg_SCK_normal_noedge_posedge + : VitalDelayType := UnitDelay; -- tCSS / + tsetup_CSNeg_SCK_DDR_noedge_posedge + : VitalDelayType := UnitDelay; -- tCSS / + tsetup_SI_SCK_normal_noedge_posedge: VitalDelayType + := UnitDelay; -- tSU:DAT / + tsetup_WPNeg_CSNeg : VitalDelayType := UnitDelay; -- tWPS \ + tsetup_HOLDNeg_SCK : VitalDelayType := UnitDelay; + tsetup_RSTNeg_CSNeg : VitalDelayType := UnitDelay; -- tRP + -- DDR operation values + tsetup_SI_SCK_DDR_noedge_posedge: VitalDelayType + := UnitDelay; -- tSU / + tsetup_SI_SCK_DDR_noedge_negedge: VitalDelayType + := UnitDelay; -- tSU \ + + -- thold values: hold times + -- hold time is minimum time the input should be present stable + -- after the referent signal edge + thold_CSNeg_SCK_normal_noedge_posedge + : VitalDelayType := UnitDelay; -- tCSH / + thold_CSNeg_SCK_DDR_noedge_posedge + : VitalDelayType := UnitDelay; -- tCSH / + thold_SI_SCK_normal_noedge_posedge: VitalDelayType + := UnitDelay; -- tHD:DAT / + thold_WPNeg_CSNeg : VitalDelayType := UnitDelay; -- tWPH / + thold_HOLDNeg_SCK : VitalDelayType := UnitDelay; -- + thold_CSNeg_RSTNeg : VitalDelayType := UnitDelay; -- tRPH + -- DDR operation values + thold_SI_SCK_DDR_noedge_posedge: VitalDelayType + := UnitDelay; -- tHD / + thold_SI_SCK_DDR_noedge_negedge: VitalDelayType + := UnitDelay; -- tHD \ + + --tpw values: pulse width + tpw_SCK_serial_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_dual_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_fast_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_quadpg_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_serial_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_SCK_dual_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_SCK_fast_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_SCK_quadpg_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_CSNeg_read_posedge : VitalDelayType := UnitDelay; -- tCS + tpw_CSNeg_pgers_posedge : VitalDelayType := UnitDelay; -- tCS + tpw_RSTNeg_negedge : VitalDelayType := UnitDelay; -- tRP + tpw_RSTNeg_posedge : VitalDelayType := UnitDelay; -- tRS + -- DDR operation values + tpw_SCK_DDR_posedge : VitalDelayType := UnitDelay; -- tWH(66MHz) + tpw_SCK_DDR_negedge : VitalDelayType := UnitDelay; -- tWL(66Hz) + + -- tperiod min (calculated as 1/max freq) + tperiod_SCK_serial_rd : VitalDelayType := UnitDelay; --fSCK=50MHz + tperiod_SCK_fast_rd : VitalDelayType := UnitDelay; --fSCK=133MHz + tperiod_SCK_dual_rd : VitalDelayType := UnitDelay; --fSCK=104MHz + tperiod_SCK_quadpg : VitalDelayType := UnitDelay; --fSCK=80MHz + -- DDR operation values + tperiod_SCK_DDR_rd : VitalDelayType := UnitDelay; --fSCK=66MHz + + -- tdevice values: values for internal delays + --timing values that are internal to the model and not associated + --with any port. + -- Page Program Operation (Page Size 256) + tdevice_PP256 : VitalDelayType := 550 us; --tPP + -- Page Program Operation (Page Size 512) + tdevice_PP512 : VitalDelayType := 750 us; --tPP + -- Typical Byte Programming Time + tdevice_BP : VitalDelayType := 400 us; --tBP + -- Sector Erase Operation(256KB Sectors) + tdevice_SE256 : VitalDelayType := 1875 ms; --tSE + -- Sector Erase Operation(64KB Sectors) + tdevice_SE64 : VitalDelayType := 650 ms; --tSE + -- Bulk Erase Operation + tdevice_BE : VitalDelayType := 165 sec; --tBE + -- WRR Cycle Time + tdevice_WRR : VitalDelayType := 200 ms; --tW + -- Erase Suspend/Erase Resume Time + tdevice_ERSSUSP : VitalDelayType := 40 us; --tESL + -- Program Suspend/Program Resume Time + tdevice_PRGSUSP : VitalDelayType := 40 us; -- + -- VCC (min) to CS# Low + tdevice_PU : VitalDelayType := 300 us; --tPU + -- PPB Erase Time + tdevice_PPBERASE :VitalDelayType := 15 ms; -- + -- Password Unlock Time + tdevice_PASSULCK :VitalDelayType := 1 us; -- + -- Password Unlock Time + tdevice_PASSACC :VitalDelayType := 100 us; + + --------------------------------------------------------------------------- + -- CONTROL GENERICS: + --------------------------------------------------------------------------- + -- generic control parameters + InstancePath : STRING := DefaultInstancePath; + TimingChecksOn : BOOLEAN := DefaultTimingChecks; + MsgOn : BOOLEAN := DefaultMsgOn; + XOn : BOOLEAN := DefaultXon; + -- memory file to be loaded + mem_file_name : STRING := "s25fl128s.mem"; + otp_file_name : STRING := "s25fl128sOTP.mem"; + + UserPreload : BOOLEAN := FALSE; --TRUE; + LongTimming : BOOLEAN := TRUE; + + -- For FMF SDF technology file usage + TimingModel : STRING + ); + PORT ( + -- Data Inputs/Outputs + SI : INOUT std_ulogic := 'U'; -- serial data input/IO0 + SO : INOUT std_ulogic := 'U'; -- serial data output/IO1 + -- Controls + SCK : IN std_ulogic := 'U'; -- serial clock input + CSNeg : IN std_ulogic := 'U'; -- chip select input + RSTNeg : IN std_ulogic := 'U'; -- hardware reset pin + WPNeg : INOUT std_ulogic := 'U'; -- write protect input/IO2 + HOLDNeg : INOUT std_ulogic := 'U' -- hold input/IO3 + + ); + + ATTRIBUTE VITAL_LEVEL0 of s25fl128s : ENTITY IS TRUE; +END s25fl128s; + +------------------------------------------------------------------------------- +-- ARCHITECTURE DECLARATION +------------------------------------------------------------------------------- +ARCHITECTURE vhdl_behavioral of s25fl128s IS + ATTRIBUTE VITAL_LEVEL0 OF vhdl_behavioral : ARCHITECTURE IS TRUE; + + --------------------------------------------------------------------------- + -- CONSTANT AND SIGNAL DECLARATION + --------------------------------------------------------------------------- + --Declaration of constants - memory characteristics + -- The constant declared here are used to enable the creation of models + -- of memories within a family with a minimum amount of editing + + CONSTANT PartID : STRING := "s25fl128s"; + CONSTANT MaxData : NATURAL := 16#FF#; --255; + CONSTANT MemSize : NATURAL := 16#FFFFFF#; + CONSTANT SecSize256 : NATURAL := 16#3FFFF#; --256KB + CONSTANT SecSize64 : NATURAL := 16#FFFF#; --64KB + CONSTANT SecSize4 : NATURAL := 16#FFF#; --4KB + CONSTANT SecNum64 : NATURAL := 285; + CONSTANT SecNum256 : NATURAL := 63; + CONSTANT PageNum64 : NATURAL := 16#1FFFF#; + CONSTANT PageNum256 : NATURAL := 16#7FFF#; + CONSTANT AddrRANGE : NATURAL := 16#0FFFFFF#; + CONSTANT HiAddrBit : NATURAL := 31; + CONSTANT OTPSize : NATURAL := 1023; + CONSTANT OTPLoAddr : NATURAL := 16#000#; + CONSTANT OTPHiAddr : NATURAL := 16#3FF#; + CONSTANT BYTE : NATURAL := 8; + + --Manufacturer Identification + CONSTANT Manuf_ID : NATURAL := 16#01#; + CONSTANT DeviceID : NATURAL := 16#17#; + --Electronic Signature + CONSTANT ESignature : NATURAL := 16#17#; + --Device ID + --Manufacturer Identification && Memory Type && Memory Capacity + CONSTANT Jedec_ID : NATURAL := 16#01#; -- first byte of Device ID + CONSTANT DeviceID1 : NATURAL := 16#20#; + CONSTANT DeviceID2 : NATURAL := 16#18#; + CONSTANT ExtendedBytes : NATURAL := 16#4D#; + CONSTANT ExtendedID64 : NATURAL := 16#01#; + CONSTANT ExtendedID256 : NATURAL := 16#00#; + CONSTANT DieRev : NATURAL := 16#03#; + CONSTANT MaskRev : NATURAL := 16#00#; + + -- Declaration of signals that will hold the delayed values of ports + SIGNAL SI_ipd : std_ulogic := 'U'; + SIGNAL SO_ipd : std_ulogic := 'U'; + SIGNAL SCK_ipd : std_ulogic := 'U'; + SIGNAL CSNeg_ipd : std_ulogic := 'U'; + SIGNAL RSTNeg_ipd : std_ulogic := 'U'; + SIGNAL WPNeg_ipd : std_ulogic := 'U'; + SIGNAL HOLDNeg_ipd : std_ulogic := 'U'; + SIGNAL HOLDNeg_pullup : std_ulogic := 'U'; + SIGNAL WPNeg_pullup : std_ulogic := 'U'; + SIGNAL RSTNeg_pullup : std_ulogic := 'U'; + + -- internal delays + SIGNAL PP256_in : std_ulogic := '0'; + SIGNAL PP256_out : std_ulogic := '0'; + SIGNAL PP512_in : std_ulogic := '0'; + SIGNAL PP512_out : std_ulogic := '0'; + SIGNAL BP_in : std_ulogic := '0'; + SIGNAL BP_out : std_ulogic := '0'; + SIGNAL SE64_in : std_ulogic := '0'; + SIGNAL SE64_out : std_ulogic := '0'; + SIGNAL SE256_in : std_ulogic := '0'; + SIGNAL SE256_out : std_ulogic := '0'; + SIGNAL BE_in : std_ulogic := '0'; + SIGNAL BE_out : std_ulogic := '0'; + SIGNAL WRR_in : std_ulogic := '0'; + SIGNAL WRR_out : std_ulogic := '0'; + SIGNAL ERSSUSP_in : std_ulogic := '0'; + SIGNAL ERSSUSP_out : std_ulogic := '0'; + SIGNAL PRGSUSP_in : std_ulogic := '0'; + SIGNAL PRGSUSP_out : std_ulogic := '0'; + SIGNAL PU_in : std_ulogic := '0'; + SIGNAL PU_out : std_ulogic := '0'; + SIGNAL RST_in : std_ulogic := '0';-- Hardware Reset Timeout + SIGNAL RST_out : std_ulogic := '1';-- + SIGNAL PPBERASE_in : std_ulogic := '0'; + SIGNAL PPBERASE_out : std_ulogic := '0'; + SIGNAL PASSULCK_in : std_ulogic := '0'; + SIGNAL PASSULCK_out : std_ulogic := '0'; + SIGNAL PASSACC_in : std_ulogic := '0'; + SIGNAL PASSACC_out : std_ulogic := '0'; + + FUNCTION ReturnSectorIDRdPswdMd(TBPROT : std_logic) RETURN NATURAL IS + VARIABLE result : NATURAL; + BEGIN + IF TBPROT = '0' THEN + result := 0; + ELSE + IF (TimingModel(16) = '1') THEN + result := SecNum256; + ELSE + result := 255; + END IF; + END IF; + RETURN result; + END ReturnSectorIDRdPswdMd; + +BEGIN + + --------------------------------------------------------------------------- + -- Internal Delays + --------------------------------------------------------------------------- + -- Artificial VITAL primitives to incorporate internal delays + -- Because a tdevice generics is used, there must be a VITAL_primitives + -- assotiated with them + PP256 :VitalBuf(PP256_out, PP256_in, (tdevice_PP256 ,UnitDelay)); + PP512 :VitalBuf(PP512_out, PP512_in, (tdevice_PP512 ,UnitDelay)); + BP :VitalBuf(BP_out, BP_in, (tdevice_BP ,UnitDelay)); + SE64 :VitalBuf(SE64_out, SE64_in, (tdevice_SE64 ,UnitDelay)); + SE256 :VitalBuf(SE256_out, SE256_in, (tdevice_SE256 ,UnitDelay)); + BE :VitalBuf(BE_out, BE_in, (tdevice_BE ,UnitDelay)); + WRR :VitalBuf(WRR_out, WRR_in, (tdevice_WRR ,UnitDelay)); + ERSSUSP :VitalBuf(ERSSUSP_out, ERSSUSP_in, (tdevice_ERSSUSP ,UnitDelay)); + PRGSUSP :VitalBuf(PRGSUSP_out, PRGSUSP_in, (tdevice_PRGSUSP ,UnitDelay)); + PU :VitalBuf(PU_out, PU_in, (tdevice_PU ,UnitDelay)); + PPBERASE :VitalBuf(PPBERASE_out,PPBERASE_in,(tdevice_PPBERASE,UnitDelay)); + PASSULCK :VitalBuf(PASSULCK_out,PASSULCK_in,(tdevice_PASSULCK,UnitDelay)); + PASSACC :VitalBuf(PASSACC_out, PASSACC_in, (tdevice_PASSACC ,UnitDelay)); + + --------------------------------------------------------------------------- + -- Wire Delays + --------------------------------------------------------------------------- + WireDelay : BLOCK + BEGIN + + w_1 : VitalWireDelay (SI_ipd, SI, tipd_SI); + w_2 : VitalWireDelay (SO_ipd, SO, tipd_SO); + w_3 : VitalWireDelay (SCK_ipd, SCK, tipd_SCK); + w_4 : VitalWireDelay (CSNeg_ipd, CSNeg, tipd_CSNeg); + w_5 : VitalWireDelay (RSTNeg_ipd, RSTNeg, tipd_RSTNeg); + w_6 : VitalWireDelay (WPNeg_ipd, WPNeg, tipd_WPNeg); + w_7 : VitalWireDelay (HOLDNeg_ipd, HOLDNeg, tipd_HOLDNeg); + + END BLOCK; + + --------------------------------------------------------------------------- + -- Main Behavior Block + --------------------------------------------------------------------------- + Behavior: BLOCK + + PORT ( + SIIn : IN std_ulogic := 'U'; + SIOut : OUT std_ulogic := 'U'; + SOIn : IN std_logic := 'U'; + SOut : OUT std_logic := 'U'; + SCK : IN std_ulogic := 'U'; + CSNeg : IN std_ulogic := 'U'; + RSTNeg : IN std_ulogic := 'U'; + HOLDNegIn : IN std_ulogic := 'U'; + HOLDNegOut : OUT std_ulogic := 'U'; + WPNegIn : IN std_ulogic := 'U'; + WPNegOut : OUT std_ulogic := 'U' + ); + + PORT MAP ( + SIIn => SI_ipd, + SIOut => SI, + SOIn => SO_ipd, + SOut => SO, + SCK => SCK_ipd, + CSNeg => CSNeg_ipd, + RSTNeg => RSTNeg_ipd, + HOLDNegIn => HOLDNeg_ipd, + HOLDNegOut => HOLDNeg, + WPNegIn => WPNeg_ipd, + WPNegOut => WPNeg + ); + + -- State Machine : State_Type + TYPE state_type IS (IDLE, + RESET_STATE, + AUTOBOOT, + WRITE_SR, + PAGE_PG, + OTP_PG, + PG_SUSP, + SECTOR_ERS, + BULK_ERS, + ERS_SUSP, + ERS_SUSP_PG, + ERS_SUSP_PG_SUSP, + PASS_PG, + PASS_UNLOCK, + PPB_PG, + PPB_ERS, + AUTOBOOT_PG, + ASP_PG, + PLB_PG, + DYB_PG, + NVDLR_PG + ); + + -- Instruction Type + TYPE instruction_type IS ( NONE, + WREN, -- Write Enable + WRDI, -- Write Disable + WRR, -- Write Register + READ, -- Read Normal (3Byte Address) + RD4, -- Read Normal (4Byte +) + OTPR, -- OTP Read + RDSR, -- Read Status Register 1 + RDSR2, -- Read Status Register 2 + RDCR, -- Read Configuration Register 1 + REMS, -- Read ID (SST) + RDID, -- Read ID JEDEC + RES, -- Read ID + FSTRD, -- Fast Read (3Byte Address) + FSTRD4, -- Fast Read (4Byte +) + DDRFR, -- Fast Read DDR (3Byte Address) + DDRFR4, -- Fast Read DDR (4Byte +) + DOR, -- Read Dual Out (3Byte Address) + DOR4, -- Read Dual Out (4Byte +) + DIOR, -- Read Dual I/O (3Byte Address) + DIOR4, -- Read Dual I/O (4Byte +) + DDRDIOR, -- Read DDR Dual I/O (3Byte) + DDRDIOR4, -- Read DDR Dual I/O (4Byte +) + QOR, -- Read Quad Out (3Byte Address) + QOR4, -- Read Quad Out (4Byte +) + QIOR, -- Read Quad I/O (3Byte Address) + QIOR4, -- Read Quad I/O (4Byte +) + DDRQIOR, -- Read DDR Quad I/O (3Byte) + DDRQIOR4, -- Read DDR Quad I/O (4Byte +) + PP, -- Program Page (3Byte Address) + PP4, -- Program Page (4Byte +) + QPP, -- Quad Page Program (3Byte) + QPP4, -- Quad Page Program (4Byte +) + OTPP, -- OTP Program + PGSP, -- Program Suspend + PGRS, -- Program Resume + BE, -- Bulk Erase + SE, -- Erase 128/256KB (3Byte) + SE4, -- Erase 128/256KB (4Byte +) + P4E, -- 4KB-sector Erase (3Byte Addr) + P4E4, -- 4KB-sector Erase (4Byte Addr) + ERSP, -- Erase Suspend + ERRS, -- Erase Resume + ABRD, -- AutoBoot Register Read + ABWR, -- AutoBoot Register Write + BRRD, -- Bank Register Read + BRWR, -- Bank Register Write + BRAC, -- Bank Register Access + DLPRD, -- Read Data Learning Pattern + PNVDLR, -- Program NVDLP Reg + WVDLR, -- Write Volatile DLP Reg + ASPRD, -- ASP Read + ASPP, -- ASP Program + DYBRD, -- DYB Read + DYBWR, -- DYB Write + PPBRD, -- PPB Read + PPBP, -- PPB Program + PPBERS, -- PPB Erase + PLBWR, -- PPB Lock Bit Write + PLBRD, -- PPB Lock Bit Read + PASSRD, -- Password Read + PASSP, -- Password Program + PASSU, -- Password Unlock + RESET, -- Reset + MBR, -- Mode Bit Reset + MPM, -- Multi-I/O-High Perf Mode + CLSR -- Clear Status Register + ); + + TYPE WByteType IS ARRAY (0 TO 511) OF INTEGER RANGE -1 TO MaxData; + -- Flash Memory Array + TYPE MemArray IS ARRAY (0 TO AddrRANGE) OF INTEGER RANGE -1 TO MaxData; + -- OTP Memory Array + TYPE OTPArray IS ARRAY (OTPLoAddr TO OTPHiAddr) OF INTEGER + RANGE -1 TO MaxData; + --CFI Array (Common Flash Interface Query codes) + TYPE CFItype IS ARRAY (16#00# TO 16#55#) OF + INTEGER RANGE -1 TO 16#FF#; + ----------------------------------------------------------------------- + -- memory declaration + ----------------------------------------------------------------------- + -- Memory + SHARED VARIABLE Mem : MemArray := (OTHERS => MaxData); + -- OTP Sector + SHARED VARIABLE OTPMem : OTPArray := (OTHERS => MaxData); + --CFI Array + SHARED VARIABLE CFI_array : CFItype := (OTHERS => 0); + -- Programming Buffer + SIGNAL WByte : WByteType := (OTHERS => MaxData); + + -- states + SIGNAL current_state : state_type; + SIGNAL next_state : state_type; + + SIGNAL Instruct : instruction_type; + --zero delay signal + SIGNAL SOut_zd : std_logic := 'Z'; + SIGNAL SIOut_zd : std_logic := 'Z'; + SIGNAL HOLDNegOut_zd : std_logic := 'Z'; + SIGNAL WPNegOut_zd : std_logic := 'Z'; + --HOLD delay on output data + SIGNAL SOut_z : std_logic := 'Z'; + SIGNAL SIOut_z : std_logic := 'Z'; + -- powerup + SIGNAL PoweredUp : std_logic := '0'; + + ----------------------------------------------------------------------- + -- Registers + ----------------------------------------------------------------------- + -- *** Status Register 1 *** + SHARED VARIABLE Status_reg1 : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Status_reg1_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Status Register Write Disable Bit + ALIAS SRWD :std_logic IS Status_reg1(7); + -- Status Register Programming Error Bit + ALIAS P_ERR :std_logic IS Status_reg1(6); + -- Status Register Erase Error Bit + ALIAS E_ERR :std_logic IS Status_reg1(5); + -- Status Register Block Protection Bits + ALIAS BP2 :std_logic IS Status_reg1(4); + ALIAS BP1 :std_logic IS Status_reg1(3); + ALIAS BP0 :std_logic IS Status_reg1(2); + -- Status Register Write Enable Latch Bit + ALIAS WEL :std_logic IS Status_reg1(1); + -- Status Register Write In Progress Bit + ALIAS WIP :std_logic IS Status_reg1(0); + + -- *** Status Register 2 *** + SHARED VARIABLE Status_reg2 : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Status_reg2_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Status Register Write Enable Latch Bit + ALIAS ES :std_logic IS Status_reg2(1); + -- Status Register Write In Progress Bit + ALIAS PS :std_logic IS Status_reg2(0); + + -- *** Configuration Register 1 *** + SHARED VARIABLE Config_reg1 : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Config_reg1_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Latency code + ALIAS LC1 :std_logic IS Config_reg1(7); + ALIAS LC0 :std_logic IS Config_reg1(6); + -- Configuration Register TBPROT bit + ALIAS TBPROT :std_logic IS Config_reg1(5); + -- Configuration Register LOCK bit + ALIAS LOCK :std_logic IS Config_reg1(4); + -- Configuration Register BPNV bit + ALIAS BPNV :std_logic IS Config_reg1(3); + -- Configuration Register TBPARM bit + ALIAS TBPARM :std_logic IS Config_reg1(2); + -- Configuration Register QUAD bit + ALIAS QUAD :std_logic IS Config_reg1(1); + -- Configuration Register FREEZE bit + ALIAS FREEZE :std_logic IS Config_reg1(0); + + -- *** VDLR Register *** + SHARED VARIABLE VDLR_reg : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL VDLR_reg_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- *** NVDLR Register *** + SHARED VARIABLE NVDLR_reg : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL NVDLR_reg_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- *** AutoBoot Register *** + SHARED VARIABLE AutoBoot_reg : std_logic_vector(31 downto 0) + := (others => '0'); + SIGNAL AutoBoot_reg_in : std_logic_vector(31 downto 0) + := (others => '0'); + --AutoBoot Enable Bit + ALIAS ABE :std_logic IS AutoBoot_reg(0); + + -- *** Bank Address Register *** + SHARED VARIABLE Bank_Addr_reg : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Bank_Addr_reg_in : std_logic_vector(7 downto 0) + := (others => '0'); + --Bank Address Register EXTADD bit + ALIAS EXTADD :std_logic IS Bank_Addr_reg(7); + + -- *** ASP Register *** + SHARED VARIABLE ASP_reg : std_logic_vector(15 downto 0); + SIGNAL ASP_reg_in : std_logic_vector(15 downto 0) + := (others => '1'); + --Read Password Mode Enable Bit + ALIAS RPME :std_logic IS ASP_reg(5); + --PPB OTP Bit + ALIAS PPBOTP :std_logic IS ASP_reg(3); + -- Password Protection Mode Lock Bit + ALIAS PWDMLB :std_logic IS ASP_reg(2); + --Persistent Protection Mode Lock Bit + ALIAS PSTMLB :std_logic IS ASP_reg(1); + + -- *** Password Register *** + SHARED VARIABLE Password_reg : std_logic_vector(63 downto 0) + := (others => '1'); + SIGNAL Password_reg_in : std_logic_vector(63 downto 0) + := (others => '1'); + -- *** PPB Lock Register *** + SHARED VARIABLE PPBL : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL PPBL_in : std_logic_vector(7 downto 0) + := (others => '0'); + --Persistent Protection Mode Lock Bit + ALIAS PPB_LOCK : std_logic IS PPBL(0); + SIGNAL PPB_LOCK_temp : std_ulogic := '0'; + + -- *** PPB Access Register *** + SHARED VARIABLE PPBAR : std_logic_vector(7 downto 0) + := (others => '1'); + SIGNAL PPBAR_in : std_logic_vector(7 downto 0) + := (others => '1'); + -- PPB_bits(Sec) + SHARED VARIABLE PPB_bits : std_logic_vector(SecNum64 downto 0) + := (OTHERS => '1'); + -- *** DYB Access Register *** + SHARED VARIABLE DYBAR : std_logic_vector(7 downto 0) + := (others => '1'); + SIGNAL DYBAR_in : std_logic_vector(7 downto 0) + := (others => '1'); + -- DYB(Sec) + SHARED VARIABLE DYB_bits : std_logic_vector(SecNum64 downto 0); + + -- The Lock Protection Registers for OTP Memory space + SHARED VARIABLE LOCK_BYTE1 :std_logic_vector(7 downto 0); + SHARED VARIABLE LOCK_BYTE2 :std_logic_vector(7 downto 0); + SHARED VARIABLE LOCK_BYTE3 :std_logic_vector(7 downto 0); + SHARED VARIABLE LOCK_BYTE4 :std_logic_vector(7 downto 0); + + --Command Register + SIGNAL write : std_logic := '0'; + SIGNAL cfg_write : std_logic := '0'; + SIGNAL read_out : std_logic := '0'; + + SIGNAL rd : boolean := false; + SIGNAL dual : boolean := false; + SIGNAL fast_rd : boolean := true; + SIGNAL ddr : boolean := false; + SIGNAL any_read : boolean := false; + + SIGNAL quadpg : boolean := false; + + SIGNAL oe : boolean := false; + SIGNAL oe_z : boolean := false; + + SHARED VARIABLE hold_mode : boolean := false; + + -- Memory Array Configuration + SIGNAL BottomBoot : boolean := false; + SIGNAL TopBoot : boolean := false; + SIGNAL UniformSec : boolean := false; + + --FSM control signals + SIGNAL PDONE : std_logic := '1'; --Page Prog. Done + SIGNAL PSTART : std_logic := '0'; --Start Page Programming + SIGNAL PGSUSP : std_logic := '0'; --Suspend Program + SIGNAL PGRES : std_logic := '0'; --Resume Program + + SIGNAL RES_TO_SUSP_MIN_TIME : std_logic := '0';--Resume to Suspend Flag + SIGNAL RES_TO_SUSP_TYP_TIME : std_logic := '0';--Resume to Suspend Flag + + SIGNAL WDONE : std_logic := '1'; --Write operation Done + SIGNAL WSTART : std_logic := '0'; --Start Write operation + + SIGNAL ESTART : std_logic := '0'; --Start Erase operation + SIGNAL EDONE : std_logic := '1'; --Erase operation Done + SIGNAL ESUSP : std_logic := '0'; --Suspend Erase + SIGNAL ERES : std_logic := '0'; --Resume Erase + + SIGNAL ERS_SUSP_PG_SUSP_ACT: std_logic := '0'; --During Erase Suspend + --Program Suspend + --is Active + + --reset timing + SIGNAL RST : std_logic := '0'; + SIGNAL Reseted : std_logic := '0'; --Reset Timing Control + --Lock Bit is enabled for customer programming + SIGNAL WRLOCKENABLE : BOOLEAN := TRUE; + --Flag that mark if ASP Register is allready programmed + SIGNAL ASPOTPFLAG : BOOLEAN := FALSE; + SIGNAL ASP_INIT : NATURAL RANGE 0 TO 1; + SIGNAL INITIAL_CONFIG : std_logic := '0'; + + SHARED VARIABLE PageSize : NATURAL := 0 ; + SHARED VARIABLE PageNum : NATURAL := 0 ; + SHARED VARIABLE SecNum : NATURAL := 0 ; + SHARED VARIABLE SecNumMax : NATURAL := 0 ; + SHARED VARIABLE SecSize : NATURAL := 0 ; + SHARED VARIABLE b_act : NATURAL := 0 ; + + SHARED VARIABLE ASP_ProtSE : NATURAL := 0; + SHARED VARIABLE Sec_ProtSE : NATURAL := 0; + + SHARED VARIABLE SecAddr : NATURAL RANGE 0 TO SecNum64:= 0; + + SHARED VARIABLE Sec_addr : NATURAL := 0; + + SHARED VARIABLE Page_addr : NATURAL; + SHARED VARIABLE pgm_page : NATURAL; + + --Flag for Password unlock command + SIGNAL PASS_UNLOCKED : boolean := FALSE; + SIGNAL PASS_TEMP : std_logic_vector(63 downto 0) + := (others => '1'); + + SHARED VARIABLE DOUBLE : BOOLEAN := FALSE; + SHARED VARIABLE EHP : BOOLEAN := FALSE; + + SHARED VARIABLE read_cnt : NATURAL := 0; + SHARED VARIABLE byte_cnt : NATURAL := 1; + SHARED VARIABLE read_addr : NATURAL RANGE 0 TO AddrRANGE ; + SHARED VARIABLE read_addr_tmp : NATURAL RANGE 0 TO AddrRANGE ; + + SHARED VARIABLE start_delay : NATURAL RANGE 0 TO 7; + SHARED VARIABLE ABSD : NATURAL RANGE 0 TO 7; + SIGNAL start_autoboot : std_logic := '0'; + + SIGNAL change_addr : std_logic := '0'; + SIGNAL Address : NATURAL RANGE 0 TO AddrRANGE := 0; + SIGNAL SectorSuspend : NATURAL RANGE 0 TO SecNum64 := 0; + + -- Sector address + SIGNAL SA : NATURAL RANGE 0 TO SecNum64 := 0; + + -- Sector is protect if Sec_Prot(SecNum) = '1' + SHARED VARIABLE Sec_Prot : std_logic_vector(SecNum64 downto 0) := + (OTHERS => '0'); + + SIGNAL change_TBPARM : std_logic := '0'; + + SIGNAL change_BP : std_logic := '0'; + SHARED VARIABLE BP_bits : std_logic_vector(2 downto 0) := "000"; + + SHARED VARIABLE CFI_array_tmp : std_logic_vector(647 downto 0); + + SIGNAL Byte_number : NATURAL RANGE 0 TO 511 := 0; + + TYPE bus_cycle_type IS (STAND_BY, + OPCODE_BYTE, + ADDRESS_BYTES, + DUMMY_BYTES, + MODE_BYTE, + DATA_BYTES + ); + SHARED VARIABLE bus_cycle_state : bus_cycle_type; + -- switch between Data bytes and Dummy bytes + SHARED VARIABLE DummyBytes_act : X01 := '0'; + SIGNAL dummy_cnt_act_temp : NATURAL := 0; + SIGNAL dummy_cnt_act : NATURAL := 0; + --Read Password Protection Mode Active flag + SIGNAL RdPswdProtMode : std_ulogic := '0'; + --Read Password Protection Mode Support flag + SIGNAL RdPswdProtEnable : std_ulogic := '0'; + SIGNAL BAR_ACC : std_ulogic := '0'; + + SHARED VARIABLE Latency_code : NATURAL RANGE 0 TO 7; + SHARED VARIABLE opcode_cnt : NATURAL := 0; + SHARED VARIABLE addr_cnt : NATURAL := 0; + SHARED VARIABLE mode_cnt : NATURAL := 0; + SHARED VARIABLE dummy_cnt : NATURAL := 0; + SHARED VARIABLE data_cnt : NATURAL := 0; + + SHARED VARIABLE PARAM_REGION : BOOLEAN := FALSE; + + -- timing check violation + SIGNAL Viol : X01 := '0'; + + PROCEDURE ADDRHILO_SEC( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE Addr : NATURAL) IS + VARIABLE sector : NATURAL RANGE 0 TO 285; + BEGIN + + IF (TimingModel(16) = '0') THEN + IF TBPARM = '0' THEN + IF Addr/(SecSize64+1) <= 1 AND + (Instruct = P4E OR Instruct = P4E4) THEN --4KB Sectors + sector := Addr/(SecSize4+1); + AddrLOW := sector*(SecSize4+1); + AddrHIGH := sector*(SecSize4+1) + SecSize4; + ELSE + sector := Addr/(SecSize64+1); + AddrLOW := sector*(SecSize64+1); + AddrHIGH := sector*(SecSize64+1) + SecSize64; + END IF; + ELSE + IF Addr/(SecSize64+1) >= 254 AND + (Instruct = P4E OR Instruct = P4E4) THEN --4KB Sectors + sector := 254 + (Addr-(SecSize64+1)*254)/(SecSize4+1); + AddrLOW := 254*(SecSize64+1)+(sector-254)*(SecSize4+1); + AddrHIGH := 254*(SecSize64+1)+(sector-254)*(SecSize4+1) + + SecSize4; + ELSE + sector := Addr/(SecSize64+1); + AddrLOW := sector*(SecSize64+1); + AddrHIGH := sector*(SecSize64+1) + SecSize64; + END IF; + END IF; + ELSE + sector := Addr/(SecSize256+1); + AddrLOW := sector*(SecSize256+1); + AddrHIGH := sector*(SecSize256+1) + SecSize256; + END IF; + END ADDRHILO_SEC; + + PROCEDURE ADDRHILO_PG( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to AddrRANGE; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to AddrRANGE; + VARIABLE Addr : NATURAL) IS + VARIABLE page : NATURAL RANGE 0 TO PageNum; + BEGIN + page := Addr/PageSize; + AddrLOW := Page*PageSize; + AddrHIGH := Page*PageSize + (PageSize-1); + END AddrHILO_PG; + + PROCEDURE ReturnSectorID( + VARIABLE result : INOUT NATURAL; + SIGNAL ADDR : NATURAL RANGE 0 TO AddrRANGE) IS + VARIABLE conv : NATURAL; + BEGIN + IF (TimingModel(16) = '0') THEN + conv := ADDR / (SecSize64+1); + IF BottomBoot = TRUE THEN + IF conv <= 1 THEN --4KB Sectors + result := ADDR/(SecSize4+1); + ELSE + result := conv + 30; + END IF; + ELSIF TopBoot = TRUE THEN + IF conv >= 254 THEN --4KB Sectors + result := 254 + (ADDR-(SecSize64+1)*254)/(SecSize4+1); + ELSE + result := conv; + END IF; + END IF; + ELSE + result := ADDR/(SecSize256+1); + END IF; + END ReturnSectorID; + + BEGIN + --------------------------------------------------------------------------- + --Power Up time + --------------------------------------------------------------------------- + + PoweredUp <= '1' AFTER tdevice_PU; + + --------------------------------------------------------------------------- + --sector structure + --------------------------------------------------------------------------- + UniformSec <= TRUE WHEN (TimingModel(16) = '1') + ELSE FALSE; + TimingModelSel: PROCESS + BEGIN + IF TimingModel(16) = '1' THEN + -- Sector Number/Sector Size + SecNumMax:= SecNum256; + SecNum := SecNum256; + SecSize := SecSize256; + -- 256B/512B Page Size + PageSize := 512; + PageNum := 16#FFFF#; + ELSE + -- Sector Number/Sector Size + SecNumMax:= SecNum64; + SecNum := 255; + SecSize := SecSize64; + -- 256B/512B Page Size + PageSize := 256; + PageNum := 16#1FFFF#; + END IF; + --Enhanced High Performance Flag + IF (TimingModel(15) = '0' OR TimingModel(15) = '2' OR + TimingModel(15) = '3' OR TimingModel(15) = 'R' OR + TimingModel(15) = 'A' OR TimingModel(15) = 'B' OR + TimingModel(15) = 'C' OR TimingModel(15) = 'D' OR + TimingModel(15) = 'Y' OR TimingModel(15) = 'Z' OR + TimingModel(15) = 'S' OR TimingModel(15) = 'T' OR + TimingModel(15) = 'K' OR TimingModel(15) = 'L') THEN + EHP := TRUE; + IF (TimingModel(15) = 'Y' OR TimingModel(15) = 'Z' OR + TimingModel(15) = 'S' OR TimingModel(15) = 'T' OR + TimingModel(15) = 'K' OR TimingModel(15) = 'L') THEN + RdPswdProtEnable <= '1'; + END IF; + ELSIF (TimingModel(15) = '4' OR TimingModel(15) = '6' OR + TimingModel(15) = '7' OR TimingModel(15) = '8' OR + TimingModel(15) = '9' OR TimingModel(15) = 'Q') THEN + EHP := FALSE; + END IF; + + IF (TimingModel(15) ='0' OR TimingModel(15) ='2' OR + TimingModel(15) ='3' OR TimingModel(15) ='R' OR + TimingModel(15) ='A' OR TimingModel(15) ='B' OR + TimingModel(15) ='C' OR TimingModel(15) ='D' OR + TimingModel(15) ='4' OR TimingModel(15) ='6' OR + TimingModel(15) ='7' OR TimingModel(15) ='8' OR + TimingModel(15) ='9' OR TimingModel(15) ='Q') THEN + ASP_INIT <= 1; + ELSIF (TimingModel(15) ='Y' OR TimingModel(15) ='Z' OR + TimingModel(15) ='S' OR TimingModel(15) ='T' OR + TimingModel(15) ='K' OR TimingModel(15) ='L') THEN + ASP_INIT <= 0; + END IF; + WAIT; + END PROCESS; + + RSTtiming: PROCESS(RSTNeg_pullup,Instruct) + BEGIN + IF falling_edge(RSTNeg_pullup) THEN + RST <= '1', '0' AFTER 200 ns; + ELSIF Instruct = RESET THEN + Reseted <= '0', '1' AFTER 10 ns; + END IF; + END PROCESS; + + DUMMYcnt: PROCESS(dummy_cnt_act_temp) + BEGIN + dummy_cnt_act <= dummy_cnt_act_temp; + END PROCESS; + + ReadPasswordProtectionMode: PROCESS(PPB_LOCK_temp, + ASP_reg_in(2), ASP_reg_in(5)) + BEGIN + IF (PPB_LOCK = '0' AND PWDMLB = '0' AND RPME = '0' AND + RdPswdProtEnable = '1') THEN + RdPswdProtMode <= '1'; + ABE := '0'; + ELSE + RdPswdProtMode <= '0'; + END IF; + END PROCESS; + --------------------------------------------------------------------------- + -- autoboot control logic + --------------------------------------------------------------------------- + AutoBootControl: PROCESS(SCK_ipd, current_state) + BEGIN + IF (current_state = AUTOBOOT) THEN + IF rising_edge(SCK_ipd) THEN + IF (start_delay > 0) THEN + start_delay := start_delay - 1; + END IF; + END IF; + + IF (start_delay = 0) THEN + start_autoboot <= '1'; + ELSE + start_autoboot <= '0'; + END IF; + END IF; + END PROCESS; + + --------------------------------------------------------------------------- + -- VITAL Timing Checks Procedures + --------------------------------------------------------------------------- + VITALTimingCheck: PROCESS(SIIn, SOIn, SCK_ipd, CSNeg_ipd, RSTNeg_ipd, + HOLDNegIn, WPNegIn) + + -- Timing Check Variables + -- Setup/Hold Checks variables + VARIABLE Tviol_CSNeg_SCK_normal : X01 := '0'; + VARIABLE TD_CSNeg_SCK_normal : VitalTimingDataType; + + VARIABLE Tviol_CSNeg_SCK_DDR : X01 := '0'; + VARIABLE TD_CSNeg_SCK_DDR : VitalTimingDataType; + + VARIABLE Tviol_CSNeg_RSTNeg : X01 := '0'; + VARIABLE TD_CSNeg_RSTNeg : VitalTimingDataType; + + VARIABLE Tviol_SI_SCK : X01 := '0'; + VARIABLE TD_SI_SCK : VitalTimingDataType; + + VARIABLE Tviol_WPNeg_CSNeg_setup : X01 := '0'; + VARIABLE TD_WPNeg_CSNeg_setup : VitalTimingDataType; + + VARIABLE Tviol_WPNeg_CSNeg_hold : X01 := '0'; + VARIABLE TD_WPNeg_CSNeg_hold : VitalTimingDataType; + + VARIABLE Tviol_HOLDNeg_SCK : X01 := '0'; + VARIABLE TD_HOLDNeg_SCK : VitalTimingDataType; + + VARIABLE Tviol_SI_SCK_DDR_R : X01 := '0'; + VARIABLE TD_SI_SCK_DDR_R : VitalTimingDataType; + + VARIABLE Tviol_SI_SCK_DDR_F : X01 := '0'; + VARIABLE TD_SI_SCK_DDR_F : VitalTimingDataType; + + VARIABLE Tviol_RSTNeg_CSNeg : X01 := '0'; + VARIABLE TD_RSTNeg_CSNeg : VitalTimingDataType; + + --Pulse Width and Period Check Variables + VARIABLE Pviol_SCK_serial : X01 := '0'; + VARIABLE PD_SCK_serial : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_dual : X01 := '0'; + VARIABLE PD_SCK_dual : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_fast : X01 := '0'; + VARIABLE PD_SCK_fast : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_quadpg : X01 := '0'; + VARIABLE PD_SCK_quadpg : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_DDR : X01 := '0'; + VARIABLE PD_SCK_DDR : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_CSNeg_read : X01 := '0'; + VARIABLE PD_CSNeg_read : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_CSNeg_pgers : X01 := '0'; + VARIABLE PD_CSNeg_pgers : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_RSTNeg : X01 := '0'; + VARIABLE PD_RSTNeg : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_serial_rd : X01 := '0'; + VARIABLE PD_SCK_serial_rd : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_fast_rd : X01 := '0'; + VARIABLE PD_SCK_fast_rd : VitalPeriodDataType:=VitalPeriodDataInit; + + VARIABLE Pviol_SCK_dual_rd : X01 := '0'; + VARIABLE PD_SCK_dual_rd : VitalPeriodDataType:=VitalPeriodDataInit; + + VARIABLE Pviol_SCK_DDR_rd : X01 := '0'; + VARIABLE PD_SCK_DDR_rd : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_quad_pg : X01 := '0'; + VARIABLE PD_SCK_quad_pg : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Violation : X01 := '0'; + + BEGIN + --------------------------------------------------------------------------- + -- Timing Check Section + --------------------------------------------------------------------------- + IF (TimingChecksOn) THEN + + -- Setup/Hold Check between CS# and SCK + VitalSetupHoldCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_CSNeg_SCK_normal_noedge_posedge, + SetupLow => tsetup_CSNeg_SCK_normal_noedge_posedge, + HoldHigh => thold_CSNeg_SCK_normal_noedge_posedge, + HoldLow => thold_CSNeg_SCK_normal_noedge_posedge, + CheckEnabled => ddr = false, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_CSNeg_SCK_normal, + Violation => Tviol_CSNeg_SCK_normal + ); + + -- Setup/Hold Check between CS# and SCK + VitalSetupHoldCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_CSNeg_SCK_DDR_noedge_posedge, + SetupLow => tsetup_CSNeg_SCK_DDR_noedge_posedge, + HoldHigh => thold_CSNeg_SCK_DDR_noedge_posedge, + HoldLow => thold_CSNeg_SCK_DDR_noedge_posedge, + CheckEnabled => ddr, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_CSNeg_SCK_DDR, + Violation => Tviol_CSNeg_SCK_DDR + ); + + -- Hold Check between CSNeg and RSTNeg + VitalSetupHoldCheck ( + TestSignal => CSNeg, + TestSignalName => "CSNeg", + RefSignal => RSTNeg, + RefSignalName => "RSTNeg", + HoldHigh => thold_CSNeg_RSTNeg, + CheckEnabled => TRUE, + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_CSNeg_RSTNeg, + Violation => Tviol_CSNeg_RSTNeg + ); + + -- Setup/Hold Check between SI and SCK, serial mode + VitalSetupHoldCheck ( + TestSignal => SIIn, + TestSignalName => "SI", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_normal_noedge_posedge, + SetupLow => tsetup_SI_SCK_normal_noedge_posedge, + HoldHigh => thold_SI_SCK_normal_noedge_posedge, + HoldLow => thold_SI_SCK_normal_noedge_posedge, + CheckEnabled => NOT(DOUBLE) AND SIOut_z /= SIIn , + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_SI_SCK, + Violation => Tviol_SI_SCK + ); + + -- Setup Check between WP# and CS# \ + VitalSetupHoldCheck ( + TestSignal => WPNegIn, + TestSignalName => "WP#", + RefSignal => CSNeg_ipd, + RefSignalName => "CS#", + SetupHigh => tsetup_WPNeg_CSNeg, + CheckEnabled => true, + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WPNeg_CSNeg_setup, + Violation => Tviol_WPNeg_CSNeg_setup + ); + + -- Hold Check between WP# and CS# / + VitalSetupHoldCheck ( + TestSignal => WPNegIn, + TestSignalName => "WP#", + RefSignal => CSNeg_ipd, + RefSignalName => "CS#", + HoldHigh => thold_WPNeg_CSNeg, + CheckEnabled => SRWD = '1' AND WEL = '1', + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WPNeg_CSNeg_hold, + Violation => Tviol_WPNeg_CSNeg_hold + ); + + -- Setup/Hold Check between HOLD# and SCK / + VitalSetupHoldCheck ( + TestSignal => HOLDNegIn, + TestSignalName => "HOLD#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupLow => tsetup_HOLDNeg_SCK, + SetupHigh => tsetup_HOLDNeg_SCK, + HoldLow => thold_HOLDNeg_SCK, + HoldHigh => thold_HOLDNeg_SCK, + CheckEnabled => QUAD = '0' + AND HOLDNegOut_zd /= HOLDNegIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_HOLDNeg_SCK, + Violation => Tviol_HOLDNeg_SCK + ); + + -- Setup/Hold Check between SI and SCK, DDR mode + VitalSetupHoldCheck ( + TestSignal => SIIn, + TestSignalName => "SI", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_DDR_noedge_posedge, + SetupLow => tsetup_SI_SCK_DDR_noedge_posedge, + HoldHigh => thold_SI_SCK_DDR_noedge_posedge, + HoldLow => thold_SI_SCK_DDR_noedge_posedge, + CheckEnabled => DOUBLE AND dual = false + AND SIOut_z /= SIIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_SI_SCK_DDR_R, + Violation => Tviol_SI_SCK_DDR_R + ); + + -- Setup/Hold Check between SI and SCK, DDR mode + VitalSetupHoldCheck ( + TestSignal => SIIn, + TestSignalName => "SI", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_DDR_noedge_negedge, + SetupLow => tsetup_SI_SCK_DDR_noedge_negedge, + HoldHigh => thold_SI_SCK_DDR_noedge_negedge, + HoldLow => thold_SI_SCK_DDR_noedge_negedge, + CheckEnabled => ddr AND dual = false + AND SIOut_z /= SIIn , + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_SI_SCK_DDR_F, + Violation => Tviol_SI_SCK_DDR_F + ); + + -- Setup Check between RSTNeg and SCK, DDR fast mode + VitalSetupHoldCheck ( + TestSignal => RSTNeg, + TestSignalName => "RSTNeg", + RefSignal => CSNeg, + RefSignalName => "CSNeg", + SetupHigh => tsetup_RSTNeg_CSNeg, + CheckEnabled => TRUE, + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_RSTNeg_CSNeg, + Violation => Tviol_RSTNeg_CSNeg + ); + + --Pulse Width and Period Check Variables + -- Pulse Width Check SCK for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_serial_negedge, + PulseWidthHigh => tpw_SCK_serial_posedge, + PeriodData => PD_SCK_serial, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_serial, + HeaderMsg => InstancePath & PartID, + CheckEnabled => rd); + + -- Pulse Width Check SCK for DUAL_READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_dual_negedge, + PulseWidthHigh => tpw_SCK_dual_posedge, + PeriodData => PD_SCK_dual, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_dual, + HeaderMsg => InstancePath & PartID, + CheckEnabled => dual); + + -- Pulse Width Check SCK for FAST_READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_fast_negedge, + PulseWidthHigh => tpw_SCK_fast_posedge, + PeriodData => PD_SCK_fast, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_fast, + HeaderMsg => InstancePath & PartID, + CheckEnabled => fast_rd ); + + -- Pulse Width Check SCK for QPP + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_quadpg_negedge, + PulseWidthHigh => tpw_SCK_quadpg_posedge, + PeriodData => PD_SCK_quadpg, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_quadpg, + HeaderMsg => InstancePath & PartID, + CheckEnabled => quadpg); + + -- Pulse Width Check CS# for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + PulseWidthHigh => tpw_CSNeg_read_posedge, + PeriodData => PD_CSNeg_read, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_CSNeg_read, + HeaderMsg => InstancePath & PartID, + CheckEnabled => any_read ); + + -- Pulse Width Check CS# for Program/Erase, serial mode + VitalPeriodPulseCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + PulseWidthHigh => tpw_CSNeg_pgers_posedge, + PeriodData => PD_CSNeg_pgers, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_CSNeg_pgers, + HeaderMsg => InstancePath & PartID, + CheckEnabled => NOT(any_read)); + + -- Pulse Width Check RSTNeg + VitalPeriodPulseCheck ( + TestSignal => RSTNeg_ipd, + TestSignalName => "RSTNeg", + PulseWidthLow => tpw_RSTNeg_negedge, + PulseWidthHigh => tpw_RSTNeg_posedge, + CheckEnabled => TRUE, + HeaderMsg => InstancePath & PartID, + PeriodData => PD_RSTNeg, + Violation => Pviol_RSTNeg + ); + + -- Pulse Width Check SCK for DDR READ + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_DDR_negedge, + PulseWidthHigh => tpw_SCK_DDR_posedge, + PeriodData => PD_SCK_DDR, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_DDR, + HeaderMsg => InstancePath & PartID, + CheckEnabled => ddr); + + -- Period Check SCK for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_serial_rd, + PeriodData => PD_SCK_serial_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_serial_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => rd ); + + -- Period Check SCK for FAST READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_fast_rd, + PeriodData => PD_SCK_fast_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_fast_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => fast_rd ); + + -- Period Check SCK for DUAL READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_dual_rd, + PeriodData => PD_SCK_dual_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_dual_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => dual ); + + -- Period Check SCK for QPP + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_quadpg, + PeriodData => PD_SCK_quad_pg, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_quad_pg, + HeaderMsg => InstancePath & PartID, + CheckEnabled => quadpg ); + + -- Period Check SCK for DDR READ + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_DDR_rd, + PeriodData => PD_SCK_DDR_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_DDR_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => ddr ); + + Violation := Tviol_CSNeg_SCK_normal OR + Tviol_CSNeg_SCK_DDR OR + Tviol_CSNeg_RSTNeg OR + Tviol_SI_SCK OR + Tviol_WPNeg_CSNeg_setup OR + Tviol_WPNeg_CSNeg_hold OR + Tviol_HOLDNeg_SCK OR + Tviol_SI_SCK_DDR_R OR + Tviol_SI_SCK_DDR_F OR + Tviol_RSTNeg_CSNeg OR + Pviol_SCK_serial OR + Pviol_SCK_dual OR + Pviol_SCK_fast OR + Pviol_SCK_quadpg OR + Pviol_CSNeg_read OR + Pviol_CSNeg_pgers OR + Pviol_SCK_DDR OR + Pviol_SCK_serial_rd OR + Pviol_SCK_fast_rd OR + Pviol_SCK_dual_rd OR + Pviol_SCK_quad_pg OR + Pviol_SCK_DDR_rd; + + Viol <= Violation; + + ASSERT Violation = '0' + REPORT InstancePath & partID & ": simulation may be" & + " inaccurate due to timing violations" + SEVERITY WARNING; + + END IF; + END PROCESS VITALTimingCheck; + + ---------------------------------------------------------------------------- + -- sequential process for FSM state transition + ---------------------------------------------------------------------------- + StateTransition : PROCESS(next_state, RST, PoweredUp, RST_out) + + BEGIN + IF PoweredUp = '1' THEN + IF RSTNeg_pullup = '1' and RST_out= '1' THEN + IF next_state'EVENT THEN + current_state <= next_state; + END IF; + ELSIF RSTNeg_pullup = '0' AND falling_edge(RST) THEN + --no state transition while RESET# low + current_state <= RESET_STATE; + RST_in <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END PROCESS StateTransition; + + Threset : PROCESS(RST_in) + BEGIN + IF rising_edge(RST_in) THEN + RST_out <= '0', '1' AFTER (thold_CSNeg_RSTNeg-200 ns); + END IF; + END PROCESS Threset; + + --------------------------------------------------------------------------- + -- Write cycle decode + --------------------------------------------------------------------------- + BusCycleDecode : PROCESS(SCK_ipd, CSNeg_ipd, HOLDNeg_pullup, SIIn, RST_out, + WPNeg_pullup) + + TYPE quad_data_type IS ARRAY (0 TO 1023) OF INTEGER RANGE 0 TO 15; + + VARIABLE bit_cnt : NATURAL := 0; + VARIABLE Data_in : std_logic_vector(4095 downto 0) + := (others => '0'); + + VARIABLE opcode : std_logic_vector(7 downto 0); + VARIABLE opcode_in : std_logic_vector(7 downto 0); + VARIABLE addr_bytes : std_logic_vector(31 downto 0); + VARIABLE hiaddr_bytes : std_logic_vector(31 downto 0); + VARIABLE Address_in : std_logic_vector(31 downto 0); + VARIABLE mode_bytes : std_logic_vector(7 downto 0); + VARIABLE mode_in : std_logic_vector(7 downto 0); + VARIABLE quad_data_in : quad_data_type; + VARIABLE quad_nybble : std_logic_vector(3 downto 0); + VARIABLE Quad_slv : std_logic_vector(3 downto 0); + VARIABLE Byte_slv : std_logic_vector(7 downto 0); + + VARIABLE CLK_PER : time; + VARIABLE LAST_CLK : time; + VARIABLE Check_freq : boolean := FALSE; + + BEGIN + + IF rising_edge(CSNeg_ipd) AND NOT(bus_cycle_state = DATA_BYTES) + AND NOT(bus_cycle_state = DUMMY_BYTES) THEN + bus_cycle_state := STAND_BY; + ELSE + CASE bus_cycle_state IS + WHEN STAND_BY => + IF falling_edge(CSNeg_ipd) THEN + Instruct <= NONE; + write <= '1'; + cfg_write <= '0'; + opcode_cnt:= 0; + addr_cnt := 0; + mode_cnt := 0; + dummy_cnt := 0; + dummy_cnt_act_temp <= dummy_cnt; + data_cnt := 0; + DOUBLE := FALSE; + CLK_PER := 0 ns; + LAST_CLK := 0 ns; + IF current_state = AUTOBOOT THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := OPCODE_BYTE; + END IF; + END IF; + + WHEN OPCODE_BYTE => + IF rising_edge(SCK_ipd) THEN + + Latency_code := to_nat(LC1 & LC0); + CLK_PER := NOW - LAST_CLK; + LAST_CLK := NOW; + IF Check_freq THEN + IF (CLK_PER < 20 ns AND Latency_code = 3) OR + (CLK_PER < 12.5 ns AND Latency_code = 0) OR + (CLK_PER < 11.1 ns AND Latency_code = 1) OR + (CLK_PER < 9.6 ns AND Latency_code = 2) THEN + ASSERT FALSE + REPORT "More wait states are required for " & + "this clock frequency value" + SEVERITY warning; + END IF; + END IF; + Check_freq := FALSE; + + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1') THEN + --One-byte of instruction opcode is shifted into the + --device on the SI serial input pin with the most + --significant bit (MSB) first.Each bit input on the + --SI serial input pin is latched on the rising edge of + --the SCK serial clock signal. + opcode_in(opcode_cnt) := SIIn; + opcode_cnt := opcode_cnt + 1; + IF opcode_cnt = BYTE THEN + --MSB first + FOR I IN 7 DOWNTO 0 LOOP + opcode(i) := opcode_in(7-i); + END LOOP; + + CASE opcode IS + WHEN "00000110" => --06h + Instruct <= WREN; + bus_cycle_state := DATA_BYTES; + WHEN "00000100" => --04h + Instruct <= WRDI; + bus_cycle_state := DATA_BYTES; + WHEN "00000001" => --01h + Instruct <= WRR; + bus_cycle_state := DATA_BYTES; + WHEN "00000011" => --03h + Instruct <= READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00010011" => --13h + Instruct <= RD4; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01001011" => --4Bh + Instruct <= OTPR; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00000101" => --05h + Instruct <= RDSR; + bus_cycle_state := DATA_BYTES; + WHEN "00000111" => --07h + Instruct <= RDSR2; + bus_cycle_state := DATA_BYTES; + WHEN "00110101" => --35h + Instruct <= RDCR; + bus_cycle_state := DATA_BYTES; + WHEN "10010000" => --90h + Instruct <= REMS; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10011111" => --9Fh + Instruct <= RDID; + bus_cycle_state := DATA_BYTES; + WHEN "10101011" => --ABh + Instruct <= RES; + bus_cycle_state := DUMMY_BYTES; + WHEN "00001011" => --0Bh + Instruct <= FSTRD; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00001100" => --0Ch + Instruct <= FSTRD4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00001101" => --0Dh + Instruct <= DDRFR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00001110" => --0Eh + Instruct <= DDRFR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00111011" => --3Bh + Instruct <= DOR; + Check_freq := TRUE; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00111100" => --3Ch + Instruct <= DOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "10111011" => --BBh + Instruct <= DIOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "10111100" => --BCh + Instruct <= DIOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "10111101" => --BDh + Instruct <= DDRDIOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "10111110" => --BEh + Instruct <= DDRDIOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "01101011" => --6Bh + Instruct <= QOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "01101100" => --6Ch + Instruct <= QOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "11101011" => --EBh + Instruct <= QIOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "11101100" => --ECh + Instruct <= QIOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "11101101" => --EDh + Instruct <= DDRQIOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "11101110" => --EEh + Instruct <= DDRQIOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00000010" => --02h + Instruct <= PP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00010010" => --12h + Instruct <= PP4; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00110010" => --32h + Instruct <= QPP; + bus_cycle_state := ADDRESS_BYTES; + quadpg <= TRUE; + WHEN "00111000" => --38h + Instruct <= QPP; + bus_cycle_state := ADDRESS_BYTES; + quadpg <= TRUE; + WHEN "00110100" => --34h + Instruct <= QPP4; + bus_cycle_state := ADDRESS_BYTES; + quadpg <= TRUE; + WHEN "01000010" => --42h + Instruct <= OTPP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10000101" => --85h + Instruct <= PGSP; + bus_cycle_state := DATA_BYTES; + WHEN "10001010" => --8Ah + Instruct <= PGRS; + bus_cycle_state := DATA_BYTES; + WHEN "11000111" => --C7h + Instruct <= BE; + bus_cycle_state := DATA_BYTES; + WHEN "01100000" => --60h + Instruct <= BE; + bus_cycle_state := DATA_BYTES; + WHEN "11011000" => --D8h + Instruct <= SE; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11011100" => --DCh + Instruct <= SE4; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00100000" => --20h + Instruct <= P4E; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00100001" => --21h + Instruct <= P4E4; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01110101" => --75h + Instruct <= ERSP; + bus_cycle_state := DATA_BYTES; + WHEN "01111010" => --7Ah + Instruct <= ERRS; + bus_cycle_state := DATA_BYTES; + WHEN "00010100" => --14h + Instruct <= ABRD; + bus_cycle_state := DATA_BYTES; + WHEN "00010101" => --15h + Instruct <= ABWR; + bus_cycle_state := DATA_BYTES; + WHEN "00010110" => --16h + Instruct <= BRRD; + bus_cycle_state := DATA_BYTES; + WHEN "00010111" => --17h + Instruct <= BRWR; + bus_cycle_state := DATA_BYTES; + WHEN "10111001" => --B9h + Instruct <= BRAC; + bus_cycle_state := DATA_BYTES; + WHEN "00101011" => --2Bh + Instruct <= ASPRD; + bus_cycle_state := DATA_BYTES; + WHEN "00101111" => --2Fh + Instruct <= ASPP; + bus_cycle_state := DATA_BYTES; + WHEN "11100000" => --E0h + Instruct <= DYBRD; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11100001" => --E1h + Instruct <= DYBWR; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11100010" => --E2h + Instruct <= PPBRD; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11100011" => --E3h + Instruct <= PPBP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11100100" => --E4h + Instruct <= PPBERS; + bus_cycle_state := DATA_BYTES; + WHEN "10100110" => --A6h + Instruct <= PLBWR; + bus_cycle_state := DATA_BYTES; + WHEN "10100111" => --A7h + Instruct <= PLBRD; + bus_cycle_state := DATA_BYTES; + WHEN "11100111" => --E7h + Instruct <= PASSRD; + bus_cycle_state := DATA_BYTES; + WHEN "11101000" => --E8h + Instruct <= PASSP; + bus_cycle_state := DATA_BYTES; + WHEN "11101001" => --E9h + Instruct <= PASSU; + bus_cycle_state := DATA_BYTES; + WHEN "11110000" => --F0h + Instruct <= RESET; + bus_cycle_state := DATA_BYTES; + WHEN "11111111" => --FFh + Instruct <= MBR; + bus_cycle_state := MODE_BYTE; + WHEN "01000001" => -- 41h + Instruct <= DLPRD; + bus_cycle_state := DATA_BYTES; + WHEN "01000011" => -- 43h + Instruct <= PNVDLR; + bus_cycle_state := DATA_BYTES; + WHEN "01001010" => -- 4Ah + Instruct <= WVDLR; + bus_cycle_state := DATA_BYTES; + WHEN "00110000" => --30h + Instruct <= CLSR; + bus_cycle_state := DATA_BYTES; + WHEN others => + null; + + END CASE; + END IF; + END IF; + END IF; + + WHEN ADDRESS_BYTES => + IF Instruct= DDRFR OR Instruct= DDRFR4 OR Instruct= DDRDIOR + OR Instruct = DDRDIOR4 OR Instruct = DDRQIOR OR + Instruct = DDRQIOR4 THEN + DOUBLE := TRUE; + ELSE + DOUBLE := FALSE; + END IF; + + IF (rising_edge(SCK_ipd) AND NOT(DOUBLE) AND + (CSNeg_ipd= '0')) THEN + IF (((Instruct=FSTRD AND EXTADD= '0' ) + OR (Instruct=DOR AND EXTADD= '0') + OR Instruct=OTPR) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) + OR (Instruct=QOR AND QUAD= '1' AND EXTADD='0') THEN + --Instruction + 3 Bytes Address + Dummy Byte + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 3*BYTE THEN + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 24) := "00000000"; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF (Instruct=FSTRD OR Instruct=DOR OR + Instruct=QOR) THEN + IF (Latency_code = 3) THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF ((((Instruct=FSTRD4) OR (Instruct=DOR4) OR + ((Instruct=FSTRD) AND EXTADD= '1') OR + ((Instruct=DOR) AND EXTADD= '1')) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) OR + ((Instruct=QOR4) AND QUAD='1') OR + ((Instruct=QOR) AND QUAD='1' AND EXTADD='1')) THEN + --Instruction + 4 Bytes Address + Dummy Byte + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 4*BYTE THEN + FOR I IN 31 DOWNTO 0 LOOP + hiaddr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(hiaddr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF Latency_code = 3 THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := DUMMY_BYTES; + IF (DOUBLE AND NOT(hold_mode) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + ELSIF Instruct = DIOR AND EXTADD= '0' AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1') THEN + -- DUAL I/O High Performance Read (3Bytes Address) + IF SOIn /= 'Z' THEN + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt+1) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = (3*BYTE) / 2 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 24) := "00000000"; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSE + bus_cycle_state := STAND_BY; + END IF; + ELSIF ((Instruct = DIOR4 OR + (Instruct = DIOR AND EXTADD= '1')) AND + ((HOLDNeg_pullup = '1' AND QUAD = '0') OR + QUAD = '1')) THEN + -- DUAL I/O High Performance Read (4Bytes Address) + IF SOIn /= 'Z' THEN + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt+1) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = (4*BYTE) / 2 THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + hiaddr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(hiaddr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSE + bus_cycle_state := STAND_BY; + END IF; + ELSIF (Instruct = QIOR AND EXTADD= '0') THEN + -- QUAD I/O High Performance Read (3Bytes Address) + IF QUAD = '1' THEN + IF SOIn /= 'Z' THEN + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = (3*BYTE) / 4 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 24) := "00000000"; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + END IF; + ELSE + bus_cycle_state := STAND_BY; + END IF; + ELSIF (Instruct = QIOR4 OR + (Instruct = QIOR AND EXTADD= '1')) THEN + -- QUAD I/O High Performance Read (4Bytes Address) + IF QUAD = '1' THEN + IF SOIn /= 'Z' THEN + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = (4*BYTE) / 4 THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + hiaddr_bytes(31-i) + := Address_in(i); + END LOOP; + Address <= to_nat(hiaddr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + END IF; + ELSE + bus_cycle_state := STAND_BY; + END IF; + ELSIF (((Instruct = RD4 OR Instruct = PP4 OR + Instruct = SE4 OR Instruct = PPBRD OR + Instruct = DYBRD OR Instruct = DYBWR OR + Instruct = PPBP OR Instruct = P4E4 OR + (Instruct = READ AND EXTADD= '1' ) OR + (Instruct = PP AND EXTADD= '1' ) OR + (Instruct = SE AND EXTADD= '1' )) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) + OR (QUAD ='1' AND (Instruct=QPP4 OR + (Instruct = QPP AND EXTADD= '1' ))))THEN + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 4*BYTE THEN + FOR I IN 31 DOWNTO 0 LOOP + hiaddr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(hiaddr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (((HOLDNeg_pullup='1' AND QUAD='0') + OR QUAD='1') AND EXTADD= '0') THEN + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 3*BYTE THEN + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 24) := "00000000"; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF (SCK_ipd'EVENT AND DOUBLE AND addr_cnt /= 0 ) OR + (rising_edge(SCK_ipd) AND DOUBLE AND addr_cnt = 0 ) THEN + IF (Instruct=DDRFR AND EXTADD= '0' ) THEN + --Fast DDR Read Mode + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = 3*BYTE THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 24) := "00000000"; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF (Instruct=DDRFR4 OR + (Instruct=DDRFR AND EXTADD= '1' )) THEN + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = 4*BYTE THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + addr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + ELSIF (Instruct= DDRDIOR AND EXTADD= '0' ) THEN + --Dual I/O DDR Read Mode + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt+1):= SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = (3*BYTE)/2 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 24) := "00000000"; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF (Instruct=DDRDIOR4 OR + (Instruct=DDRDIOR AND EXTADD= '1' )) THEN + --Dual I/O DDR Read Mode + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt+1) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = (4*BYTE)/2 THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + addr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + ELSIF (Instruct=DDRQIOR AND EXTADD= '0' ) AND + QUAD = '1' THEN + --Quad I/O DDR Read Mode + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = (3*BYTE)/4 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 24) := "00000000"; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 5 ns; + bus_cycle_state := MODE_BYTE; + END IF; + ELSIF QUAD = '1' AND (Instruct=DDRQIOR4 OR + (Instruct=DDRQIOR AND EXTADD= '1' )) THEN + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = (4*BYTE)/4 THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + addr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + END IF; + END IF; + + WHEN MODE_BYTE => + IF rising_edge(SCK_ipd) THEN + IF ((Instruct=DIOR OR Instruct = DIOR4) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) THEN + mode_in(2*mode_cnt) := SOIn; + mode_in(2*mode_cnt+1) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/2 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + IF Latency_code = 0 OR Latency_code = 3 THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF (Instruct=QIOR OR Instruct = QIOR4) + AND QUAD = '1' THEN + mode_in(4*mode_cnt) := HOLDNegIn; + mode_in(4*mode_cnt+1) := WPNegIn; + mode_in(4*mode_cnt+2) := SOIn; + mode_in(4*mode_cnt+3) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/4 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DUMMY_BYTES; + END IF; + ELSIF Instruct=DDRFR OR Instruct = DDRFR4 THEN + mode_in(2*mode_cnt) := SIIn; + ELSIF Instruct=DDRDIOR OR Instruct = DDRDIOR4 THEN + mode_in(4*mode_cnt) := SOIn; + mode_in(4*mode_cnt+1) := SIIn; + ELSIF (Instruct=DDRQIOR OR Instruct = DDRQIOR4) + AND QUAD = '1' THEN + mode_in(0) := HOLDNegIn; + mode_in(1) := WPNegIn; + mode_in(2) := SOIn; + mode_in(3) := SIIn; + END IF; + dummy_cnt := 0; + dummy_cnt_act_temp <= dummy_cnt; + ELSIF falling_edge(SCK_ipd) THEN + IF Instruct=DDRFR OR Instruct = DDRFR4 THEN + mode_in(2*mode_cnt+1) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/2 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + ELSIF Instruct=DDRDIOR OR Instruct = DDRDIOR4 THEN + mode_in(4*mode_cnt+2) := SOIn; + mode_in(4*mode_cnt+3) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/4 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + ELSIF (Instruct=DDRQIOR OR Instruct = DDRQIOR4) + AND QUAD = '1' THEN + mode_in(4) := HOLDNegIn; + mode_in(5) := WPNegIn; + mode_in(6) := SOIn; + mode_in(7) := SIIn; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + + WHEN DUMMY_BYTES => + IF rising_edge(SCK_ipd) THEN + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + IF (((Instruct=FSTRD OR Instruct=FSTRD4 OR + Instruct=DOR OR Instruct=DOR4 OR + Instruct=OTPR) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) OR + ((Instruct = QOR OR Instruct = QOR4) AND + QUAD = '1'))THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF dummy_cnt = BYTE THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct=DDRFR OR Instruct=DDRFR4) THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF EHP THEN + IF ((Latency_code = 3 AND dummy_cnt=1) OR + (Latency_code = 0 AND dummy_cnt=2) OR + (Latency_code = 1 AND dummy_cnt=4) OR + (Latency_code = 2 AND dummy_cnt=5)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + ELSE + IF ((Latency_code = 3 AND dummy_cnt = 4) OR + (Latency_code = 0 AND dummy_cnt = 5) OR + (Latency_code = 1 AND dummy_cnt = 6) OR + (Latency_code = 2 AND dummy_cnt = 7)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF Instruct=RES THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF dummy_cnt = 3*BYTE THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct = DIOR OR Instruct = DIOR4) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1') THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF EHP THEN + IF ((Latency_code = 1 AND dummy_cnt = 1) OR + (Latency_code = 2 AND dummy_cnt = 2)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + ELSE + IF ((Latency_code = 3 AND dummy_cnt = 4) OR + (Latency_code = 0 AND dummy_cnt = 4) OR + (Latency_code = 1 AND dummy_cnt = 5) OR + (Latency_code = 2 AND dummy_cnt = 6)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF EHP THEN + IF ((Latency_code = 3 AND dummy_cnt = 2) OR + (Latency_code = 0 AND dummy_cnt = 4) OR + (Latency_code = 1 AND dummy_cnt = 5) OR + (Latency_code = 2 AND dummy_cnt = 6)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + ELSE + IF ((Latency_code = 3 AND dummy_cnt = 4) OR + (Latency_code = 0 AND dummy_cnt = 6) OR + (Latency_code = 1 AND dummy_cnt = 7) OR + (Latency_code = 2 AND dummy_cnt = 8)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF ((Instruct = QIOR OR Instruct = QIOR4) AND + QUAD = '1') THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF ((Latency_code = 3 AND dummy_cnt = 1) OR + (Latency_code = 0 AND dummy_cnt = 4) OR + (Latency_code = 1 AND dummy_cnt = 4) OR + (Latency_code = 2 AND dummy_cnt = 5)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct = DDRQIOR OR Instruct = DDRQIOR4) + AND QUAD = '1' THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF ((Latency_code = 3 AND dummy_cnt = 3) OR + (Latency_code = 0 AND dummy_cnt = 6) OR + (Latency_code = 1 AND dummy_cnt = 7) OR + (Latency_code = 2 AND dummy_cnt = 8)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF falling_edge(SCK_ipd) THEN + IF NOT(hold_mode) THEN + IF (DOUBLE AND VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + + WHEN DATA_BYTES => + IF rising_edge(CSNeg_ipd) THEN + IF ((mode_bytes(7 downto 4) = "1010" AND + (Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QIOR OR Instruct = QIOR4)) OR + ((mode_bytes(7 downto 4) = + NOT(mode_bytes(3 downto 0))) AND + (Instruct = DDRFR OR Instruct = DDRFR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 OR + Instruct = DDRQIOR OR Instruct = DDRQIOR4))) THEN + bus_cycle_state := ADDRESS_BYTES; + ELSE + bus_cycle_state := STAND_BY; + END IF; + END IF; + IF falling_edge(SCK_ipd) AND CSNeg_ipd = '0' AND + NOT(DOUBLE) THEN + IF ((Instruct = READ OR Instruct=RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = RDSR OR Instruct = RDSR2 OR + Instruct = RDCR OR Instruct = OTPR OR + Instruct = DOR OR Instruct = DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = ABRD OR Instruct = BRRD OR + Instruct = ASPRD OR Instruct = DYBRD OR + Instruct = PPBRD OR + Instruct = PASSRD OR Instruct = RDID OR + Instruct = RES OR Instruct = REMS OR + Instruct = PLBRD OR Instruct = DLPRD) + AND ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) + OR (current_state = AUTOBOOT AND start_delay = 0)OR + ((Instruct=QOR OR Instruct=QIOR OR Instruct=QOR4 + OR Instruct= QIOR4) AND QUAD = '1') THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + ELSIF SCK_ipd'EVENT AND CSNeg_ipd = '0' AND DOUBLE THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + + IF rising_edge(SCK_ipd) THEN + IF QUAD = '1' AND (Instruct=QPP OR Instruct = QPP4)THEN + quad_nybble := HOLDNegIn & WPNegIn & SOIn & SIIn; + IF data_cnt > (PageSize*2-1) THEN + --In case of quad mode and QPP, + --if more than 512 bytes are sent to the device + FOR I IN 0 TO (PageSize*2-2) LOOP + quad_data_in(i) := quad_data_in(i+1); + END LOOP; + quad_data_in((PageSize*2-1)) := + to_nat(quad_nybble); + data_cnt := data_cnt +1; + ELSE + IF quad_nybble /= "ZZZZ" THEN + quad_data_in(data_cnt) := + to_nat(quad_nybble); + END IF; + data_cnt := data_cnt +1; + END IF; + ELSIF ((HOLDNeg_pullup='1' AND QUAD='0') + OR QUAD='1') THEN + IF data_cnt > (PageSize*8-1) THEN + --In case of serial mode and PP, + -- if more than 512 bytes are sent to the device + -- previously latched data are discarded and last + -- 512 data bytes are guaranteed to be programmed + -- correctly within the same page. + IF bit_cnt = 0 THEN + FOR I IN 0 TO ((PageSize-1)*BYTE - 1) LOOP + Data_in(i) := Data_in(i+8); + END LOOP; + END IF; + Data_in((PageSize-1)*BYTE + bit_cnt) := SIIn; + bit_cnt := bit_cnt + 1; + IF bit_cnt = 8 THEN + bit_cnt := 0; + END IF; + data_cnt := data_cnt + 1; + ELSE + Data_in(data_cnt) := SIIn; + data_cnt := data_cnt + 1; + bit_cnt := 0; + END IF; + END IF; + END IF; + + IF rising_edge(CSNeg_ipd) THEN + CASE Instruct IS + WHEN WREN | WRDI | BE | SE | SE4 | CLSR | RESET | + PPBP | PPBERS | PGSP | PGRS | ERSP | BRAC | + ERRS | P4E | P4E4 | PLBWR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') + OR QUAD='1') THEN + IF data_cnt = 0 THEN + write <= '0'; + END IF; + END IF; + + WHEN WRR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') + OR QUAD='1') THEN + IF ((data_cnt mod 8) = 0 AND data_cnt > 0) THEN + IF data_cnt = 8 THEN + --If CS# is driven high after eight + --cycle,only the Status Register is + --written to. + write <= '0'; + FOR i IN 0 TO 7 LOOP + Status_reg1_in(i) <= Data_in(7-i); + END LOOP; + ELSIF data_cnt = 16 THEN + --After the 16th cycle both the + --Status and Configuration Registers + --are written to. + write <= '0'; + cfg_write <= '1'; + FOR i IN 0 TO 7 LOOP + Status_reg1_in(i) <= Data_in(7-i); + Config_reg1_in(i) <= Data_in(15-i); + END LOOP; + END IF; + END IF; + END IF; + + WHEN PP | PP4 | OTPP => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt > 0 THEN + IF (data_cnt mod 8) = 0 THEN + write <= '0'; + FOR I IN 0 TO (PageSize-1) LOOP + FOR J IN 7 DOWNTO 0 LOOP + IF Data_in((i*8) + (7-j)) + /= 'X' THEN + Byte_slv(j) := + Data_in((i*8) + (7-j)); + END IF; + END LOOP; + WByte(i) <= + to_nat(Byte_slv); + END LOOP; + IF data_cnt > PageSize*BYTE THEN + Byte_number <= PageSize-1; + ELSE + Byte_number <= data_cnt/8-1; + END IF; + END IF; + END IF; + END IF; + + WHEN QPP | QPP4=> + IF data_cnt > 0 THEN + IF data_cnt mod 2 = 0 THEN + quadpg <= FALSE; + write <= '0'; + FOR I IN 0 TO (PageSize-1) LOOP + FOR J IN 1 DOWNTO 0 LOOP + Quad_slv := + to_slv(quad_data_in((i*2) + + (1-j)),4); + + Byte_slv(4*j+3 DOWNTO 4*j) := + Quad_slv; + END LOOP; + WByte(i) <= to_nat(Byte_slv); + END LOOP; + IF data_cnt > PageSize*2 THEN + Byte_number <= PageSize-1; + ELSE + Byte_number <= data_cnt/2-1; + END IF; + END IF; + END IF; + + WHEN ABWR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 32 THEN + write <= '0'; + FOR J IN 0 TO 31 LOOP + AutoBoot_reg_in(J) <= + Data_in(31-J); + END LOOP; + END IF; + END IF; + + WHEN BRWR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 8 THEN + write <= '0'; + FOR J IN 0 TO 7 LOOP + Bank_Addr_reg_in(J) <= + Data_in(7-J); + END LOOP; + END IF; + END IF; + + WHEN ASPP => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 16 THEN + write <= '0'; + FOR J IN 0 TO 15 LOOP + ASP_reg_in(J) <= + Data_in(15-J); + END LOOP; + END IF; + END IF; + + WHEN DYBWR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 8 THEN + write <= '0'; + FOR J IN 0 TO 7 LOOP + DYBAR_in(J) <= + Data_in(7-J); + END LOOP; + END IF; + END IF; + + WHEN PNVDLR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 8 THEN + write <= '0'; + FOR J IN 0 TO 7 LOOP + NVDLR_reg_in(J) <= Data_in(7-J); + END LOOP; + END IF; + END IF; + + WHEN WVDLR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 8 THEN + write <= '0'; + FOR J IN 0 TO 7 LOOP + VDLR_reg_in(J) <= Data_in(7-J); + END LOOP; + END IF; + END IF; + + WHEN PASSP => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 64 THEN + write <= '0'; + FOR J IN 1 TO 8 LOOP + FOR K IN 1 TO 8 LOOP + Password_reg_in(J*8-K) <= + Data_in(8*(J-1)+K-1); + END LOOP; + END LOOP; + END IF; + END IF; + + WHEN PASSU => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 64 THEN + write <= '0'; + FOR J IN 1 TO 8 LOOP + FOR K IN 1 TO 8 LOOP + PASS_TEMP(J*8-K) <= + Data_in(8*(J-1)+K-1); + END LOOP; + END LOOP; + END IF; + END IF; + + WHEN others => + null; + + END CASE; + END IF; + END CASE; + END IF; + + END PROCESS BusCycleDecode; + + --------------------------------------------------------------------------- + -- Timing control for the Page Program + --------------------------------------------------------------------------- + ProgTime : PROCESS(PSTART, PGSUSP, PGRES, RST, Reseted) + VARIABLE pob : time; + VARIABLE elapsed : time; + VARIABLE start : time; + VARIABLE duration : time; + BEGIN + IF rising_edge(PSTART) AND PDONE = '1' THEN + IF Instruct = PP OR Instruct = PP4 OR Instruct = OTPP OR + Instruct = QPP OR Instruct = QPP4 THEN + IF PageSize = 256 THEN + pob := tdevice_PP256; + ELSE + pob := tdevice_PP512; + END IF; + ELSE + pob := tdevice_BP; + END IF; + elapsed := 0 ns; + start := NOW; + PDONE <= '0', '1' AFTER pob; + ELSIF PGSUSP'EVENT AND PGSUSP = '1' AND PDONE /= '1' THEN + elapsed := NOW - start; + duration := pob - elapsed; + PDONE <= '0'; + ELSIF PGRES'EVENT AND PGRES = '1' AND PDONE /= '1'THEN + start := NOW; + PDONE <= '0', '1' AFTER duration; + END IF; + + IF (RST'EVENT AND RST = '0') THEN + PDONE <= '1'; -- reset done, programing terminated + ELSIF rising_edge(Reseted) THEN + PDONE <= '1'; -- reset done, programing terminated + END IF; + + END PROCESS ProgTime; + + --------------------------------------------------------------------------- + -- Timing control for the Write Status Register + --------------------------------------------------------------------------- + WriteTime : PROCESS(WSTART) + VARIABLE wob : time; + BEGIN + IF LongTimming THEN + wob := tdevice_WRR; + ELSE + wob := tdevice_WRR / 100; + END IF; + IF rising_edge(WSTART) AND WDONE = '1' THEN + WDONE <= '0', '1' AFTER wob; + END IF; + + IF (RST'EVENT AND RST = '0') THEN + WDONE <= '1'; -- reset done, programing terminated + ELSIF rising_edge(Reseted) THEN + WDONE <= '1'; -- reset done, programing terminated + END IF; + + END PROCESS WriteTime; + + --------------------------------------------------------------------------- + -- Timing control for the Bulk Erase + --------------------------------------------------------------------------- + ErsTime : PROCESS(ESTART, ESUSP, ERES, RST, Reseted) + VARIABLE seo : time; + VARIABLE beo : time; + VARIABLE elapsed : time; + VARIABLE start : time; + VARIABLE duration : time; + BEGIN + IF LongTimming THEN + IF UniformSec THEN + seo := tdevice_SE256; + ELSE + seo := tdevice_SE64; + END IF; + beo := tdevice_BE; + ELSE + IF UniformSec THEN + seo := tdevice_SE256 / 1000; + ELSE + seo := tdevice_SE64 / 100; + END IF; + beo := tdevice_BE / 1000; + END IF; + IF rising_edge(ESTART) AND EDONE = '1' THEN + IF Instruct = BE THEN + duration := beo; + ELSE --Instruct = SE OR SE4 OR P4E OR P4E4 + duration := seo; + END IF; + elapsed := 0 ns; + EDONE <= '0', '1' AFTER duration; + start := NOW; + ELSIF ESUSP'EVENT AND ESUSP = '1' AND EDONE /= '1' THEN + elapsed := NOW - start; + duration := duration - elapsed; + EDONE <= '0'; + ELSIF ERES'EVENT AND ERES = '1' AND EDONE /= '1' THEN + start := NOW; + EDONE <= '0', '1' AFTER duration; + END IF; + + IF (RST'EVENT AND RST = '0') THEN + EDONE <= '1'; -- reset done, eras terminated + ELSIF rising_edge(Reseted) THEN + EDONE <= '1'; -- reset done, erase terminated + END IF; + + END PROCESS ErsTime; + + CheckCEOnPowerUP :PROCESS(CSNeg_ipd) + BEGIN + IF (PoweredUp = '0' AND falling_edge(CSNeg_ipd)) THEN + REPORT InstancePath & partID & + ": Device is selected during Power Up" + SEVERITY WARNING; + END IF; + END PROCESS; + + --------------------------------------------------------------------------- + -- Main Behavior Process + -- combinational process for next state generation + --------------------------------------------------------------------------- + StateGen :PROCESS(PoweredUp, write, CSNeg_ipd, RSTNeg_pullup, WDONE, PDONE, + ERSSUSP_out, PRGSUSP_out, EDONE, RST_out, PPBERASE_in, + PASSULCK_in) + + VARIABLE sect : NATURAL RANGE 0 TO SecNum64; + + BEGIN + + IF rising_edge(PoweredUp) THEN + IF ABE = '1' AND RPME /= '0' THEN + --Autoboot is enabled and The Read Password feature is not enabled + next_state <= AUTOBOOT; + read_cnt := 0; + byte_cnt := 1; + read_addr := to_nat(AutoBoot_reg(31 DOWNTO 9)&"000000000"); + start_delay := to_nat(AutoBoot_reg(8 DOWNTO 1)); + ABSD := to_nat(AutoBoot_reg(8 DOWNTO 1)); + ELSE + next_state <= IDLE; + END IF; + ELSE + IF RST_out= '0' then + next_state <= current_state; + ELSIF falling_edge(write) AND Instruct = RESET THEN + IF ABE = '1' AND RPME /= '0' THEN + read_cnt := 0; + byte_cnt := 1; + read_addr := to_nat(AutoBoot_reg(31 DOWNTO 9)& + "000000000"); + start_delay:= to_nat(AutoBoot_reg(8 DOWNTO 1)); + ABSD := to_nat(AutoBoot_reg(8 DOWNTO 1)); + next_state <= AUTOBOOT; + ELSE + next_state <= IDLE; + END IF; + ELSE + CASE current_state IS + WHEN RESET_STATE => + IF rising_edge(RST_out) THEN + IF ABE = '1' AND RPME /= '0' + AND RdPswdProtMode = '0' THEN + next_state <= AUTOBOOT; + read_cnt := 0; + byte_cnt := 1; + read_addr := to_nat(AutoBoot_reg(31 DOWNTO 9)& + "000000000"); + start_delay := to_nat(AutoBoot_reg(8 DOWNTO 1)); + ABSD := to_nat(AutoBoot_reg(8 DOWNTO 1)); + ELSE + next_state <= IDLE; + END IF; + END IF; + + WHEN IDLE => + IF falling_edge(write) AND RdPswdProtMode = '0' THEN + + IF (Instruct = WRR AND WEL = '1' AND BAR_ACC = '0') THEN + IF ((not(SRWD = '1' AND WPNeg_pullup = '0') AND + QUAD = '0') OR QUAD = '1') THEN + -- can not execute if HPM is entered + -- or if WEL bit is zero + IF ((TBPROT='1' AND Config_reg1_in(5)='0') OR + (TBPARM='1' AND Config_reg1_in(2)='0') OR + (BPNV ='1' AND Config_reg1_in(3)='0')) AND + cfg_write = '1' THEN + ASSERT cfg_write = '0' + REPORT "Changing value of Configuration " & + "Register OTP bit from 1 to 0 is " & + "not allowed!!!" + SEVERITY WARNING; + ELSE + next_state <= WRITE_SR; + END IF; + END IF; + ELSIF (Instruct = WRR AND BAR_ACC = '1') THEN + -- Write to the lower address bits of the BAR + IF (P_ERR = '0' AND E_ERR = '0')THEN + REPORT "WARNING: Changing values of " & + "Bank Address Register RFU bits" & + " are not allowed!!!" + SEVERITY WARNING; + END IF; + ELSIF (Instruct = PP OR Instruct = QPP OR + Instruct = PP4 OR Instruct = QPP4) AND + WEL = '1' THEN + ReturnSectorID(sect,Address); + pgm_page := Address/(PageSize+1); + IF (Sec_Prot(sect) = '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + next_state <= PAGE_PG; + END IF; + ELSIF Instruct=OTPP AND WEL = '1' AND FREEZE = '0' THEN + IF ((((Address >= 16#10# AND Address <= 16#13#) OR + (Address >= 16#20# AND Address <= 16#FF#)) + AND LOCK_BYTE1(Address/32) = '1') OR + ((Address >= 16#100# AND Address <= 16#1FF#) + AND LOCK_BYTE2((Address-16#100#)/32) = '1') OR + ((Address >= 16#200# AND Address <= 16#2FF#) + AND LOCK_BYTE3((Address-16#200#)/32) = '1') OR + ((Address >= 16#300# AND Address <= 16#3FF#) + AND LOCK_BYTE4((Address-16#300#)/32) = '1')) AND + (Address + Byte_number <= OTPHiAddr) THEN + next_state <= OTP_PG; + END IF; + ELSIF (Instruct= SE OR Instruct= SE4) AND WEL= '1' THEN + ReturnSectorID(sect,Address); + IF UniformSec = TRUE OR + (TopBoot = TRUE AND sect < 254) OR + (BottomBoot = TRUE AND sect > 31) THEN + IF (Sec_Prot(sect) = '0' AND PPB_bits(sect)='1' + AND DYB_bits(sect)='1') THEN + next_state <= SECTOR_ERS; + END IF; + ELSIF (TopBoot = TRUE AND sect >= 254) OR + (BottomBoot = TRUE AND sect <= 31) THEN + IF Sec_ProtSE = 32 AND ASP_ProtSE = 32 THEN + --Sector erase command is applied to a 64 KB + --range that includes 4 KB sectors. + next_state <= SECTOR_ERS; + END IF; + END IF; + ELSIF (Instruct=P4E OR Instruct=P4E4) AND WEL='1' THEN + ReturnSectorID(sect,Address); + IF UniformSec = TRUE OR + (TopBoot = TRUE AND sect < 254) OR + (BottomBoot = TRUE AND sect > 31) THEN + --A P4E instruction applied to a sector that + --is larger than 4 KB will not be executed + --and will not set the E_ERR status. + REPORT "The instruction is applied to a "& + "sector that is larger than 4 KB. "& + "Instruction is ignored!!!" + SEVERITY warning; + ELSE + IF Sec_Prot(sect) = '0' AND PPB_bits(sect)='1' + AND DYB_bits(sect)='1' THEN + next_state <= SECTOR_ERS; + END IF; + END IF; + ELSIF Instruct = BE AND WEL = '1' AND + (BP0='0' AND BP1='0' AND BP2='0') THEN + next_state <= BULK_ERS; + ELSIF Instruct = ABWR AND WEL = '1' THEN + --Autoboot Register Write Command + next_state <= AUTOBOOT_PG; + ELSIF Instruct = BRWR THEN + --Bank Register Write Command + next_state <= IDLE; + ELSIF Instruct = ASPP AND WEL = '1' THEN + --ASP Register Program Command + IF not(ASPOTPFLAG) THEN + next_state <= ASP_PG; + END IF; + ELSIF Instruct = PLBWR AND WEL = '1' AND + RdPswdProtEnable = '0' THEN + next_state <= PLB_PG; + ELSIF Instruct = PASSP AND WEL = '1' THEN + IF not(PWDMLB='0' AND PSTMLB='1') THEN + next_state <= PASS_PG; + END IF; + ELSIF Instruct = PASSU AND WEL= '1' AND WIP= '0' THEN + next_state <= PASS_UNLOCK; + ELSIF Instruct = PPBP AND WEL = '1' THEN + next_state <= PPB_PG; + ELSIF (Instruct=PPBERS AND WEL='1' AND PPBOTP='1') THEN + next_state <= PPB_ERS; + ELSIF Instruct = DYBWR AND WEL = '1' THEN + next_state <= DYB_PG; + ELSIF Instruct = PNVDLR AND WEL = '1' THEN + next_state <= NVDLR_PG; + ELSE + next_state <= IDLE; + END IF; + END IF; + IF falling_edge(write) AND RdPswdProtMode = '1' AND + WIP = '0' THEN + IF Instruct = PASSU THEN + next_state <= PASS_UNLOCK; + END IF; + END IF; + + WHEN AUTOBOOT => + IF rising_edge(CSNeg_ipd) THEN + next_state <= IDLE; + END IF; + + WHEN WRITE_SR => + IF rising_edge(WDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PAGE_PG => + IF PRGSUSP_out'EVENT AND PRGSUSP_out = '1' THEN + next_state <= PG_SUSP; + ELSIF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PG_SUSP => + IF falling_edge(write) THEN + IF Instruct = BRWR THEN + next_state <= PG_SUSP; + ELSIF Instruct = PGRS THEN + next_state <= PAGE_PG; + END IF; + ELSE + next_state <= PG_SUSP; + END IF; + + WHEN OTP_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN BULK_ERS => + IF rising_edge(EDONE) THEN + next_state <= IDLE; + END IF; + + WHEN SECTOR_ERS => + IF ERSSUSP_out'EVENT AND ERSSUSP_out = '1' THEN + next_state <= ERS_SUSP; + ELSIF rising_edge(EDONE) THEN + next_state <= IDLE; + END IF; + + WHEN ERS_SUSP => + IF falling_edge(write) THEN + IF (Instruct = PP OR Instruct = QPP OR + Instruct = PP4 OR Instruct = QPP4) AND + WEL = '1' THEN + IF (PARAM_REGION = TRUE AND + SectorSuspend /= Address/(SecSize+1)) OR + (PARAM_REGION = FALSE AND + SectorSuspend/=Address/(SecSize+1)+30*b_act) THEN + ReturnSectorID(sect,Address); + pgm_page := Address / (PageSize+1); + IF PPB_bits(sect)='1' AND + DYB_bits(sect)='1' THEN + next_state <= ERS_SUSP_PG; + END IF; + END IF; + ELSIF Instruct = BRWR THEN + next_state <= ERS_SUSP; + ELSIF (Instruct = DYBWR AND WEL = '1') THEN + next_state <= DYB_PG; + ELSIF Instruct = ERRS THEN + next_state <= SECTOR_ERS; + END IF; + ELSE + next_state <= ERS_SUSP; + END IF; + + WHEN ERS_SUSP_PG => + IF PRGSUSP_out'EVENT AND PRGSUSP_out = '1' THEN + next_state <= ERS_SUSP_PG_SUSP; + ELSIF rising_edge(PDONE) THEN + next_state <= ERS_SUSP; + END IF; + + WHEN ERS_SUSP_PG_SUSP => + IF falling_edge(write) THEN + IF Instruct = BRWR THEN + next_state <= ERS_SUSP_PG_SUSP; + ELSIF Instruct = PGRS THEN + next_state <= ERS_SUSP_PG; + END IF; + ELSE + next_state <= ERS_SUSP_PG_SUSP; + END IF; + + WHEN PASS_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PASS_UNLOCK => + IF falling_edge(PASSULCK_in) THEN + next_state <= IDLE; + END IF; + + WHEN PPB_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PPB_ERS => + IF falling_edge(PPBERASE_in) THEN + next_state <= IDLE; + END IF; + + WHEN AUTOBOOT_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PLB_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN DYB_PG => + IF rising_edge(PDONE) THEN + IF ES = '1' THEN + next_state <= ERS_SUSP; + ELSE + next_state <= IDLE; + END IF; + END IF; + + WHEN ASP_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN NVDLR_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + END CASE; + END IF; + END IF; + + END PROCESS StateGen; + + ReadEnable: PROCESS (read_out) + BEGIN + oe_z <= rising_edge(read_out) AND PoweredUp = '1'; + + IF read_out'EVENT AND read_out = '0' AND PoweredUp = '1' THEN + oe <= TRUE, FALSE AFTER 1 ns; + END IF; + END PROCESS ReadEnable; + --------------------------------------------------------------------------- + --FSM Output generation and general funcionality + --------------------------------------------------------------------------- + Functional : PROCESS(write,current_state,start_autoboot,CSNeg_ipd, + HOLDNeg_pullup, Instruct, Address, WByte,change_addr, + PoweredUp, WPNeg_pullup, WDONE, PDONE, EDONE, + PRGSUSP_out,ERSSUSP_out, PASSACC_out, oe, oe_z) + + VARIABLE WData : WByteType:= (OTHERS => MaxData); + + VARIABLE AddrLo : NATURAL; + VARIABLE AddrHi : NATURAL; + VARIABLE Addr : NATURAL; + VARIABLE Addr_tmp : NATURAL; + + VARIABLE data_out : std_logic_vector(7 downto 0); + VARIABLE ident_out : std_logic_vector(647 downto 0); + + VARIABLE ExtendedID : NATURAL; + + VARIABLE old_bit : std_logic_vector(7 downto 0); + VARIABLE new_bit : std_logic_vector(7 downto 0); + VARIABLE old_int : INTEGER RANGE -1 to MaxData; + VARIABLE new_int : INTEGER RANGE -1 to MaxData; + VARIABLE old_pass : std_logic_vector(63 downto 0); + VARIABLE new_pass : std_logic_vector(63 downto 0); + VARIABLE wr_cnt : NATURAL RANGE 0 TO 511; + --Data Learning Pattern Enable + VARIABLE dlp_act : BOOLEAN := FALSE; + + VARIABLE sect : NATURAL RANGE 0 TO SecNum64; + VARIABLE cnt : NATURAL RANGE 0 TO 512 := 0; + + VARIABLE sec_tmp : NATURAL RANGE 0 TO SecNum64; + + BEGIN + + ----------------------------------------------------------------------- + -- Functionality Section + ----------------------------------------------------------------------- + + IF Instruct'EVENT THEN + read_cnt := 0; + byte_cnt := 1; + fast_rd <= true; + dual <= false; + rd <= false; + any_read <= false; + END IF; + + IF PASSACC_out'EVENT AND PASSACC_out = '1' THEN + WIP := '0'; + PASSACC_in <= '0'; + END IF; + + IF rising_edge(PoweredUp) THEN + --the default condition after power-up + --The Bank Address Register is loaded to all zeroes + Bank_Addr_reg := (others => '0'); + --The Configuration Register FREEZE bit is cleared. + FREEZE := '0'; + --The WEL bit is cleared. + WEL := '0'; + --When BPNV is set to '1'. the BP2-0 bits in Status Register are + --volatile and will be reset binary 111 after power-on reset + IF BPNV = '1' AND LOCK='0' AND FREEZE = '0' THEN + BP0 := '1'; + BP1 := '1'; + BP2 := '1'; + BP_bits := BP2 & BP1 & BP0; + change_BP <= '1', '0' AFTER 1 ns; + END IF; + --As shipped from the factory, all devices default ASP to the + --Persistent Protection mode, with all sectors unprotected, + --when power is applied. The device programmer or host system must + --then choose which sector protection method to use. + --For Persistent Protection mode, PPBLOCK defaults to "1" + PPB_LOCK := '1'; + PPB_LOCK_temp <= '1'; + DYB_bits := (OTHERS => '1'); + + END IF; + + IF falling_edge(write) AND Instruct = RESET THEN + --The Configuration Register is set for Address mode + Bank_Addr_reg := (others => '0'); + --P_ERR bit is cleared + P_ERR := '0'; + --E_ERR bit is cleared + E_ERR := '0'; + --The WEL bit is cleared. + WEL := '0'; + --The WIP bit is cleared. + WIP := '0'; + --The ES bit is cleared. + ES := '0'; + --The PS bit is cleared. + PS := '0'; + + DummyBytes_act := '0'; + --When BPNV is set to '1'. the BP2-0 bits in Status + --Register are volatile and will be reseted after + --reset command + IF BPNV = '1' AND LOCK='0' AND FREEZE = '0' THEN + BP0 := '1'; + BP1 := '1'; + BP2 := '1'; + BP_bits := BP2 & BP1 & BP0; + change_BP <= '1', '0' AFTER 1 ns; + END IF; + END IF; + + IF change_addr'EVENT THEN + read_addr := Address; + END IF; + + CASE current_state IS + WHEN IDLE => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + ASP_ProtSE := 0; + Sec_ProtSE := 0; + PARAM_REGION := false; + IF falling_edge(write) AND RdPswdProtMode = '1' THEN + IF Instruct = PASSU THEN + IF WIP = '0' THEN + PASSULCK_in <= '1'; + ELSE + REPORT "The PASSU command cannot be accepted"& + " any faster than once every 100us" + SEVERITY WARNING; + END IF; + ELSIF Instruct = CLSR THEN + --The Clear Status Register Command resets bit SR1[5] + --(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + E_ERR := '0'; + P_ERR := '0'; + END IF; + END IF; + IF BottomBoot = TRUE THEN + FOR J IN 31 DOWNTO 0 LOOP + IF (PPB_bits(J)='1' AND DYB_bits(J)='1') THEN + ASP_ProtSE := ASP_ProtSE + 1; + END IF; + IF (Sec_Prot(J)='0') THEN + Sec_ProtSE := Sec_ProtSE + 1; + END IF; + END LOOP; + ELSIF TopBoot = TRUE THEN + FOR J IN 285 DOWNTO 254 LOOP + IF (PPB_bits(J)='1' AND DYB_bits(J)='1') THEN + ASP_ProtSE := ASP_ProtSE + 1; + END IF; + IF (Sec_Prot(J)='0') THEN + Sec_ProtSE := Sec_ProtSE + 1; + END IF; + END LOOP; + END IF; + IF falling_edge(write) AND RdPswdProtMode = '0' THEN + read_cnt := 0; + byte_cnt := 1; + IF Instruct = WREN THEN + WEL := '1'; + ELSIF Instruct = WRDI THEN + WEL := '0'; + ELSIF Instruct = WRR AND WEL = '1' AND BAR_ACC = '0' THEN + IF (not(SRWD = '1' AND WPNeg_pullup = '0') AND + QUAD ='0') OR QUAD ='1' THEN + -- can not execute if Hardware Protection Mode + -- is entered or if WEL bit is zero + + IF ((TBPROT='1' AND Config_reg1_in(5)='0') OR + (TBPARM='1' AND Config_reg1_in(2)='0') OR + (BPNV ='1' AND Config_reg1_in(3)='0')) AND + cfg_write = '1' THEN + P_ERR := '1'; + ELSE + WSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + END IF; + ELSE + WEL := '0'; + END IF; + ELSIF (Instruct = PP OR Instruct = PP4) AND WEL = '1' THEN + ReturnSectorID(sect,Address); + Addr := Address; + IF (Sec_Prot(sect) = '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + SA <= sect; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + P_ERR := '1'; + WEL := '0'; + END IF; + ELSIF (Instruct = QPP OR Instruct = QPP4) AND WEL = '1' THEN + ReturnSectorID(sect,Address); + Addr := Address; + pgm_page := Address/(PageSize+1); + IF (Sec_Prot(sect)= '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + SA <= sect; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + P_ERR := '1'; + WEL := '0'; + END IF; + ELSIF Instruct = OTPP AND WEL = '1' THEN + -- As long as the FREEZE bit remains cleared to a logic '0' + --the OTP address space is programmable. + IF FREEZE = '0' THEN + IF ((((Address >= 16#0010# AND Address <= 16#13#)OR + (Address >= 16#0020# AND Address <= 16#FF#)) + AND LOCK_BYTE1(Address/32) = '1') OR + ((Address >= 16#100# AND Address <= 16#1FF#) + AND LOCK_BYTE2((Address-16#100#)/32) = '1') OR + ((Address >= 16#200# AND Address <= 16#2FF#) + AND LOCK_BYTE3((Address-16#200#)/32) = '1') OR + ((Address >= 16#300# AND Address <= 16#3FF#) + AND LOCK_BYTE4((Address-16#300#)/32) = '1')) AND + (Address + Byte_number <= OTPHiAddr) THEN + PSTART <= '1', '0' AFTER 1 ns; + WIP := '1'; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSIF (Address < 16#0010# OR (Address > 16#0013# AND + Address < 16#0020#) OR Address > 16#3FF# ) THEN + P_ERR := '1'; + WEL := '0'; + IF Address < 16#0020# THEN + ASSERT false + REPORT "Given address is in" & + "reserved address range" + SEVERITY warning; + ELSIF Address > 16#3FF# THEN + ASSERT false + REPORT "Given address is out of" & + "OTP address range" + SEVERITY warning; + END IF; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSIF (Instruct = SE OR Instruct = SE4) AND WEL = '1' THEN + ReturnSectorID(sect,Address); + IF UniformSec = TRUE OR + (TopBoot = TRUE AND sect < 254) OR + (BottomBoot = TRUE AND sect > 31) THEN + SectorSuspend <= sect; + PARAM_REGION := FALSE; + IF (Sec_Prot(sect) = '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + Addr := Address; + ELSE + E_ERR := '1'; + WEL := '0'; + END IF; + ELSIF (TopBoot = TRUE AND sect >= 254) OR + (BottomBoot = TRUE AND sect <= 31) THEN + IF Sec_ProtSE = 32 AND ASP_ProtSE = 32 THEN + --Sector erase command is applied to a 64 KB range + --that includes 4 KB sectors + IF TopBoot = TRUE THEN + SectorSuspend <= 254 + (285 - sect)/16; + ELSE + SectorSuspend <= sect/16; + END IF; + PARAM_REGION := TRUE; + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + Addr := Address; + ELSE + E_ERR := '1'; + WEL := '0'; + END IF; + END IF; + ELSIF (Instruct = P4E OR Instruct = P4E4) AND WEL = '1' THEN + ReturnSectorID(sect,Address); + IF UniformSec = TRUE OR + (TopBoot = TRUE AND sect < 254) OR + (BottomBoot = TRUE AND sect > 31) THEN + WEL := '0'; + ELSE + IF (Sec_Prot(sect) = '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + --A P4E instruction applied to a sector + --that has been Write Protected through the + --Block Protect Bits or ASP will not be + --executed and will set the E_ERR status + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + Addr := Address; + ELSE + E_ERR := '1'; + WEL := '0'; + END IF; + END IF; + ELSIF Instruct = BE AND WEL = '1' THEN + IF (BP0='0' AND BP1='0' AND BP2='0') THEN + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + ELSE + --The Bulk Erase command will not set E_ERR if a + --protected sector is found during the command + --execution. + WEL := '0'; + END IF; + ELSIF Instruct = PASSP AND WEL = '1' THEN + IF not(PWDMLB='0' AND PSTMLB='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSE + REPORT "Password programming is not allowed" & + " in Password Protection Mode." + SEVERITY warning; + END IF; + ELSIF Instruct = PASSU AND WEL = '1' THEN + PASSULCK_in <= '1'; + ELSIF Instruct = BRWR THEN + Bank_Addr_reg(7) := Bank_Addr_reg_in(7); + ELSIF Instruct = ASPP AND WEL = '1' THEN + IF not(ASPOTPFLAG) THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSE + WEL := '0'; + P_ERR := '1'; + REPORT "Once the Protection Mode is selected," & + "no further changes to the ASP register" & + "is allowed." + SEVERITY warning; + END IF; + ELSIF Instruct = ABWR AND WEL = '1' THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = PPBP AND WEL = '1' THEN + ReturnSectorID(sect,Address); + Addr := Address; + pgm_page := Address/(PageSize+1); + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = PPBERS AND WEL = '1' THEN + IF PPBOTP = '1' THEN + PPBERASE_in <= '1'; + WIP := '1'; + ELSE + E_ERR := '1'; + END IF; + ELSIF Instruct = PLBWR AND WEL = '1' AND + RdPswdProtEnable = '0' THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = DYBWR AND WEL = '1' THEN + ReturnSectorID(sect,Address); + Addr := Address; + pgm_page := Address/(PageSize+1); + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = PNVDLR AND WEL = '1' THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = WVDLR AND WEL = '1' THEN + VDLR_reg := VDLR_reg_in; + WEL := '0'; + ELSIF Instruct = CLSR THEN + --The Clear Status Register Command resets bit SR1[5] + --(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + E_ERR := '0'; + P_ERR := '0'; + END IF; + + IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' THEN + BAR_ACC <= '1'; + ELSE + BAR_ACC <= '0'; + END IF; + ELSIF oe_z THEN + IF Instruct = READ OR Instruct = RD4 OR + Instruct = RES OR Instruct = DLPRD THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSIF Instruct = DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + ELSIF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = READ OR Instruct = RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = DDRFR OR Instruct = DDRFR4 THEN + --Read Memory array + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + IF ((bus_cycle_state = DUMMY_BYTES OR + DummyBytes_act='1') AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct = DDRFR OR Instruct = DDRFR4) THEN + IF EHP THEN + IF Latency_code = 1 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3 OR + Latency_code = 0) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + dlp_act := FALSE; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + read_addr_tmp := read_addr; + SecAddr := read_addr/(SecSize+1); + Sec_addr := read_addr - SecAddr*(SecSize+1); + SecAddr := ReturnSectorIDRdPswdMd(TBPROT); + read_addr := Sec_addr + SecAddr*(SecSize+1); + IF RdPswdProtMode = '0' THEN + read_addr := read_addr_tmp; + END IF; + IF Mem(read_addr) /= -1 THEN + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + ELSE + SOut_zd <= 'U'; + END IF; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct = DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + --Read Memory array + IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct = DDRDIOR OR Instruct = DDRDIOR4) THEN + IF EHP THEN + IF Latency_code = 0 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + read_addr_tmp := read_addr; + SecAddr := read_addr/(SecSize+1); + Sec_addr := read_addr - SecAddr*(SecSize+1); + SecAddr := ReturnSectorIDRdPswdMd(TBPROT); + read_addr := Sec_addr + SecAddr*(SecSize+1); + IF RdPswdProtMode = '0' THEN + read_addr := read_addr_tmp; + END IF; + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF (Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 OR + Instruct = DDRQIOR OR Instruct= DDRQIOR4) + AND QUAD = '1' THEN + --Read Memory array + IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF ((Instruct = DDRQIOR OR Instruct = DDRQIOR4) AND + QUAD = '1') THEN + IF EHP THEN + IF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + read_addr_tmp := read_addr; + SecAddr := read_addr/(SecSize+1); + Sec_addr := read_addr - SecAddr*(SecSize+1); + SecAddr := ReturnSectorIDRdPswdMd(TBPROT); + read_addr := Sec_addr + SecAddr*(SecSize+1); + IF RdPswdProtMode = '0' THEN + read_addr := read_addr_tmp; + END IF; + + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct = OTPR THEN + IF (read_addr>=OTPLoAddr) AND + (read_addr<=OTPHiAddr) AND RdPswdProtMode = '0' THEN + --Read OTP Memory array + fast_rd <= true; + rd <= false; + data_out := to_slv(OTPMem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + ELSIF (read_addr > OTPHiAddr) + OR RdPswdProtMode = '1' THEN + --OTP Read operation will not wrap to the + --starting address after the OTP address is at + --its maximum or Read Password Protection Mode + --is selected; instead, the data beyond the + --maximum OTP address will be undefined. + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF Instruct = REMS THEN + --Read Manufacturer and Device ID + IF read_addr MOD 2 = 0 THEN + data_out := to_slv(Manuf_ID,8); + SOut_zd <= data_out(7 - read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + ELSE + data_out := to_slv(DeviceID,8); + SOut_zd <= data_out(7 - read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := 0; + END IF; + END IF; + ELSIF Instruct = RDID THEN + IF UniformSec THEN + ExtendedID := ExtendedID256; + ELSE + ExtendedID := ExtendedID64; + END IF; + ident_out := CFI_array_tmp; + IF read_cnt < 648 THEN + SOut_zd <= ident_out(647-read_cnt); + read_cnt := read_cnt + 1; + ELSE + --Continued shifting of output beyond the end of + --the defined ID-CFI address space will provide + --undefined data. + SOut_zd <= 'U'; + END IF; + ELSIF Instruct = RES THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + data_out := to_slv(ESignature,8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = DLPRD THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + SOut_zd <= VDLR_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = ABRD THEN + --Read AutoBoot register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= AutoBoot_reg(31-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 32 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = BRRD THEN + --Read Bank Address Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Bank_Addr_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = ASPRD THEN + --Read ASP Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= ASP_reg(15-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 16 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = PASSRD THEN + --Read Password Register + IF not (PWDMLB='0' AND PSTMLB='1') THEN + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Password_reg((8*byte_cnt-1)-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + byte_cnt := byte_cnt + 1; + IF byte_cnt = 9 THEN + byte_cnt := 1; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 64 THEN + read_cnt := 0; + END IF; + IF read_cnt = 0 THEN + ASSERT false + REPORT "Verification of password is not " & + " allowed in Password Protection Mode." + SEVERITY warning; + END IF; + END IF; + ELSIF Instruct = PLBRD THEN + --Read PPB Lock Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= PPBL(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = DYBRD THEN + --Read DYB Access Register + ReturnSectorID(sect,Address); + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + DYBAR(7 downto 0) := "UUUUUUUU"; + IF RdPswdProtMode = '0' THEN + IF DYB_bits(sect) = '1' THEN + DYBAR(7 downto 0) := "11111111"; + ELSE + DYBAR(7 downto 0) := "00000000"; + END IF; + END IF; + SOut_zd <= DYBAR(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = PPBRD THEN + --Read PPB Access Register + ReturnSectorID(sect,Address); + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + PPBAR(7 downto 0) := "UUUUUUUU"; + IF RdPswdProtMode = '0' THEN + IF PPB_bits(sect) = '1' THEN + PPBAR(7 downto 0) := "11111111"; + ELSE + PPBAR(7 downto 0) := "00000000"; + END IF; + END IF; + SOut_zd <= PPBAR(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + + WHEN AUTOBOOT => + IF start_autoboot = '1' THEN + IF (oe) THEN + any_read <= true; + IF QUAD = '1' THEN + IF ABSD > 0 THEN --If ABSD > 0, + fast_rd <= false; --max SCK frequency is 104MHz + rd <= false; + dual <= true; + ddr <= false; + ELSE -- If ABSD = 0, max SCK frequency is 50 MHz + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + END IF; + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + ELSE + IF ABSD > 0 THEN --If ABSD > 0, + fast_rd <= true; --max SCK frequency is 133MHz + rd <= false; + dual <= false; + ddr <= false; + ELSE -- If ABSD = 0, max SCK frequency is 50 MHz + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + END IF; + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + END IF; + ELSIF oe_z THEN + IF QUAD = '1' THEN + IF ABSD > 0 THEN --If ABSD > 0, + fast_rd <= false; --max SCK frequency is 104MHz + rd <= false; + dual <= true; + ddr <= false; + ELSE -- If ABSD = 0, max SCK frequency is 50 MHz + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + END IF; + ELSE + IF ABSD > 0 THEN --If ABSD > 0, + fast_rd <= true; --max SCK frequency is 133MHz + rd <= false; + dual <= false; + ddr <= false; + ELSE -- If ABSD = 0, max SCK frequency is 50 MHz + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + END IF; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + END IF; + + WHEN WRITE_SR => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF WDONE = '1' THEN + WIP := '0'; + WEL := '0'; + SRWD := Status_reg1_in(7);--MSB first + + IF LOCK='0' THEN + IF FREEZE='0' THEN + --The Freeze Bit, when set to 1, locks the current + --state of the BP2-0 bits in Status Register, + --the TBPROT and TBPARM bits in the Config Register + --As long as the FREEZE bit remains cleared to logic + --'0', the other bits of the Configuration register + --including FREEZE are writeable. + BP2 := Status_reg1_in(4); + BP1 := Status_reg1_in(3); + BP0 := Status_reg1_in(2); + + BP_bits := BP2 & BP1 & BP0; + + IF TBPROT = '0' AND INITIAL_CONFIG = '0' THEN + TBPROT := Config_reg1_in(5); + END IF; + + IF (TBPARM = '0' AND INITIAL_CONFIG = '0' AND + TimingModel(16) = '0') THEN + TBPARM := Config_reg1_in(2); + change_TBPARM <= '1', '0' AFTER 1 ns; + END IF; + + change_BP <= '1', '0' AFTER 1 ns; + + LC1 := Config_reg1_in(7); + LC0 := Config_reg1_in(6); + QUAD := Config_reg1_in(1); + + IF FREEZE = '0' THEN + FREEZE := Config_reg1_in(0); + END IF; + + IF WRLOCKENABLE AND LOCK = '0' THEN + LOCK := Config_reg1_in(4); + WRLOCKENABLE <= false; + END IF; + + IF BPNV = '0' THEN + BPNV := Config_reg1_in(3); + END IF; + END IF; + END IF; + END IF; + + WHEN PAGE_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF falling_edge(PDONE) THEN + + ADDRHILO_PG(AddrLo, AddrHi, Addr); + cnt := 0; + + FOR i IN 0 TO wr_cnt LOOP + new_int := WData(i); + old_int := Mem(Addr + i - cnt); + IF new_int > -1 THEN + new_bit := to_slv(new_int,8); + IF old_int > -1 THEN + old_bit := to_slv(old_int,8); + FOR j IN 0 TO 7 LOOP + IF old_bit(j) = '0' THEN + new_bit(j) := '0'; + END IF; + END LOOP; + new_int := to_nat(new_bit); + END IF; + WData(i) := new_int; + ELSE + WData(i) := -1; + END IF; + + Mem(Addr + i - cnt) := -1; + + IF (Addr + i) = AddrHi THEN + Addr := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + cnt :=0; + END IF; + + IF PDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO wr_cnt LOOP + Mem(Addr_tmp + i - cnt) := WData(i); + IF (Addr_tmp + i) = AddrHi THEN + Addr_tmp := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + ELSIF Instruct = PGSP AND PRGSUSP_in = '0' THEN + IF RES_TO_SUSP_MIN_TIME = '0' THEN + PGSUSP <= '1', '0' AFTER 1 ns; + PRGSUSP_in <= '1'; + ASSERT RES_TO_SUSP_TYP_TIME = '0' + REPORT "Typical periods are needed for " & + "Program to progress to completion" + SEVERITY warning; + ELSE + ASSERT FALSE + REPORT "Minimum for tPRS is not satisfied! " & + "PGSP command is ignored" + SEVERITY warning; + END IF; + END IF; + + WHEN PG_SUSP => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF PRGSUSP_out = '1' AND PRGSUSP_in = '1' THEN + PRGSUSP_in <= '0'; + --The RDY/BSY bit in the Status Register will indicate that + --the device is ready for another operation. + WIP := '0'; + --The Program Suspend (PS) bit in the Status Register will + --be set to the logical “1” state to indicate that the + --program operation has been suspended. + PS := '1'; + END IF; + + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = BRRD THEN + --Read Bank Address Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Bank_Addr_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + --Read Array Operations + ELSIF Instruct = READ OR Instruct = RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = DDRFR OR Instruct = DDRFR4 THEN + --Read Memory array + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + + IF pgm_page /= read_addr/(PageSize+1) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRFR OR Instruct=DDRFR4) THEN + IF EHP THEN + IF Latency_code = 1 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3 OR + Latency_code = 0) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:= VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + read_cnt:=read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + --Read Memory array + IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF pgm_page /= read_addr/(PageSize+1) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRDIOR OR Instruct=DDRDIOR4) THEN + IF EHP THEN + IF Latency_code = 0 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency"& + " is set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:=VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + SIOut_zd<=data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF (Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 OR + Instruct = DDRQIOR OR Instruct= DDRQIOR4) + AND QUAD = '1' THEN + --Read Memory array + IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + + IF pgm_page /= read_addr/(PageSize+1) THEN + + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF EHP THEN + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + HOLDNegOut_zd <= 'U'; + WPNegOut_zd <= 'U'; + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + END IF; + ELSIF oe_z THEN + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + ELSIF Instruct = BRWR THEN + Bank_Addr_reg(7) := Bank_Addr_reg_in(7); + ELSIF Instruct = WRR AND BAR_ACC = '1' THEN + -- Write to the lower address bits of the BAR + IF (P_ERR = '0' AND E_ERR = '0')THEN + REPORT "WARNING: Changing values of " & + "Bank Address Register RFU bits" & + " are not allowed!!!" + SEVERITY WARNING; + END IF; + ELSIF Instruct = PGRS THEN + PGRES <= '1', '0' AFTER 5 ns; + PS := '0'; + WIP := '1'; + RES_TO_SUSP_MIN_TIME <= '1', '0' AFTER 60 ns; + RES_TO_SUSP_TYP_TIME <= '1', '0' AFTER 100 us; + END IF; + + IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' AND + RdPswdProtMode = '0' THEN + BAR_ACC <= '1'; + ELSE + BAR_ACC <= '0'; + END IF; + + WHEN ERS_SUSP_PG_SUSP => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF PRGSUSP_out = '1' AND PRGSUSP_in = '1' THEN + PRGSUSP_in <= '0'; + --The RDY/BSY bit in the Status Register will indicate that + --the device is ready for another operation. + WIP := '0'; + --The Program Suspend (PS) bit in the Status Register will + --be set to the logical “1” state to indicate that the + --program operation has been suspended. + PS := '1'; + END IF; + + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = BRRD THEN + --Read Bank Address Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Bank_Addr_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + --Read Array Operations + ELSIF Instruct = READ OR Instruct = RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = DDRFR OR Instruct = DDRFR4 THEN + --Read Memory array + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + + IF (SectorSuspend /= read_addr/(SecSize+1)+30*b_act AND + pgm_page /= read_addr/(PageSize+1)) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + + IF (Instruct=DDRFR OR Instruct=DDRFR4) THEN + IF EHP THEN + IF Latency_code = 1 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3 OR + Latency_code = 0) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:= VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + read_cnt:=read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + --Read Memory array + + IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF (SectorSuspend /= read_addr/(SecSize+1)+30*b_act AND + pgm_page /= read_addr/(PageSize+1)) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + + DummyBytes_act := '0'; + IF (Instruct=DDRDIOR OR Instruct=DDRDIOR4) THEN + IF EHP THEN + IF Latency_code = 0 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency"& + " is set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:=VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + SIOut_zd<=data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF (Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 OR + Instruct = DDRQIOR OR Instruct= DDRQIOR4) + AND QUAD = '1' THEN + + --Read Memory array + IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF (SectorSuspend /= read_addr/(SecSize+1)+30*b_act AND + pgm_page /= read_addr/(PageSize+1)) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF EHP THEN + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + HOLDNegOut_zd <= 'U'; + WPNegOut_zd <= 'U'; + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + END IF; + ELSIF oe_z THEN + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + ELSIF Instruct = BRWR THEN + Bank_Addr_reg(7) := Bank_Addr_reg_in(7); + ELSIF Instruct = WRR AND BAR_ACC = '1' THEN + -- Write to the lower address bits of the BAR + IF (P_ERR = '0' AND E_ERR = '0')THEN + REPORT "WARNING: Changing values of " & + "Bank Address Register RFU bits" & + " are not allowed!!!" + SEVERITY WARNING; + END IF; + ELSIF Instruct = PGRS THEN + PGRES <= '1', '0' AFTER 5 ns; + PS := '0'; + WIP := '1'; + RES_TO_SUSP_MIN_TIME <= '1', '0' AFTER 60 ns; + RES_TO_SUSP_TYP_TIME <= '1', '0' AFTER 100 us; + END IF; + + IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' AND + RdPswdProtMode = '0' THEN + BAR_ACC <= '1'; + ELSE + BAR_ACC <= '0'; + END IF; + + WHEN OTP_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF Address + wr_cnt <= OTPHiAddr THEN + FOR i IN 0 TO wr_cnt LOOP + new_int := WData(i); + old_int := OTPMem(Addr + i); + IF new_int > -1 THEN + new_bit := to_slv(new_int,8); + IF old_int > -1 THEN + old_bit := to_slv(old_int,8); + FOR j IN 0 TO 7 LOOP + IF old_bit(j) = '0' THEN + new_bit(j) := '0'; + END IF; + END LOOP; + new_int := to_nat(new_bit); + END IF; + WData(i) := new_int; + ELSE + WData(i) := -1; + END IF; + + OTPMem(Addr + i) := -1; + END LOOP; + ELSE + ASSERT false + REPORT "Programming will reach over address limit"& + " of OTP array" + SEVERITY warning; + END IF; + + IF PDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO wr_cnt LOOP + OTPMem(Addr_tmp + i) := WData(i); + END LOOP; + LOCK_BYTE1 := to_slv(OTPMem(16#10#),8); + LOCK_BYTE2 := to_slv(OTPMem(16#11#),8); + LOCK_BYTE3 := to_slv(OTPMem(16#12#),8); + LOCK_BYTE4 := to_slv(OTPMem(16#13#),8); + END IF; + + WHEN SECTOR_ERS => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := -1; + END LOOP; + IF EDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := MaxData; + END LOOP; + ELSIF Instruct = ERSP AND ERSSUSP_in = '0' THEN + ESUSP <= '1', '0' AFTER 10 ns; + ERSSUSP_in <= '1'; + ASSERT RES_TO_SUSP_TYP_TIME = '0' + REPORT "Typical periods are needed for " & + "Program to progress to completion" + SEVERITY warning; + END IF; + + WHEN BULK_ERS => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF falling_edge(EDONE) THEN + FOR i IN 0 TO AddrRANGE LOOP + -- Sector ID calculation + IF TimingModel(16) = '0' THEN + sec_tmp := i / (SecSize64+1); + IF BottomBoot THEN + IF sec_tmp <= 1 THEN --4KB Sectors + sect := i/(SecSize4+1); + ELSE + sect := sec_tmp + 30; + END IF; + ELSIF TopBoot THEN + IF sec_tmp >= 254 THEN --4KB Sectors + sect := + 254+(i-(SecSize64+1)*254)/(SecSize4+1); + ELSE + sect := sec_tmp; + END IF; + END IF; + ELSE + sect := i/(SecSize256+1); + END IF; + IF PPB_bits(sect) = '1' AND DYB_bits(sect) = '1' THEN + Mem(i) := -1; + END IF; + END LOOP; + END IF; + + IF EDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO AddrRANGE LOOP + -- Sector ID calculation + IF TimingModel(16) = '0' THEN + sec_tmp := i / (SecSize64+1); + IF BottomBoot THEN + IF sec_tmp <= 1 THEN --4KB Sectors + sect := i/(SecSize4+1); + ELSE + sect := sec_tmp + 30; + END IF; + ELSIF TopBoot THEN + IF sec_tmp >= 254 THEN --4KB Sectors + sect := + 254+(i-(SecSize64+1)*254)/(SecSize4+1); + ELSE + sect := sec_tmp; + END IF; + END IF; + ELSE + sect := i/(SecSize256+1); + END IF; + IF PPB_bits(sect) = '1' AND DYB_bits(sect) = '1' THEN + Mem(i) := MaxData; + END IF; + END LOOP; + END IF; + + WHEN ERS_SUSP => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF ERSSUSP_out = '1' THEN + ERSSUSP_in <= '0'; + --The Erase Suspend (ES) bit in the Status Register will + --be set to the logical “1” state to indicate that the + --erase operation has been suspended. + ES := '1'; + --The WIP bit in the Status Register will indicate that + --the device is ready for another operation. + WIP := '0'; + END IF; + + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = DYBRD THEN + --Read DYB Access Register + ReturnSectorID(sect,Address); + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF DYB_bits(sect) = '1' THEN + DYBAR(7 downto 0) := "11111111"; + ELSE + DYBAR(7 downto 0) := "00000000"; + END IF; + SOut_zd <= DYBAR(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = BRRD THEN + --Read Bank Address Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Bank_Addr_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = PPBRD THEN + --Read PPB Access Register + ReturnSectorID(sect,Address); + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + PPBAR(7 downto 0) := "UUUUUUUU"; + IF RdPswdProtMode = '0' THEN + IF PPB_bits(sect) = '1' THEN + PPBAR(7 downto 0) := "11111111"; + ELSE + PPBAR(7 downto 0) := "00000000"; + END IF; + END IF; + SOut_zd <= PPBAR(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + --Read Array Operations + ELSIF Instruct = READ OR Instruct = RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = DDRFR OR Instruct = DDRFR4 THEN + --Read Memory array + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + + IF (PARAM_REGION = TRUE AND + SectorSuspend /= read_addr/(SecSize+1)) OR + (PARAM_REGION = FALSE AND + SectorSuspend /= read_addr/(SecSize+1)+30*b_act) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRFR OR Instruct=DDRFR4) THEN + IF EHP THEN + IF Latency_code = 1 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3 OR + Latency_code = 0) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:= VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + read_cnt:=read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + --Read Memory array + IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF (PARAM_REGION = TRUE AND + SectorSuspend /= read_addr/(SecSize+1)) OR + (PARAM_REGION = FALSE AND + SectorSuspend /= read_addr/(SecSize+1)+30*b_act) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRDIOR OR Instruct=DDRDIOR4) THEN + IF EHP THEN + IF Latency_code = 0 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency"& + " is set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:=VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + SIOut_zd<=data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF (Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 OR + Instruct = DDRQIOR OR Instruct= DDRQIOR4) + AND QUAD = '1' THEN + --Read Memory array + IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF (PARAM_REGION = TRUE AND + SectorSuspend /= read_addr/(SecSize+1)) OR + (PARAM_REGION = FALSE AND + SectorSuspend /= read_addr/(SecSize+1)+30*b_act) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF EHP THEN + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + HOLDNegOut_zd <= 'U'; + WPNegOut_zd <= 'U'; + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + + END IF; + END IF; + ELSIF oe_z THEN + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF falling_edge(write) THEN + IF (Instruct = PP OR Instruct = PP4) AND WEL = '1' THEN + IF (PARAM_REGION = TRUE AND + SectorSuspend /= Address/(SecSize+1)) OR + (PARAM_REGION = FALSE AND + SectorSuspend/=Address/(SecSize+1)+30*b_act) THEN + ReturnSectorID(sect,Address); + Addr := Address; + pgm_page := Address/(PageSize+1); + IF (Sec_Prot(sect) = '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + WIP := '1' ; + SA <= sect; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSIF (Instruct = QPP OR Instruct = QPP4) AND WEL = '1' THEN + IF (PARAM_REGION = TRUE AND + SectorSuspend /= Address/(SecSize+1)) OR + (PARAM_REGION = FALSE AND + SectorSuspend/=Address/(SecSize+1)+30*b_act) THEN + ReturnSectorID(sect,Address); + Addr := Address; + pgm_page := Address/(PageSize+1); + IF (Sec_Prot(sect)='0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + WIP := '1' ; + SA <= sect; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSIF Instruct = WREN THEN + WEL := '1'; + ELSIF Instruct = CLSR THEN + --The Clear Status Register Command resets bit SR1[5] + --(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + E_ERR := '0'; + P_ERR := '0'; + ELSIF Instruct = BRWR THEN + Bank_Addr_reg(7) := Bank_Addr_reg_in(7); + ELSIF Instruct = WRR AND BAR_ACC = '1' THEN + -- Write to the lower address bits of the BAR + IF (P_ERR = '0' AND E_ERR = '0')THEN + REPORT "WARNING: Changing values of " & + "Bank Address Register RFU bits" & + " are not allowed!!!" + SEVERITY WARNING; + END IF; + ELSIF Instruct = DYBWR AND WEL = '1' THEN + ReturnSectorID(sect,Address); + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = ERRS THEN + ERES <= '1', '0' AFTER 5 ns; + ES := '0'; + WIP := '1'; + IF BottomBoot = TRUE THEN + IF PARAM_REGION = TRUE THEN + Addr := SectorSuspend*(SecSize+1); + ELSE + Addr := (SectorSuspend-30)*(SecSize+1); + END IF; + ELSE + Addr := SectorSuspend*(SecSize+1); + END IF; + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + RES_TO_SUSP_TYP_TIME <= '1', '0' AFTER 100 us; + END IF; + + IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' AND + RdPswdProtMode = '0' THEN + BAR_ACC <= '1'; + ELSE + BAR_ACC <= '0'; + END IF; + END IF; + + WHEN ERS_SUSP_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + ADDRHILO_PG(AddrLo, AddrHi, Addr); + cnt := 0; + + FOR i IN 0 TO wr_cnt LOOP + new_int := WData(i); + old_int := Mem(Addr + i - cnt); + IF new_int > -1 THEN + new_bit := to_slv(new_int,8); + IF old_int > -1 THEN + old_bit := to_slv(old_int,8); + FOR j IN 0 TO 7 LOOP + IF old_bit(j) = '0' THEN + new_bit(j) := '0'; + END IF; + END LOOP; + new_int := to_nat(new_bit); + END IF; + WData(i) := new_int; + ELSE + WData(i) := -1; + END IF; + + IF (Addr + i) = AddrHi THEN + Addr := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + cnt :=0; + + IF PDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO wr_cnt LOOP + Mem(Addr_tmp + i - cnt) := WData(i); + IF (Addr_tmp + i) = AddrHi THEN + Addr_tmp := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + ELSIF Instruct = PGSP AND PRGSUSP_in = '0' THEN + PGSUSP <= '1', '0' AFTER 1 ns; + PRGSUSP_in <= '1'; + END IF; + + WHEN PASS_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + new_pass := Password_reg_in; + old_pass := Password_reg; + FOR j IN 0 TO 63 LOOP + IF old_pass(j) = '0' THEN + new_pass(j) := '0'; + END IF; + END LOOP; + + IF PDONE = '1' THEN + Password_reg := new_pass; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN PASS_UNLOCK => + WIP := '1'; + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PASS_TEMP = Password_reg THEN + PASS_UNLOCKED <= TRUE; + ELSE + PASS_UNLOCKED <= FALSE; + END IF; + + IF PASSULCK_out = '1' THEN + IF PASS_UNLOCKED AND PWDMLB = '0' THEN + PPB_LOCK := '1'; + PPB_LOCK_temp <= '1'; + WIP := '0'; + ELSE + P_ERR := '1'; + REPORT "Incorrect Password!" + SEVERITY warning; + PASSACC_in <= '1'; + END IF; + WEL := '0'; + PASSULCK_in <= '0'; + END IF; + + WHEN PPB_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + IF PPB_LOCK /= '0' THEN + PPB_bits(sect):= '0'; + WIP := '0'; + WEL := '0'; + ELSE + P_ERR := '0'; + WIP := '0'; + WEL := '0'; + END IF; + END IF; + + WHEN PPB_ERS => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PPBERASE_out = '1' THEN + IF PPB_LOCK /= '0' AND PPBOTP = '1' THEN + PPB_bits:= (OTHERS => '1'); + ELSE + E_ERR := '1'; + END IF; + WIP := '0'; + WEL := '0'; + PPBERASE_in <= '0'; + END IF; + + WHEN AUTOBOOT_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + AutoBoot_reg := AutoBoot_reg_in; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN PLB_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + PPB_LOCK := '0'; + PPB_LOCK_temp <= '0'; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN DYB_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + DYBAR := DYBAR_in; + IF DYBAR = "11111111" THEN + DYB_bits(sect):= '1'; + ELSIF DYBAR = "00000000" THEN + DYB_bits(sect):= '0'; + ELSE + P_ERR := '1'; + END IF; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN ASP_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + + IF (RPME = '0' AND ASP_reg_in(5) = '1') THEN + P_ERR := '1'; + REPORT "RPME bit is allready programmed" + SEVERITY warning; + ELSE + RPME := ASP_reg_in(5); + END IF; + + IF (PPBOTP = '0' AND ASP_reg_in(3) ='1') THEN + P_ERR := '1'; + REPORT "PPBOTP bit is allready programmed" + SEVERITY warning; + ELSE + PPBOTP := ASP_reg_in(3); + END IF; + + IF (PWDMLB = '1' AND PSTMLB = '1') THEN + IF (ASP_reg_in(2) = '0' AND ASP_reg_in(1) = '0') THEN + REPORT "ASPR[2:1] = 00 Illegal condition" + SEVERITY warning; + P_ERR := '1'; + ELSE + IF (ASP_reg_in(2) /= '1' OR + ASP_reg_in(1) /= '1') THEN + ASPOTPFLAG <= TRUE; + END IF; + PWDMLB := ASP_reg_in(2); + PSTMLB := ASP_reg_in(1); + END IF; + END IF; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN NVDLR_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + IF NVDLR_reg = "00000000" THEN + NVDLR_reg :=NVDLR_reg_in; + VDLR_reg := NVDLR_reg_in; + WIP := '0'; + WEL := '0'; + ELSE + WIP := '0'; + WEL := '0'; + P_ERR := '1'; + REPORT "NVDLR is allready programmed" + SEVERITY warning; + END IF; + END IF; + + WHEN RESET_STATE => + --the default condition hardware reset + --The Bank Address Register is loaded to all zeroes + Bank_Addr_reg := (others => '0'); + IF BPNV = '1' AND LOCK='0' AND FREEZE = '0' THEN + BP0 := '1'; + BP1 := '1'; + BP2 := '1'; + BP_bits := BP2 & BP1 & BP0; + change_BP <= '1', '0' AFTER 1 ns; + END IF; + --Resets the Status register 1 + P_ERR := '0'; + E_ERR := '0'; + WEL := '0'; + WIP := '0'; + --Resets the Status register 2 + ES := '0'; + PS := '0'; + --Resets the Configuration register 1 + FREEZE := '0'; + --On reset cycles the data pattern reverts back + --to what is in the NVDLR + VDLR_reg := NVDLR_reg; + dlp_act := FALSE; + --Loads the Program Buffer with all ones + WData := (OTHERS => MaxData); + + IF PWDMLB = '0' THEN + PPB_LOCK := '0'; + PPB_LOCK_temp <= '0'; + ELSE + PPB_LOCK := '1'; + PPB_LOCK_temp <= '1'; + END IF; + + END CASE; + + --Output Disable Control + IF (CSNeg_ipd = '1') THEN + SIOut_zd <= 'Z'; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + END IF; + + END PROCESS Functional; + + --------------------------------------------------------------------------- + -- CFI Process + --------------------------------------------------------------------------- + CFIPreload: PROCESS + + BEGIN + ------------------------------------------------------------------------ + --CFI array data + ------------------------------------------------------------------------ + -- Manufacturer and Device ID + CFI_array(16#00#) := 16#01#; + CFI_array(16#01#) := 16#20#; + CFI_array(16#02#) := 16#18#; + CFI_array(16#03#) := 16#00#; + IF TimingModel(16) = '0' THEN + CFI_array(16#04#) := 16#01#;--256B page + ELSIF TimingModel(16) = '1' THEN + CFI_array(16#04#) := 16#00#;--512B page + END IF; + CFI_array(16#05#) := 16#80#; + + CFI_array(16#06#) := 16#00#; + CFI_array(16#07#) := 16#00#; + CFI_array(16#08#) := 16#00#; + CFI_array(16#09#) := 16#00#; + CFI_array(16#0A#) := 16#00#; + CFI_array(16#0B#) := 16#00#; + CFI_array(16#0C#) := 16#00#; + CFI_array(16#0D#) := 16#00#; + CFI_array(16#0E#) := 16#00#; + CFI_array(16#0F#) := 16#00#; + --CFI Query Identification String + CFI_array(16#10#) := 16#51#; + CFI_array(16#11#) := 16#52#; + CFI_array(16#12#) := 16#59#; + CFI_array(16#13#) := 16#02#; + CFI_array(16#14#) := 16#00#; + CFI_array(16#15#) := 16#40#; + CFI_array(16#16#) := 16#00#; + CFI_array(16#17#) := 16#53#; + CFI_array(16#18#) := 16#46#; + CFI_array(16#19#) := 16#51#; + CFI_array(16#1A#) := 16#00#; + --CFI system interface string + CFI_array(16#1B#) := 16#27#; + CFI_array(16#1C#) := 16#36#; + CFI_array(16#1D#) := 16#00#; + CFI_array(16#1E#) := 16#00#; + CFI_array(16#1F#) := 16#06#; + IF TimingModel(16) = '0' THEN + CFI_array(16#20#) := 16#08#;--256B page + CFI_array(16#21#) := 16#08#;--64KB + ELSIF TimingModel(16) = '1' THEN + CFI_array(16#20#) := 16#09#;--512B page + CFI_array(16#21#) := 16#09#;--256KB + END IF; + + CFI_array(16#22#) := 16#0F#; + CFI_array(16#23#) := 16#02#; + CFI_array(16#24#) := 16#02#; + CFI_array(16#25#) := 16#03#; + CFI_array(16#26#) := 16#03#; + --Device Geometry Definition + CFI_array(16#27#) := 16#18#; + CFI_array(16#28#) := 16#02#; + CFI_array(16#29#) := 16#01#; + IF TimingModel(16) = '0' THEN + CFI_array(16#2A#) := 16#08#;--256B page + ELSIF TimingModel(16) = '1' THEN + CFI_array(16#2A#) := 16#09#;--512B page + END IF; + CFI_array(16#2B#) := 16#00#; + IF TimingModel(16) = '1' THEN + CFI_array(16#2C#) := 16#01#; --Uniform Device + CFI_array(16#2D#) := 16#3F#; + CFI_array(16#2E#) := 16#00#; + CFI_array(16#2F#) := 16#00#; + CFI_array(16#30#) := 16#04#; + CFI_array(16#31#) := 16#FF#; + CFI_array(16#32#) := 16#FF#; + CFI_array(16#33#) := 16#FF#; + CFI_array(16#34#) := 16#FF#; + ELSE + CFI_array(16#2C#) := 16#02#; --Boot device + IF TBPARM = '1' THEN + CFI_array(16#2D#) := 16#FD#; + CFI_array(16#2E#) := 16#00#; + CFI_array(16#2F#) := 16#00#; + CFI_array(16#30#) := 16#01#; + CFI_array(16#31#) := 16#1F#; + CFI_array(16#32#) := 16#00#; + CFI_array(16#33#) := 16#10#; + CFI_array(16#34#) := 16#00#; + ELSE + CFI_array(16#2D#) := 16#1F#; + CFI_array(16#2E#) := 16#00#; + CFI_array(16#2F#) := 16#10#; + CFI_array(16#30#) := 16#00#; + CFI_array(16#31#) := 16#FD#; + CFI_array(16#32#) := 16#00#; + CFI_array(16#33#) := 16#00#; + CFI_array(16#34#) := 16#01#; + END IF; + END IF; + CFI_array(16#35#) := 16#FF#; + CFI_array(16#36#) := 16#FF#; + CFI_array(16#37#) := 16#FF#; + CFI_array(16#38#) := 16#FF#; + CFI_array(16#39#) := 16#FF#; + CFI_array(16#3A#) := 16#FF#; + CFI_array(16#3B#) := 16#FF#; + CFI_array(16#3C#) := 16#FF#; + CFI_array(16#3D#) := 16#FF#; + CFI_array(16#3E#) := 16#FF#; + CFI_array(16#3F#) := 16#FF#; + --CFI Primary Vendor-Specific Extended Query + CFI_array(16#40#) := 16#50#; + CFI_array(16#41#) := 16#52#; + CFI_array(16#42#) := 16#49#; + CFI_array(16#43#) := 16#31#; + CFI_array(16#44#) := 16#33#; + CFI_array(16#45#) := 16#21#; + CFI_array(16#46#) := 16#02#; + CFI_array(16#47#) := 16#01#; + CFI_array(16#48#) := 16#00#; + CFI_array(16#49#) := 16#08#; + CFI_array(16#4A#) := 16#00#; + CFI_array(16#4B#) := 16#01#; + CFI_array(16#4C#) := 16#00#; + CFI_array(16#4D#) := 16#00#; + CFI_array(16#4E#) := 16#00#; + CFI_array(16#4F#) := 16#07#; + CFI_array(16#50#) := 16#01#; + CFI_array(16#51#) := 16#41#; + CFI_array(16#52#) := 16#4C#; + CFI_array(16#53#) := 16#54#; + CFI_array(16#54#) := 16#32#; + CFI_array(16#55#) := 16#30#; + + CFI_array_tmp :=to_slv(CFI_array(16#00#), 8) & + to_slv(CFI_array(16#01#), 8) & + to_slv(CFI_array(16#02#), 8) & + to_slv(CFI_array(16#03#), 8) & + to_slv(CFI_array(16#04#), 8) & + to_slv(CFI_array(16#05#), 8) & + to_slv(CFI_array(16#06#), 8) & + to_slv(CFI_array(16#07#), 8) & + to_slv(CFI_array(16#08#), 8) & + to_slv(CFI_array(16#09#), 8) & + to_slv(CFI_array(16#0A#), 8) & + to_slv(CFI_array(16#0B#), 8) & + to_slv(CFI_array(16#0C#), 8) & + to_slv(CFI_array(16#0D#), 8) & + to_slv(CFI_array(16#0E#), 8) & + to_slv(CFI_array(16#0F#), 8) & + to_slv(CFI_array(16#10#), 8) & + to_slv(CFI_array(16#11#), 8) & + to_slv(CFI_array(16#12#), 8) & + to_slv(CFI_array(16#13#), 8) & + to_slv(CFI_array(16#14#), 8) & + to_slv(CFI_array(16#15#), 8) & + to_slv(CFI_array(16#16#), 8) & + to_slv(CFI_array(16#17#), 8) & + to_slv(CFI_array(16#18#), 8) & + to_slv(CFI_array(16#19#), 8) & + to_slv(CFI_array(16#1A#), 8) & + to_slv(CFI_array(16#1B#), 8) & + to_slv(CFI_array(16#1C#), 8) & + to_slv(CFI_array(16#1D#), 8) & + to_slv(CFI_array(16#1E#), 8) & + to_slv(CFI_array(16#1F#), 8) & + to_slv(CFI_array(16#20#), 8) & + to_slv(CFI_array(16#21#), 8) & + to_slv(CFI_array(16#22#), 8) & + to_slv(CFI_array(16#23#), 8) & + to_slv(CFI_array(16#24#), 8) & + to_slv(CFI_array(16#25#), 8) & + to_slv(CFI_array(16#26#), 8) & + to_slv(CFI_array(16#27#), 8) & + to_slv(CFI_array(16#28#), 8) & + to_slv(CFI_array(16#29#), 8) & + to_slv(CFI_array(16#2A#), 8) & + to_slv(CFI_array(16#2B#), 8) & + to_slv(CFI_array(16#2C#), 8) & + to_slv(CFI_array(16#2D#), 8) & + to_slv(CFI_array(16#2E#), 8) & + to_slv(CFI_array(16#2F#), 8) & + to_slv(CFI_array(16#30#), 8) & + to_slv(CFI_array(16#31#), 8) & + to_slv(CFI_array(16#32#), 8) & + to_slv(CFI_array(16#33#), 8) & + to_slv(CFI_array(16#34#), 8) & + to_slv(CFI_array(16#35#), 8) & + to_slv(CFI_array(16#36#), 8) & + to_slv(CFI_array(16#37#), 8) & + to_slv(CFI_array(16#38#), 8) & + to_slv(CFI_array(16#39#), 8) & + to_slv(CFI_array(16#3A#), 8) & + to_slv(CFI_array(16#3B#), 8) & + to_slv(CFI_array(16#3C#), 8) & + to_slv(CFI_array(16#3D#), 8) & + to_slv(CFI_array(16#3E#), 8) & + to_slv(CFI_array(16#3F#), 8) & + to_slv(CFI_array(16#40#), 8) & + to_slv(CFI_array(16#41#), 8) & + to_slv(CFI_array(16#42#), 8) & + to_slv(CFI_array(16#43#), 8) & + to_slv(CFI_array(16#44#), 8) & + to_slv(CFI_array(16#45#), 8) & + to_slv(CFI_array(16#46#), 8) & + to_slv(CFI_array(16#47#), 8) & + to_slv(CFI_array(16#48#), 8) & + to_slv(CFI_array(16#49#), 8) & + to_slv(CFI_array(16#4A#), 8) & + to_slv(CFI_array(16#4B#), 8) & + to_slv(CFI_array(16#4C#), 8) & + to_slv(CFI_array(16#4D#), 8) & + to_slv(CFI_array(16#4E#), 8) & + to_slv(CFI_array(16#4F#), 8) & + to_slv(CFI_array(16#50#), 8); + + WAIT; + + END PROCESS CFIPreload; + + AspRegInit: PROCESS(ASP_INIT) + BEGIN + IF ASP_INIT = 0 THEN + ASP_reg := to_slv(16#FE4F#,16); + ELSE + ASP_reg := to_slv(16#FE7F#,16); + END IF; + END PROCESS AspRegInit; + + TopBottom: PROCESS(change_TBPARM, PoweredUp) + BEGIN + IF (TimingModel(16)= '0') THEN + IF TBPARM = '0' THEN + BottomBoot <= TRUE; + b_act := 1; + ELSE + TopBoot <= TRUE; + BottomBoot <= FALSE; + b_act := 0; + END IF; + END IF; + END PROCESS TopBottom; + + Protect : PROCESS(change_BP) + BEGIN + IF rising_edge(change_BP) THEN + + CASE BP_bits IS + WHEN "000" => + Sec_Prot := (OTHERS => '0'); + WHEN "001" => + IF TBPROT = '0' THEN + Sec_Prot(SecNumMax downto ((SecNum+1)*63/64+30*b_act)) + := (OTHERS => '1'); + Sec_Prot(((SecNum+1)*63/64 + 30*b_act) - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/64 + 30*b_act - 1 downto 0) + := (OTHERS => '1'); + Sec_Prot(SecNumMax downto (SecNum+1)/64 + 30*b_act) + := (OTHERS => '0'); + END IF; + WHEN "010" => + IF TBPROT = '0' THEN + Sec_Prot(SecNumMax downto ((SecNum+1)*31/32+30*b_act)) + := (OTHERS => '1'); + Sec_Prot(((SecNum+1)*31/32+30*b_act) - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/32 + 30*b_act - 1 downto 0) + := (others => '1'); + Sec_Prot(SecNumMax downto (SecNum+1)/32 + 30*b_act) + := (OTHERS => '0'); + END IF; + WHEN "011" => + IF TBPROT = '0' THEN + Sec_Prot(SecNumMax downto ((SecNum+1)*15/16+30*b_act)) + := (OTHERS => '1'); + Sec_Prot(((SecNum+1)*15/16 + 30*b_act) - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/16 + 30*b_act - 1 downto 0) + := (OTHERS => '1'); + Sec_Prot(SecNumMax downto (SecNum+1)/16 + 30*b_act) + := (OTHERS => '0'); + END IF; + WHEN "100" => + IF TBPROT = '0' THEN + Sec_Prot(SecNumMax downto ((SecNum+1)*7/8 + 30*b_act)) + := (OTHERS => '1'); + Sec_Prot(((SecNum+1)*7/8 + 30*b_act) - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/8 + 30*b_act - 1 downto 0) + := (OTHERS => '1'); + Sec_Prot(SecNumMax downto (SecNum+1)/8 + 30*b_act) + := (OTHERS => '0'); + END IF; + WHEN "101" => + IF TBPROT = '0' THEN + Sec_Prot(SecNumMax downto ((SecNum+1)*3/4 + 30*b_act)) + := (OTHERS => '1'); + Sec_Prot(((SecNum+1)*3/4 + 30*b_act) - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/4 + 30*b_act - 1 downto 0) + := (OTHERS => '1'); + Sec_Prot(SecNumMax downto (SecNum+1)/4 + 30*b_act) + := (OTHERS => '0'); + END IF; + WHEN "110" => + IF TBPROT = '0' THEN + Sec_Prot(SecNumMax downto ((SecNum+1)/2 + 30*b_act)) + := (OTHERS => '1'); + Sec_Prot(((SecNum+1)/2 + 30*b_act) - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/2 + 30*b_act - 1 downto 0) + := (OTHERS => '1'); + Sec_Prot(SecNumMax downto (SecNum+1)/2 + 30*b_act) + := (OTHERS => '0'); + END IF; + WHEN OTHERS => + Sec_Prot := (OTHERS => '1'); + END CASE; + END IF; + END PROCESS Protect; + + HOLD_FRAME_ON_PO_ZD : PROCESS(SOut_zd, SIOut_zd, HOLDNeg_pullup) + BEGIN + IF (HOLDNeg_pullup = '0' AND QUAD /= '1') THEN + hold_mode := TRUE; + SIOut_z <= 'Z'; + SOut_z <= 'Z'; + ELSE + IF hold_mode THEN + SIOut_z <= SIOut_zd AFTER tpd_HOLDNeg_SO(trz0); + SOut_z <= SOut_zd AFTER tpd_HOLDNeg_SO(trz0); + hold_mode := FALSE; + ELSE + SIOut_z <= SIOut_zd; + SOut_z <= SOut_zd; + hold_mode := FALSE; + END IF; + END IF; + END PROCESS HOLD_FRAME_ON_PO_ZD; + + HOLD_PULL_UP : PROCESS(HOLDNegIn) + BEGIN + IF (QUAD = '0') THEN + IF (HOLDNegIn = 'Z') THEN + HOLDNeg_pullup <= '1'; + ELSE + HOLDNeg_pullup <= HOLDNegIn; + END IF; + END IF; + END PROCESS HOLD_PULL_UP; + + WP_PULL_UP : PROCESS(WPNegIn) + BEGIN + IF (QUAD = '0') THEN + IF (WPNegIn = 'Z') THEN + WPNeg_pullup <= '1'; + ELSE + WPNeg_pullup <= WPNegIn; + END IF; + END IF; + END PROCESS WP_PULL_UP; + + RST_PULL_UP : PROCESS(RSTNeg) + BEGIN + IF (RSTNeg = 'Z') THEN + RSTNeg_pullup <= '1'; + ELSE + RSTNeg_pullup <= RSTNeg; + END IF; + END PROCESS RST_PULL_UP; + + --------------------------------------------------------------------------- + ---- File Read Section - Preload Control + --------------------------------------------------------------------------- + MemPreload : PROCESS + + -- text file input variables + FILE mem_file : text is mem_file_name; + FILE otp_file : text is otp_file_name; + VARIABLE ind : NATURAL RANGE 0 TO AddrRANGE := 0; + VARIABLE otp_ind : NATURAL RANGE 16#000# TO 16#3FF# := 16#000#; + VARIABLE buf : line; + + BEGIN + --------------------------------------------------------------------------- + --s25fl128s memory preload file format +----------------------------------- + --------------------------------------------------------------------------- + -- / - comment + -- @aaaaaa - stands for address + -- dd -
is byte to be written at Mem(aaaaaa++) + -- (aaaaaa is incremented at every load) + -- only first 1-7 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + --------------------------------------------------------------------------- + + -- memory preload + IF (mem_file_name /= "none" AND UserPreload) THEN + ind := 0; + Mem := (OTHERS => MaxData); + WHILE (not ENDFILE (mem_file)) LOOP + READLINE (mem_file, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + IF ind > AddrRANGE THEN + ASSERT false + REPORT "Given preload address is out of" & + "memory address range" + SEVERITY warning; + ELSE + ind := h(buf(2 to 7)); --address + END IF; + ELSE + Mem(ind) := h(buf(1 to 2)); + IF ind < AddrRANGE THEN + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + --------------------------------------------------------------------------- + --s25fl128s_otp memory preload file format + --------------------------------------------------------------------------- + -- / - comment + -- @aaa - stands for address + -- dd -
is byte to be written at OTPMem(aaa++) + -- (aaa is incremented at every load) + -- only first 1-4 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + --------------------------------------------------------------------------- + + -- memory preload + IF (otp_file_name /= "none" AND UserPreload) THEN + otp_ind := 16#000#; + OTPMem := (OTHERS => MaxData); + WHILE (not ENDFILE (otp_file)) LOOP + READLINE (otp_file, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + IF otp_ind > 16#3FF# OR otp_ind < 16#000# THEN + ASSERT false + REPORT "Given preload address is out of" & + "OTP address range" + SEVERITY warning; + ELSE + otp_ind := h(buf(2 to 4)); --address + END IF; + ELSE + OTPMem(otp_ind) := h(buf(1 to 2)); + otp_ind := otp_ind + 1; + END IF; + END LOOP; + END IF; + + LOCK_BYTE1 := to_slv(OTPMem(16#10#),8); + LOCK_BYTE2 := to_slv(OTPMem(16#11#),8); + LOCK_BYTE3 := to_slv(OTPMem(16#12#),8); + LOCK_BYTE4 := to_slv(OTPMem(16#13#),8); + + WAIT; + END PROCESS MemPreload; + + ---------------------------------------------------------------------------- + -- Path Delay Section + ---------------------------------------------------------------------------- + + S_Out_PathDelay_Gen : PROCESS(SOut_z) + + VARIABLE SO_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => SOut, + OutSignalName => "SO", + OutTemp => SOut_z, + Mode => VitalTransport, + GlitchData => SO_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal), + PathCondition => NOT(ddr)), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR), + PathCondition => (ddr OR fast_rd)), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1'), + 3 => (InputChangeTime => HOLDNegIn'LAST_EVENT, + PathDelay => tpd_HOLDNeg_SO, + PathCondition => QUAD = '0') + ) + ); + END PROCESS; + + SI_Out_PathDelay : PROCESS(SIOut_z) + + VARIABLE SI_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => SIOut, + OutSignalName => "SI", + OutTemp => SIOut_z, + Mode => VitalTransport, + GlitchData => SI_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal), + PathCondition => dual AND NOT(ddr)), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR), + PathCondition => dual AND ddr), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1'), + 3 => (InputChangeTime => HOLDNegIn'LAST_EVENT, + PathDelay => tpd_HOLDNeg_SO, + PathCondition => dual AND QUAD = '0') + ) + ); + END PROCESS; + + HOLD_Out_PathDelay : PROCESS(HOLDNegOut_zd) + + VARIABLE HOLD_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => HOLDNegOut, + OutSignalName => "HOLDNeg", + OutTemp => HOLDNegOut_zd, + Mode => VitalTransport, + GlitchData => HOLD_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal), + PathCondition => dual AND not(ddr) AND QUAD = '1'), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR), + PathCondition => ddr AND QUAD = '1'), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND + HOLDNegOut_zd = 'Z' AND QUAD = '1') + ) + ); + END PROCESS; + + WP_Out_PathDelay : PROCESS(WPNegOut_zd) + + VARIABLE WP_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => WPNegOut, + OutSignalName => "WPNeg", + OutTemp => WPNegOut_zd, + Mode => VitalTransport, + GlitchData => WP_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal), + PathCondition => dual AND not(ddr) AND QUAD = '1'), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR), + PathCondition => ddr AND QUAD = '1'), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND + WPNegOut_zd = 'Z' AND QUAD = '1') + ) + ); + END PROCESS; + + END BLOCK behavior; +END vhdl_behavioral; \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl128s/model/s25fl128s_ver.ftm b/lib/models/memory/flash/serial/S25fl128s/model/s25fl128s_ver.ftm new file mode 100644 index 0000000..219d3b1 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128s/model/s25fl128s_ver.ftm @@ -0,0 +1,726 @@ + +FMF Timing for s25fl128s Parts + + +version: | author: | mod date: | changes made: + V1.0 R. Prokopovic 09 Nov 19 Initial release + V1.1 V.Mancev 10 Oct 07 Latest datasheet aligned + V1.2 V.Mancev 11 May 11 CS# High Time modifications + V1.3 V.Mancev 11 June 27 Latest datasheet aligned + V1.4 V.Mancev 11 Nov 16 Time tHO is changed to 1 ns + +1ns +s25fl128s + +S25FL128SAGMFI000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR01_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR11_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR01_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR11_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI200_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI203_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI210_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI213_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI300_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI303_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI310_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI313_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV200_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV203_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV210_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV213_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV300_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV303_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV310_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV313_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for VIO=VCC=2.7V to 3.6V, CL=30pF + +(DELAY (ABSOLUTE + (COND ~ddr (IOPATH SCK SO (5.4:6.7:8) (5.4:6.7:8) (1) (5.4:6.7:8) (1) (5.4:6.7:8))) + (COND (ddr || rd_fast) (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && dual (IOPATH SCK SI (5.4:6.7:8) (5.4:6.7:8) (1) (5.4:6.7:8) (1) (5.4:6.7:8))) + (COND ddr && dual (IOPATH SCK SI (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND ~ddr && QUAD (IOPATH SCK HOLDNeg (5.4:6.7:8) (5.4:6.7:8) (1) (5.4:6.7:8) (1) (5.4:6.7:8))) + (COND ddr && QUAD (IOPATH SCK HOLDNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && QUAD (IOPATH SCK WPNeg (5.4:6.7:8) (5.4:6.7:8) (1) (5.4:6.7:8) (1) (5.4:6.7:8))) + (COND ddr && QUAD (IOPATH SCK WPNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && dual (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~QUAD (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND ~QUAD && dual (IOPATH HOLDNeg SI () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP CSNeg (COND sdr_rd SCK) (3)) + (SETUP CSNeg (COND ddr_rd SCK) (3)) + (SETUP SI (COND deg_sin(posedge SCK)) (3)) + (SETUP SI (COND ddro(posedge SCK)) (2)) + (SETUP SI (COND ddro(negedge SCK)) (2)) + (SETUP WPNeg (COND wr_prot(negedge CSNeg)) (20)) + (SETUP HOLDNeg (COND quad_rd (posedge SCK)) (3)) + (SETUP RSTNeg CSNeg (50)) + + (HOLD CSNeg (COND sdr_rd SCK) (3)) + (HOLD CSNeg (COND ddr_rd SCK) (3)) + (HOLD SI (COND deg_sin (posedge SCK)) (2)) + (HOLD SI (COND ddro (posedge SCK)) (2)) + (HOLD SI (COND ddro (negedge SCK)) (2)) + (HOLD WPNeg (COND wr_prot (posedge CSNeg)) (100)) + (HOLD HOLDNeg (COND quad_rd (posedge SCK)) (3)) + (HOLD CSNeg RSTNeg (35000)) + + (WIDTH (COND rd (posedge SCK)) (10)) + (WIDTH (COND rd (negedge SCK)) (10)) + (WIDTH (COND dual_rd (posedge SCK)) (4.8)) + (WIDTH (COND dual_rd (negedge SCK)) (4.8)) + (WIDTH (COND fast_rd (negedge SCK)) (3.75)) + (WIDTH (COND fast_rd (posedge SCK)) (3.75)) + (WIDTH (COND quadpg (posedge SCK)) (6.25)) + (WIDTH (COND quadpg (negedge SCK)) (6.25)) + (WIDTH (COND ddrd (posedge SCK)) (7.5)) + (WIDTH (COND ddrd (negedge SCK)) (7.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (7.52)) + (PERIOD (COND dual_rd SCK) (9.6)) + (PERIOD (COND quadpg SCK) (12.5)) + (PERIOD (COND ddrd SCK) (15)) +) + + + +S25FL128SAGMFI000_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI001_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI003_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR01_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR11_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV000_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV001_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV003_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR01_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR11_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI000_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI001_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI003_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV000_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV001_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV003_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI200_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI203_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI210_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI213_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI300_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI303_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI310_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI313_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV200_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV203_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV210_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV213_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV300_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV303_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV310_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV313_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=30pF + +(DELAY (ABSOLUTE + (COND ~ddr (IOPATH SCK SO (4.3:6.0:7.65) (4.3:6.0:7.65) (1) (4.3:6.0:7.65) (1) (4.3:6.0:7.65))) + (COND (ddr || rd_fast) (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && dual (IOPATH SCK SI (4.3:6.0:7.65) (4.3:6.0:7.65) (1) (4.3:6.0:7.65) (1) (4.3:6.0:7.65))) + (COND ddr && dual (IOPATH SCK SI (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND ~ddr && QUAD (IOPATH SCK HOLDNeg (4.3:6.0:7.65) (4.3:6.0:7.65) (1) (4.3:6.0:7.65) (1) (4.3:6.0:7.65))) + (COND ddr && QUAD (IOPATH SCK HOLDNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && QUAD (IOPATH SCK WPNeg (4.3:6.0:7.65) (4.3:6.0:7.65) (1) (4.3:6.0:7.65) (1) (4.3:6.0:7.65))) + (COND ddr && QUAD (IOPATH SCK WPNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && dual (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~QUAD (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND ~QUAD && dual (IOPATH HOLDNeg SI () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP CSNeg (COND sdr_rd SCK) (3)) + (SETUP CSNeg (COND ddr_rd SCK) (3)) + (SETUP SI (COND deg_sin(posedge SCK)) (3)) + (SETUP SI (COND ddro(posedge SCK)) (2)) + (SETUP SI (COND ddro(negedge SCK)) (2)) + (SETUP WPNeg (COND wr_prot(negedge CSNeg)) (20)) + (SETUP HOLDNeg (COND quad_rd (posedge SCK)) (3)) + (SETUP RSTNeg CSNeg (50)) + + (HOLD CSNeg (COND sdr_rd SCK) (3)) + (HOLD CSNeg (COND ddr_rd SCK) (3)) + (HOLD SI (COND deg_sin (posedge SCK)) (2)) + (HOLD SI (COND ddro (posedge SCK)) (2)) + (HOLD SI (COND ddro (negedge SCK)) (2)) + (HOLD WPNeg (COND wr_prot (posedge CSNeg)) (100)) + (HOLD HOLDNeg (COND quad_rd (posedge SCK)) (3)) + (HOLD CSNeg RSTNeg (35000)) + + (WIDTH (COND rd (posedge SCK)) (10)) + (WIDTH (COND rd (negedge SCK)) (10)) + (WIDTH (COND dual_rd (posedge SCK)) (4.8)) + (WIDTH (COND dual_rd (negedge SCK)) (4.8)) + (WIDTH (COND fast_rd (negedge SCK)) (3.75)) + (WIDTH (COND fast_rd (posedge SCK)) (3.75)) + (WIDTH (COND quadpg (posedge SCK)) (6.25)) + (WIDTH (COND quadpg (negedge SCK)) (6.25)) + (WIDTH (COND ddrd (posedge SCK)) (7.5)) + (WIDTH (COND ddrd (negedge SCK)) (7.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (7.52)) + (PERIOD (COND dual_rd SCK) (9.6)) + (PERIOD (COND quadpg SCK) (12.5)) + (PERIOD (COND ddrd SCK) (15)) +) + + + +S25FL128SAGMFI000_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI001_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI003_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR01_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR11_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV000_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV001_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV003_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR01_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR11_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI000_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI001_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI003_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV000_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV001_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV003_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI200_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI203_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI210_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI213_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI300_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI303_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI310_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI313_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV200_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV203_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV210_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV213_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV300_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV303_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV310_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV313_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=15pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND ~ddr (IOPATH SCK SO (4.5:5.5:6.5) (4.5:5.5:6.5) (1) (4.5:5.5:6.5) (1) (4.5:5.5:6.5))) + (COND (ddr || rd_fast) (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && dual (IOPATH SCK SI (4.5:5.5:6.5) (4.5:5.5:6.5) (1) (4.5:5.5:6.5) (1) (4.5:5.5:6.5))) + (COND ddr && dual (IOPATH SCK SI (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND ~ddr && QUAD (IOPATH SCK HOLDNeg (4.5:5.5:6.5) (4.5:5.5:6.5) (1) (4.5:5.5:6.5) (1) (4.5:5.5:6.5))) + (COND ddr && QUAD (IOPATH SCK HOLDNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && QUAD (IOPATH SCK WPNeg (4.5:5.5:6.5) (4.5:5.5:6.5) (1) (4.5:5.5:6.5) (1) (4.5:5.5:6.5))) + (COND ddr && QUAD (IOPATH SCK WPNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && dual (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~QUAD (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND ~QUAD && dual (IOPATH HOLDNeg SI () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP CSNeg (COND sdr_rd SCK) (3)) + (SETUP CSNeg (COND ddr_rd SCK) (3)) + (SETUP SI (COND deg_sin(posedge SCK)) (3)) + (SETUP SI (COND ddro(posedge SCK)) (2)) + (SETUP SI (COND ddro(negedge SCK)) (2)) + (SETUP WPNeg (COND wr_prot(negedge CSNeg)) (20)) + (SETUP HOLDNeg (COND quad_rd (posedge SCK)) (3)) + (SETUP RSTNeg CSNeg (50)) + + (HOLD CSNeg (COND sdr_rd SCK) (3)) + (HOLD CSNeg (COND ddr_rd SCK) (3)) + (HOLD SI (COND deg_sin (posedge SCK)) (2)) + (HOLD SI (COND ddro (posedge SCK)) (2)) + (HOLD SI (COND ddro (negedge SCK)) (2)) + (HOLD WPNeg (COND wr_prot (posedge CSNeg)) (100)) + (HOLD HOLDNeg (COND quad_rd (posedge SCK)) (3)) + (HOLD CSNeg RSTNeg (35000)) + + (WIDTH (COND rd (posedge SCK)) (10)) + (WIDTH (COND rd (negedge SCK)) (10)) + (WIDTH (COND dual_rd (posedge SCK)) (4.8)) + (WIDTH (COND dual_rd (negedge SCK)) (4.8)) + (WIDTH (COND fast_rd (negedge SCK)) (3.75)) + (WIDTH (COND fast_rd (posedge SCK)) (3.75)) + (WIDTH (COND quadpg (posedge SCK)) (6.25)) + (WIDTH (COND quadpg (negedge SCK)) (6.25)) + (WIDTH (COND ddrd (posedge SCK)) (7.5)) + (WIDTH (COND ddrd (negedge SCK)) (7.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (7.52)) + (PERIOD (COND dual_rd SCK) (9.6)) + (PERIOD (COND quadpg SCK) (12.5)) + (PERIOD (COND ddrd SCK) (15)) +) + + + +S25FL128SDPMFIR00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR01_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR11_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI200_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI203_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI210_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI213_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI300_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI303_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI310_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI313_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHIC00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHIC03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHIC10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHIC13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHID00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHID03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHID10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHID13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for Vcc range VCC=2.7V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND ~ddr (IOPATH SCK SO (1.5:8:14.5) (1.5:8:14.5) (1) (1.5:8:14.5) (1) (1.5:8:14.5))) + (COND (ddr || rd_fast) (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && dual (IOPATH SCK SI (1.5:8:14.5) (1.5:8:14.5) (1) (1.5:8:14.5) (1) (1.5:8:14.5))) + (COND ddr && dual (IOPATH SCK SI (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND ~ddr && QUAD (IOPATH SCK HOLDNeg (1.5:8:14.5) (1.5:8:14.5) (1) (1.5:8:14.5) (1) (1.5:8:14.5))) + (COND ddr && QUAD (IOPATH SCK HOLDNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && QUAD (IOPATH SCK WPNeg (1.5:8:14.5) (1.5:8:14.5) (1) (1.5:8:14.5) (1) (1.5:8:14.5))) + (COND ddr && QUAD (IOPATH SCK WPNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && dual (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~QUAD (IOPATH HOLDNeg SO () () (7:10.5:14) (7:10.5:14) (7:10.5:14) (7:10.5:14))) + (COND ~QUAD && dual (IOPATH HOLDNeg SI () () (7:10.5:14) (7:10.5:14) (7:10.5:14) (7:10.5:14))) + + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP CSNeg (COND sdr_rd SCK) (3)) + (SETUP CSNeg (COND ddr_rd SCK) (3)) + (SETUP SI (COND deg_sin(posedge SCK)) (5)) + (SETUP SI (COND ddro(posedge SCK)) (2)) + (SETUP SI (COND ddro(negedge SCK)) (2)) + (SETUP WPNeg (COND wr_prot(negedge CSNeg)) (20)) + (SETUP HOLDNeg (COND quad_rd (posedge SCK)) (5)) + (SETUP RSTNeg CSNeg (50)) + + (HOLD CSNeg (COND sdr_rd SCK) (3)) + (HOLD CSNeg (COND ddr_rd SCK) (3)) + (HOLD SI (COND deg_sin (posedge SCK)) (4)) + (HOLD SI (COND ddro (posedge SCK)) (2)) + (HOLD SI (COND ddro (negedge SCK)) (2)) + (HOLD WPNeg (COND wr_prot (posedge CSNeg)) (100)) + (HOLD HOLDNeg (COND quad_rd (posedge SCK)) (5)) + (HOLD CSNeg RSTNeg (35000)) + + (WIDTH (COND rd (posedge SCK)) (10)) + (WIDTH (COND rd (negedge SCK)) (10)) + (WIDTH (COND dual_rd (posedge SCK)) (7.5)) + (WIDTH (COND dual_rd (negedge SCK)) (7.5)) + (WIDTH (COND fast_rd (negedge SCK)) (7.5)) + (WIDTH (COND fast_rd (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (negedge SCK)) (7.5)) + (WIDTH (COND ddrd (posedge SCK)) (7.5)) + (WIDTH (COND ddrd (negedge SCK)) (7.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (15)) + (PERIOD (COND dual_rd SCK) (15)) + (PERIOD (COND quadpg SCK) (15)) + (PERIOD (COND ddrd SCK) (15)) +) + + + +S25FL128SDPMFIR00_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR01_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR03_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR10_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR11_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR13_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI000_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI001_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI003_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI010_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI011_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI013_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI200_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI203_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI210_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI213_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI300_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI303_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI310_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI313_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHIC00_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHIC03_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHIC10_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHIC13_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHID00_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHID03_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHID10_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHID13_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for Vcc range VCC=2.7V to 3.6V, CL=15pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND ~ddr (IOPATH SCK SO (2:7:12) (2:7:12) (1) (2:7:12) (1) (2:7:12))) + (COND (ddr || rd_fast) (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && dual (IOPATH SCK SI (2:7:12) (2:7:12) (1) (2:7:12) (1) (2:7:12))) + (COND ddr && dual (IOPATH SCK SI (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND ~ddr && QUAD (IOPATH SCK HOLDNeg (2:7:12) (2:7:12) (1) (2:7:12) (1) (2:7:12))) + (COND ddr && QUAD (IOPATH SCK HOLDNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && QUAD (IOPATH SCK WPNeg (2:7:12) (2:7:12) (1) (2:7:12) (1) (2:7:12))) + (COND ddr && QUAD (IOPATH SCK WPNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && dual (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~QUAD (IOPATH HOLDNeg SO () () (7:10.5:14) (7:10.5:14) (7:10.5:14) (7:10.5:14))) + (COND ~QUAD && dual (IOPATH HOLDNeg SI () () (7:10.5:14) (7:10.5:14) (7:10.5:14) (7:10.5:14))) + + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP CSNeg (COND sdr_rd SCK) (3)) + (SETUP CSNeg (COND ddr_rd SCK) (3)) + (SETUP SI (COND deg_sin(posedge SCK)) (5)) + (SETUP SI (COND ddro(posedge SCK)) (2)) + (SETUP SI (COND ddro(negedge SCK)) (2)) + (SETUP WPNeg (COND wr_prot(negedge CSNeg)) (20)) + (SETUP HOLDNeg (COND quad_rd (posedge SCK)) (5)) + (SETUP RSTNeg CSNeg (50)) + + (HOLD CSNeg (COND sdr_rd SCK) (3)) + (HOLD CSNeg (COND ddr_rd SCK) (3)) + (HOLD SI (COND deg_sin (posedge SCK)) (4)) + (HOLD SI (COND ddro (posedge SCK)) (2)) + (HOLD SI (COND ddro (negedge SCK)) (2)) + (HOLD WPNeg (COND wr_prot (posedge CSNeg)) (100)) + (HOLD HOLDNeg (COND quad_rd (posedge SCK)) (5)) + (HOLD CSNeg RSTNeg (35000)) + + (WIDTH (COND rd (posedge SCK)) (10)) + (WIDTH (COND rd (negedge SCK)) (10)) + (WIDTH (COND dual_rd (posedge SCK)) (7.5)) + (WIDTH (COND dual_rd (negedge SCK)) (7.5)) + (WIDTH (COND fast_rd (negedge SCK)) (7.5)) + (WIDTH (COND fast_rd (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (negedge SCK)) (7.5)) + (WIDTH (COND ddrd (posedge SCK)) (7.5)) + (WIDTH (COND ddrd (negedge SCK)) (7.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (15)) + (PERIOD (COND dual_rd SCK) (15)) + (PERIOD (COND quadpg SCK) (15)) + (PERIOD (COND ddrd SCK) (15)) +) + + \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl128s/model/s25fl128s_vhd.ftm b/lib/models/memory/flash/serial/S25fl128s/model/s25fl128s_vhd.ftm new file mode 100644 index 0000000..7d90f2c --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128s/model/s25fl128s_vhd.ftm @@ -0,0 +1,783 @@ + +FMF Timing for s25fl128s Parts + + +version: | author: | mod date: | changes made: + V1.0 V.Mancev 09 Nov 26 Initial release + V1.1 V. Mancev 10 Oct 21 New datasheet aligned + R. Prokopovic + V1.2 V.Mancev 11 June 27 Latest datasheet aligned + V1.3 V.Mancev 11 Nov 16 Time tHO is changed to 1 ns + +1ns +s25fl128s + +S25FL128SAGMFI000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR01_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR11_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR01_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR11_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI200_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI203_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI210_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI213_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI300_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI303_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI310_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI313_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV200_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV203_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV210_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV213_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV300_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV303_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV310_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV313_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for VCC=2.7V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND normal (IOPATH SCK SO (5.4:6.7:8) (5.4:6.7:8) (1) (5.4:6.7:8) (1) (5.4:6.7:8))) + (COND DDR (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP (COND normal CSNeg) (posedge SCK) (3)) + (SETUP (COND DDR CSNeg) (posedge SCK) (3)) + (SETUP (COND normal SI) (posedge SCK) (3)) + (SETUP WPNeg CSNeg (20)) + (SETUP HOLDNeg SCK (3)) + (SETUP RSTNeg CSNeg (50)) + (SETUP (COND DDR SI) (posedge SCK) (2)) + (SETUP (COND DDR SI) (negedge SCK) (2)) + + (HOLD (COND normal CSNeg) (posedge SCK) (3)) + (HOLD (COND DDR CSNeg) (posedge SCK) (3)) + (HOLD (COND normal SI) (posedge SCK) (2)) + (HOLD WPNeg CSNeg (100)) + (HOLD HOLDNeg SCK (3)) + (HOLD CSNeg RSTNeg (35000)) + (HOLD (COND DDR SI) (posedge SCK) (2)) + (HOLD (COND DDR SI) (negedge SCK) (2)) + + (WIDTH (COND serial (posedge SCK)) (10)) + (WIDTH (COND serial (negedge SCK)) (10)) + (WIDTH (COND dual (posedge SCK)) (4.8)) + (WIDTH (COND dual (negedge SCK)) (4.8)) + (WIDTH (COND fast (negedge SCK)) (3.75)) + (WIDTH (COND fast (posedge SCK)) (3.75)) + (WIDTH (COND quadpg (posedge SCK)) (6.25)) + (WIDTH (COND quadpg (negedge SCK)) (6.25)) + (WIDTH (COND DDR (posedge SCK)) (7.5)) + (WIDTH (COND DDR (negedge SCK)) (7.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgers (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND serial_rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (7.52)) + (PERIOD (COND dual_rd SCK) (9.6)) + (PERIOD (COND quadpg SCK) (12.5)) + (PERIOD (COND DDR_rd SCK) (15)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP256) (DELAY (ABSOLUTE (DEVICE(183e3:366e3:550e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP512) (DELAY (ABSOLUTE (DEVICE(250e3:500e3:750e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BP) (DELAY (ABSOLUTE (DEVICE(133e3:266e3:400e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE64) (DELAY (ABSOLUTE (DEVICE(217e6:434e6:650e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE256) (DELAY (ABSOLUTE (DEVICE(625e6:1250e6:1875e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(55e9:110e9:165e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WRR) (DELAY (ABSOLUTE(DEVICE(200e6:200e6:200e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300e3:300e3:300e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PRGSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/ERSSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PPBERASE) (DELAY (ABSOLUTE (DEVICE(15e6:15e6:15e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSULCK) (DELAY (ABSOLUTE (DEVICE(1000:1000:1000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSACC) (DELAY (ABSOLUTE (DEVICE(100e3:100e3:100e3) ) ) ) + + + +S25FL128SAGMFI000_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI001_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI003_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR01_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR11_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV000_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV001_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV003_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR01_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR11_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI000_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI001_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI003_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV000_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV001_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV003_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI200_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI203_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI210_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI213_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI300_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI303_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI310_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI313_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV200_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV203_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV210_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV213_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV300_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV303_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV310_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV313_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND normal (IOPATH SCK SO (4.3:6.0:7.65) (4.3:6.0:7.65) (1) (4.3:6.0:7.65) (1) (4.3:6.0:7.65))) + (COND DDR (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP (COND normal CSNeg) (posedge SCK) (3)) + (SETUP (COND DDR CSNeg) (posedge SCK) (3)) + (SETUP (COND normal SI) (posedge SCK) (3)) + (SETUP WPNeg CSNeg (20)) + (SETUP HOLDNeg SCK (3)) + (SETUP RSTNeg CSNeg (50)) + (SETUP (COND DDR SI) (posedge SCK) (2)) + (SETUP (COND DDR SI) (negedge SCK) (2)) + + (HOLD (COND normal CSNeg) (posedge SCK) (3)) + (HOLD (COND DDR CSNeg) (posedge SCK) (3)) + (HOLD (COND normal SI) (posedge SCK) (2)) + (HOLD WPNeg CSNeg (100)) + (HOLD HOLDNeg SCK (3)) + (HOLD CSNeg RSTNeg (35000)) + (HOLD (COND DDR SI) (posedge SCK) (2)) + (HOLD (COND DDR SI) (negedge SCK) (2)) + + (WIDTH (COND serial (posedge SCK)) (10)) + (WIDTH (COND serial (negedge SCK)) (10)) + (WIDTH (COND dual (posedge SCK)) (4.8)) + (WIDTH (COND dual (negedge SCK)) (4.8)) + (WIDTH (COND fast (negedge SCK)) (3.75)) + (WIDTH (COND fast (posedge SCK)) (3.75)) + (WIDTH (COND quadpg (posedge SCK)) (6.25)) + (WIDTH (COND quadpg (negedge SCK)) (6.25)) + (WIDTH (COND DDR (posedge SCK)) (7.5)) + (WIDTH (COND DDR (negedge SCK)) (7.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgers (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND serial_rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (7.52)) + (PERIOD (COND dual_rd SCK) (9.6)) + (PERIOD (COND quadpg SCK) (12.5)) + (PERIOD (COND DDR_rd SCK) (15)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP256) (DELAY (ABSOLUTE (DEVICE(183e3:366e3:550e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP512) (DELAY (ABSOLUTE (DEVICE(250e3:500e3:750e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BP) (DELAY (ABSOLUTE (DEVICE(133e3:266e3:400e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE64) (DELAY (ABSOLUTE (DEVICE(217e6:434e6:650e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE256) (DELAY (ABSOLUTE (DEVICE(625e6:1250e6:1875e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(55e9:110e9:165e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WRR) (DELAY (ABSOLUTE(DEVICE(200e6:200e6:200e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300e3:300e3:300e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PRGSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/ERSSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PPBERASE) (DELAY (ABSOLUTE (DEVICE(15e6:15e6:15e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSULCK) (DELAY (ABSOLUTE (DEVICE(1000:1000:1000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSACC) (DELAY (ABSOLUTE (DEVICE(100e3:100e3:100e3) ) ) ) + + + +S25FL128SAGMFI000_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI001_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI003_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFI013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR01_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR11_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFIR13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV000_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV001_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV003_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFV013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR01_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR11_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGMFVR13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI000_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI001_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI003_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFI013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV000_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV001_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV003_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGNFV013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI200_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI203_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI210_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI213_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI300_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI303_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI310_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHI313_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIA13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIB13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIC13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHID13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV200_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV203_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV210_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV213_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV300_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV303_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV310_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHV313_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVA13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVB13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVC13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHVD13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIY13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIZ13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIS13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIT13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIK13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SAGBHIL13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=15pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND normal (IOPATH SCK SO (4.5:5.5:6.5) (4.5:5.5:6.5) (1) (4.5:5.5:6.5) (1) (4.5:5.5:6.5))) + (COND DDR (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP (COND normal CSNeg) (posedge SCK) (3)) + (SETUP (COND DDR CSNeg) (posedge SCK) (3)) + (SETUP (COND normal SI) (posedge SCK) (3)) + (SETUP WPNeg CSNeg (20)) + (SETUP HOLDNeg SCK (3)) + (SETUP RSTNeg CSNeg (50)) + (SETUP (COND DDR SI) (posedge SCK) (2)) + (SETUP (COND DDR SI) (negedge SCK) (2)) + + (HOLD (COND normal CSNeg) (posedge SCK) (3)) + (HOLD (COND DDR CSNeg) (posedge SCK) (3)) + (HOLD (COND normal SI) (posedge SCK) (2)) + (HOLD WPNeg CSNeg (100)) + (HOLD HOLDNeg SCK (3)) + (HOLD CSNeg RSTNeg (35000)) + (HOLD (COND DDR SI) (posedge SCK) (2)) + (HOLD (COND DDR SI) (negedge SCK) (2)) + + (WIDTH (COND serial (posedge SCK)) (10)) + (WIDTH (COND serial (negedge SCK)) (10)) + (WIDTH (COND dual (posedge SCK)) (4.8)) + (WIDTH (COND dual (negedge SCK)) (4.8)) + (WIDTH (COND fast (negedge SCK)) (3.75)) + (WIDTH (COND fast (posedge SCK)) (3.75)) + (WIDTH (COND quadpg (posedge SCK)) (6.25)) + (WIDTH (COND quadpg (negedge SCK)) (6.25)) + (WIDTH (COND DDR (posedge SCK)) (7.5)) + (WIDTH (COND DDR (negedge SCK)) (7.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgers (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND serial_rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (7.52)) + (PERIOD (COND dual_rd SCK) (9.6)) + (PERIOD (COND quadpg SCK) (12.5)) + (PERIOD (COND DDR_rd SCK) (15)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP256) (DELAY (ABSOLUTE (DEVICE(183e3:366e3:550e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP512) (DELAY (ABSOLUTE (DEVICE(250e3:500e3:750e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BP) (DELAY (ABSOLUTE (DEVICE(133e3:266e3:400e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE64) (DELAY (ABSOLUTE (DEVICE(217e6:434e6:650e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE256) (DELAY (ABSOLUTE (DEVICE(625e6:1250e6:1875e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(55e9:110e9:165e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WRR) (DELAY (ABSOLUTE(DEVICE(200e6:200e6:200e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300e3:300e3:300e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PRGSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/ERSSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PPBERASE) (DELAY (ABSOLUTE (DEVICE(15e6:15e6:15e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSULCK) (DELAY (ABSOLUTE (DEVICE(1000:1000:1000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSACC) (DELAY (ABSOLUTE (DEVICE(100e3:100e3:100e3) ) ) ) + + + +S25FL128SDPMFIR00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR01_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR11_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI200_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI203_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI210_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI213_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI300_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI303_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI310_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI313_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHIC00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHIC03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHIC10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHIC13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHID00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHID03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHID10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHID13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND normal (IOPATH SCK SO (1.5:8:14.5) (1.5:8:14.5) (1) (1.5:8:14.5) (1) (1.5:8:14.5))) + (COND DDR (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + (IOPATH HOLDNeg SO () () (10:12:14) (10:12:14) (10:12:14) (10:12:14)) + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP (COND normal CSNeg) (posedge SCK) (3)) + (SETUP (COND DDR CSNeg) (posedge SCK) (3)) + (SETUP (COND normal SI) (posedge SCK) (5)) + (SETUP WPNeg CSNeg (20)) + (SETUP HOLDNeg SCK (5)) + (SETUP RSTNeg CSNeg (50)) + (SETUP (COND DDR SI) (posedge SCK) (2)) + (SETUP (COND DDR SI) (negedge SCK) (2)) + + (HOLD (COND normal CSNeg) (posedge SCK) (3)) + (HOLD (COND DDR CSNeg) (posedge SCK) (3)) + (HOLD (COND normal SI) (posedge SCK) (4)) + (HOLD WPNeg CSNeg (100)) + (HOLD HOLDNeg SCK (5)) + (HOLD CSNeg RSTNeg (35000)) + (HOLD (COND DDR SI) (posedge SCK) (2)) + (HOLD (COND DDR SI) (negedge SCK) (2)) + + (WIDTH (COND serial (posedge SCK)) (10)) + (WIDTH (COND serial (negedge SCK)) (10)) + (WIDTH (COND dual (posedge SCK)) (7.5)) + (WIDTH (COND dual (negedge SCK)) (7.5)) + (WIDTH (COND fast (negedge SCK)) (7.5)) + (WIDTH (COND fast (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (negedge SCK)) (7.5)) + (WIDTH (COND DDR (posedge SCK)) (7.5)) + (WIDTH (COND DDR (negedge SCK)) (7.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgers (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND serial_rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (15)) + (PERIOD (COND dual_rd SCK) (15)) + (PERIOD (COND quadpg SCK) (15)) + (PERIOD (COND DDR_rd SCK) (15)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP256) (DELAY (ABSOLUTE (DEVICE(183e3:366e3:550e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP512) (DELAY (ABSOLUTE (DEVICE(250e3:500e3:750e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BP) (DELAY (ABSOLUTE (DEVICE(133e3:266e3:400e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE64) (DELAY (ABSOLUTE (DEVICE(217e6:434e6:650e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE256) (DELAY (ABSOLUTE (DEVICE(625e6:1250e6:1875e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(55e9:110e9:165e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WRR) (DELAY (ABSOLUTE(DEVICE(200e6:200e6:200e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300e3:300e3:300e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PRGSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/ERSSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PPBERASE) (DELAY (ABSOLUTE (DEVICE(15e6:15e6:15e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSULCK) (DELAY (ABSOLUTE (DEVICE(1000:1000:1000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSACC) (DELAY (ABSOLUTE (DEVICE(100e3:100e3:100e3) ) ) ) + + + +S25FL128SDPMFIR00_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR01_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR03_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR10_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR11_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPMFIR13_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI000_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI001_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI003_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI010_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI011_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPNFI013_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI200_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI203_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI210_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI213_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI300_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI303_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI310_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHI313_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHIC00_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHIC03_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHIC10_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHIC13_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHID00_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHID03_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHID10_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL128SDPBHID13_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=15pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND normal (IOPATH SCK SO (2:7:12) (2:7:12) (1) (2:7:12) (1) (2:7:12))) + (COND DDR (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + (IOPATH HOLDNeg SO () () (10:12:14) (10:12:14) (10:12:14) (10:12:14)) + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP (COND normal CSNeg) (posedge SCK) (3)) + (SETUP (COND DDR CSNeg) (posedge SCK) (3)) + (SETUP (COND normal SI) (posedge SCK) (5)) + (SETUP WPNeg CSNeg (20)) + (SETUP HOLDNeg SCK (5)) + (SETUP RSTNeg CSNeg (50)) + (SETUP (COND DDR SI) (posedge SCK) (2)) + (SETUP (COND DDR SI) (negedge SCK) (2)) + + (HOLD (COND normal CSNeg) (posedge SCK) (3)) + (HOLD (COND DDR CSNeg) (posedge SCK) (3)) + (HOLD (COND normal SI) (posedge SCK) (4)) + (HOLD WPNeg CSNeg (100)) + (HOLD HOLDNeg SCK (5)) + (HOLD CSNeg RSTNeg (35000)) + (HOLD (COND DDR SI) (posedge SCK) (2)) + (HOLD (COND DDR SI) (negedge SCK) (2)) + + (WIDTH (COND serial (posedge SCK)) (10)) + (WIDTH (COND serial (negedge SCK)) (10)) + (WIDTH (COND dual (posedge SCK)) (7.5)) + (WIDTH (COND dual (negedge SCK)) (7.5)) + (WIDTH (COND fast (negedge SCK)) (7.5)) + (WIDTH (COND fast (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (negedge SCK)) (7.5)) + (WIDTH (COND DDR (posedge SCK)) (7.5)) + (WIDTH (COND DDR (negedge SCK)) (7.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgers (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND serial_rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (15)) + (PERIOD (COND dual_rd SCK) (15)) + (PERIOD (COND quadpg SCK) (15)) + (PERIOD (COND DDR_rd SCK) (15)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP256) (DELAY (ABSOLUTE (DEVICE(183e3:366e3:550e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP512) (DELAY (ABSOLUTE (DEVICE(250e3:500e3:750e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BP) (DELAY (ABSOLUTE (DEVICE(133e3:266e3:400e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE64) (DELAY (ABSOLUTE (DEVICE(217e6:434e6:650e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE256) (DELAY (ABSOLUTE (DEVICE(625e6:1250e6:1875e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(55e9:110e9:165e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WRR) (DELAY (ABSOLUTE(DEVICE(200e6:200e6:200e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300e3:300e3:300e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PRGSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/ERSSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PPBERASE) (DELAY (ABSOLUTE (DEVICE(15e6:15e6:15e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSULCK) (DELAY (ABSOLUTE (DEVICE(1000:1000:1000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSACC) (DELAY (ABSOLUTE (DEVICE(100e3:100e3:100e3) ) ) ) + + \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl128s/utilities/CreateSDF/mk_sdf.cmd b/lib/models/memory/flash/serial/S25fl128s/utilities/CreateSDF/mk_sdf.cmd new file mode 100644 index 0000000..f6d6cc7 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128s/utilities/CreateSDF/mk_sdf.cmd @@ -0,0 +1,10 @@ +SET sdffile_suffix .sdf +SET use_global_timing_dir false +SET timingfile_dir /user/USERNAME/CreateSDF +SET timingfile_suffix .ftm +SET time_scale 1ns +SET local_path . +SET vendor MODELSIM_HOME +SET diagnostics on +SET vhdl_file testbench.vhd +SET lwb false diff --git a/lib/models/memory/flash/serial/S25fl128s/utilities/CreateSDF/mk_sdf_204.pl b/lib/models/memory/flash/serial/S25fl128s/utilities/CreateSDF/mk_sdf_204.pl new file mode 100644 index 0000000..5f2f2b8 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128s/utilities/CreateSDF/mk_sdf_204.pl @@ -0,0 +1,462 @@ +#!/usr/local/bin/perl +# +# mk_sdf : Perl replacement for C mk_sdf +# +# Copyright (C) 2000, 1999 Free Model Foundry; http:/vhdl.org/fmf/ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# Author : R. Munden +# Date : 20001115 +# Version : 2.0.4 +# +# Revision history: +# 2.0: 19990702 +# o Intial release of perl version +# 2.0.1: 19990722 +# o fixed problem with . in path for TimingModels +# 2.0.2: 20000616 +# o changed instance search to work with Mentor +# 2.0.3: 20001115 +# o changed to parse ":" without leading space +# o fixed problem with . in path for TimingModels again +# 2.0.4: 20030405 +# o chaged SDF version to 3.0 +# +################################################################# +# +# command line arguments: + +# ARGV[0] - name of VHDL netlist + +# global variables: + +# %component_list - list of instance names by component name +# %instance_isin - list architectures by instances contained therein +# %instance_comp - list of component names by instance name +# %comp_lib - library each component (by name) is configured to +# @instance_list - array of all instance names in design in order found + +$version = "2.0.4"; +$design_name = ''; +$timing_dir = ''; +$diags = "off"; + +%keywords = (architecture => 1, + component => 1, + timingmodel => 1); + +# INPUT files +$CMD = "mk_sdf.cmd"; +$VHD = ''; # name of VHDL netlist + +# OUTPUT files +$RFV = "/tmp/short.vhd"; # reformatted VHDL +$sdf_file = ''; # name of SDF file + +&read_cmd_file; +&get_names; +&reformat; + +open INPUT, $RFV; +@lines = ; +close INPUT; + +$current_architecture = ""; + +foreach $line (@lines) +{ + @words = split / /, $line; + foreach $word (@words) + { + $keywords{$word} == "1" and do { &$word(@words);}; + if ($component_list{$word}) + { + $line =~ /(.+) : $word/ and do { + if ($1 !~ /for/) { # instantiation found + $component_list{$word} = $component_list{$word} . $1; + push (@instance_list, $1); + $instance_name = $1; + } + }; + $instance_comp{$1} = $word; + $instance_isin{$1} = $current_architecture; + if ( $diags ne off ) { + print "reading instance $instance_name: $word in $current_architecture\n"; + } + $line =~ /for all : $word use entity (.+)/ and do + { + @config = split(/\./, $1); + $comp_lib{$word} = $config[0];}; + } + } +} +if ( $diags ne off ) { + print "finished with netlist\n\n"; +} + +&begin_sdf; +&build_paths; +&close_sdf; +`rm $RFV`; + +print "$time\n"; + +sub architecture +{ + $current_architecture = $_[3]; + push (@architectures, $current_architecture); +} + +sub component +{ + if ($_[0] ne "end") + { + $name = $_[1]; + $arch_list{$current_architecture} = + $arch_list{$current_architecture} . " " . $name; + unless ($component_list{$name}) { $component_list{$name} = " ";} + } +} + +sub timingmodel +{ + $line =~ /timingmodel => \"(.+)\"/ and do { + $model = $1; + $model_name{$instance_name} = $model; + }; +} + +sub begin_sdf +{ + if ( $diags ne off ) { + print "writing SDF boilerplate\n"; + } + $time = localtime; + if (open(SDF, ">$sdf_file") !=1) { die "can't open $sdf_file\n";} + print "Opening $sdf_file\n"; + print SDF "(DELAYFILE\n"; + print SDF " (SDFVERSION \"3.0\")\n"; + print SDF " (DESIGN \"$design_name\")\n"; + print SDF " (DATE \"$time\")\n"; + print SDF " (VENDOR \"Free Model Foundry\")\n"; + print SDF " (PROGRAM \"SDF timing utility(tm)\")\n"; + print SDF " (VERSION \"$version\")\n"; + print SDF " (DIVIDER /)\n"; + print SDF " (VOLTAGE)\n"; + print SDF " (PROCESS)\n"; + print SDF " (TEMPERATURE)\n"; + print SDF " (TIMESCALE 1ns)\n"; +} + +sub build_paths +{ + foreach $instance_list (@instance_list) + { + @instance = $instance_list; + foreach $instance (@instance) + { + if ( $diags ne off ) { + print "working on $instance\n"; + } + if ($gtd =~ /true/i) { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; +# $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}./$timing_dir"; + } else { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; + } + $timing_file = "$path/$instance_comp{$instance}_vhd.ftm"; + $timing_file =~ s/\s//; + if ( $diags ne off ) { + print "$instance should be in $timing_file\n"; + } + if (-e $timing_file) { + if ($model_name{$instance} ne "") { + print SDF " (CELL\n"; + print SDF " (CELLTYPE \"$instance_comp{$instance}\")\n"; + $inst = $instance; + $full_inst = $instance; + while ($component_list{$instance_isin{$inst}}) { + $full_inst = "$component_list{$instance_isin{$inst}}/$full_inst"; + $full_inst =~ s/\s+//; + $inst = $component_list{$instance_isin{$inst}}; + $inst =~ s/\s+//; +# print SDF " (INSTANCE $component_list{$instance_isin{$instance}}/$instance)\n"; + } + print SDF " (INSTANCE $full_inst)\n"; + &add_timing; + } + } else { + if ( $diags ne off ) { + print "$timing_file not found!\n"; + } + } + } + } +} + +sub add_timing +{ + $timing_found = "false"; + $part_found = "false"; +# unless ($lib_path{$comp_lib{$instance_comp{$instance}}}) + unless ($timing_file) + { + print "path to $timing_file not found\n"; + exit; + } + if ($gtd =~ /true/i) { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; +# $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}./$timing_dir"; + } else { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; + } + $timing_file = "$path/$instance_comp{$instance}_vhd.ftm"; + if (open(TF, "<$timing_file") !=1) { warn "can't open $timing_file\n"; } + if ( $diags ne off ) { + print "reading $timing_file\n"; + } + $section_found = "false"; + while () + { + next unless (/$model_name{$instance}/i || ($part_found eq "true")); + $part_found = "true"; + if ( $diags ne off ) { + print "found entry for $model_name{$instance}\n"; + } + next unless (//i || ($timing_found eq "true")); + $timing_found = "true"; + next if (//i); + if (/<\/timing>/i) + { + print SDF " )\n"; + $timing_found = "false"; + $part_found = "false"; + $section_found = "true"; + last; + } else { + if (/%LABEL%/) + { + if ($component_list{$instance_isin{$instance}}) + { + $_ =~ s/%LABEL%/$component_list{$instance_isin{$instance}}\/$instance/; + } else { + $_ =~ s/%LABEL%/$instance/; + } + } + print SDF $_; + } + } + unless ($section_found eq "true") { + print "$model_name not found\n"; + } +} + +sub close_sdf +{ + print SDF ")\n"; + print "closing $sdf_file\n"; + close(SDF); +} + +# read mk_sdf.cmd + +sub read_cmd_file { + + if (open(CMD, $CMD) !=1) { die "can't open $CMD\n"; } + while () { + chop; + @fields = ''; + @fields = split; + unless ($fields[0] =~ /#/) { + if ($fields[0] =~ /SET/) { + if ($fields[1] =~ /vhdl_file/) {$VHD = $fields[2]} + if ($fields[1] =~ /sdffile_suffix/) {$suffix = $fields[2]} + if ($fields[1] =~ /use_global_timing_dir/) {$gtd = $fields[2]} + if ($fields[1] =~ /timingfile_dir/) {$timing_dir = $fields[2]} + if ($fields[1] =~ /vendor/) {$vendor = $fields[2]} + if ($fields[1] =~ /diagnostics/) {$diags = $fields[2]} + } + } + } + if ( $diags ne off ) { + print "\nmk_sdf diagnostics on\n\n"; + print "vhdl_file $VHD\n"; + print "sdffile_suffix $suffix\n"; + print "use_global_timing_dir $gtd\n"; + print "timingfile_dir $timing_dir\n"; + print "vendor $vendor\n\n"; + } +} +# + +# get name of netlist + +sub get_names +{ + + if ($ARGV[0] ne "") { $VHD = "$ARGV[0]"; } + + if ($ARGV[1] eq "") + { + @name = split(/\./,$VHD); + $design_name = $name[0]; + } else { + $design_name = "$ARGV[1]"; + } + $sdf_file = $design_name . $suffix; + if ($gtd =~ /false/i) + { + if ($vendor =~ /modeltech/i) { &read_mti; } + if ($vendor =~ /cadence/i) { &read_cds; } + } + if ( $diags ne off ) { + print "design name is $design_name\n\n"; + } +} +# +################################################################ +# + +# reformat netlist + +sub reformat +{ + $entfound = false; + + if (open(VHD, $VHD) !=1) { die "can't open $VHD\n"; } + if (open(OUT, ">$RFV") !=1) { die "can't open $OUT\n"; } + + while () { + if (/^--|library|package/i) { next } + if (/--/) { # strip embeded comments + @line = split("--"); + $_ = $line[0]; + } + s/:/ : /g; + s/;/ ;/g; + s/\s+/ /g; # reduces spaces and tabs + s/^\s//g; # no leading spaces + if (/entity/i) { + $entfound = "true"; + } + chomp; + if ( $entfound eq true ) { + print OUT lc($_); + if (/;|is|begin/i) { print OUT "\n"; } + } + } + + close OUT; + if ( $diags ne off ) { + print "reformatted netlist written to $RFV\n\n"; + } + +} + +# read ModelTech's modelsim.ini file + +sub read_mti +{ + $lib_found = "false"; + if ($ENV{MODELPATH}) + { + $ini_file = "$ENV{MODELPATH}/../modelsim.ini"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + if ($lib_found eq "true") + { + chomp; + if (/\[.+\]/) { last; } + s/\s+//; + @lib_line = split(/=/); + $lib_line[1] =~ s/\/work//; + $lib_path{$lib_line[0]} = $lib_line[1]; + } elsif (/\[Library\]/i) + { + $lib_found = "true"; + next; + } + } + } else { + print "\$MODELPATH environment variable not found\n"; + } + $lib_found = "false"; + if (-e "modelsim.ini") + { + $ini_file = "modelsim.ini"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + if ($lib_found eq "true") + { + chomp; + if (/\[.+\]/) { last; } + s/\s+//; + @lib_line = split(/=/); + $lib_line[1] =~ s/\/work//; + $lib_path{$lib_line[0]} = $lib_line[1]; + } elsif (/\[Library\]/i) + { + $lib_found = "true"; + next; + } + } + } else { + print "local modelsim.ini file not found, may not be needed\n"; + } +} + +# read Cadence's cds.lib file + +sub read_cds +{ + if ($ENV{CDS_VHDL}) + { + $ini_file = "$ENV{CDS_VHDL}/files/cds.lib"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + chomp; + s/\s+/ /; + if (/define/i) + { + @lib_line = split; + $lib_path{$lib_line[1]} = $lib_line[2]; + } + } + } else { + print "\$CDS_VHDL environment variable not found\n"; + } + if (-e "cds.lib") + { + $ini_file = "cds.lib"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + chomp; + s/\s+/ /; + if (/define/i) + { + @lib_line = split; + $lib_path{$lib_line[1]} = $lib_line[2]; + } + } + } else { + print "local cds.lib file not found, may not be needed\n"; + } +} diff --git a/lib/models/memory/flash/serial/S25fl128s/utilities/CreateSDF/my_mem_vhd.ftm b/lib/models/memory/flash/serial/S25fl128s/utilities/CreateSDF/my_mem_vhd.ftm new file mode 100644 index 0000000..2fc35c2 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128s/utilities/CreateSDF/my_mem_vhd.ftm @@ -0,0 +1,205 @@ + +FMF Timing for testbench Parts + + +version: | author: | mod date: | changes made: + V1.0 VHD2FTM 03 July 11 Initial release + +1ns +am29lv640m + +MY_MEM +AM29LV640MH90R +AM29LV640ML90R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (90:90:90) (90:90:90)) + (IOPATH A0 DQ1 (25:25:25) (25:25:25)) + (IOPATH CENeg DQ0 (85:85:85) (85:85:85) (11:11:11) (85:85:85) (11:11:11) (85:85:85)) + (IOPATH OENeg DQ0 (20:20:20) (20:20:20) (11:11:11) (20:20:20) (11:11:11) (20:20:20)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (90)) + (IOPATH WENeg RY (0) (90)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (90:90:90)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH101 +AM29LV640ML101 +AM29LV640MH101R +AM29LV640ML101R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (100:100:100) (100:100:100)) + (IOPATH A0 DQ1 (30:30:30) (30:30:30)) + (IOPATH CENeg DQ0 (95:95:95) (95:95:95) (11:11:11) (95:95:95) (11:11:11) (95:95:95)) + (IOPATH OENeg DQ0 (25:25:25) (25:25:25) (11:11:11) (25:25:25) (11:11:11) (25:25:25)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (100)) + (IOPATH WENeg RY (0) (100)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (100:100:100)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH112 +AM29LV640ML112 +AM29LV640MH112R +AM29LV640ML112R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (110:110:110) (110:110:110)) + (IOPATH A0 DQ1 (40:40:40) (40:40:40)) + (IOPATH CENeg DQ0 (105:105:105) (105:105:105) (11:11:11) (105:105:105) (11:11:11) (105:105:105)) + (IOPATH OENeg DQ0 (35:35:35) (35:35:35) (11:11:11) (35:35:35) (11:11:11) (35:35:35)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (110)) + (IOPATH WENeg RY (0) (110)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (110:110:110)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH120 +AM29LV640ML120 +AM29LV640MH120R +AM29LV640ML120R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (120:120:120) (120:120:120)) + (IOPATH A0 DQ1 (40:40:40) (40:40:40)) + (IOPATH CENeg DQ0 (115:115:115) (115:115:115) (11:11:11) (115:115:115) (11:11:11) (115:115:115)) + (IOPATH OENeg DQ0 (35:35:35) (35:35:35) (11:11:11) (35:35:35) (11:11:11) (35:35:35)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (120)) + (IOPATH WENeg RY (0) (120)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (120:120:120)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + diff --git a/lib/models/memory/flash/serial/S25fl128s/utilities/CreateSDF/testbench.sdf b/lib/models/memory/flash/serial/S25fl128s/utilities/CreateSDF/testbench.sdf new file mode 100644 index 0000000..02495dd --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128s/utilities/CreateSDF/testbench.sdf @@ -0,0 +1,58 @@ +(DELAYFILE + (SDFVERSION "3.0") + (DESIGN "testbench") + (DATE "Wed Jan 28 15:15:41 2004") + (VENDOR "Free Model Foundry") + (PROGRAM "SDF timing utility(tm)") + (VERSION "2.0.4") + (DIVIDER /) + (VOLTAGE) + (PROCESS) + (TEMPERATURE) + (TIMESCALE 1ns) + (CELL + (CELLTYPE "my_mem") + (INSTANCE dut) + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (90:90:90) (90:90:90)) + (IOPATH A0 DQ1 (25:25:25) (25:25:25)) + (IOPATH CENeg DQ0 (85:85:85) (85:85:85) (11:11:11) (85:85:85) (11:11:11) (85:85:85)) + (IOPATH OENeg DQ0 (20:20:20) (20:20:20) (11:11:11) (20:20:20) (11:11:11) (20:20:20)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (90)) + (IOPATH WENeg RY (0) (90)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (90:90:90)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + ) +) diff --git a/lib/models/memory/flash/serial/S25fl128s/utilities/CreateSDF/testbench.vhd b/lib/models/memory/flash/serial/S25fl128s/utilities/CreateSDF/testbench.vhd new file mode 100644 index 0000000..c7d852a --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128s/utilities/CreateSDF/testbench.vhd @@ -0,0 +1,1606 @@ +------------------------------------------------------------------------------ +-- File name : testbench_640.vhd +------------------------------------------------------------------------------- +-- Copyright (C) 2003 AMD. +-- +-- MODIFICATION HISTORY : +-- +-- version: | author: | mod date: | changes made: +-- V0.1 M.Marinkovic 11 July 03 Initial +-- v0.2 M.Marinkovic 28 Aug 03 Changed protected sector selection +-- +------------------------------------------------------------------------------- +-- PART DESCRIPTION: +-- +-- Description: +-- Generic test enviroment for verification of AMD flash memory +-- VITAL models.my_mem +-- +------------------------------------------------------------------------------- +-- Note: VHDL code formating not done +-- For High/Low sector protection selection change: +-- TimingModel constant and TimingModel generic value +-- +------------------------------------------------------------------------------- +LIBRARY IEEE; + USE IEEE.std_logic_1164.ALL; +--USE IEEE.VITAL_timing.ALL; +--USE IEEE.VITAL_primitives.ALL; + USE STD.textio.ALL; + +LIBRARY VITAL2000; + USE VITAL2000.vital_timing.ALL; + USE VITAL2000.vital_primitives.ALL; + +LIBRARY FMF; + USE FMF.gen_utils.ALL; + USE FMF.conversions.ALL; + + +LIBRARY work; + USE work.amd_tc_pkg.ALL; + +------------------------------------------------------------------------------- +-- ENTITY DECLARATION +------------------------------------------------------------------------------- +ENTITY testbench_640 IS +END testbench_640; + + +------------------------------------------------------------------------------- +-- ARCHITECTURE DECLARATION +------------------------------------------------------------------------------- +ARCHITECTURE vhdl_behavioral of testbench_640 IS + COMPONENT my_mem + GENERIC ( + -- tipd delays: interconnect path delays + tipd_A0 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A1 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A2 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A3 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A4 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A5 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A6 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A7 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A8 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A9 : VitalDelayType01 := VitalZeroDelay01; --address + tipd_A10 : VitalDelayType01 := VitalZeroDelay01; --lines + tipd_A11 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A12 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A13 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A14 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A15 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A16 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A17 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A18 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A19 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A20 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A21 : VitalDelayType01 := VitalZeroDelay01; -- + + tipd_DQ0 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ1 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ2 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ3 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ4 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ5 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ6 : VitalDelayType01 := VitalZeroDelay01; -- data + tipd_DQ7 : VitalDelayType01 := VitalZeroDelay01; -- lines + tipd_DQ8 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ9 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ10 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ11 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ12 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ13 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ14 : VitalDelayType01 := VitalZeroDelay01; -- + + tipd_DQ15 : VitalDelayType01 := VitalZeroDelay01; -- DQ15/A-1 + + tipd_CENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_OENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_RESETNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; --WP#/ACC + tipd_BYTENeg : VitalDelayType01 := VitalZeroDelay01; + + -- tpd delays + tpd_A0_DQ0 : VitalDelayType01 := UnitDelay01;--tACC + tpd_A0_DQ1 : VitalDelayType01 := UnitDelay01;--tPACC + tpd_CENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(tCE,tCE,tDF,-,tDF,-) + tpd_OENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(tOE,tOE,tDF,-,tDF,-) + tpd_RESETNeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(-,-,0,-,0,-) + tpd_CENeg_RY : VitalDelayType01 := UnitDelay01; --tBUSY + tpd_WENeg_RY : VitalDelayType01 := UnitDelay01; --tBUSY + + --tsetup values + tsetup_A0_CENeg : VitalDelayType := UnitDelay; --tAS edge \ + tsetup_A0_OENeg : VitalDelayType := UnitDelay; --tASO edge \ + tsetup_DQ0_CENeg : VitalDelayType := UnitDelay; --tDS edge / + + --thold values + thold_CENeg_RESETNeg: VitalDelayType := UnitDelay; --tRH edge / + thold_OENeg_WENeg : VitalDelayType := UnitDelay; --tOEH edge / + thold_A0_CENeg : VitalDelayType := UnitDelay; --tAH edge \ + thold_A0_OENeg : VitalDelayType := UnitDelay; --tAHT edge \ + thold_DQ0_CENeg : VitalDelayType := UnitDelay; --tDH edge / + thold_WENeg_OENeg : VitalDelayType := UnitDelay; --tGHWL edge / + + --tpw values: pulse width + tpw_RESETNeg_negedge: VitalDelayType := UnitDelay; --tRP + tpw_OENeg_posedge : VitalDelayType := UnitDelay; --tOEPH + tpw_WENeg_negedge : VitalDelayType := UnitDelay; --tWP + tpw_WENeg_posedge : VitalDelayType := UnitDelay; --tWPH + tpw_CENeg_negedge : VitalDelayType := UnitDelay; --tCP + tpw_CENeg_posedge : VitalDelayType := UnitDelay; --tCEPH + tpw_A0_negedge : VitalDelayType := UnitDelay; --tWC tRC + + + -- tdevice values: values for internal delays + --Effective Write Buffer Program Operation tWHWH1 + tdevice_WBPB : VitalDelayType := 11 us; + --Program Operation + tdevice_POB : VitalDelayType := 100 us; + --Sector Erase Operation tWHWH2 + tdevice_SEO : VitalDelayType := 500 ms; + --Timing Limit Exceeded + tdevice_HANG : VitalDelayType := 400 ms; --? + --program/erase suspend timeout + tdevice_START_T1 : VitalDelayType := 5 us; + --sector erase command sequence timeout + tdevice_CTMOUT : VitalDelayType := 50 us; + --device ready after Hardware reset(during embeded algorithm) + tdevice_READY : VitalDelayType := 20 us; --tReady + + -- generic control parameters + InstancePath : STRING := DefaultInstancePath; + TimingChecksOn : BOOLEAN := DefaultTimingChecks; + MsgOn : BOOLEAN := DefaultMsgOn; + XOn : BOOLEAN := DefaultXon; + -- memory file to be loaded + mem_file_name : STRING ;--:= "am29lv640m.mem"; + prot_file_name : STRING ;--:= "am29lv640m_prot.mem"; + secsi_file_name : STRING ;--:= "am29lv_secsi.mem"; + + UserPreload : BOOLEAN ;--:= TRUE; + LongTimming : BOOLEAN ;--:= TRUE; + + -- For FMF SDF technology file usage + TimingModel : STRING --:= "AM29LV640MH90R" + ); + PORT ( + A21 : IN std_logic := 'U'; -- + A20 : IN std_logic := 'U'; -- + A19 : IN std_logic := 'U'; -- + A18 : IN std_logic := 'U'; -- + A17 : IN std_logic := 'U'; -- + A16 : IN std_logic := 'U'; -- + A15 : IN std_logic := 'U'; -- + A14 : IN std_logic := 'U'; -- + A13 : IN std_logic := 'U'; --address + A12 : IN std_logic := 'U'; --lines + A11 : IN std_logic := 'U'; -- + A10 : IN std_logic := 'U'; -- + A9 : IN std_logic := 'U'; -- + A8 : IN std_logic := 'U'; -- + A7 : IN std_logic := 'U'; -- + A6 : IN std_logic := 'U'; -- + A5 : IN std_logic := 'U'; -- + A4 : IN std_logic := 'U'; -- + A3 : IN std_logic := 'U'; -- + A2 : IN std_logic := 'U'; -- + A1 : IN std_logic := 'U'; -- + A0 : IN std_logic := 'U'; -- + + DQ15 : INOUT std_logic := 'U'; -- DQ15/A-1 + DQ14 : INOUT std_logic := 'U'; -- + DQ13 : INOUT std_logic := 'U'; -- + DQ12 : INOUT std_logic := 'U'; -- + DQ11 : INOUT std_logic := 'U'; -- + DQ10 : INOUT std_logic := 'U'; -- + DQ9 : INOUT std_logic := 'U'; -- data + DQ8 : INOUT std_logic := 'U'; -- lines + DQ7 : INOUT std_logic := 'U'; -- + DQ6 : INOUT std_logic := 'U'; -- + DQ5 : INOUT std_logic := 'U'; -- + DQ4 : INOUT std_logic := 'U'; -- + DQ3 : INOUT std_logic := 'U'; -- + DQ2 : INOUT std_logic := 'U'; -- + DQ1 : INOUT std_logic := 'U'; -- + DQ0 : INOUT std_logic := 'U'; -- + + CENeg : IN std_logic := 'U'; + OENeg : IN std_logic := 'U'; + WENeg : IN std_logic := 'U'; + RESETNeg : IN std_logic := 'U'; + WPNeg : IN std_logic := 'U'; --WP#/ACC + BYTENeg : IN std_logic := 'U'; + RY : OUT std_logic := 'U' --RY/BY# + ); + END COMPONENT; + + FOR ALL: my_mem USE ENTITY WORK.my_mem(VHDL_BEHAVIORAL); + + --------------------------------------------------------------------------- + --memory configuration + --------------------------------------------------------------------------- + CONSTANT MaxData : NATURAL := 16#FF#; --255; + CONSTANT SecSize : NATURAL := 16#FFFF#; --65535 + CONSTANT SecSiSize : NATURAL := 255; + CONSTANT SecNum : NATURAL := 127; + CONSTANT HiAddrBit : NATURAL := 21; + --Address of the Protected Sector +-- CONSTANT ProtSecNum : NATURAL := SecNum; + + --------------------------------------------------------------------------- + --model configuration + --------------------------------------------------------------------------- + CONSTANT mem_file : STRING := "am29lv640m.mem"; + CONSTANT prot_file : STRING := "am29lv640m_prot.mem"; + CONSTANT secsi_file : STRING := "am29lv_secsi.mem"; + + CONSTANT UserPreload : boolean := TRUE; + CONSTANT DebugInfo : boolean := FALSE; + CONSTANT LongTimming : boolean := TRUE; + CONSTANT TimingModel : STRING := "MY_MEM"; + -- "AM29LV640MH90R";--High sect prot. + -- "AM29LV128ML93R";--Low sect. prot. + --------------------------------------------------------------------------- + SIGNAL ProtSecNum : NATURAL := SecNum ; + + --Flash Memory Array + TYPE SecType IS ARRAY (0 TO SecSize) OF + INTEGER RANGE -1 TO MaxData; + TYPE MemArray IS ARRAY (0 TO SecNum) OF + SecType; + + --Common Flash Interface Query codes + TYPE CFItype IS ARRAY (16#10# TO 16#50#) OF + NATURAL RANGE 0 TO 16#FF#; + + --SecSi Sector + TYPE SecSiType IS ARRAY ( 0 TO SecSiSize) OF + INTEGER RANGE -1 TO MaxData; + + --------------------------------------------------------------------------- + -- memory declaration + --------------------------------------------------------------------------- + -- -- Mem(SecAddr)(Address).... + SHARED VARIABLE Mem : MemArray := (OTHERS => (OTHERS=> MaxData)); + SHARED VARIABLE CFI_array : CFItype :=(OTHERS=>0); + SHARED VARIABLE SecSi : SecSiType :=(OTHERS=>0); + + --command sequence + SHARED VARIABLE cmd_seq : cmd_seq_type; + + SIGNAL status : status_type := none; + SIGNAL sts_check : std_logic_vector(7 downto 0); + + + SIGNAL check_err : std_logic := '0'; + SIGNAL ErrorInTest : std_logic := '0'; -- + ---------------------------------------------------------------------------- + --Personality module: + -- + -- instanciates the DUT module and adapts generic test signals to it + -- TBD: block port + ---------------------------------------------------------------------------- + --DUT port + SIGNAL T_DQ : std_logic_vector(15 downto 0) := (OTHERS=>'U'); + SIGNAL T_A : std_logic_vector(HiAddrBit downto 0) := (OTHERS=>'U'); + SIGNAL T_RESETNeg : std_logic := 'U'; + SIGNAL T_CENeg : std_logic := 'U'; + SIGNAL T_WENeg : std_logic := 'U'; + SIGNAL T_OENeg : std_logic := 'U'; + SIGNAL T_WPNeg : std_logic := 'U'; + SIGNAL T_BYTENeg : std_logic := 'U'; + SIGNAL T_RY : std_logic := 'U'; + + --------------------------------------------------------------------------- + -- + --------------------------------------------------------------------------- + --SecSi ProtectionStatus + SHARED VARIABLE FactoryProt : std_logic := '1'; + --Sector Protection Status + SHARED VARIABLE Sec_Prot : std_logic_vector (SecNum downto 0) := + (OTHERS => '0'); + SHARED VARIABLE Sect : NATURAL RANGE 0 TO SecNum := 0; + SHARED VARIABLE Addr : NATURAL RANGE 0 TO SecSize := 0; + SHARED VARIABLE WriteData : NATURAL RANGE 0 TO MaxData := 0; + + + --CONSTANT + --timming parameters + CONSTANT RESETNeg_pw : time := 500 ns; --tRP + + SIGNAL pwron : std_logic := '0'; + + SIGNAL Tseries : NATURAL; + SIGNAL Tcase : NATURAL; + + SHARED VARIABLE ts_cnt : NATURAL RANGE 1 TO 30:=1; -- testseries counter + SHARED VARIABLE tc_cnt : NATURAL RANGE 0 TO 10:=0; -- testcase counter + + + BEGIN + DUT : my_mem + GENERIC MAP ( + -- tipd delays: interconnect path delays + tipd_A0 => VitalZeroDelay01, -- + tipd_A1 => VitalZeroDelay01, -- + tipd_A2 => VitalZeroDelay01, -- + tipd_A3 => VitalZeroDelay01, -- + tipd_A4 => VitalZeroDelay01, -- + tipd_A5 => VitalZeroDelay01, -- + tipd_A6 => VitalZeroDelay01, -- + tipd_A7 => VitalZeroDelay01, -- + tipd_A8 => VitalZeroDelay01, -- + tipd_A9 => VitalZeroDelay01, --address + tipd_A10 => VitalZeroDelay01, --lines + tipd_A11 => VitalZeroDelay01, -- + tipd_A12 => VitalZeroDelay01, -- + tipd_A13 => VitalZeroDelay01, -- + tipd_A14 => VitalZeroDelay01, -- + tipd_A15 => VitalZeroDelay01, -- + tipd_A16 => VitalZeroDelay01, -- + tipd_A17 => VitalZeroDelay01, -- + tipd_A18 => VitalZeroDelay01, -- + tipd_A19 => VitalZeroDelay01, -- + tipd_A20 => VitalZeroDelay01, -- + tipd_A21 => VitalZeroDelay01, -- + + tipd_DQ0 => VitalZeroDelay01, -- + tipd_DQ1 => VitalZeroDelay01, -- + tipd_DQ2 => VitalZeroDelay01, -- + tipd_DQ3 => VitalZeroDelay01, -- + tipd_DQ4 => VitalZeroDelay01, -- + tipd_DQ5 => VitalZeroDelay01, -- + tipd_DQ6 => VitalZeroDelay01, -- data + tipd_DQ7 => VitalZeroDelay01, -- lines + tipd_DQ8 => VitalZeroDelay01, -- + tipd_DQ9 => VitalZeroDelay01, -- + tipd_DQ10 => VitalZeroDelay01, -- + tipd_DQ11 => VitalZeroDelay01, -- + tipd_DQ12 => VitalZeroDelay01, -- + tipd_DQ13 => VitalZeroDelay01, -- + tipd_DQ14 => VitalZeroDelay01, -- + + tipd_DQ15 => VitalZeroDelay01, -- DQ15/A-1 + + tipd_CENeg => VitalZeroDelay01, + tipd_OENeg => VitalZeroDelay01, + tipd_WENeg => VitalZeroDelay01, + tipd_RESETNeg => VitalZeroDelay01, + tipd_WPNeg => VitalZeroDelay01,--WP#/ACC + tipd_BYTENeg => VitalZeroDelay01, + + -- tpd delays + tpd_A0_DQ0 => UnitDelay01,--tACC + tpd_A0_DQ1 => UnitDelay01,--tPACC + tpd_CENeg_DQ0 => UnitDelay01Z, + --(tCE,tCE,tDF,-,tDF + tpd_OENeg_DQ0 => UnitDelay01Z, + --(tOE,tOE,tDF,-,tDF + tpd_RESETNeg_DQ0 => UnitDelay01Z, + --(-,-,0,-,0,-) + tpd_CENeg_RY => UnitDelay01, --tBUSY + tpd_WENeg_RY => UnitDelay01, --tBUSY + + --tsetup values + tsetup_A0_CENeg => UnitDelay, --tAS edge \ + tsetup_A0_OENeg => UnitDelay, --tASO edge \ + tsetup_DQ0_CENeg => UnitDelay, --tDS edge / + + --thold values + thold_CENeg_RESETNeg=> UnitDelay, --tRH edge / + thold_OENeg_WENeg => UnitDelay, --tOEH edge / + thold_A0_CENeg => UnitDelay, --tAH edge \ + thold_A0_OENeg => UnitDelay, --tAHT edge \ + thold_DQ0_CENeg => UnitDelay, --tDH edge / + thold_WENeg_OENeg => UnitDelay, --tGHVL edge / + + --tpw values: pulse width + tpw_RESETNeg_negedge=> UnitDelay, --tRP + tpw_OENeg_posedge => UnitDelay, --tOEPH + tpw_WENeg_negedge => UnitDelay, --tWP + tpw_WENeg_posedge => UnitDelay, --tWPH + tpw_CENeg_negedge => UnitDelay, --tCP + tpw_CENeg_posedge => UnitDelay, --tCEPH + tpw_A0_negedge => UnitDelay, --tWC tRC + -- tdevice values: values for internal delays + --Effective Write Buffer Program Operation tWHWH1 + tdevice_WBPB => 11 us, + --Program Operation + tdevice_POB => 100 us, + --Sector Erase Operation tWHWH2 + tdevice_SEO => 500 ms, + --Timing Limit Exceeded + tdevice_HANG => 400 ms, --? + --program/erase suspend timeout + tdevice_START_T1 => 5 us, + --sector erase command sequence timeout + tdevice_CTMOUT => 50 us, + --device ready after Hardware reset(during embeded algorithm) + tdevice_READY => 20 us, --tReady + + -- generic control parameters + InstancePath => DefaultInstancePath, + TimingChecksOn => TRUE,--DefaultTimingChecks, + MsgOn => DefaultMsgOn, + XOn => DefaultXon, + -- memory file to be loaded + mem_file_name => mem_file, + prot_file_name => prot_file , + secsi_file_name => secsi_file, + + UserPreload => UserPreload, + LongTimming => LongTimming, + -- For FMF SDF technology file usage + TimingModel => "AM29LV640MH90R" -- TimingModel + ) + PORT MAP( + A21 => T_A(21), -- + A20 => T_A(20), -- + A19 => T_A(19), -- + A18 => T_A(18), -- + A17 => T_A(17), -- + A16 => T_A(16), -- + A15 => T_A(15), -- + A14 => T_A(14), -- + A13 => T_A(13), --address + A12 => T_A(12), --lines + A11 => T_A(11), -- + A10 => T_A(10), -- + A9 => T_A(9), -- + A8 => T_A(8), -- + A7 => T_A(7), -- + A6 => T_A(6), -- + A5 => T_A(5),-- + A4 => T_A(4),-- + A3 => T_A(3), -- + A2 => T_A(2), -- + A1 => T_A(1), -- + A0 => T_A(0), -- + + DQ15 => T_DQ(15), -- DQ15/A-1 + DQ14 => T_DQ(14), -- + DQ13 => T_DQ(13), -- + DQ12 => T_DQ(12), -- + DQ11 => T_DQ(11), -- + DQ10 => T_DQ(10), -- + DQ9 => T_DQ(9), -- data + DQ8 => T_DQ(8), -- lines + DQ7 => T_DQ(7), -- + DQ6 => T_DQ(6), -- + DQ5 => T_DQ(5), -- + DQ4 => T_DQ(4), -- + DQ3 => T_DQ(3), -- + DQ2 => T_DQ(2), -- + DQ1 => T_DQ(1), -- + DQ0 => T_DQ(0), -- + + CENeg => T_CENeg, + OENeg => T_OENeg, + WENeg => T_WENeg, + RESETNeg => T_RESETNeg, + WPNeg => T_WPNeg, --WP#/ACC + BYTENeg => T_BYTENeg, + RY => T_RY --RY/BY# + ); + + --------------------------------------------------------------------------- + --protected sector + --------------------------------------------------------------------------- + ProtSecNum <= SecNum WHEN TimingModel(11) = 'H' ELSE + 0 ;-- WHEN TimingModel = "AM29LV128ML93R" + + pwron <= '0', '1' after 1 ns; + +--At the end of the simulation, if ErrorInTest='0' there were no errors +err_ctrl : PROCESS ( check_err ) + BEGIN + IF check_err = '1' THEN + ErrorInTest <= '1'; + END IF; + END PROCESS err_ctrl; + +tb :PROCESS + + -------------------------------------------------------------------------- + --= PROCEDURE to select TC + -- can be modified to read TC list from file, or to generate random list + -------------------------------------------------------------------------- + PROCEDURE Pick_TC + (Model : IN STRING := "AM29LV640MH90R" ) + IS + BEGIN + IF TC_cnt < tc(TS_cnt) THEN + TC_cnt := TC_cnt+1; + ELSE + TC_cnt:=1; + IF TS_cnt<30 THEN + TS_cnt := TS_cnt+1; + ELSE + -- end test + IF ErrorInTest='0' THEN + REPORT "Test Ended without errors" + SEVERITY note; + ELSE + REPORT "There were errors in test" + SEVERITY note; + END IF; + WAIT; + END IF; + END IF; + END PROCEDURE Pick_TC; + + --------------------------------------------------------------------------- + --bus commands, device specific implementation + --------------------------------------------------------------------------- + TYPE bus_type IS (bus_idle, + bus_standby, --CE# deasseretd, others are don't care + bus_enable, --CE# asserted, others deasserted + bus_output_disable, + bus_reset, + bus_write, + bus_read); + + --bus drive for specific command sequence cycle + PROCEDURE bus_cycle( + bus_cmd :IN bus_type := bus_idle; + byte :IN boolean ; + data :IN INTEGER RANGE -2 TO MaxData := -2; -- -1 for all Z + dataHi :IN INTEGER RANGE -2 TO MaxData := -2; -- -2 for ignore + sector :IN INTEGER RANGE -1 TO SecNum := -1; -- -1 for ignore addr + address :IN NATURAL RANGE 0 TO SecSize := 0; + disable :IN boolean := false; + violate :IN boolean := false; + tm :IN TIME := 10 ns) + IS + + VARIABLE tmp : std_logic_vector(15 downto 0); + BEGIN + + IF data=-1 THEN -- HiZ + T_DQ(7 downto 0) <= (OTHERS => 'Z'); + END IF; + + IF (NOT byte)THEN --word access + IF dataHi=-1 THEN -- HiZ + T_DQ(15 downto 8) <= (OTHERS => 'Z'); + END IF; + T_BYTENeg <= '1'; + ELSE --byte access + T_BYTENeg <= '0'; + T_DQ(14 downto 8) <= (OTHERS => 'Z'); + END IF; + + IF sector > -1 THEN + T_A(HiAddrBit downto 15) <= to_slv(sector, HiAddrbit-14); + tmp := to_slv(address, 16); + IF byte THEN + T_A(14 downto 0) <= tmp(15 downto 1); + T_DQ(15) <= tmp(0); + ELSE + T_A(14 downto 0) <= tmp(14 downto 0); + END IF; + + END IF; + + wait for 1 ns; + + CASE bus_cmd IS + WHEN bus_output_disable => + T_OENeg <= '1'; + WAIT FOR 20 ns; + + WHEN bus_idle => + T_RESETNeg <= '1'; + T_WENeg <= '1'; + T_CENeg <= '1'; + T_OENeg <= '1'; + IF disable THEN + T_WPNeg <= '0'; + ELSE + T_WPNeg <= '1'; + END IF; + WAIT FOR 30 ns; + + WHEN bus_standby => + T_CENeg <= '1'; + WAIT FOR 30 ns; + + WHEN bus_reset => + T_RESETNeg <= '0', '1' AFTER tm ; + -- WAIT FOR 500 ns should follow this bus cmd for reset to + --complete + WAIT FOR 30 ns; + + WHEN bus_enable => + T_WENeg <= '1' AFTER 50 ns; --- + T_CENeg <= '0' AFTER 50 ns; --- + T_OENeg <= '1' AFTER 30 ns; --- + + WAIT FOR tm ; + + WHEN bus_write => + T_OENeg <= '1' ;-- AFTER 5 ns; + T_CENeg <= '0' AFTER 10 ns ; + T_WENeg <= '0' AFTER 20 ns; + + IF data>-1 THEN + T_DQ(7 downto 0) <= to_slv(data,8); + END IF; + IF NOT byte THEN + IF dataHi>-1 THEN + T_DQ(15 downto 8) <= to_slv(dataHi,8); + END IF; + END IF; + + IF violate THEN + T_WENeg <= '1'; + WAIT FOR 50 ns; + T_WENeg <= '0', '1' AFTER tm; + WAIT FOR 50 ns; + ELSE + WAIT FOR 100 ns; + END IF; + + WHEN bus_read => + + T_CENeg <= '0' ; + T_WENeg <= '1'AFTER 10 ns; + IF NOT disable THEN + T_OENeg <= '0' AFTER 15 ns; + ELSE + T_OENeg <= '1'; + END IF; + + IF NOT byte THEN + T_DQ(15 downto 8) <= (OTHERS => 'Z'); + END IF; + T_DQ(7 downto 0) <= (OTHERS => 'Z'); + + WAIT FOR 100 ns; + + -- T_OENeg <= '1' ; ----------- + + END CASE; + + + END PROCEDURE; + + + --------------------------------------------------------------------------- + --procedure to decode commands into specific bus command sequence + --------------------------------------------------------------------------- + PROCEDURE cmd_dc + ( command : IN cmd_rec ) + IS + VARIABLE D_hi : NATURAL ;--RANGE 0 to MaxData; + VARIABLE D_lo : NATURAL RANGE 0 to MaxData; + VARIABLE Addr : NATURAL RANGE 0 to SecSize :=0; + VARIABLE Addrfix : NATURAL RANGE 0 to SecSize/2:=0; + VARIABLE Sect : INTEGER RANGE -1 to SecNum :=0; + VARIABLE slv_1, slv_2 : std_logic_vector(7 downto 0); + VARIABLE byte : boolean; + VARIABLE i : NATURAL; + BEGIN + CASE command.cmd IS + WHEN idle => + bus_cycle(bus_cmd => bus_idle, + byte => command.byte, + disable => command.aux=disable); + + WHEN h_reset => + bus_cycle(bus_cmd => bus_reset, + byte => command.byte, + tm => command.wtime); + + WHEN rd => + bus_cycle(bus_cmd => bus_enable, + byte => command.byte, + data => -1, + sector => command.sect, + address => command.addr, + tm => 90 ns); + + bus_cycle(bus_cmd => bus_read, + byte => command.byte, + data => -1, + dataHi => -1, + sector => command.sect, + address => command.addr, + disable => command.aux=disable); + + bus_cycle(bus_cmd => bus_output_disable, + byte => command.byte); + + WHEN rd_page => + bus_cycle(bus_cmd => bus_enable, + byte => command.byte, + data => -1, + sector => 0, + address => 0, + tm => 90 ns); + + Addr := command.addr; + Sect := command.sect; + byte := command.byte; + ---- 08July---- + WAIT FOR 10 ns; + -------------- + i := 0; + WHILE i < command.d_hi LOOP + + IF command.wtime > 0 ns THEN + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + --byte toggle mode + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + byte := false; + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + Addrfix := Addr /2; + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + --word read; + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addrfix); + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + byte := true; + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 30 ns); + + --first byte read + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addr); + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + i := i +3; + wait for 10 ns; ------- + ELSE + byte := command.byte; + END IF; + --second byte read in byte toggle mode + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addr); + + + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + i := i +1; + WAIT FOR 10 ns; + END LOOP; + bus_cycle(bus_cmd => bus_output_disable, + byte => command.byte); + + + + WHEN w_cycle => + + D_lo := 16#AA# ; --first command data + Addr := 16#AAA#; --first command byte address + D_hi := 16#55#; --second command data + Addrfix := 16#555#; --second command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + Addrfix := 16#2AA#; --second command byte address + END IF; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_lo, + dataHi => 0, + sector => 0, + address => Addr, + violate => command.aux=violate, + tm => command.wtime); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_hi, + dataHi => 0, + sector => 0, + address => Addrfix); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_reset | w_prog | w_erase | w_unlock | + w_autoselect | w_enter_sec => + Addr := 16#AAA#; + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + + CASE command.cmd IS + WHEN w_reset => + d_lo := 16#F0#; + WHEN w_prog => + d_lo := 16#A0#; + WHEN w_erase => + d_lo := 16#80#; + WHEN w_unlock => + d_lo := 16#20#; + WHEN w_autoselect => + d_lo := 16#90#; + WHEN w_enter_sec => + d_lo := 16#88#; + WHEN OTHERS => + d_lo := 0; + END CASE; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => d_lo, + dataHi => 0, + sector => 0, + address => Addr); + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + + WHEN w_unlock_reset => + Addr := 16#AAA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#90#, + dataHi => 0, + sector => 0, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#F0#, + dataHi => 0, + sector => 0, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + WHEN w_chip_ers => + Addr := 16#AAA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#10#, + dataHi => 0, + sector => 0, + Address => Addr); + FOR i IN 0 TO SecNum LOOP + IF Sec_Prot(i)/='1' THEN + mem(i) := (OTHERS=>16#FF#); + END IF; + END LOOP; + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_cfi => + Addr := 16#AA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#55#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#98#, + dataHi => 0, + sector => 0, + Address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + + WHEN w_suspend => + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#B0#, + dataHi => 0, + sector => -1); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + WHEN w_resume => + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#30#, + dataHi => 0, + sector => -1); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_data => + + D_hi := command.d_hi MOD 16#100#; + D_lo := command.d_lo ; + Addr := command.addr; + Sect := command.sect; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_lo, + dataHi => D_hi, + sector => Sect, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + IF NOT command.byte THEN + Addr := Addr*2; + END IF; + + --write value(s) in default mem + IF status = erase_active AND Sec_Prot(Sect)/='1'THEN + --sector should be erased + mem(Sect) := (OTHERS=>16#FF#); + + ELSIF status = erase_na AND Sec_Prot(Sect)/='1'THEN + --sector erase terminated = data integrity violated + mem(Sect) := (OTHERS=>-1); + + ELSIF status = readX AND Sec_Prot(Sect)/='1' THEN + mem(Sect)(Addr) := -1; + IF NOT command.byte THEN + mem(Sect)(Addr+1) := -1; + END IF; + + -- Write to Secure Silicon Sector Region + ELSIF status = rd_SecSi AND FactoryProt/='1' THEN + slv_1 := to_slv(d_lo,8); + IF SecSi(Addr)>-1 THEN + slv_2 := to_slv(SecSi(Addr),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + SecSi(Addr) := to_nat(slv_1); + IF NOT command.byte THEN + slv_1 := to_slv(d_hi,8); + IF SecSi(Addr+1)>-1 THEN + slv_2 := to_slv(SecSi(Addr+1),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + SecSi(Addr+1) := to_nat(slv_1); + END IF; + + ELSIF status=buff_wr_busy THEN + --Write to Buffer command cycle + null; + + ELSIF status=erase_na THEN + --sector erase command sequence violation + null; + + -- Write to Flash Memory Array + ELSIF status /= err AND Sec_Prot(Sect)/='1'THEN + slv_1 := to_slv(d_lo,8); + IF mem(Sect)(Addr)>-1 THEN + slv_2 := to_slv(mem(Sect)(Addr),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + mem(Sect)(Addr) := to_nat(slv_1); + IF NOT command.byte THEN + slv_1 := to_slv(d_hi,8); + IF mem(Sect)(Addr+1)>-1 THEN + slv_2 := to_slv(mem(Sect)(Addr+1),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + mem(Sect)(Addr+1) := to_nat(slv_1); + END IF; + END IF; + + + WHEN wt => + WAIT FOR command.wtime; + + WHEN wt_rdy => + IF T_RY/='1' THEN + WAIT UNTIL rising_edge(T_RY) FOR command.wtime; + END IF; + + WHEN wt_bsy => + IF T_RY='1' THEN + WAIT UNTIL falling_edge(T_RY) FOR command.wtime; + END IF; + + WHEN OTHERS => null; + END CASE; + END PROCEDURE; + + + VARIABLE cmd_cnt : NATURAL; + VARIABLE command : cmd_rec; -- + +BEGIN + Pick_TC (Model => "AM29LV640MH90R" ); + + Tseries <= ts_cnt ; + Tcase <= tc_cnt ; + + Generate_TC + (Model => "AM29LV640MH90R" , + Series => ts_cnt, + TestCase => tc_cnt, + command_seq => cmd_seq); + + + cmd_cnt := 1; + WHILE cmd_seq(cmd_cnt).cmd/=done LOOP + command:= cmd_seq(cmd_cnt); + IF command.sect = -1 THEN + command.sect := ProtSecNum; + END IF; + status <= command.status; + sts_check<= to_slv(command.d_lo,8); --used only for toggle/status check + cmd_dc(command); + cmd_cnt :=cmd_cnt +1; + + END LOOP; + +END PROCESS tb; + +--process to monitor WP# +PROCESS(T_WPNeg) +VARIABLE reg : std_logic; +BEGIN + IF falling_edge(T_WPNeg) THEN + reg := Sec_Prot(ProtSecNum); + Sec_Prot(ProtSecNum) := '1'; + ELSIF rising_edge(T_WPNeg) THEN + Sec_Prot(ProtSecNum) := reg; + END IF; +END PROCESS; + +-------------------------------------------------------------------------------- +-- Checker process, +-- Bus transition extractor: when bus cycle is read samples addr and data +-- Transition checker : verifies correct read data using default memory +-------------------------------------------------------------------------------- +checker: PROCESS + VARIABLE RAddr : NATURAL; + VARIABLE RSect : NATURAL; + VARIABLE longread : boolean; + VARIABLE shortread : boolean; + VARIABLE toggle : boolean:=false; + VARIABLE toggle_sts : std_logic_vector(7 downto 0); + +BEGIN +-- Transition extractor + IF (T_CENeg='0'AND T_OENeg='0'AND T_WENeg='1') THEN + IF T_BYTENeg='1' THEN + RAddr := to_nat(T_A(14 downto 0)&'0'); + ELSE + RAddr := to_nat(T_A(14 downto 0)&T_DQ(15)); + END IF; + RSect := to_nat(T_A(HiAddrBit downto 15)); + + shortread:= false; + longread := false; + + --DUT specific timing + IF (T_CENeg'EVENT OR T_WENeg'EVENT OR T_A(HiAddrBit downto 2)'EVENT)AND -- + (status=read OR status=rd_cfi OR status=rd_secsi) THEN --OR status=readX) + longread := true; + CASE TimingModel IS + WHEN "AM29LV640MH90R" | + "AM29LV640ML90R" => WAIT FOR 95 ns; +-- WHEN "AM29LV640MH101" | +-- "AM29LV640ML101" => WAIT FOR 105 ns; +-- WHEN "AM29LV640MH101R" | +-- "AM29LV640ML101R" => WAIT FOR 105 ns; +-- WHEN "AM29LV640MH112" | +-- "AM29LV640ML112" => WAIT FOR 115 ns; +-- WHEN "AM29LV640MH112R" | +-- "AM29LV640ML112R" => WAIT FOR 115 ns; +-- WHEN "AM29LV640MH120" | +-- "AM29LV640ML120" => WAIT FOR 125 ns; +-- WHEN "AM29LV640MH120R" | +-- "AM29LV640ML120R" => WAIT FOR 125 ns; + WHEN OTHERS => + REPORT "Timing model NOT supported : "&TimingModel + SEVERITY error; + END CASE; + + ELSIF T_A(1 downto 0)'EVENT OR + (T_DQ(15)'EVENT AND T_BYTENeg='0')OR + (T_BYTENeg'EVENT) OR + T_OENeg'EVENT OR + (status/=read AND status/=rd_cfi AND + status/=rd_secsi) THEN --AND status/=readX) + shortread:=true; + CASE TimingModel IS + WHEN "AM29LV640MH90R" | + "AM29LV640ML90R" => WAIT FOR 30 ns; +-- WHEN "AM29LV640MH101" | +-- "AM29LV640ML101" => WAIT FOR 40 ns; +-- WHEN "AM29LV640MH101R" | +-- "AM29LV640ML101R" => WAIT FOR 40 ns; +-- WHEN "AM29LV640MH112" | +-- "AM29LV640ML112" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH112R" | +-- "AM29LV640ML112R" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH120" | +-- "AM29LV640ML120" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH120R" | +-- "AM29LV640ML120R" => WAIT FOR 45 ns; + WHEN OTHERS => + REPORT "Timing model NOT supported : "&TimingModel + SEVERITY error; + END CASE; + + END IF; + + + + --Checker + IF longread OR shortread THEN + + CASE status IS + WHEN none => + toggle := false; + + -- read memory array data + WHEN read => + toggle := false; + Check_read ( + DQ => T_DQ, + D_lo => mem(RSect)(RAddr), + D_hi => mem(RSect)(RAddr+1), + Byte => T_BYTENeg, + check_err=> check_err); + + -- read secure silicon region + WHEN rd_secsi => + toggle := false; + Check_SecSi ( + DQ => T_DQ, + D_lo => SecSi(RAddr), + D_hi => SecSi(RAddr+1), + Byte => T_BYTENeg, + check_err=>check_err); + + + --read CFI query codes + WHEN rd_cfi => + RAddr := to_nat(T_A(14 downto 0)); --x16 addressing + toggle := false; + Check_CFI ( + DQ => T_DQ, + D_lo => CFI_array(RAddr) , + D_hi => 0 , + Byte => T_BYTENeg, + check_err=>check_err); + + + + -- read Autoselect codes + WHEN rd_AS => + RAddr := to_nat(T_A(14 downto 0)); --x16 addressing + toggle := false; + Check_AS ( + DQ => T_DQ, + addr => RAddr, + ProtSecNum=>ProtSecNum, + secProt => Sec_Prot(RSect), + FactoryProt=>FactoryProt , + Byte => T_BYTENeg, + AS_E => to_slv(16#0C#,8), + AS_F => to_slv(1,8), + + check_err=>check_err); + + + WHEN rd_HiZ => + toggle:=false; + Check_Z ( + DQ => T_DQ, + check_err=>check_err); + + + + WHEN readX => + toggle:=false; + Check_X ( + DQ => T_DQ, + check_err=>check_err); + + + WHEN erase_na | erase_active => + IF toggle THEN + Check_Erase ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN ers_susp_e => + IF toggle THEN + Check_Ers_Susp ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + +-- + + WHEN ers_susp_prog_na | ers_susp_prog => + IF toggle THEN + Check_Ers_Susp_Prog ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + +-- + + WHEN prog_na | prog_active => + IF toggle THEN + Check_Progr ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN buff_wr_busy | buff_wr_N_busy => + IF toggle THEN + Check_Buff_Busy ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN buff_abort => + IF toggle THEN + Check_Abort ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + WHEN OTHERS => null; + END CASE; + + -- get firs data for toggle check + CASE status IS + WHEN prog_active | prog_na | + erase_active | erase_na | + ers_susp_e | + ers_susp_prog | ers_susp_prog_na | + buff_wr_busy | buff_wr_N_busy | + buff_abort | get_toggle => + + IF (NOT toggle) OR (status=get_toggle) THEN + toggle:=true; + toggle_sts := T_DQ(7 downto 0); + END IF; + + WHEN OTHERS => null; + END CASE; + + + END IF; + + END IF; + + WAIT ON T_A, T_CENeg, T_OENeg, T_WENeg, T_DQ(15), T_BYTENeg; + +END PROCESS checker; + + +default: PROCESS + -- text file input variables + FILE mem_f : text is mem_file; + FILE prot_f : text is prot_file; + FILE secsi_f : text is secsi_file; + + VARIABLE S_ind : NATURAL RANGE 0 TO SecNum:= 0; + VARIABLE ind : NATURAL RANGE 0 TO SecSize:= 0; + VARIABLE buf : line; + +BEGIN + --Preload Control + ----------------------------------------------------------------------- + -- File Read Section + ----------------------------------------------------------------------- + IF UserPreload THEN + --- Sector protection preload + IF (prot_file /= "none" ) THEN + ind := 0; + FactoryProt := '0'; + Sec_Prot := (OTHERS => '0'); + WHILE (not ENDFILE (prot_f)) LOOP + READLINE (prot_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 3)); --address + ELSE + IF ind > SecNum THEN + --SecSi Factory protect preload + IF buf(1)='1' THEN + FactoryProt := '1'; + END IF; + ELSE + -- Standard Sector prload + IF buf(1)='1' THEN + Sec_Prot(ind):= '1'; + END IF; + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + -- Secure Silicon Sector Region preload + IF (SecSi_file /= "none" ) THEN + SecSi := (OTHERS => MaxData); + ind := 0; + WHILE (not ENDFILE (SecSi_f)) LOOP + READLINE (SecSi_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 3)); --address + ELSE + IF ind <= SecSiSize THEN + SecSi(ind) := h(buf(1 TO 2)); + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + --- Memory Preload + IF (mem_file /= "none" ) THEN + ind := 0; + Mem := (OTHERS => (OTHERS => MaxData)); + -- load sector 0 + WHILE (not ENDFILE (mem_f)) LOOP + READLINE (mem_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 5)); --address + ELSE + IF ind <= SecSize THEN + Mem(0)(ind) := h(buf(1 to 2)); + ind := ind + 1; + END IF; + END IF; + END LOOP; + -- load other sectors + FOR i IN 1 TO SecNum LOOP + Mem(i) := Mem(0); + END LOOP; + END IF; + + END IF; + ----------------------------------------------------------------------- + --CFI array data / AM29LV640MH90R !!! DEVICE SPECIFIC + ----------------------------------------------------------------------- + --CFI query identification string + -- !!!!!! WORD ADDRESSES (x16) - for x8 addressing double addr + --CFI query identification string + CFI_array(16#10#) := 16#51#; + CFI_array(16#11#) := 16#52#; + CFI_array(16#12#) := 16#59#; + CFI_array(16#13#) := 16#02#; + CFI_array(16#14#) := 16#00#; + CFI_array(16#15#) := 16#40#; + CFI_array(16#16#) := 16#00#; + CFI_array(16#17#) := 16#00#; + CFI_array(16#18#) := 16#00#; + CFI_array(16#19#) := 16#00#; + CFI_array(16#1A#) := 16#00#; + --system interface string + CFI_array(16#1B#) := 16#27#; + CFI_array(16#1C#) := 16#36#; + CFI_array(16#1D#) := 16#00#; + CFI_array(16#1E#) := 16#00#; + CFI_array(16#1F#) := 16#07#; + CFI_array(16#20#) := 16#07#; + CFI_array(16#21#) := 16#0A#; + CFI_array(16#22#) := 16#00#; + CFI_array(16#23#) := 16#01#; + CFI_array(16#24#) := 16#05#; + CFI_array(16#25#) := 16#04#; + CFI_array(16#26#) := 16#00#; + --device geometry definition + CFI_array(16#27#) := 16#17#; + CFI_array(16#28#) := 16#02#; + CFI_array(16#29#) := 16#00#; + CFI_array(16#2A#) := 16#05#; + CFI_array(16#2B#) := 16#00#; + CFI_array(16#2C#) := 16#01#; + CFI_array(16#2D#) := 16#7F#; + CFI_array(16#2E#) := 16#00#; + CFI_array(16#2F#) := 16#00#; + CFI_array(16#30#) := 16#01#; + CFI_array(16#31#) := 16#00#; + CFI_array(16#32#) := 16#00#; + CFI_array(16#33#) := 16#00#; + CFI_array(16#34#) := 16#00#; + CFI_array(16#35#) := 16#00#; + CFI_array(16#36#) := 16#00#; + CFI_array(16#37#) := 16#00#; + CFI_array(16#38#) := 16#00#; + CFI_array(16#39#) := 16#00#; + CFI_array(16#3A#) := 16#00#; + CFI_array(16#3B#) := 16#00#; + CFI_array(16#3C#) := 16#00#; + --primary vendor-specific extended query + CFI_array(16#40#) := 16#50#; + CFI_array(16#41#) := 16#52#; + CFI_array(16#42#) := 16#49#; + CFI_array(16#43#) := 16#31#; + CFI_array(16#44#) := 16#33#; + CFI_array(16#45#) := 16#08#; + CFI_array(16#46#) := 16#02#; + CFI_array(16#47#) := 16#01#; + CFI_array(16#48#) := 16#01#; + CFI_array(16#49#) := 16#04#; + CFI_array(16#4A#) := 16#00#; + CFI_array(16#4B#) := 16#00#; + CFI_array(16#4C#) := 16#01#; + CFI_array(16#4D#) := 16#B5#; + CFI_array(16#4E#) := 16#C5#; + IF TimingModel(11) = 'L' THEN + CFI_array(16#4F#) := 16#04#; + ELSE + CFI_array(16#4F#) := 16#05#; --uniform sectors top protect + END IF; + CFI_array(16#50#) := 16#01#; + + WAIT; + +END PROCESS default; + + + +END vhdl_behavioral; + diff --git a/lib/models/memory/flash/serial/S25fl128s/utilities/conversions.vhd b/lib/models/memory/flash/serial/S25fl128s/utilities/conversions.vhd new file mode 100644 index 0000000..e5fc0d6 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128s/utilities/conversions.vhd @@ -0,0 +1,1035 @@ +-------------------------------------------------------------------------------- +-- File Name: conversions_p.vhd +-------------------------------------------------------------------------------- +-- Copyright (C) 1997, 1998, 2001 Free Model Foundry; http://eda.org/fmf/ +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License version 2 as +-- published by the Free Software Foundation. +-- +-- This package was written by SEVA Technologies, Inc. and donated to the FMF. +-- www.seva.com +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 R. Steele 97 DEC 05 Added header and formatting to SEVA file +-- V1.1 R. Munden 98 NOV 28 Corrected some comments +-- Corrected function b +-- V1.2 R. Munden 01 MAY 27 Corrected function to_nat for weak values +-- and combined into a single file +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; + +-------------------------------------------------------------------------------- +-- CONVERSION FUNCTION SELECTION TABLES +-------------------------------------------------------------------------------- +-- +-- FROM TO: std_logic_vector std_logic natural time string +-- -----------------|---------------|---------|---------|---------|----------- +-- std_logic_vector | N/A | N/A | to_nat | combine | see below +-- std_logic | N/A | N/A | to_nat | combine | see below +-- natural | to_slv | to_sl | N/A | to_time | see below +-- time | N/A | N/A | to_nat | N/A | to_time_str +-- hex string | h | N/A | h | combine | N/A +-- decimal string | d | N/A | d | combine | N/A +-- octal string | o | N/A | o | combine | N/A +-- binary string | b | N/A | b | combine | N/A +-- -----------------|---------------|---------|---------|---------|----------- +-- +-- FROM TO: hex string decimal string octal string binary string +-- -----------------|------------|-------------|------------|---------------- +-- std_logic_vector | to_hex_str | to_int_str | to_oct_str | to_bin_str +-- std_logic | N/A | N/A | N/A | to_bin_str +-- natural | to_hex_str | to_int_str | to_oct_str | to_bin_str +-- -----------------|------------|-------------|------------|---------------- +-- +-------------------------------------------------------------------------------- + +PACKAGE conversions IS + + ---------------------------------------------------------------------------- + -- the conversions in this package are not guaranteed to be synthesizable. + -- + -- others functions available + -- fill creates a variable length string of the fill character + -- + -- + -- + -- input parameters of type natural or integer can be in the form: + -- normal -> 8, 99, 4_237 + -- base#value# -> 2#0101#, 16#fa4C#, 8#6_734# + -- with exponents(x10) -> 8e4, 16#2e#E4 + -- + -- input parameters of type string can be in the form: + -- "99", "4_237", "0101", "1010_1010" + -- + -- for bit/bit_vector <-> std_logic/std_logic_vector conversions use + -- package std_logic_1164 + -- to_bit(std_logic) + -- to_bitvector(std_logic_vector) + -- to_stdlogic(bit) + -- to_stdlogicvector(bit_vector) + -- + -- for "synthesizable" signed/unsigned/std_logic_vector/integer + -- conversions use + -- package std_logic_arith + -- conv_integer(signed/unsigned) + -- conv_unsigned(integer/signed,size) + -- conv_signed(integer/unsigned,size) + -- conv_std_logic_vector(integer/signed/unsigned,size) + -- + -- for "synthesizable" std_logic_vector -> integer conversions use + -- package std_logic_unsigned/std_logic_signed + -- + -- conv_integer(std_logic_vector) + -- + -- type1'(expression of type2) + -- + -- most conversions have 4 parmeters: + -- x : value to be converted + -- rtn_len : size of the return value + -- justify : justify value 'left' or 'right', default is right + -- basespec : print the base of the value - 'yes'/'no', default is yes + -- + -- Typical ways to call these functions: + -- simple, all defaults used + -- to_bin_str(x) + -- x will be converted to a string of minimum size with a + -- base specification appended for clarity + -- if x is 10101 then return is b"10101" + -- + -- to control size of return string + -- to_hex_str(x, + -- 6) + -- length of string returned will be 6 characters + -- value will be right justified in the field + -- if x is 10101 then return is ....h"15" + -- where '.' represents a blank + -- if 'rtn_len' parm defaults or is set to 0 then + -- return string will always be minimum size + -- + -- to left justify and suppress base specification + -- to_int_str(x, + -- 6, + -- justify => left, + -- basespec => yes) + -- length of return string will be 6 characters + -- the base specification will be suppressed + -- if x is 10101 then return is 21.... + -- where '.' represents a blank + -- + -- other usage notes + -- + -- if rtn_len less than or equal to x'length then ignore + -- rtn_len and return string of x'length + -- the 'justify' parm is effectively ignored in this case + -- + -- if rtn_len greater than x'length then return string + -- of rtn_len with blanks based on 'justify' parm + -- + -- these routines do not handle negative numbers + ---------------------------------------------------------------------------- + + type justify_side is (left, right); + type b_spec is (no , yes); + + -- std_logic_vector to binary string + function to_bin_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- std_logic to binary string + function to_bin_str(x : std_logic; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to binary string + function to_bin_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to hex string + function to_hex_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to hex string + function to_hex_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to octal string + function to_oct_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to octal string + function to_oct_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- natural to integer string + function to_int_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to integer string + function to_int_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- time to string + function to_time_str (x : time) + return string; + + -- add characters to a string + function fill (fill_char : character := '*'; + rtn_len : integer := 1) + return string; + -- usage: + -- fill + -- returns * + -- fill(' ',10) + -- returns .......... when '.' represents a blank + -- fill(lf) or fill(ht) + -- returns line feed character or tab character respectively + + -- std_logic_vector to natural + function to_nat (x : std_logic_vector) + return natural; + + -- std_logic to natural + function to_nat (x : std_logic) + return natural; + + -- time to natural + function to_nat (x : time) + return natural; + + -- hex string to std_logic_vector + function h (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or a,A to f,F + -- or x,X,z,Z,u,U,-,w,W, result will be 0 + + -- decimal string to std_logic_vector + function d (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- octal string to std_logic_vector + function o (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 7 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- binary string to std_logic_vector + function b (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 1 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- hex string to natural + function h (x : string) + return natural; + -- if x is other than characters 0 to 9 or a,A to f,F, result will be 0 + + -- decimal string to natural + function d (x : string) + return natural; + -- if x is other than characters 0 to 9, result will be 0 + + -- octal string to natural + function o (x : string) + return natural; + -- if x is other than characters 0 to 7, result will be 0 + + -- binary string to natural + function b (x : string) + return natural; + -- if x is other than characters 0 to 1, result will be 0 + + -- natural to std_logic_vector + function to_slv (x : natural; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than sizeof(x), result will be truncated on the left + -- see note above regarding possible formats for x + + -- natural to std_logic + function to_sl (x : natural) + return std_logic; + + -- natural to time + function to_time (x : natural) + return time; + -- see note above regarding possible formats for x + +END conversions; +-- +-------------------------------------------------------------------------------- +-- + +PACKAGE BODY conversions IS + + -- private declarations for this package + type basetype is (binary, octal, decimal, hex); + + function max(x,y: integer) return integer is + begin + if x > y then return x; else return y; end if; + end max; + + function min(x,y: integer) return integer is + begin + if x < y then return x; else return y; end if; + end min; + + -- consider function sizeof for string/slv/???, return natural + + -- function size(len: natural) return natural is + -- begin + -- if len=0 then + -- return 31; + -- else return len; + -- end if; + -- end size; + + function nextmultof (x : positive; + size : positive) return positive is + begin + case x mod size is + when 0 => return size * x/size; + when others => return size * (x/size + 1); + end case; + end nextmultof; + + function rtn_base (base : basetype) return character is + begin + case base is + when binary => return 'b'; + when octal => return 'o'; + when decimal => return 'd'; + when hex => return 'h'; + end case; + end rtn_base; + + function format (r : string; + base : basetype; + rtn_len : natural ; + justify : justify_side; + basespec : b_spec) return string is + variable int_rtn_len : integer; + begin + if basespec=yes then + int_rtn_len := rtn_len - 3; + else + int_rtn_len := rtn_len; + end if; + if int_rtn_len <= r'length then + case basespec is + when no => return r ; + when yes => return rtn_base(base) & '"' & r & '"'; + end case; + else + case justify is + when left => + case basespec is + when no => + return r & fill(' ',int_rtn_len - r'length); + when yes => + return rtn_base(base) & '"' & r & '"' & + fill(' ',int_rtn_len - r'length); + end case; + when right => + case basespec is + when no => + return fill(' ',int_rtn_len - r'length) & r ; + when yes => + return fill(' ',int_rtn_len - r'length) & + rtn_base(base) & '"' & r & '"'; + end case; + end case; + end if; + end format; + + -- convert numeric string of any base to natural + function cnvt_base (x : string; + inbase : natural range 2 to 16) return natural is + -- assumes x is an unsigned number string of base 'inbase' + -- values larger than natural'high are not supported + variable r,t : natural := 0; + variable place : positive := 1; + begin + for i in x'reverse_range loop + case x(i) is + when '0' => t := 0; + when '1' => t := 1; + when '2' => t := 2; + when '3' => t := 3; + when '4' => t := 4; + when '5' => t := 5; + when '6' => t := 6; + when '7' => t := 7; + when '8' => t := 8; + when '9' => t := 9; + when 'a'|'A' => t := 10; + when 'b'|'B' => t := 11; + when 'c'|'C' => t := 12; + when 'd'|'D' => t := 13; + when 'e'|'E' => t := 14; + when 'f'|'F' => t := 15; + when '_' => t := 0; -- ignore these characters + place := place / inbase; + when others => + assert false + report lf & + "CNVT_BASE found input value larger than base: " & lf & + "Input value: " & x(i) & + " Base: " & to_int_str(inbase) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + if t / inbase > 1 then -- invalid value for base + assert false + report lf & + "CNVT_BASE found input value larger than base: " & lf & + "Input value: " & x(i) & + " Base: " & to_int_str(inbase) & lf & + "converting input to integer 0" + severity warning; + return 0; + else + r := r + (t * place); + place := place * inbase; + end if; + end loop; + return r; + end cnvt_base; + + function extend (x : std_logic; + len : positive) return std_logic_vector is + variable v : std_logic_vector(1 to len) := (others => x); + begin + return v; + end extend; + + + -- implementation of public declarations + + function to_bin_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + + variable int : std_logic_vector(1 to x'length):=x; + variable r : string(1 to x'length):=(others=>'$'); + begin + for i in int'range loop + r(i to i) := to_bin_str(int(i),basespec=>no); + end loop; + return format (r,binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_bin_str(x : std_logic; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable r : string(1 to 1); + begin + case x is + when '0' => r(1) := '0'; + when '1' => r(1) := '1'; + when 'U' => r(1) := 'U'; + when 'X' => r(1) := 'X'; + when 'Z' => r(1) := 'Z'; + when 'W' => r(1) := 'W'; + when 'H' => r(1) := 'H'; + when 'L' => r(1) := 'L'; + when '-' => r(1) := '-'; + end case; + return format (r,binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_bin_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 2 to 32 := 32; + variable r : string(2 to 32):=(others=>'$'); + begin + if int = 0 then + return format ("0",binary,rtn_len,justify,basespec); + end if; + + while int > 0 loop + case int rem 2 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when others => + assert false report lf & "TO_BIN_STR, shouldn't happen" + severity failure; + return "$"; + null; + end case; + int := int / 2; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 32),binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_hex_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + -- will return x'length/4 + variable nxt : positive := nextmultof(x'length,4); + variable int : std_logic_vector(1 to nxt):= (others => '0'); + variable ptr : positive range 1 to (nxt/4)+1 := 1; + variable r : string(1 to nxt/4):=(others=>'$'); + subtype slv4 is std_logic_vector(1 to 4); + begin + int(nxt-x'length+1 to nxt) := x; + if nxt-x'length > 0 and x(x'left) /= '1' then + int(1 to nxt-x'length) := extend(x(x'left),nxt-x'length); + end if; + for i in int'range loop + next when i rem 4 /= 1; + case slv4'(int(i to i+3)) is + when "0000" => r(ptr) := '0'; + when "0001" => r(ptr) := '1'; + when "0010" => r(ptr) := '2'; + when "0011" => r(ptr) := '3'; + when "0100" => r(ptr) := '4'; + when "0101" => r(ptr) := '5'; + when "0110" => r(ptr) := '6'; + when "0111" => r(ptr) := '7'; + when "1000" => r(ptr) := '8'; + when "1001" => r(ptr) := '9'; + when "1010" => r(ptr) := 'A'; + when "1011" => r(ptr) := 'B'; + when "1100" => r(ptr) := 'C'; + when "1101" => r(ptr) := 'D'; + when "1110" => r(ptr) := 'E'; + when "1111" => r(ptr) := 'F'; + when "ZZZZ" => r(ptr) := 'Z'; + when "WWWW" => r(ptr) := 'W'; + when "LLLL" => r(ptr) := 'L'; + when "HHHH" => r(ptr) := 'H'; + when "UUUU" => r(ptr) := 'U'; + when "XXXX" => r(ptr) := 'X'; + when "----" => r(ptr) := '-'; + when others => + assert false + report lf & + "TO_HEX_STR found illegal value: " & + to_bin_str(int(i to i+3)) & lf & + "converting input to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr + 1; + end loop; + return format (r,hex,rtn_len,justify,basespec); + end to_hex_str; + + function to_hex_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 20 := 20; + variable r : string(1 to 20):=(others=>'$'); + begin + if x=0 then return format ("0",hex,rtn_len,justify,basespec); end if; + while int > 0 loop + case int rem 16 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when 8 => r(ptr) := '8'; + when 9 => r(ptr) := '9'; + when 10 => r(ptr) := 'A'; + when 11 => r(ptr) := 'B'; + when 12 => r(ptr) := 'C'; + when 13 => r(ptr) := 'D'; + when 14 => r(ptr) := 'E'; + when 15 => r(ptr) := 'F'; + when others => + assert false report lf & "TO_HEX_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 16; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 20),hex,rtn_len,justify,basespec); + end to_hex_str; + + function to_oct_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + -- will return x'length/3 + variable nxt : positive := nextmultof(x'length,3); + variable int : std_logic_vector(1 to nxt):= (others => '0'); + variable ptr : positive range 1 to (nxt/3)+1 := 1; + variable r : string(1 to nxt/3):=(others=>'$'); + subtype slv3 is std_logic_vector(1 to 3); + begin + int(nxt-x'length+1 to nxt) := x; + if nxt-x'length > 0 and x(x'left) /= '1' then + int(1 to nxt-x'length) := extend(x(x'left),nxt-x'length); + end if; + for i in int'range loop + next when i rem 3 /= 1; + case slv3'(int(i to i+2)) is + when "000" => r(ptr) := '0'; + when "001" => r(ptr) := '1'; + when "010" => r(ptr) := '2'; + when "011" => r(ptr) := '3'; + when "100" => r(ptr) := '4'; + when "101" => r(ptr) := '5'; + when "110" => r(ptr) := '6'; + when "111" => r(ptr) := '7'; + when "ZZZ" => r(ptr) := 'Z'; + when "WWW" => r(ptr) := 'W'; + when "LLL" => r(ptr) := 'L'; + when "HHH" => r(ptr) := 'H'; + when "UUU" => r(ptr) := 'U'; + when "XXX" => r(ptr) := 'X'; + when "---" => r(ptr) := '-'; + when others => + assert false + report lf & + "TO_OCT_STR found illegal value: " & + to_bin_str(int(i to i+2)) & lf & + "converting input to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr + 1; + end loop; + return format (r,octal,rtn_len,justify,basespec); + end to_oct_str; + + function to_oct_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 20 := 20; + variable r : string(1 to 20):=(others=>'$'); + begin + if x=0 then return format ("0",octal,rtn_len,justify,basespec); end if; + while int > 0 loop + case int rem 8 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when others => + assert false report lf & "TO_OCT_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 8; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 20),octal,rtn_len,justify,basespec); + end to_oct_str; + + function to_int_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 32 := 32; + variable r : string(1 to 32):=(others=>'$'); + begin + if x=0 then return format ("0",hex,rtn_len,justify,basespec); + else + while int > 0 loop + case int rem 10 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when 8 => r(ptr) := '8'; + when 9 => r(ptr) := '9'; + when others => + assert false report lf & "TO_INT_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 10; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 32),decimal,rtn_len,justify,basespec); + end if; + end to_int_str; + + function to_int_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string is + begin + return to_int_str(to_nat(x),rtn_len,justify,basespec); + end to_int_str; + + + function to_time_str (x : time) + return string is + begin + return to_int_str(to_nat(x),basespec=>no) & " ns"; + end to_time_str; + + function fill (fill_char : character := '*'; + rtn_len : integer := 1) + return string is + variable r : string(1 to max(rtn_len,1)) := (others => fill_char); + variable len : integer; + begin + if rtn_len < 2 then -- always returns at least 1 fill char + len := 1; + else + len := rtn_len; + end if; + return r(1 to len); + end fill; + + function to_nat(x : std_logic_vector) return natural is + -- assumes x is an unsigned number, lsb on right, + -- more than 31 bits are truncated on left + variable t : std_logic_vector(1 to x'length) := x; + variable int : std_logic_vector(1 to 31) := (others => '0'); + variable r : natural := 0; + variable place : positive := 1; + begin + if x'length < 32 then + int(max(32-x'length,1) to 31) := t(1 to x'length); + else -- x'length >= 32 + int(1 to 31) := t(x'length-30 to x'length); + end if; + for i in int'reverse_range loop + case int(i) is + when '1' | 'H' => r := r + place; + when '0' | 'L' => null; + when others => + assert false + report lf & + "TO_NAT found illegal value: " & to_bin_str(int(i)) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + exit when i=1; + place := place * 2; + end loop; + return r; + end to_nat; + + function to_nat (x : std_logic) + return natural is + begin + case x is + when '0' => return 0 ; + when '1' => return 1 ; + when others => + assert false + report lf & + "TO_NAT found illegal value: " & to_bin_str(x) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + end to_nat; + + function to_nat (x : time) + return natural is + begin + return x / 1 ns; + end to_nat; + + function h(x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or a,A to f,F or + -- x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length*4,rtn_len); + variable ptr : integer range -3 to size := size; + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr-3 to ptr) := "0000"; + when '1' => r(ptr-3 to ptr) := "0001"; + when '2' => r(ptr-3 to ptr) := "0010"; + when '3' => r(ptr-3 to ptr) := "0011"; + when '4' => r(ptr-3 to ptr) := "0100"; + when '5' => r(ptr-3 to ptr) := "0101"; + when '6' => r(ptr-3 to ptr) := "0110"; + when '7' => r(ptr-3 to ptr) := "0111"; + when '8' => r(ptr-3 to ptr) := "1000"; + when '9' => r(ptr-3 to ptr) := "1001"; + when 'a'|'A' => r(ptr-3 to ptr) := "1010"; + when 'b'|'B' => r(ptr-3 to ptr) := "1011"; + when 'c'|'C' => r(ptr-3 to ptr) := "1100"; + when 'd'|'D' => r(ptr-3 to ptr) := "1101"; + when 'e'|'E' => r(ptr-3 to ptr) := "1110"; + when 'f'|'F' => r(ptr-3 to ptr) := "1111"; + when 'U' => r(ptr-3 to ptr) := "UUUU"; + when 'X' => r(ptr-3 to ptr) := "XXXX"; + when 'Z' => r(ptr-3 to ptr) := "ZZZZ"; + when 'W' => r(ptr-3 to ptr) := "WWWW"; + when 'H' => r(ptr-3 to ptr) := "HHHH"; + when 'L' => r(ptr-3 to ptr) := "LLLL"; + when '-' => r(ptr-3 to ptr) := "----"; + when '_' => ptr := ptr + 4; + when others => + assert false + report lf & + "O conversion found illegal input character: " & + int(i) & lf & "converting character to '----'" + severity warning; + r(ptr-3 to ptr) := "----"; + end case; + ptr := ptr - 4; + end loop; + return r(size-rtn_len+1 to size); + end h; + + function d (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than binary length of x, result will be truncated on + -- the left + -- if x is other than characters 0 to 9, result will be 0 + begin + return to_slv(cnvt_base(x,10),rtn_len); + end d; + + function o (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length*3, result will be truncated on the left + -- if x is other than characters 0 to 7 or or x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length*3,rtn_len); + variable ptr : integer range -2 to size := size; + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr-2 to ptr) := "000"; + when '1' => r(ptr-2 to ptr) := "001"; + when '2' => r(ptr-2 to ptr) := "010"; + when '3' => r(ptr-2 to ptr) := "011"; + when '4' => r(ptr-2 to ptr) := "100"; + when '5' => r(ptr-2 to ptr) := "101"; + when '6' => r(ptr-2 to ptr) := "110"; + when '7' => r(ptr-2 to ptr) := "111"; + when 'U' => r(ptr-2 to ptr) := "UUU"; + when 'X' => r(ptr-2 to ptr) := "XXX"; + when 'Z' => r(ptr-2 to ptr) := "ZZZ"; + when 'W' => r(ptr-2 to ptr) := "WWW"; + when 'H' => r(ptr-2 to ptr) := "HHH"; + when 'L' => r(ptr-2 to ptr) := "LLL"; + when '-' => r(ptr-2 to ptr) := "---"; + when '_' => ptr := ptr + 3; + when others => + assert false + report lf & + "O conversion found illegal input character: " & + int(i) & lf & "converting character to '---'" + severity warning; + r(ptr-2 to ptr) := "---"; + end case; + ptr := ptr - 3; + end loop; + return r(size-rtn_len+1 to size); + end o; + + function b (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length, result will be truncated on the left + -- if x is other than characters 0 to 1 or x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length,rtn_len); + variable ptr : integer range 0 to size+1 := size; -- csa + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr) := '0'; + when '1' => r(ptr) := '1'; + when 'U' => r(ptr) := 'U'; + when 'X' => r(ptr) := 'X'; + when 'Z' => r(ptr) := 'Z'; + when 'W' => r(ptr) := 'W'; + when 'H' => r(ptr) := 'H'; + when 'L' => r(ptr) := 'L'; + when '-' => r(ptr) := '-'; + when '_' => ptr := ptr + 1; + when others => + assert false + report lf & + "B conversion found illegal input character: " & + int(i) & lf & "converting character to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr - 1; + end loop; + return r(size-rtn_len+1 to size); + end b; + + function h (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 9 + -- a,A to f,F + -- blanks, underscore + begin + return cnvt_base(x,16); + end h; + + function d (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 9 + -- blanks, underscore + begin + return cnvt_base(x,10); + end d; + + function o (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 7 + -- blanks, underscore + begin + return cnvt_base(x,8); + end o; + + function b (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 1 + -- blanks, underscore + begin + return cnvt_base(x,2); + end b; + + function to_slv(x : natural; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than sizeof(x), result will be truncated on the left + variable int : natural := x; + variable ptr : positive := 32; + variable r : std_logic_vector(1 to 32) := (others=>'0'); + begin + while int > 0 loop + case int rem 2 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when others => + assert false report lf & "TO_SLV, shouldn't happen" + severity failure; + return "0"; + end case; + int := int / 2; + ptr := ptr - 1; + end loop; + return r(33-rtn_len to 32); + end to_slv; + + function to_sl(x : natural) + return std_logic is + variable r : std_logic := '0'; + begin + case x is + when 0 => null; + when 1 => r := '1'; + when others => + assert false + report lf & + "TO_SL found illegal input character: " & + to_int_str(x) & lf & "converting character to '-'" + severity warning; + return '-'; + end case; + return r; + end to_sl; + + function to_time (x: natural) return time is + begin + return x * 1 ns; + end to_time; + +END conversions; diff --git a/lib/models/memory/flash/serial/S25fl128s/utilities/gen_utils.vhd b/lib/models/memory/flash/serial/S25fl128s/utilities/gen_utils.vhd new file mode 100644 index 0000000..65c0e77 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl128s/utilities/gen_utils.vhd @@ -0,0 +1,144 @@ +-------------------------------------------------------------------------------- +-- File name: gen_utils.vhd +-------------------------------------------------------------------------------- +-- Copyright (C) 1996, 1998, 2001 Free Model Foundry; http://eda.org/fmf/ +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License version 2 as +-- published by the Free Software Foundation. +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 R. Steele 96 SEP 26 Initial release +-- V1.1 REV3 97 Feb 27 Added Xon and MsgOn generics +-- V1.2 R. Steele 97 APR 16 Changed wired-or to wired-and +-- V1.3 R. Steele 97 APR 16 Added diff. receiver table +-- V1.4 R. Munden 98 APR 13 Added GenParity and CheckParity +-- V1.5 R. Munden 01 NOV 24 Added UnitDelay01ZX +-- +-------------------------------------------------------------------------------- +LIBRARY IEEE; USE IEEE.std_Logic_1164.ALL; + USE IEEE.VITAL_primitives.ALL; + USE IEEE.VITAL_timing.ALL; + +PACKAGE gen_utils IS + + ---------------------------------------------------------------------------- + -- Result map for Wired-and output values (open collector) + ---------------------------------------------------------------------------- + CONSTANT STD_wired_and_rmap : VitalResultMapType := ('U','X','0','Z'); + + ---------------------------------------------------------------------------- + -- Table for computing a single signal from a differential receiver input + -- pair. + ---------------------------------------------------------------------------- + CONSTANT diff_rec_tab : VitalStateTableType := ( + + ------INPUTS--|-PREV-|-OUTPUT---- + -- A ANeg | Aint | Aint' -- + --------------|------|----------- + ( 'X', '-', '-', 'X'), -- A unknown + ( '-', 'X', '-', 'X'), -- A unknown + ( '1', '-', 'X', '1'), -- Recover from 'X' + ( '0', '-', 'X', '0'), -- Recover from 'X' + ( '/', '0', '0', '1'), -- valid diff. rising edge + ( '1', '\', '0', '1'), -- valid diff. rising edge + ( '\', '1', '1', '0'), -- valid diff. falling edge + ( '0', '/', '1', '0'), -- valid diff. falling edge + ( '-', '-', '-', 'S') -- default + ); -- end of VitalStateTableType definition + + + ---------------------------------------------------------------------------- + -- Default Constants + ---------------------------------------------------------------------------- + CONSTANT UnitDelay : VitalDelayType := 1 ns; + CONSTANT UnitDelay01 : VitalDelayType01 := (1 ns, 1 ns); + CONSTANT UnitDelay01Z : VitalDelayType01Z := (others => 1 ns); + CONSTANT UnitDelay01ZX : VitalDelayType01ZX := (others => 1 ns); + + CONSTANT DefaultInstancePath : STRING := "*"; + CONSTANT DefaultTimingChecks : BOOLEAN := FALSE; + CONSTANT DefaultTimingModel : STRING := "UNIT"; + CONSTANT DefaultXon : BOOLEAN := TRUE; + CONSTANT DefaultMsgOn : BOOLEAN := TRUE; + + -- Older VITAL generic being phased out + CONSTANT DefaultXGeneration : BOOLEAN := TRUE; + + ------------------------------------------------------------------- + -- Generate Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION GenParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic_vector; + + ------------------------------------------------------------------- + -- Check Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION CheckParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic; -- '0' - Parity Error + +END gen_utils; + +PACKAGE BODY gen_utils IS + + function XOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 403 + variable result: STD_LOGIC; + begin + result := '0'; + for i in ARG'range loop + result := result xor ARG(i); + end loop; + return result; + end; + ------------------------------------------------------------------- + -- Generate Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION GenParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic_vector + IS + VARIABLE I: NATURAL; + VARIABLE Result: std_logic_vector (Data'Length - 1 DOWNTO 0); + BEGIN + I := 0; + WHILE (I < SIZE) LOOP + Result(I+7 DOWNTO I) := Data(I+7 downto I); + Result(I+8) := XOR_REDUCE( Data(I+7 downto I) ) XOR ODDEVEN; + I := I + 9; + END LOOP; + RETURN Result; + END GenParity; + + ------------------------------------------------------------------- + -- Check Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION CheckParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic -- '0' - Parity Error + IS + VARIABLE I: NATURAL; + VARIABLE Result: std_logic; + BEGIN + I := 0; Result := '1'; + WHILE (I < SIZE) LOOP + Result := Result AND + NOT (XOR_REDUCE( Data(I+8 downto I) ) XOR ODDEVEN); + I := I + 9; + END LOOP; + RETURN Result; + END CheckParity; + +END gen_utils; diff --git a/lib/models/memory/flash/serial/S25fl256s/Model_Manual_English.pdf b/lib/models/memory/flash/serial/S25fl256s/Model_Manual_English.pdf new file mode 100644 index 0000000..954c3f6 Binary files /dev/null and b/lib/models/memory/flash/serial/S25fl256s/Model_Manual_English.pdf differ diff --git a/lib/models/memory/flash/serial/S25fl256s/Model_Manual_Japanese.pdf b/lib/models/memory/flash/serial/S25fl256s/Model_Manual_Japanese.pdf new file mode 100644 index 0000000..de2f909 Binary files /dev/null and b/lib/models/memory/flash/serial/S25fl256s/Model_Manual_Japanese.pdf differ diff --git a/lib/models/memory/flash/serial/S25fl256s/model/model_release_history.txt b/lib/models/memory/flash/serial/S25fl256s/model/model_release_history.txt new file mode 100644 index 0000000..97a7bd9 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl256s/model/model_release_history.txt @@ -0,0 +1,350 @@ +########################################## +Date (DD/MM/YYYY) - 16.11.2009 + +Model name - S25FL256S + +Vendor - Spansion (www.spansion.com) + +Publication ID - S25FL128 256 512 01GS MRS Rev0 98 + +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Ranko Prokopovic + r-prokopovic@hdl-dh.com +########################################## +########################################## +INITIAL RELEASE + +# Release Label => vital-amd-serial-s25fl-REL-s25fl256s-2009-11-16-1.tar.gz +# Release Date (DD/MM/YYYY) => 16/11/2009 +# Release Version => 1.0 + +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Ranko Prokopovic + r-prokopovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl256s-2009-11-19-2.tar.gz +# Release Date (DD/MM/YYYY) => 19/11/2009 +# Release Version => 1.1 + +# Corrections: +# 1.Negative tests which show how model behaves when reset pulse +# width is less than specified and when write and erase operations are interrupted . +# with reset signal are interrupted with reset signal are added. +# 2.Implementation of Continuous Read Mode +# 3.After 8 clock cycles for instruction, first address bit is latched on the next +# rising edge of clock. + +# Files modified +-s25fl256s.vhd +-testbench_s25fl256s_vhdl.vhd +-spansion_tc_pkg.vhd +-s25fl256s.ftm +-s25fl256s_vhdl.sdf +-s25fl256s.v +-testbench_s25fl256s_verilog.vhd +-s25fl256s.ftmv +-s25fl256s_verilog.sdf +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl256s-2010-03-04-1.tar.gz +# Release Date (DD/MM/YYYY) => 04/03/2010 +# Release Version => 1.2 + +# Corrections: +# 1.Array variable WByte in sensitivity list is replaced with signal WB_flag to enable +# compilation in NCSim +# 2.addr_cnt for second read in high performance read continuous mode can change its +# value only when CSNeg = '0' + +# Files modified +-s25fl256s.v +-s25fl256s.vhd +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl256s-2010-04-15-1.tar.gz +# Release Date (DD/MM/YYYY) => 15/04/2010 +# Release Version => 1.3 + +# Corrections: +# 1.HOLD mode corrected +# 2.Condition for PP operation corrected + +# Files modified +-s25fl256s.v +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl256s-2010-05-21-1.tar.gz +# Release Date (DD/MM/YYYY) => 21/05/2010 +# Release Version => 1.4 + +# Corrections: +# 1.SRWD bit assignment is corrected +# 2.Condition for WRR command in write_cycle_decode section is corrected +# 3.Blocking assignments for signals WSTART and PSTART are replaced with +# nonblocking assignments +# 4.Conditions in Page Program section are fixed +# + +# Files modified +-s25fl256s.v +-s25fl256s.vhd +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl256s-2010-05-25-1.tar.gz +# Release Date (DD/MM/YYYY) => 25/05/2010 +# Release Version => 1.5 + +# Corrections: +# 1. Timing control sections for Program and Erase operation are changed +# 2. Conditions in Page Program section are fixed +# + +# Files modified +-s25fl256s.v +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl256s-2010-06-03-2.tar.gz +# Release Date (DD/MM/YYYY) => 03/06/2010 +# Release Version => 1.6 + +# Corrections: +# 1. bus_cycle_state section for PGSP command is fixed +# + +# Files modified +-s25fl256s.v +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl256s-2010-07-28-1.tar.gz +# Release Date (DD/MM/YYYY) => 28/07/2010 +# Release Version => 1.7 + +# Corrections: +# 1. During the QUAD mode HOLD# input is not monitored for its normal function +# 2. Internal pull-up resistors for HOLD# and WP# inputs are implemented + +# Files modified +-s25fl256s.v +-s25fl256s.vhd +########################################## +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl256s-2010-08-24-1.tar.gz +# Release Date (DD/MM/YYYY) => 24/08/2010 +# Release Version => 1.8 + +# Corrections: +# 1. All redundant signals are removed from BusCycle process + +# Files modified +-s25fl256s.v +-s25fl256s.vhd +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Branislav Colakovic + b-colakovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl256s-2010-10-14-1.tar.gz +# Release Date (DD/MM/YYYY) => 14/10/2010 +# Release Version => 1.9 + +# Corrections: +# 1. Latest datasheet aligned (VERILOG files only) + +# Files modified +-spansion_tc_pkg.vhd +-s25fl256s.v +-testbench_s25fl256s_verilog.vhd +-s25fl256s.ftmv +-s25fl256s_verilog.sdf +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Branislav Colakovic + b-colakovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl256s-2010-10-20-1.tar.gz +# Release Date (DD/MM/YYYY) => 20/10/2010 +# Release Version => 2.0 + +# Corrections: +# 1. Latest datasheet aligned (VHDL files added) + +# Files modified +-s25fl256s.vhd +-testbench_s25fl256s_vhdl.vhd +-s25fl256s.ftm +-s25fl256s_vhdl.sdf +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl256s-2010-11-05-1.tar.gz +# Release Date (DD/MM/YYYY) => 05/11/2010 +# Release Version => 2.1 + +# Corrections: +# 1. Hybrid configuration added + +# Files modified +-spansion_tc_pkg.vhd +-s25fl256s.v +-testbench_s25fl256s_verilog.vhd +-s25fl256s.vhd +-testbench_s25fl256s_vhdl.vhd +-s25fl256s.ftm +-s25fl256s_vhdl.sdf +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl256s-2010-11-15-1.tar.gz +# Release Date (DD/MM/YYYY) => 15/11/2010 +# Release Version => 2.2 + +# Corrections: +# 1. QUAD Program operation during Erase Suspend is added +# 2. Warning for Resume to Suspend time is added +# 3. During Erase Suspend, after Program operation is completed, WEL bit is cleared +# 4. Implementation of Software Reset is Changed + +# Files modified +-spansion_tc_pkg.vhd +-s25fl256s.v +-s25fl256s.vhd +########################################## +########################################## +VITAL model author - Snezana Petrovic + s-petrovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl256s-2011-04-18-1.tar.gz +# Release Date (DD/MM/YYYY) => 18/04/2011 +# Release Version => 2.3 + +# Corrections: +- corrected timing for internal signal rising_edge_CSNeg_ipd + +# Files modified +-s25fl256s.v +########################################## +########################################## +VITAL model author - Branislav Colakovic + b-colakovic@hdl-dh.com + Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl256s-2011-07-05-1.tar.gz +# Release Date (DD/MM/YYYY) => 05/07/2011 +# Release Version => 2.4 + +# Corrections: +- Latest Datasheet Aligned + +# Files modified +-s25fl256s.v +-s25fl256s.vhd +-testbench_s25fl256s_verilog.vhd +-testbench_s25fl256s_vhdl.vhd +-spansion_tc_pkg.vhd +-s25fl256s.ftmv +-s25fl256s.ftm +-s25fl256s_verilog.sdf +-s25fl256s_vhdl.sdf +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Branislav Colakovic + b-colakovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl256s-2011-07-14-1.tar.gz +# Release Date (DD/MM/YYYY) => 14/07/2011 +# Release Version => 2.5 + +# Corrections: +- Optimization issue is fixed + +# Files modified +-s25fl256s.v +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl256s-2011-07-19-1.tar.gz +# Release Date (DD/MM/YYYY) => 19/07/2011 +# Release Version => 2.6 + +# Corrections: +- Timing check issue is fixed + +# Files modified +-s25fl256s.v +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl256s-2011-11-18-1.tar.gz +# Release Date (DD/MM/YYYY) => 18/11/2011 +# Release Version => 2.7 + +# Corrections: +- Time tHO is changed to 1 ns (customer's request) +- Setting of Device protection mode is modified (customer's request) +- BRWR instruction is corrected + +# Files modified +-s25fl256s.v +-s25fl256s.vhd +-testbench_s25fl256s_verilog.vhd +-testbench_s25fl256s_vhdl.vhd +-s25fl256s.ftmv +-s25fl256s.ftm +-s25fl256s_verilog.sdf +-s25fl256s_vhdl.sdf +########################################## +########################################## +VITAL model author - Snezana Petrovic + s-petrovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl256s-2012-08-28-2.tar.gz +# Release Date (DD/MM/YYYY) => 28/08/2012 +# Release Version => 2.8 + +# Corrections: +- QPP Instruction allowed on previosly programmed page + +# Files modified +-s25fl256s.v +-s25fl256s.vhd +-testbench_s25fl256s_verilog.vhd +-testbench_s25fl256s_vhdl.vhd +-spansion_tc_pkg.vhd + diff --git a/lib/models/memory/flash/serial/S25fl256s/model/s25fl256s.v b/lib/models/memory/flash/serial/S25fl256s/model/s25fl256s.v new file mode 100644 index 0000000..7981057 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl256s/model/s25fl256s.v @@ -0,0 +1,8062 @@ +/////////////////////////////////////////////////////////////////////////////// +// File name : s25fl256s.v +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2012 Spansion, LLC. +// +// MODIFICATION HISTORY : +// +// version: | author: | mod date: | changes made: +// V1.0 V.Mancev 19 Nov 09 Initial +// R.Prokopovic +// V1.1 V.Mancev 04 Mar 10 addr_cnt for second read in +// high performance read continuous +// mode can change its value only +// when CSNeg = '0' +// V1.2 V.Mancev 23 Mar 10 During read operations read_out +// signal changes its value in +// shorter interval +// V1.3 V.Mancev 12 Apr 10 HOLD mode corrected +// Condition for PP operation +// corrected +// V1.4 V.Mancev 20 May 10 SRWD bit assignment is corrected +// Condition for WRR command in +// write_cycle _decode section is +// corrected +// Blocking assignments for signals +// WSTART and PSTART are replaced +// with nonblocking assignments +// Conditions in Page Program +// section are fixed +// V1.5 V.Mancev 25 May 10 Conditions in programming +// sections are fixed +// Timing control sections for +// Program and Erase operation are +// changed +// V1.6 V.Mancev 03 June 10 bus_cycle_state section for +// PGSP command is fixed +// V1.7 V.Mancev 28 July 10 During the QUAD mode HOLD# input +// is not monitored for its normal +// function +// write cycle decode section is +// changed +// V1.8 B.Colakovic 24 Aug 10 All redundant signals are removed +// from BusCycle process +// V1.9 V.Mancev 30 Sep 10 Latest datasheet aligned +// B.Colakovic +// +// V2.0 V.Mancev 05 Nov 10 Hybrid configuration added +// +// V2.1 V.Mancev 12 Nov 10 QUAD Program operation during Erase +// Suspend is added +// Warning for Resume to Suspend time +// is added +// During Erase Suspend, after Program +// operation is completed, WEL bit is +// cleared +// Implemetation of Software Reset is +// Changed +// V2.2 S.Petrovic 18 Apr 11 Corrected timing in always block +// that generates rising_edge_CSNeg_ipd +// V2.3 B.Colakovic 05 July 11 Latest datasheet aligned +// V2.4 B.Colakovic 14 July 11 Optimization issue is fixed +// V2.5 V.Mancev 19 July 11 Timing check issue is fixed +// V2.6 V. Mancev 18 Nov 11 Time tHO is changed to 1 ns +// (customer's request) +// BRWR instruction is corrected +// V2.7 S.Petrovic 28 Aug 12 QPP Instruction is allowed on +// previously programmed page +// +/////////////////////////////////////////////////////////////////////////////// +// PART DESCRIPTION: +// +// Library: FLASH +// Technology: FLASH MEMORY +// Part: S25FL256S +// +// Description: 256 Megabit Serial Flash Memory +// +////////////////////////////////////////////////////////////////////////////// +// Comments : +// For correct simulation, simulator resolution should be set to 1 ps +// A device ordering (trim) option determines whether a feature is enabled +// or not, or provide relevant parameters: +// -15th character in TimingModel determines if enhanced high +// performance option is available +// (0,2,3,R,A,B,C,D) EHPLC +// (Y,Z,S,T,K,L) Security EHPLC +// (4,6,7,8,9,Q) HPLC +// -15th character in TimingModel determines if RESET# input +// is available +// (R,A,B,C,D,Q.6,7,K,L,S,T,M,N,U,V) RESET# is available +// (0,2,3,4,8,9,Y.Z.W,X) RESET# is tied to the inactive +// state,inside the package. +// -16th character in TimingModel determines Sector and Page Size: +// (0) Sector Size = 64 kB; Page Size = 256 bytes +// Hybrid Top/Bottom sector size architecture +// (1) Sector Size = 256 kB; Page Size = 512 bytes +// Uniform sector size architecture +////////////////////////////////////////////////////////////////////////////// +// Known Bugs: +// +////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// MODULE DECLARATION // +////////////////////////////////////////////////////////////////////////////// +`timescale 1 ps/1 ps + +module s25fl256s + ( + // Data Inputs/Outputs + SI , + SO , + // Controls + SCK , + CSNeg , + RSTNeg , + WPNeg , + HOLDNeg + +); + +/////////////////////////////////////////////////////////////////////////////// +// Port / Part Pin Declarations +/////////////////////////////////////////////////////////////////////////////// + + inout SI ; + inout SO ; + + input SCK ; + input CSNeg ; + input RSTNeg ; + inout HOLDNeg ; + inout WPNeg ; + + // interconnect path delay signals + wire SCK_ipd ; + wire SI_ipd ; + wire SO_ipd ; + + wire SI_in ; + assign SI_in = SI_ipd ; + + wire SI_out ; + assign SI_out = SI ; + + wire SO_in ; + assign SO_in = SO_ipd ; + + wire SO_out ; + assign SO_out = SO ; + + wire CSNeg_ipd ; + wire HOLDNeg_ipd ; + wire WPNeg_ipd ; + wire RSTNeg_ipd ; + + wire HOLDNeg_in ; + //Internal pull-up + assign HOLDNeg_in = (HOLDNeg_ipd === 1'bx) ? 1'b1 : HOLDNeg_ipd; + + wire HOLDNeg_out ; + assign HOLDNeg_out = HOLDNeg ; + + wire WPNeg_in ; + //Internal pull-up + assign WPNeg_in = (WPNeg_ipd === 1'bx) ? 1'b1 : WPNeg_ipd; + + wire WPNeg_out ; + assign WPNeg_out = WPNeg ; + + wire RSTNeg_in ; + //Internal pull-up + assign RSTNeg_in = (RSTNeg_ipd === 1'bx) ? 1'b1 : RSTNeg_ipd; + + // internal delays + reg PP_in ; + reg PP_out ; + reg BP_in ; + reg BP_out ; + reg SE_in ; + reg SE_out ; + reg BE_in ; + reg BE_out ; + reg WRR_in ; + reg WRR_out ; + reg ERSSUSP_in ; + reg ERSSUSP_out ; + reg PRGSUSP_in ; + reg PRGSUSP_out ; + reg PU_in ; + reg PU_out ; + reg RST_in ; + reg RST_out ; + reg PPBERASE_in ; + reg PPBERASE_out; + reg PASSULCK_in ; + reg PASSULCK_out; + reg PASSACC_in ; + reg PASSACC_out; + + // event control registers + reg PRGSUSP_out_event; + reg ERSSUSP_out_event; + reg Reseted_event; + reg SCK_ipd_event; + reg next_state_event; + + reg rising_edge_PoweredUp; + reg rising_edge_Reseted; + reg rising_edge_PASSULCK_in; + reg rising_edge_RES_out; + reg rising_edge_PSTART; + reg rising_edge_WSTART; + reg rising_edge_ESTART; + reg rising_edge_RSTNeg; + reg rising_edge_RST; + reg falling_edge_RSTNeg; + reg falling_edge_RST; + reg rising_edge_RST_out; + reg rising_edge_CSNeg_ipd = 1'b0; + reg falling_edge_CSNeg_ipd = 1'b0; + reg rising_edge_SCK_ipd = 1'b0; + reg falling_edge_SCK_ipd = 1'b0; + + reg RST ; + + reg SOut_zd = 1'bZ ; + reg SOut_z = 1'bZ ; + + wire SI_z ; + wire SO_z ; + + reg SIOut_zd = 1'bZ ; + reg SIOut_z = 1'bZ ; + + reg WPNegOut_zd = 1'bZ ; + reg HOLDNegOut_zd = 1'bZ ; + + assign SI_z = SIOut_z; + assign SO_z = SOut_z; + + parameter UserPreload = 1; + parameter mem_file_name = "none";//"s25fl256s.mem"; + parameter otp_file_name = "s25fl256sOTP.mem";//"none"; + + parameter TimingModel = "DefaultTimingModel"; + + parameter PartID = "s25fl256s"; + parameter MaxData = 255; + parameter MemSize = 28'h1FFFFFF; + parameter SecSize256 = 20'h3FFFF; + parameter SecSize64 = 16'hFFFF; + parameter SecSize4 = 12'hFFF; + parameter SecNum64 = 541; + parameter SecNum256 = 127; + parameter PageNum64 = 20'h3FFFF; + parameter PageNum256 = 16'hFFFF; + parameter AddrRANGE = 28'h1FFFFFF; + parameter HiAddrBit = 31; + parameter OTPSize = 1023; + parameter OTPLoAddr = 12'h000; + parameter OTPHiAddr = 12'h3FF; + parameter BYTE = 8; + + // Manufacturer Identification + parameter Manuf_ID = 8'h01; + parameter DeviceID = 8'h18; + // Electronic Signature + parameter ESignature = 8'h18; + // Device ID + //Manufacturer Identification && Memory Type && Memory Capacity + parameter Jedec_ID = 8'h01; + parameter DeviceID1 = 8'h02; + parameter DeviceID2 = 8'h19; + parameter ExtendedBytes = 8'h4D; + parameter ExtendedID64 = 8'h01; + parameter ExtendedID256 = 8'h00; + parameter DieRev = 8'h00; + parameter MaskRev = 8'h00; + + integer PageSize; + integer PageNum; + integer SecSize; + integer b_act = 0; + + integer ASP_ProtSE = 0; + integer Sec_ProtSE = 0; + + integer EHP; //Enhanced High Performance Mode active + + integer BAR_ACC = 0; //Bank Register Access active + + //varaibles to resolve architecture used + reg [24*8-1:0] tmp_timing;//stores copy of TimingModel + reg [7:0] tmp_char1;//Define EHPLC or HPLC Mode + reg [7:0] tmp_char2;//stores "0" or "1" character defining sector/page size + integer found = 1'b0; + + // If speedsimulation is needed uncomment following line + +// `define SPEEDSIM; + + // powerup + reg PoweredUp; + + // Memory Array Configuration + reg BottomBoot = 1'b0; + reg TopBoot = 1'b0; + reg UniformSec = 1'b0; + + // FSM control signals + reg PDONE ; + reg PSTART ; + reg PGSUSP ; + reg PGRES ; + + reg RES_TO_SUSP_MIN_TIME; + reg RES_TO_SUSP_TYP_TIME; + + reg WDONE ; + reg WSTART ; + + reg EDONE ; + reg ESTART ; + reg ESUSP ; + reg ERES ; + + reg Reseted ; + + reg PARAM_REGION = 1'b0; + + // Lock Bit is enabled for customer programming + reg WRLOCKENABLE = 1'b1; + // Flag that mark if ASP Register is allready programmed + reg ASPOTPFLAG = 1'b0; + + //Flag for Password unlock command + reg PASS_UNLOCKED = 1'b0; + reg [63:0] PASS_TEMP = 64'hFFFFFFFFFFFFFFFF; + + reg QUADRD = 1'b0; + reg INITIAL_CONFIG = 1'b0; + reg CHECK_FREQ = 1'b0; + + // Programming buffer + integer WByte[0:511]; + // CFI array + integer CFI_array[8'h00:8'h50]; + // OTP Memory Array + integer OTPMem[OTPLoAddr:OTPHiAddr]; + // Flash Memory Array + integer Mem[0:AddrRANGE]; + + // Registers + // VDLR Register + reg[7:0] VDLR_reg = 8'h00; + reg[7:0] VDLR_reg_in = 8'h00; + // NVDLR Register + reg[7:0] NVDLR_reg = 8'h00; + reg[7:0] NVDLR_reg_in = 8'h00; + reg dlp_act = 1'b0; + + // Status Register 1 + reg[7:0] Status_reg1 = 8'h00; + reg[7:0] Status_reg1_in = 8'h00; + + wire SRWD ; + wire P_ERR; + wire E_ERR; + wire [2:0]BP; + wire WEL; + wire WIP; + assign SRWD = Status_reg1[7]; + assign P_ERR = Status_reg1[6]; + assign E_ERR = Status_reg1[5]; + assign BP = Status_reg1[4:2]; + assign WEL = Status_reg1[1]; + assign WIP = Status_reg1[0]; + + // Status Register 2 + reg[7:0] Status_reg2 = 8'h00; + reg[7:0] Status_reg2_in = 8'h00; + + wire ES ; + wire PS ; + assign ES = Status_reg2[1]; + assign PS = Status_reg2[0]; + + // Configuration Register 1 + reg[7:0] Config_reg1 = 8'h00; + reg[7:0] Config_reg1_in = 8'h00; + + wire LC1 ; + wire LC0 ; + wire TBPROT ; + wire LOCK ; + wire BPNV ; + wire TBPARM ; + wire QUAD ; + wire FREEZE ; + assign LC1 = Config_reg1[7]; + assign LC0 = Config_reg1[6]; + assign TBPROT = Config_reg1[5]; + assign LOCK = Config_reg1[4]; + assign BPNV = Config_reg1[3]; + assign TBPARM = Config_reg1[2]; + assign QUAD = Config_reg1[1]; + assign FREEZE = Config_reg1[0]; + + // Autoboot Register + reg[31:0] AutoBoot_reg = 32'h00000000; + reg[31:0] AutoBoot_reg_in = 32'h00000000; + + wire ABE; + assign ABE = AutoBoot_reg[0]; + + // Bank Address Register + reg [7:0] Bank_Addr_reg = 8'h00; + reg [7:0] Bank_Addr_reg_in = 8'h00; + + wire EXTADD; + wire BA24; + + assign EXTADD = Bank_Addr_reg[7]; + assign BA24 = Bank_Addr_reg[0]; + + // ASP Register + reg[15:0] ASP_reg; + reg[15:0] ASP_reg_in; + + wire RPME ; + wire PPBOTP ; + wire PWDMLB ; + wire PSTMLB ; + assign RPME = ASP_reg[5]; + assign PPBOTP = ASP_reg[3]; + assign PWDMLB = ASP_reg[2]; + assign PSTMLB = ASP_reg[1]; + + // Password register + reg[63:0] Password_reg = 64'hFFFFFFFFFFFFFFFF; + reg[63:0] Password_reg_in = 64'hFFFFFFFFFFFFFFFF; + + // PPB Lock Register + reg[7:0] PPBL = 8'h00; + reg[7:0] PPBL_in = 8'h00; + + wire PPB_LOCK ; + assign PPB_LOCK = PPBL[0]; + + // PPB Access Register + reg[7:0] PPBAR = 8'hFF; + reg[7:0] PPBAR_in = 8'hFF; + + reg[SecNum64:0] PPB_bits = {542{1'b1}}; + + // DYB Access Register + reg[7:0] DYBAR = 8'hFF; + reg[7:0] DYBAR_in = 8'hFF; + + reg[SecNum64:0] DYB_bits = {542{1'b1}}; + + //The Lock Protection Registers for OTP Memory space + reg[7:0] LOCK_BYTE1; + reg[7:0] LOCK_BYTE2; + reg[7:0] LOCK_BYTE3; + reg[7:0] LOCK_BYTE4; + + // Command Register + reg write; + reg cfg_write; + reg read_out; + reg dual = 1'b0; + reg rd_fast = 1'b1; + reg rd_slow = 1'b0; + reg ddr = 1'b0; + reg ddr_fast = 1'b0; + reg hold_mode = 1'b0; + reg any_read = 1'b0; + reg quad_pg = 1'b0; + + wire rd ; + wire fast_rd ; + wire ddrd ; + wire fast_ddr ; + + wire quadpg ; + assign quadpg = quad_pg; + + wire RD_EQU_1; + assign RD_EQU_1 = any_read; + + wire RD_EQU_0; + assign RD_EQU_0 = ~any_read; + + reg change_TBPARM = 0; + + reg change_BP = 0; + reg [2:0] BP_bits = 3'b0; + + reg DOUBLE = 1'b0; //Double Data Rate (DDR) flag + + reg RdPswdProtMode = 1'b0;//Read Password Protection Mode Active flag + reg RdPswdProtEnable = 1'b0;//Read Password Protection Mode Support flag + + integer Byte_number = 0; + + reg oe = 1'b0; + reg oe_z = 1'b0; + + reg [647:0] CFI_array_tmp ; + reg [7:0] CFI_tmp; + + integer start_delay; + reg start_autoboot; + integer ABSD; + + reg change_addr ; + integer Address = 0; + integer SectorSuspend = 0; + + //Sector and subsector addresses + integer SA = 0; + + // Sector is protect if Sec_Prot(SecNum) = '1' + reg [SecNum64:0] Sec_Prot = 542'b0; + + // timing check violation + reg Viol = 1'b0; + + integer WOTPByte; + integer AddrLo; + integer AddrHi; + + reg[7:0] old_bit, new_bit; + integer old_int, new_int; + reg[63:0] old_pass; + reg[63:0] new_pass; + integer wr_cnt; + integer cnt; + + integer read_cnt = 0; + integer byte_cnt = 1; + integer read_addr = 0; + integer read_addr_tmp = 0; + integer Sec_addr = 0; + integer SecAddr = 0; + integer Page_addr = 0; + integer pgm_page = 0; + + reg[7:0] data_out; + reg[647:0] ident_out; + + time SCK_cycle = 0; + time prev_SCK; + time start_ddr; + time out_time; + time SCK_SO_DDR; +/////////////////////////////////////////////////////////////////////////////// +//Interconnect Path Delay Section +/////////////////////////////////////////////////////////////////////////////// + buf (SCK_ipd, SCK); + buf (SI_ipd, SI); + + buf (SO_ipd, SO); + buf (CSNeg_ipd, CSNeg); + buf (HOLDNeg_ipd, HOLDNeg); + buf (WPNeg_ipd, WPNeg); + buf (RSTNeg_ipd, RSTNeg); + +/////////////////////////////////////////////////////////////////////////////// +// Propagation delay Section +/////////////////////////////////////////////////////////////////////////////// + nmos (SI, SI_z , 1); + + nmos (SO, SO_z , 1); + nmos (HOLDNeg, HOLDNegOut_zd , 1); + nmos (WPNeg, WPNegOut_zd , 1); + + wire deg_pin; + wire deg_sin; + wire deg_holdin; + //VHDL VITAL CheckEnable equivalents + wire quad_rd; + assign quad_rd = deg_holdin && ~QUAD && (SIOut_z != 1'bz); + wire wr_prot; + assign wr_prot = SRWD && WEL && ~QUAD; + wire dual_rd; + assign dual_rd = dual ; + wire ddro; + assign ddro = ddr && ~dual ; + wire ddr_rd; + assign ddr_rd = PoweredUp && ddr; + wire sdr_rd; + assign sdr_rd = PoweredUp && ~ddr; + +specify + // tipd delays: interconnect path delays , mapped to input port delays. + // In Verilog is not necessary to declare any tipd_ delay variables, + // they can be taken from SDF file + // With all the other delays real delays would be taken from SDF file + + // tpd delays + specparam tpd_SCK_SO_normal =1; + specparam tpd_CSNeg_SO =1; + specparam tpd_HOLDNeg_SO =1; + specparam tpd_RSTNeg_SO =1; + //DDR operation values + specparam tpd_SCK_SO_DDR =1; + + //tsetup values: setup times + specparam tsetup_CSNeg_SCK =1; + specparam tsetup_SI_SCK_normal =1; + specparam tsetup_WPNeg_CSNeg =1; + specparam tsetup_HOLDNeg_SCK =1; + specparam tsetup_RSTNeg_CSNeg =1; + // DDR operation values + specparam tsetup_SI_SCK_DDR =1; + specparam tsetup_SI_SCK_DDR_fast =1; + specparam tsetup_CSNeg_SCK_DDR =1; + + //thold values: hold times + specparam thold_CSNeg_SCK =1; + specparam thold_SI_SCK_normal =1; + specparam thold_WPNeg_CSNeg =1; + specparam thold_HOLDNeg_SCK =1; + specparam thold_CSNeg_RSTNeg =1; + // DDR operation values + specparam thold_SI_SCK_DDR =1; + specparam thold_SI_SCK_DDR_fast =1; + specparam thold_CSNeg_SCK_DDR =1; + + // tpw values: pulse width + specparam tpw_SCK_serial_posedge =1; + specparam tpw_SCK_dual_posedge =1; + specparam tpw_SCK_fast_posedge =1; + specparam tpw_SCK_quadpg_posedge =1; + specparam tpw_SCK_serial_negedge =1; + specparam tpw_SCK_dual_negedge =1; + specparam tpw_SCK_fast_negedge =1; + specparam tpw_SCK_quadpg_negedge =1; + specparam tpw_CSNeg_read_posedge =1; + specparam tpw_CSNeg_pgers_posedge =1; + specparam tpw_RSTNeg_negedge =1; + specparam tpw_RSTNeg_posedge =1; + // DDR operation values + specparam tpw_SCK_DDR_posedge =1; + specparam tpw_SCK_DDR_negedge =1; + + // tperiod min (calculated as 1/max freq) + specparam tperiod_SCK_serial_rd =1;// 50 MHz + specparam tperiod_SCK_fast_rd =1;//133 MHz + specparam tperiod_SCK_dual_rd =1;//104 MHz + specparam tperiod_SCK_quadpg =1;// 80 MHz + // DDR operation values + specparam tperiod_SCK_DDR_rd =1;// 66 MHz + + `ifdef SPEEDSIM + // Page Program Operation + specparam tdevice_PP_256 = 55e7;//tPP + // Page Program Operation + specparam tdevice_PP_512 = 75e7;//tPP + // Typical Byte Programming Time + specparam tdevice_BP = 4e8;//tBP + // Sector Erase Operation + specparam tdevice_SE64 = 650e7;//tSE + // Sector Erase Operation + specparam tdevice_SE256 = 1875e7;//tSE + // Bulk Erase Operation + specparam tdevice_BE = 330e9;//tBE + // WRR Cycle Time + specparam tdevice_WRR = 2e9;//tW + // Erase Suspend/Erase Resume Time + specparam tdevice_ERSSUSP = 40e6;//tESL + // Program Suspend/Program Resume Time + specparam tdevice_PRGSUSP = 40e6;// + // VCC (min) to CS# Low + specparam tdevice_PU = 3e8;//tPU + // PPB Erase Time + specparam tdevice_PPBERASE = 15e9;// + // Password Unlock Time + specparam tdevice_PASSULCK = 1e6;// + // Password Unlock to Password Unlock Time + specparam tdevice_PASSACC = 100e6; + `else + // Page Program Operation + specparam tdevice_PP_256 = 55e7;//tPP + // Page Program Operation + specparam tdevice_PP_512 = 75e7;//tPP + // Typical Byte Programming Time + specparam tdevice_BP = 4e8;//tBP + // Sector Erase Operation + specparam tdevice_SE64 = 650e9;//tSE + // Sector Erase Operation + specparam tdevice_SE256 = 1875e9;//tSE + // Bulk Erase Operation + specparam tdevice_BE = 330e12;//tBE + // WRR Cycle Time + specparam tdevice_WRR = 2e11;//tW + // Erase Suspend/Erase Resume Time + specparam tdevice_ERSSUSP = 40e6;//tESL + // Program Suspend/Program Resume Time + specparam tdevice_PRGSUSP = 40e6;// + // VCC (min) to CS# Low + specparam tdevice_PU = 3e8;//tPU + // PPB Erase Time + specparam tdevice_PPBERASE = 15e9;// + // Password Unlock Time + specparam tdevice_PASSULCK = 1e6;// + // Password Unlock to Password Unlock Time + specparam tdevice_PASSACC = 100e6; + `endif // SPEEDSIM + +/////////////////////////////////////////////////////////////////////////////// +// Input Port Delays don't require Verilog description +/////////////////////////////////////////////////////////////////////////////// +// Path delays // +/////////////////////////////////////////////////////////////////////////////// + if (~ddr) (SCK => SO) = tpd_SCK_SO_normal; + if (ddr || rd_fast) (SCK => SO) = tpd_SCK_SO_DDR; + + if (~ddr && dual) (SCK => SI) = tpd_SCK_SO_normal; + if ( ddr && dual) (SCK => SI) = tpd_SCK_SO_DDR; + + if (~ddr && QUAD)(SCK => HOLDNeg) = tpd_SCK_SO_normal; + if ( ddr && QUAD)(SCK => HOLDNeg) = tpd_SCK_SO_DDR; + if (~ddr && QUAD)(SCK => WPNeg) = tpd_SCK_SO_normal; + if ( ddr && QUAD)(SCK => WPNeg) = tpd_SCK_SO_DDR; + + if (CSNeg) (CSNeg => SO) = tpd_CSNeg_SO; + if (CSNeg && dual) (CSNeg => SI) = tpd_CSNeg_SO; + + if (CSNeg && QUAD) (CSNeg => HOLDNeg) = tpd_CSNeg_SO; + if (CSNeg && QUAD) (CSNeg => WPNeg) = tpd_CSNeg_SO; + + if (~QUAD) (HOLDNeg => SO) = tpd_HOLDNeg_SO; + if (~QUAD && dual) (HOLDNeg => SI) = tpd_HOLDNeg_SO; + + (RSTNeg => SO) = tpd_RSTNeg_SO; +/////////////////////////////////////////////////////////////////////////////// +// Timing Violation // +/////////////////////////////////////////////////////////////////////////////// + $setup ( CSNeg , posedge SCK &&& sdr_rd, + tsetup_CSNeg_SCK, Viol); + $setup ( CSNeg , posedge SCK &&& ddr_rd, + tsetup_CSNeg_SCK_DDR, Viol); + $setup ( SI , posedge SCK &&& deg_sin, + tsetup_SI_SCK_normal, Viol); + $setup ( WPNeg , negedge CSNeg &&& wr_prot, + tsetup_WPNeg_CSNeg, Viol); + $setup ( HOLDNeg , posedge SCK &&& quad_rd, + tsetup_HOLDNeg_SCK, Viol); + $setup ( SI , posedge SCK &&& ddro, + tsetup_SI_SCK_DDR, Viol); + $setup ( SI , negedge SCK &&& ddro, + tsetup_SI_SCK_DDR, Viol); + + $setup ( RSTNeg , negedge CSNeg, + tsetup_RSTNeg_CSNeg, Viol); + + $hold ( posedge SCK &&& sdr_rd , CSNeg, + thold_CSNeg_SCK, Viol); + $hold ( posedge SCK &&& ddr_rd , CSNeg, + thold_CSNeg_SCK_DDR, Viol); + $hold ( posedge SCK &&& deg_sin , SI , + thold_SI_SCK_normal, Viol); + $hold ( posedge CSNeg &&& wr_prot , WPNeg , + thold_WPNeg_CSNeg, Viol); + $hold ( posedge SCK &&& quad_rd , HOLDNeg , + thold_HOLDNeg_SCK, Viol); + $hold ( posedge SCK &&& ddro , SI, + thold_SI_SCK_DDR, Viol); + $hold ( negedge SCK &&& ddro , SI, + thold_SI_SCK_DDR, Viol); + + $hold ( negedge RSTNeg , CSNeg, + thold_CSNeg_RSTNeg, Viol); + + $width ( posedge SCK &&& rd , tpw_SCK_serial_posedge); + $width ( negedge SCK &&& rd , tpw_SCK_serial_negedge); + $width ( posedge SCK &&& dual_rd , tpw_SCK_dual_posedge); + $width ( negedge SCK &&& dual_rd , tpw_SCK_dual_negedge); + $width ( posedge SCK &&& fast_rd , tpw_SCK_fast_posedge); + $width ( negedge SCK &&& fast_rd , tpw_SCK_fast_negedge); + $width ( posedge SCK &&& ddrd , tpw_SCK_DDR_posedge); + $width ( negedge SCK &&& ddrd , tpw_SCK_DDR_negedge); + $width ( posedge SCK &&& quadpg , tpw_SCK_quadpg_posedge); + $width ( negedge SCK &&& quadpg , tpw_SCK_quadpg_negedge); + + $width ( posedge CSNeg &&& RD_EQU_1, tpw_CSNeg_read_posedge); + $width ( posedge CSNeg &&& RD_EQU_0, tpw_CSNeg_pgers_posedge); + $width ( negedge RSTNeg , tpw_RSTNeg_negedge); + $width ( posedge RSTNeg , tpw_RSTNeg_posedge); + + $period ( posedge SCK &&& rd , tperiod_SCK_serial_rd); + $period ( posedge SCK &&& fast_rd , tperiod_SCK_fast_rd); + $period ( posedge SCK &&& dual_rd , tperiod_SCK_dual_rd); + $period ( posedge SCK &&& quadpg , tperiod_SCK_quadpg); + $period ( posedge SCK &&& ddrd , tperiod_SCK_DDR_rd); + +endspecify + +/////////////////////////////////////////////////////////////////////////////// +// Main Behavior Block // +/////////////////////////////////////////////////////////////////////////////// +// FSM states + parameter IDLE = 5'd0; + parameter RESET_STATE = 5'd1; + parameter AUTOBOOT = 5'd2; + parameter WRITE_SR = 5'd3; + parameter PAGE_PG = 5'd4; + parameter OTP_PG = 5'd5; + parameter PG_SUSP = 5'd6; + parameter SECTOR_ERS = 5'd7; + parameter BULK_ERS = 5'd8; + parameter ERS_SUSP = 5'd9; + parameter ERS_SUSP_PG = 5'd10; + parameter ERS_SUSP_PG_SUSP= 5'd11; + parameter PASS_PG = 5'd12; + parameter PASS_UNLOCK = 5'd13; + parameter PPB_PG = 5'd14; + parameter PPB_ERS = 5'd15; + parameter AUTOBOOT_PG = 5'd16; + parameter ASP_PG = 5'd17; + parameter PLB_PG = 5'd18; + parameter DYB_PG = 5'd19; + parameter NVDLR_PG = 5'd20; + + reg [4:0] current_state; + reg [4:0] next_state; + +// Instruction type + parameter NONE = 7'd0; + parameter WRR = 7'd1; + parameter PP = 7'd2; + parameter READ = 7'd3; + parameter WRDI = 7'd4; + parameter RDSR = 7'd5; + parameter WREN = 7'd6; + parameter RDSR2 = 7'd7; + parameter FSTRD = 7'd8; + parameter FSTRD4 = 7'd9; + parameter DDRFR = 7'd10; + parameter DDRFR4 = 7'd11; + parameter PP4 = 7'd12; + parameter RD4 = 7'd13; + parameter ABRD = 7'd14; + parameter ABWR = 7'd15; + parameter BRRD = 7'd16; + parameter BRWR = 7'd17; + parameter P4E = 7'd19; + parameter P4E4 = 7'd20; + parameter ASPRD = 7'd21; + parameter ASPP = 7'd22; + parameter CLSR = 7'd23; + parameter QPP = 7'd24; + parameter QPP4 = 7'd25; + parameter RDCR = 7'd26; + parameter DOR = 7'd27; + parameter DOR4 = 7'd28; + parameter DLPRD = 7'd29; + parameter OTPP = 7'd30; + parameter PNVDLR = 7'd31; + parameter OTPR = 7'd32; + parameter WVDLR = 7'd33; + parameter BE = 7'd34; + parameter QOR = 7'd35; + parameter QOR4 = 7'd36; + parameter ERSP = 7'd37; + parameter ERRS = 7'd38; + parameter PGSP = 7'd39; + parameter PGRS = 7'd40; + parameter REMS = 7'd41; + parameter RDID = 7'd42; + parameter MPM = 7'd43; + parameter PLBWR = 7'd44; + parameter PLBRD = 7'd45; + parameter RES = 7'd46; + parameter DIOR = 7'd47; + parameter DIOR4 = 7'd48; + parameter DDRDIOR = 7'd49; + parameter DDRDIOR4 = 7'd50; + parameter SE = 7'd51; + parameter SE4 = 7'd52; + parameter DYBRD = 7'd53; + parameter DYBWR = 7'd54; + parameter PPBRD = 7'd55; + parameter PPBP = 7'd56; + parameter PPBERS = 7'd57; + parameter PASSRD = 7'd58; + parameter PASSP = 7'd59; + parameter PASSU = 7'd60; + parameter QIOR = 7'd61; + parameter QIOR4 = 7'd62; + parameter DDRQIOR = 7'd63; + parameter DDRQIOR4 = 7'd64; + parameter RESET = 7'd65; + parameter MBR = 7'd66; + parameter BRAC = 7'd67; + + reg [6:0] Instruct; + +//Bus cycle state + parameter STAND_BY = 3'd0; + parameter OPCODE_BYTE = 3'd1; + parameter ADDRESS_BYTES = 3'd2; + parameter DUMMY_BYTES = 3'd3; + parameter MODE_BYTE = 3'd4; + parameter DATA_BYTES = 3'd5; + + reg [2:0] bus_cycle_state; + + reg deq_pin; + always @(SO_in, SO_z) + begin + if (SO_in==SO_z) + deq_pin=1'b0; + else + deq_pin=1'b1; + end + // check when data is generated from model to avoid setuphold check in + // this occasion + assign deg_pin=deq_pin; + + reg deq_sin; + always @(SI_in, SIOut_z) + begin + if (SI_in==SIOut_z) + deq_sin=1'b0; + else + deq_sin=1'b1; + end + // check when data is generated from model to avoid setuphold check in + // this occasion + assign deg_sin=deq_sin + && (ddr == 1'b0) && (Instruct !== DDRFR) + && (Instruct !== DDRFR4) && (Instruct !== DDRDIOR) + && (Instruct !== DDRDIOR4) && (Instruct !== DDRQIOR) + && (Instruct !== DDRQIOR4) && (SIOut_z != 1'bz); + + reg deq_holdin; + always @(HOLDNeg_ipd, HOLDNegOut_zd) + begin + if (HOLDNeg_ipd==HOLDNegOut_zd) + deq_holdin=1'b0; + else + deq_holdin=1'b1; + end + // check when data is generated from model to avoid setuphold check in + // this occasion + assign deg_holdin=deq_holdin; + + //Power Up time; + initial + begin + PoweredUp = 1'b0; + #tdevice_PU PoweredUp = 1'b1; + end + + initial + begin : Init + write = 1'b0; + cfg_write = 1'b0; + read_out = 1'b0; + Address = 0; + change_addr = 1'b0; + cnt = 0; + RST = 1'b0; + RST_in = 1'b0; + RST_out = 1'b1; + PDONE = 1'b1; + PSTART = 1'b0; + PGSUSP = 1'b0; + PGRES = 1'b0; + PRGSUSP_in = 1'b0; + ERSSUSP_in = 1'b0; + RES_TO_SUSP_MIN_TIME = 1'b0; + RES_TO_SUSP_TYP_TIME = 1'b0; + + EDONE = 1'b1; + ESTART = 1'b0; + ESUSP = 1'b0; + ERES = 1'b0; + + WDONE = 1'b1; + WSTART = 1'b0; + + Reseted = 1'b0; + + Instruct = NONE; + bus_cycle_state = STAND_BY; + current_state = IDLE; + next_state = IDLE; + end + + // initialize memory and load preload files if any + initial + begin: InitMemory + integer i; + + for (i=0;i<=AddrRANGE;i=i+1) + begin + Mem[i] = MaxData; + end + + if ((UserPreload) && !(mem_file_name == "none")) + begin + // Memory Preload + //s25fl256s.mem, memory preload file + // @aaaaaa - stands for address + // dd -
is byte to be written at Mem(aaaaaa++) + // (aaaaaa is incremented at every load) + $readmemh(mem_file_name,Mem); + end + + for (i=OTPLoAddr;i<=OTPHiAddr;i=i+1) + begin + OTPMem[i] = MaxData; + end + + if (UserPreload && !(otp_file_name == "none")) + begin + //s25fl256s_otp memory file + // / - comment + // @aaaaaa - stands for address within last defined + // sector + // dd -
is byte to be written at OTPMem(aaa++) + // (aa is incremented at every load) + // only first 1-4 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + $readmemh(otp_file_name,OTPMem); + end + + LOCK_BYTE1[7:0] = OTPMem[16]; + LOCK_BYTE2[7:0] = OTPMem[17]; + LOCK_BYTE3[7:0] = OTPMem[18]; + LOCK_BYTE4[7:0] = OTPMem[19]; + end + + // initialize memory and load preload files if any + initial + begin: InitTimingModel + integer i; + integer j; + //UNIFORM OR HYBRID arch model is used + //assumptions: + //1. TimingModel has format as S25FL128SXXXXXXXX_X_XXpF + //it is important that 16-th character from first one is "0" or "1" + //2. TimingModel does not have more then 24 characters + tmp_timing = TimingModel;//copy of TimingModel + + i = 23; + while ((i >= 0) && (found != 1'b1))//search for first non null character + begin //i keeps position of first non null character + j = 7; + while ((j >= 0) && (found != 1'b1)) + begin + if (tmp_timing[i*8+j] != 1'd0) + found = 1'b1; + else + j = j-1; + end + i = i - 1; + end + i = i +1; + if (found)//if non null character is found + begin + for (j=0;j<=7;j=j+1) + begin + //EHPLC/HPLC character is 15 + tmp_char1[j] = TimingModel[(i-14)*8+j]; + //256B/512B Page character is 16 + tmp_char2[j] = TimingModel[(i-15)*8+j]; + end + end + if (tmp_char1 == "0" || tmp_char1 == "2" || tmp_char1 == "3" || + tmp_char1 == "R" || tmp_char1 == "A" || tmp_char1 == "B" || + tmp_char1 == "C" || tmp_char1 == "D" || tmp_char1 == "Y" || + tmp_char1 == "Z" || tmp_char1 == "S" || tmp_char1 == "T" || + tmp_char1 == "K" || tmp_char1 == "L") + begin + EHP = 1; + if(tmp_char1 == "Z" || tmp_char1 == "S" || tmp_char1 == "T" || + tmp_char1 == "K" || tmp_char1 == "L" || tmp_char1 == "Y") + begin + RdPswdProtEnable = 1; + end + end + else if (tmp_char1 == "4" || tmp_char1 == "6" || tmp_char1 == "7" || + tmp_char1 == "8" || tmp_char1 == "9" || tmp_char1 == "Q") + begin + EHP = 0; + end + + if (tmp_char1 == "0" || tmp_char1 == "2" || tmp_char1 == "3" || + tmp_char1 == "R" || tmp_char1 == "A" || tmp_char1 == "B" || + tmp_char1 == "C" || tmp_char1 == "D" || tmp_char1 == "4" || + tmp_char1 == "6" || tmp_char1 == "7" || tmp_char1 == "8" || + tmp_char1 == "9" || tmp_char1 == "Q") + begin + ASP_reg = 16'hFE7F; + ASP_reg_in = 16'hFE7F; + end + else if (tmp_char1 == "Y" || tmp_char1 == "Z" || tmp_char1 == "S" || + tmp_char1 == "T" || tmp_char1 == "K" || tmp_char1 == "L") + begin + ASP_reg = 16'hFE4F; + ASP_reg_in = 16'hFE4F; + end + + if (tmp_char2 == "0") + begin + PageSize = 255; + PageNum = PageNum64; + SecSize = SecSize64; + end + else if (tmp_char2 == "1") + begin + PageSize = 511; + PageNum = PageNum256; + SecSize = SecSize256; + end + end + + //CFI + initial + begin: InitCFI + integer i; + integer j; + /////////////////////////////////////////////////////////////////////// + // ID-CFI array data + /////////////////////////////////////////////////////////////////////// + // Manufacturer and Device ID + CFI_array[8'h00] = Jedec_ID; + CFI_array[8'h01] = DeviceID1; + CFI_array[8'h02] = DeviceID2; + CFI_array[8'h03] = 8'h00; + if (tmp_char2 == "0") + // Uniform 64kB sectors + CFI_array[8'h04] = ExtendedID64; + else if (tmp_char2 == "1") + // Uniform 256kB sectors + CFI_array[8'h04] = ExtendedID256; + CFI_array[8'h05] = 8'h80; + CFI_array[8'h06] = 8'h00; + CFI_array[8'h07] = 8'h00; + CFI_array[8'h08] = 8'h00; + CFI_array[8'h09] = 8'h00; + CFI_array[8'h0A] = 8'h00; + CFI_array[8'h0B] = 8'h00; + CFI_array[8'h0C] = 8'h00; + CFI_array[8'h0D] = 8'h00; + CFI_array[8'h0E] = 8'h00; + CFI_array[8'h0F] = 8'h00; + // CFI Query Identification String + CFI_array[8'h10] = 8'h51; + CFI_array[8'h11] = 8'h52; + CFI_array[8'h12] = 8'h59; + CFI_array[8'h13] = 8'h02; + CFI_array[8'h14] = 8'h00; + CFI_array[8'h15] = 8'h40; + CFI_array[8'h16] = 8'h00; + CFI_array[8'h17] = 8'h53; + CFI_array[8'h18] = 8'h46; + CFI_array[8'h19] = 8'h51; + CFI_array[8'h1A] = 8'h00; + //CFI system interface string + CFI_array[8'h1B] = 8'h27; + CFI_array[8'h1C] = 8'h36; + CFI_array[8'h1D] = 8'h00; + CFI_array[8'h1E] = 8'h00; + CFI_array[8'h1F] = 8'h06; + if (tmp_char2 == "0") + begin + // 64kB sector and 256B page + CFI_array[8'h20] = 8'h08; + CFI_array[8'h21] = 8'h08; + end + else if (tmp_char2 == "1") + begin + // 256kB sector and 512B page + CFI_array[8'h20] = 8'h09; + CFI_array[8'h21] = 8'h09; + end + CFI_array[8'h22] = 8'h10; + CFI_array[8'h23] = 8'h02; + CFI_array[8'h24] = 8'h02; + CFI_array[8'h25] = 8'h03; + CFI_array[8'h26] = 8'h03; + // Device Geometry Definition(Uniform Sector Devices) + CFI_array[8'h27] = 8'h19; + CFI_array[8'h28] = 8'h02; + CFI_array[8'h29] = 8'h01; + if (tmp_char2 == "0") + // 64kB sectors + CFI_array[8'h2A] = 8'h08; + else if (tmp_char2 == "1") + CFI_array[8'h2A] = 8'h09; + + CFI_array[8'h2B] = 8'h00; + if (tmp_char2 == "1") + begin + CFI_array[8'h2C] = 8'h01; + CFI_array[8'h2D] = 8'h7F; + CFI_array[8'h2E] = 8'h00; + CFI_array[8'h2F] = 8'h00; + CFI_array[8'h30] = 8'h04; + CFI_array[8'h31] = 8'hFF; + CFI_array[8'h32] = 8'hFF; + CFI_array[8'h33] = 8'hFF; + CFI_array[8'h34] = 8'hFF; + end + else + begin + CFI_array[8'h2C] = 8'h02; + if (TBPARM) + begin + // 4KB physical sectors at top + CFI_array[8'h2D] = 8'hFD; + CFI_array[8'h2E] = 8'h00; + CFI_array[8'h2F] = 8'h00; + CFI_array[8'h30] = 8'h01; + CFI_array[8'h31] = 8'h1F; + CFI_array[8'h32] = 8'h01; + CFI_array[8'h33] = 8'h10; + CFI_array[8'h34] = 8'h00; + end + else + begin + // 4KB physical sectors at bottom + CFI_array[8'h2D] = 8'h1F; + CFI_array[8'h2E] = 8'h00; + CFI_array[8'h2F] = 8'h10; + CFI_array[8'h30] = 8'h00; + CFI_array[8'h31] = 8'hFD; + CFI_array[8'h32] = 8'h01; + CFI_array[8'h33] = 8'h00; + CFI_array[8'h34] = 8'h01; + end + end + CFI_array[8'h35] = 8'hFF; + CFI_array[8'h36] = 8'hFF; + CFI_array[8'h37] = 8'hFF; + CFI_array[8'h38] = 8'hFF; + CFI_array[8'h39] = 8'hFF; + CFI_array[8'h3A] = 8'hFF; + CFI_array[8'h3B] = 8'hFF; + CFI_array[8'h3C] = 8'hFF; + CFI_array[8'h3D] = 8'hFF; + CFI_array[8'h3E] = 8'hFF; + CFI_array[8'h3F] = 8'hFF; + // CFI Primary Vendor-Specific Extended Query + CFI_array[8'h40] = 8'h50; + CFI_array[8'h41] = 8'h52; + CFI_array[8'h42] = 8'h49; + CFI_array[8'h43] = 8'h31; + CFI_array[8'h44] = 8'h33; + CFI_array[8'h45] = 8'h21; + CFI_array[8'h46] = 8'h02; + CFI_array[8'h47] = 8'h01; + CFI_array[8'h48] = 8'h00; + CFI_array[8'h49] = 8'h08; + CFI_array[8'h4A] = 8'h00; + CFI_array[8'h4B] = 8'h01; + CFI_array[8'h4C] = 8'h00; + CFI_array[8'h4D] = 8'h00; + CFI_array[8'h4E] = 8'h00; + CFI_array[8'h4F] = 8'h07; + CFI_array[8'h50] = 8'h01; + + begin + for(i=80;i>=0;i=i-1) + begin + CFI_tmp = CFI_array[8'h00-i+80]; + for(j=7;j>=0;j=j-1) + begin + CFI_array_tmp[8*i+j] = CFI_tmp[j]; + end + end + end + end + + always @(next_state_event or PoweredUp or RST or RST_out) + begin: StateTransition + if (PoweredUp) + begin + if ((RSTNeg_in) && RST_out == 1'b1) + current_state = #(1000) next_state; + else if ((~RSTNeg_in || rising_edge_RSTNeg) && falling_edge_RST) + begin + // no state transition while RESET# low + current_state = RESET_STATE; + RST_in = 1'b1; + #1000 RST_in = 1'b0; + end + end + end + + always @(posedge RST_in) + begin:Threset + RST_out = 1'b0; + #(35000000-200000) RST_out = 1'b1; + end + + always @(negedge CSNeg_ipd) + begin:CheckCEOnPowerUP + if (~PoweredUp) + $display ("Device is selected during Power Up"); + end + + /////////////////////////////////////////////////////////////////////////// + //// Internal Delays + /////////////////////////////////////////////////////////////////////////// + + always @(posedge PRGSUSP_in) + begin:PRGSuspend + PRGSUSP_out = 1'b0; + #tdevice_PRGSUSP PRGSUSP_out = 1'b1; + end + + always @(posedge PPBERASE_in) + begin:PPBErs + PPBERASE_out = 1'b0; + #tdevice_PPBERASE PPBERASE_out = 1'b1; + end + + always @(posedge ERSSUSP_in) + begin:ERSSuspend + ERSSUSP_out = 1'b0; + #tdevice_ERSSUSP ERSSUSP_out = 1'b1; + end + + always @(posedge PASSULCK_in) + begin:PASSULock + PASSULCK_out = 1'b0; + #tdevice_PASSULCK PASSULCK_out = 1'b1; + end + + always @(posedge PASSACC_in) + begin:PASSAcc + PASSACC_out = 1'b0; + #tdevice_PASSACC PASSACC_out = 1'b1; + end + +/////////////////////////////////////////////////////////////////////////////// +// write cycle decode +/////////////////////////////////////////////////////////////////////////////// + integer opcode_cnt = 0; + integer addr_cnt = 0; + integer mode_cnt = 0; + integer dummy_cnt = 0; + integer data_cnt = 0; + integer bit_cnt = 0; + + reg [4095:0] Data_in = 4096'b0; + reg [7:0] opcode; + reg [7:0] opcode_in; + reg [7:0] opcode_tmp; + reg [31:0] addr_bytes; + reg [31:0] hiaddr_bytes; + reg [31:0] Address_in; + reg [7:0] mode_bytes; + reg [7:0] mode_in; + integer Latency_code; + integer quad_data_in [0:1023]; + reg [3:0] quad_nybble = 4'b0; + reg [3:0] Quad_slv; + reg [7:0] Byte_slv; + + always @(rising_edge_CSNeg_ipd or falling_edge_CSNeg_ipd or + rising_edge_SCK_ipd or falling_edge_SCK_ipd) + begin: Buscycle + integer i; + integer j; + integer k; + time CLK_PER; + time LAST_CLK; + + if (falling_edge_CSNeg_ipd) + begin + if (bus_cycle_state==STAND_BY) + begin + Instruct = NONE; + write = 1'b1; + cfg_write = 0; + opcode_cnt = 0; + addr_cnt = 0; + mode_cnt = 0; + dummy_cnt = 0; + data_cnt = 0; + opcode_tmp = 0; + DOUBLE = 1'b0; + QUADRD = 1'b0; + CLK_PER = 1'b0; + LAST_CLK = 1'b0; + if (current_state == AUTOBOOT) + begin + bus_cycle_state = DATA_BYTES; + end + else + begin + bus_cycle_state = OPCODE_BYTE; + end + end + end + + if (rising_edge_SCK_ipd) // Instructions, addresses or data present + begin // at SI are latched on the rising edge of SCK + + CLK_PER = $time - LAST_CLK; + LAST_CLK = $time; + if (CHECK_FREQ) + begin + if ((CLK_PER < 20000 && Latency_code == 3) || + (CLK_PER < 12500 && Latency_code == 0) || + (CLK_PER < 11100 && Latency_code == 1) || + (CLK_PER < 9600 && Latency_code == 2)) + begin + $display ("More wait states are required for"); + $display ("this clock frequency value"); + end + CHECK_FREQ = 0; + end + + if (~CSNeg_ipd) + begin + case (bus_cycle_state) + OPCODE_BYTE: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + opcode_in[opcode_cnt] = SI_in; + opcode_cnt = opcode_cnt + 1; + Latency_code = Config_reg1[7:6]; + if (opcode_cnt == BYTE) + begin + for(i=7;i>=0;i=i-1) + begin + opcode[i] = opcode_in[7-i]; + end + case (opcode) + 8'b00000110 : // 06h + begin + Instruct = WREN; + bus_cycle_state = DATA_BYTES; + end + 8'b00000100 : // 04h + begin + Instruct = WRDI; + bus_cycle_state = DATA_BYTES; + end + 8'b00000001 : // 01h + begin + Instruct = WRR; + bus_cycle_state = DATA_BYTES; + end + 8'b00000011 : // 03h + begin + Instruct = READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00010011 : // 13h + begin + Instruct = RD4; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01001011 : // 4Bh + begin + Instruct = OTPR; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00000101 : // 05h + begin + Instruct = RDSR; + bus_cycle_state = DATA_BYTES; + end + 8'b00000111 : // 07h + begin + Instruct = RDSR2; + bus_cycle_state = DATA_BYTES; + end + 8'b00110101 : // 35h + begin + Instruct = RDCR; + bus_cycle_state = DATA_BYTES; + end + 8'b10010000 : // 90h + begin + Instruct = REMS; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10011111 : // 9Fh + begin + Instruct = RDID; + bus_cycle_state = DATA_BYTES; + end + 8'b10101011 : // ABh + begin + Instruct = RES; + bus_cycle_state = DUMMY_BYTES; + end + 8'b00001011 : // 0Bh + begin + Instruct = FSTRD; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00001100 : // 0Ch + begin + Instruct = FSTRD4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00001101 : // 0Dh + begin + Instruct = DDRFR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00001110 : // 0Eh + begin + Instruct = DDRFR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00111011 : // 3Bh + begin + Instruct = DOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00111100 : // 3Ch + begin + Instruct = DOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b10111011 : // BBh + begin + Instruct = DIOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b10111100 : // BCh + begin + Instruct = DIOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b10111101 : // BDh + begin + Instruct = DDRDIOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b10111110 : // BEh + begin + Instruct = DDRDIOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b01101011 : // 6Bh + begin + Instruct = QOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b01101100 : // 6Ch + begin + Instruct = QOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b11101011 : // EBh + begin + Instruct = QIOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b11101100 : // ECh + begin + Instruct = QIOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b11101101 : // EDh + begin + Instruct = DDRQIOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b11101110 : // EEh + begin + Instruct = DDRQIOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00000010 : // 02h + begin + Instruct = PP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00010010 : // 12h + begin + Instruct = PP4; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00110010: // 32h + begin + Instruct = QPP; + bus_cycle_state = ADDRESS_BYTES; + quad_pg = 1'b1; + end + 8'b00111000: // 38h + begin + Instruct = QPP; + bus_cycle_state = ADDRESS_BYTES; + quad_pg = 1'b1; + end + 8'b00110100 : // 34h + begin + Instruct = QPP4; + bus_cycle_state = ADDRESS_BYTES; + quad_pg = 1'b1; + end + 8'b01000010 : // 42h + begin + Instruct = OTPP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10000101 : // 85h + begin + Instruct = PGSP; + bus_cycle_state = DATA_BYTES; + end + 8'b10001010 : // 8Ah + begin + Instruct = PGRS; + bus_cycle_state = DATA_BYTES; + end + 8'b11000111 : // C7h + begin + Instruct = BE; + bus_cycle_state = DATA_BYTES; + end + 8'b01100000 : // 60h + begin + Instruct = BE; + bus_cycle_state = DATA_BYTES; + end + 8'b11011000 : // D8h + begin + Instruct = SE; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11011100 : // DCh + begin + Instruct = SE4; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01110101 : // 75h + begin + Instruct = ERSP; + bus_cycle_state = DATA_BYTES; + end + 8'b01111010 : // 7Ah + begin + Instruct = ERRS; + bus_cycle_state = DATA_BYTES; + end + 8'b00010100 : // 14h + begin + Instruct = ABRD; + bus_cycle_state = DATA_BYTES; + end + 8'b00010101 : // 15h + begin + Instruct = ABWR; + bus_cycle_state = DATA_BYTES; + end + 8'b00010110 : // 16h + begin + Instruct = BRRD; + bus_cycle_state = DATA_BYTES; + end + 8'b00010111 : // 17h + begin + Instruct = BRWR; + bus_cycle_state = DATA_BYTES; + end + 8'b00101011 : // 2Bh + begin + Instruct = ASPRD; + bus_cycle_state = DATA_BYTES; + end + 8'b00101111 : // 2Fh + begin + Instruct = ASPP; + bus_cycle_state = DATA_BYTES; + end + 8'b11100000 : // E0h + begin + Instruct = DYBRD; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11100001 : // E1h + begin + Instruct = DYBWR; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11100010 : // E2h + begin + Instruct = PPBRD; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11100011 : // E3h + begin + Instruct = PPBP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11100100 : // E4h + begin + Instruct = PPBERS; + bus_cycle_state = DATA_BYTES; + end + 8'b10100110 : // A6h + begin + Instruct = PLBWR; + bus_cycle_state = DATA_BYTES; + end + 8'b10100111 : // A7h + begin + Instruct = PLBRD; + bus_cycle_state = DATA_BYTES; + end + 8'b11100111 : // E7h + begin + Instruct = PASSRD; + bus_cycle_state = DATA_BYTES; + end + 8'b11101000 : // E8h + begin + Instruct = PASSP; + bus_cycle_state = DATA_BYTES; + end + 8'b11101001 : // E9h + begin + Instruct = PASSU; + bus_cycle_state = DATA_BYTES; + end + 8'b11110000 : // F0h + begin + Instruct = RESET; + bus_cycle_state = DATA_BYTES; + end + 8'b00110000 : // 30h + begin + Instruct = CLSR; + bus_cycle_state = DATA_BYTES; + end + 8'b00100000 : // 20h + begin + Instruct = P4E; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00100001 : // 21h + begin + Instruct = P4E4; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01000001 : // 41h + begin + Instruct = DLPRD; + bus_cycle_state = DATA_BYTES; + end + 8'b01000011 : // 43h + begin + Instruct = PNVDLR; + bus_cycle_state = DATA_BYTES; + end + 8'b01001010 : // 4Ah + begin + Instruct = WVDLR; + bus_cycle_state = DATA_BYTES; + end + 8'b10111001 : // B9h + begin + Instruct = BRAC; + bus_cycle_state = DATA_BYTES; + end + 8'b11111111 : // FFh + begin + Instruct = MBR; + bus_cycle_state = MODE_BYTE; + end + endcase + end + end + end //end of OPCODE BYTE + + ADDRESS_BYTES : + begin + if ((Instruct == DDRFR) || (Instruct == DDRFR4) || + (Instruct == DDRDIOR) || (Instruct == DDRDIOR4) || + (Instruct == DDRQIOR) || (Instruct == DDRQIOR4)) + DOUBLE = 1'b1; + else + DOUBLE = 1'b0; + if ((Instruct == QOR) || (Instruct == QOR4) || + (Instruct == QIOR) || (Instruct == QIOR4) || + (Instruct == DDRQIOR) || (Instruct == DDRQIOR4)) + QUADRD = 1'b1; + else + QUADRD = 1'b0; + if (DOUBLE == 1'b0) + begin + if (((((Instruct == FSTRD) && (~EXTADD)) || + ((Instruct == DOR) && (~EXTADD)) || + (Instruct == OTPR)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + ((Instruct == QOR) && QUAD && (~EXTADD))) + begin + //Instruction + 3 Bytes Address + Dummy Byte + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE) + begin + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:25] = 7'b0000000; + addr_bytes[24] = Bank_Addr_reg[0]; + Address = addr_bytes ; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (Instruct==FSTRD || Instruct==DOR || + Instruct == QOR) + begin + if (Latency_code == 3) + bus_cycle_state = DATA_BYTES; + else + bus_cycle_state = DUMMY_BYTES; + end + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((((Instruct==FSTRD4) || + (Instruct==DOR4) || + ((Instruct==FSTRD) && EXTADD) || + ((Instruct==DOR) && EXTADD)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + ((Instruct==QOR4) && QUAD) || + ((Instruct==QOR) && QUAD && EXTADD)) + begin + //Instruction + 4 Bytes Address + Dummy Byte + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 4*BYTE) + begin + for(i=31;i>=0;i=i-1) + begin + hiaddr_bytes[31-i] = Address_in[i]; + end + Address = hiaddr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (Latency_code == 3) + bus_cycle_state = DATA_BYTES; + else + begin + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + + end + end + end + end + else if ((Instruct==DIOR) && (~EXTADD) && + ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + //DUAL I/O High Performance Read(3 Bytes Addr) + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt + 1] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE/2) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i]=Address_in[i]; + end + addr_bytes[31:25] = 7'b0000000; + addr_bytes[24] = Bank_Addr_reg[0]; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if (((Instruct==DIOR4) || + ((Instruct==DIOR) && EXTADD)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) + begin //DUAL I/O High Performance Read(4Bytes Addr) + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt + 1] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 4*BYTE/2) + begin + addr_cnt = 0; + for(i=31;i>=0;i=i-1) + begin + addr_bytes[31-i] = Address_in[i]; + end + Address = addr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((Instruct == QIOR) && (~EXTADD)) + begin + //QUAD I/O High Performance Read (3Bytes Address) + if (QUAD) + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE/4) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:25] = 7'b0000000; + addr_bytes[24] = Bank_Addr_reg[0]; + + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + else + bus_cycle_state = STAND_BY; + end + else if ((Instruct==QIOR4) || ((Instruct==QIOR) + && EXTADD)) + begin + //QUAD I/O High Performance Read (4Bytes Addr) + if (QUAD) + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt +1; + if (addr_cnt == 4*BYTE/4) + begin + addr_cnt =0; + for(i=31;i>=0;i=i-1) + begin + hiaddr_bytes[31-i] = Address_in[i]; + end + Address = hiaddr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + else + bus_cycle_state = STAND_BY; + end + else if ((((Instruct==RD4) || (Instruct==PP4) || + (Instruct==SE4) ||(Instruct==PPBRD) || + (Instruct==DYBRD) ||(Instruct==DYBWR) || + (Instruct==PPBP) || (Instruct==P4E4) || + ((Instruct==READ) && EXTADD) || + ((Instruct==PP) && EXTADD) || + ((Instruct==P4E) && EXTADD) || + ((Instruct==SE) && EXTADD)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + (QUAD && (Instruct==QPP4 || + ((Instruct==QPP) && EXTADD)))) + begin + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 4*BYTE) + begin + for(i=31;i>=0;i=i-1) + begin + hiaddr_bytes[31-i] = Address_in[i]; + end + Address = hiaddr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = DATA_BYTES; + end + end + else if (((HOLDNeg_in && ~QUAD) || QUAD) && + (~EXTADD)) + begin + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE) + begin + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:25] = 7'b0000000; + addr_bytes[24] = Bank_Addr_reg[0]; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = DATA_BYTES; + end + end + end + else + begin + if ((Instruct==DDRFR) && (~EXTADD)) + //Fast DDR Read Mode + begin + Address_in[addr_cnt] = SI_in; + if ((addr_cnt/2) <= 16) + begin + opcode_tmp[addr_cnt/2] = SI_in; + end + addr_cnt = addr_cnt + 1; + read_cnt = 0; + end + else if ((Instruct==DDRFR4) || + ((Instruct==DDRFR) && EXTADD)) + begin + Address_in[addr_cnt] = SI_in; + if ((addr_cnt/2) <= 16) + begin + opcode_tmp[addr_cnt/2] = SI_in; + end + addr_cnt = addr_cnt + 1; + read_cnt = 0; + end + else if ((Instruct == DDRDIOR) && (~EXTADD)) + begin //Dual I/O DDR Read Mode + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt+1]= SI_in; + if ((addr_cnt/2) <= 16) + begin + opcode_tmp[addr_cnt/2] = SI_in; + end + addr_cnt = addr_cnt + 1; + read_cnt = 0; + end + else if ((Instruct==DDRDIOR4) || + ((Instruct==DDRDIOR) && EXTADD)) + begin //Dual I/O DDR Read Mode + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt+1] = SI_in; + if ((addr_cnt/2) <= 16) + begin + opcode_tmp[addr_cnt/2] = SI_in; + end + addr_cnt = addr_cnt + 1; + read_cnt = 0; + end + else if ((Instruct==DDRQIOR) && (~EXTADD) && QUAD) + begin //Quad I/O DDR Read Mode + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + opcode_tmp[addr_cnt/2] = SI_in; + addr_cnt = addr_cnt +1; + read_cnt = 0; + end + else if (QUAD && ((Instruct==DDRQIOR4) || + ((Instruct==DDRQIOR) && EXTADD))) + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + opcode_tmp[addr_cnt/2] = SI_in; + addr_cnt = addr_cnt +1; + read_cnt = 0; + end + end + end + + MODE_BYTE : + begin + if (((Instruct==DIOR) || (Instruct == DIOR4)) + && ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + mode_in[2*mode_cnt] = SO_in; + mode_in[2*mode_cnt+1] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/2) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + if (Latency_code == 0 || Latency_code == 3) + bus_cycle_state = DATA_BYTES; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if (((Instruct==QIOR) || (Instruct == QIOR4)) + && QUAD) + begin + mode_in[4*mode_cnt] = HOLDNeg_in; + mode_in[4*mode_cnt+1] = WPNeg_in; + mode_in[4*mode_cnt+2] = SO_in; + mode_in[4*mode_cnt+3] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/4) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((Instruct == DDRFR) || (Instruct == DDRFR4)) + mode_in[2*mode_cnt] = SI_in; + else if ((Instruct==DDRDIOR) || (Instruct==DDRDIOR4)) + begin + mode_in[4*mode_cnt] = SO_in; + mode_in[4*mode_cnt+1] = SI_in; + end + else if (((Instruct==DDRQIOR) || (Instruct == DDRQIOR4)) + && QUAD) + begin + mode_in[0] = HOLDNeg_in; + mode_in[1] = WPNeg_in; + mode_in[2] = SO_in; + mode_in[3] = SI_in; + end + dummy_cnt = 0; + end + + DUMMY_BYTES : + begin + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + if ((((Instruct==FSTRD) || (Instruct==FSTRD4) || + (Instruct==DOR) || (Instruct==DOR4) || + (Instruct==OTPR)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + (((Instruct==QOR)||(Instruct==QOR4)) && QUAD)) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == BYTE) + begin + bus_cycle_state = DATA_BYTES; + end + end + + else if ((Instruct==DDRFR) || (Instruct==DDRFR4)) + begin + dummy_cnt = dummy_cnt + 1; + if (EHP) + begin + if (((Latency_code == 3) && (dummy_cnt==1)) || + ((Latency_code == 0) && (dummy_cnt==2)) || + ((Latency_code == 1) && (dummy_cnt==4)) || + ((Latency_code == 2) && (dummy_cnt==5))) + begin + bus_cycle_state = DATA_BYTES; + end + end + else + begin + if (((Latency_code == 3) && (dummy_cnt==4)) || + ((Latency_code == 0) && (dummy_cnt==5)) || + ((Latency_code == 1) && (dummy_cnt==6)) || + ((Latency_code == 2) && (dummy_cnt==7))) + begin + bus_cycle_state = DATA_BYTES; + end + end + end + else if (Instruct==RES) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == 3*BYTE) + bus_cycle_state = DATA_BYTES; + end + else if ((Instruct == DIOR) || (Instruct == DIOR4) + && ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + dummy_cnt = dummy_cnt + 1; + if (EHP) + begin + if (((Latency_code == 1) && (dummy_cnt==1)) || + ((Latency_code == 2) && (dummy_cnt==2))) + bus_cycle_state = DATA_BYTES; + end + else + begin + if (((Latency_code == 3) && (dummy_cnt==4)) || + ((Latency_code == 0) && (dummy_cnt==4)) || + ((Latency_code == 1) && (dummy_cnt==5)) || + ((Latency_code == 2) && (dummy_cnt==6))) + bus_cycle_state = DATA_BYTES; + end + end + else if ((Instruct==DDRDIOR) || (Instruct==DDRDIOR4)) + begin + dummy_cnt = dummy_cnt + 1; + if (EHP) + begin + if (((Latency_code == 3) && (dummy_cnt==2)) || + ((Latency_code == 0) && (dummy_cnt==4)) || + ((Latency_code == 1) && (dummy_cnt==5)) || + ((Latency_code == 2) && (dummy_cnt==6))) + begin + bus_cycle_state = DATA_BYTES; + end + end + else + begin + if (((Latency_code == 3) && (dummy_cnt==4)) || + ((Latency_code == 0) && (dummy_cnt==6)) || + ((Latency_code == 1) && (dummy_cnt==7)) || + ((Latency_code == 2) && (dummy_cnt==8))) + begin + bus_cycle_state = DATA_BYTES; + end + end + end + else if (((Instruct == QIOR) || (Instruct == QIOR4)) + && QUAD) + begin + dummy_cnt = dummy_cnt + 1; + if (((Latency_code == 3) && (dummy_cnt==1)) || + ((Latency_code == 0) && (dummy_cnt==4)) || + ((Latency_code == 1) && (dummy_cnt==4)) || + ((Latency_code == 2) && (dummy_cnt==5))) + begin + bus_cycle_state = DATA_BYTES; + end + end + else if (((Instruct==DDRQIOR) || (Instruct==DDRQIOR4)) + && QUAD) + begin + dummy_cnt = dummy_cnt + 1; + + if (((Latency_code == 3) && (dummy_cnt==3)) || + ((Latency_code == 0) && (dummy_cnt==6)) || + ((Latency_code == 1) && (dummy_cnt==7)) || + ((Latency_code == 2) && (dummy_cnt==8))) + begin + bus_cycle_state = DATA_BYTES; + end + end + end + + DATA_BYTES : + begin + + if (DOUBLE == 1'b1 && (hold_mode==0)) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + + if ((QUAD) && ((Instruct==QPP) || (Instruct == QPP4))) + begin + quad_nybble = {HOLDNeg_in, WPNeg_in, SO_in, SI_in}; + if (data_cnt > ((PageSize+1)*2-1)) + begin + //In case of quad mode and QPP, + //if more than 512 bytes are sent to the device + for(i=0;i<=(PageSize*2-1);i=i+1) + begin + quad_data_in[i] = quad_data_in[i+1]; + end + quad_data_in[(PageSize+1)*2-1] = quad_nybble; + data_cnt = data_cnt +1; + end + else + begin + if (quad_nybble !== 4'bZZZZ) + begin + quad_data_in[data_cnt] = quad_nybble; + end + data_cnt = data_cnt +1; + end + end + else if ((~QUADRD) && ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + if (data_cnt > ((PageSize+1)*8-1)) + begin + //In case of serial mode and PP, + //if more than PageSize are sent to the device + //previously latched data are discarded and last + //256/512 data bytes are guaranteed to be programmed + //correctly within the same page. + if (bit_cnt == 0) + begin + for(i=0;i<=(PageSize*BYTE-1);i=i+1) + begin + Data_in[i] = Data_in[i+8]; + end + end + Data_in[PageSize*BYTE + bit_cnt] = SI_in; + bit_cnt = bit_cnt + 1; + if (bit_cnt == 8) + begin + bit_cnt = 0; + end + data_cnt = data_cnt + 1; + end + else + begin + Data_in[data_cnt] = SI_in; + data_cnt = data_cnt + 1; + bit_cnt = 0; + end + end + end + endcase + end + end + + if (falling_edge_SCK_ipd) + begin + if (~CSNeg_ipd) + begin + case (bus_cycle_state) + ADDRESS_BYTES : + begin + if (DOUBLE == 1'b1) + begin + if ((Instruct==DDRFR) && (~EXTADD)) + //Fast DDR Read Mode + begin + Address_in[addr_cnt] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 3*BYTE) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:25] = 7'b0000000; + addr_bytes[24] = Bank_Addr_reg[0]; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((Instruct==DDRFR4) || + ((Instruct==DDRFR) && EXTADD)) + begin + Address_in[addr_cnt] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 4*BYTE) + begin + addr_cnt = 0; + for(i=31;i>=0;i=i-1) + begin + addr_bytes[31-i] = Address_in[i]; + end + Address = addr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + begin + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + end + else if ((Instruct == DDRDIOR) && (~EXTADD)) + begin //Dual I/O DDR Read Mode + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt+1]= SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 3*BYTE/2) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:25] = 7'b0000000; + addr_bytes[24] = Bank_Addr_reg[0]; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((Instruct==DDRDIOR4) || + ((Instruct==DDRDIOR) && EXTADD)) + begin //Dual I/O DDR Read Mode + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt+1] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 4*BYTE/2) + begin + addr_cnt = 0; + for(i=31;i>=0;i=i-1) + begin + addr_bytes[31-i] = Address_in[i]; + end + Address = addr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + begin + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + end + else if ((Instruct==DDRQIOR) && (~EXTADD) && QUAD) + begin //Quad I/O DDR Read Mode + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 3*BYTE/4) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:25] = 7'b0000000; + addr_bytes[24] = Bank_Addr_reg[0]; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + else if (QUAD && ((Instruct==DDRQIOR4) || + ((Instruct==DDRQIOR) && EXTADD))) + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 4*BYTE/4) + begin + addr_cnt = 0; + for(i=31;i>=0;i=i-1) + begin + addr_bytes[31-i] = Address_in[i]; + end + Address = addr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + end + end + + MODE_BYTE : + begin + if ((Instruct == DDRFR) || (Instruct == DDRFR4)) + begin + mode_in[2*mode_cnt+1] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/2) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + else if ((Instruct==DDRDIOR) || (Instruct==DDRDIOR4)) + begin + mode_in[4*mode_cnt+2] = SO_in; + mode_in[4*mode_cnt+3] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/4) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + else if ((Instruct==DDRQIOR) || (Instruct==DDRQIOR4)) + begin + mode_in[4] = HOLDNeg_in; + mode_in[5] = WPNeg_in; + mode_in[6] = SO_in; + mode_in[7] = SI_in; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + + DATA_BYTES: + begin + if (hold_mode==0) + begin + if (DOUBLE == 1'b1 ) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + + end + else + begin + if ((Instruct==READ) || (Instruct==RD4) || + (Instruct==FSTRD)|| (Instruct==FSTRD4)|| + (Instruct==RDSR) || (Instruct==RDSR2) || + (Instruct==RDCR) || (Instruct==OTPR) || + (Instruct==DOR) || (Instruct==DOR4) || + (Instruct==DIOR)|| (Instruct==DIOR4)|| + (Instruct==ABRD) || (Instruct==BRRD) || + (Instruct==ASPRD)|| (Instruct==DYBRD) || + (Instruct==PPBRD)|| + (Instruct==PASSRD)|| (Instruct==RDID)|| + (Instruct==RES) || (Instruct==REMS) || + (Instruct==PLBRD)|| (Instruct==DLPRD) || + (current_state == AUTOBOOT && + start_delay == 0) || + (((Instruct==QOR) || (Instruct==QIOR) || + (Instruct==QOR4) || + (Instruct==QIOR4)) && QUAD)) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + end + + DUMMY_BYTES: + begin + if (hold_mode==0) + begin + if (DOUBLE == 1'b1 && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + + endcase + end + end + + if (rising_edge_CSNeg_ipd) + begin + if ((bus_cycle_state != DATA_BYTES) && + (bus_cycle_state != DUMMY_BYTES)) + begin + if (bus_cycle_state == ADDRESS_BYTES && opcode_tmp == 8'hFF) + begin + Instruct = MBR; + end + bus_cycle_state = STAND_BY; + end + else + begin + if (bus_cycle_state == DATA_BYTES) + begin + if (((mode_bytes[7:4] == 4'b1010) && + (Instruct==DIOR || Instruct==DIOR4 || + Instruct==QIOR || Instruct==QIOR4)) || + ((mode_bytes[7:4] == ~mode_bytes[3:0]) && + (Instruct == DDRFR || Instruct == DDRFR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4))) + bus_cycle_state = ADDRESS_BYTES; + else + bus_cycle_state = STAND_BY; + + case (Instruct) + WREN, + WRDI, + BE, + SE, + SE4, + P4E, + P4E4, + CLSR, + BRAC, + RESET, + PPBERS, + PPBP, + PLBWR, + PGSP, + PGRS, + ERSP, + ERRS: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 0) + write = 1'b0; + end + end + + WRR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + //If CS# is driven high after eight + //cycle,only the Status Register is + //written to. + begin + write = 1'b0; + if (BAR_ACC == 0) + begin + for(i=0;i<=7;i=i+1) + begin + Status_reg1_in[i]= + Data_in[7-i]; + end + end + else + begin + if (P_ERR == 0 && E_ERR == 0) + begin + for(i=0;i<=7;i=i+1) + begin + Bank_Addr_reg_in[i]= + Data_in[7-i]; + end + end + end + end + else if (data_cnt == 16) + //After the 16th cycle both the + //Status and Configuration Registers + //are written to. + begin + write = 1'b0; + if (BAR_ACC == 0) + begin + cfg_write = 1'b1; + for(i=0;i<=7;i=i+1) + begin + Status_reg1_in[i]= + Data_in[7-i]; + Config_reg1_in[i]= + Data_in[15-i]; + end + end + else + begin + if (P_ERR == 0 && E_ERR == 0) + begin + for(i=0;i<=7;i=i+1) + begin + Bank_Addr_reg_in[i]= + Data_in[7-i]; + end + end + end + end + end + end + + PP, + PP4, + OTPP: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt > 0) + begin + if ((data_cnt % 8) == 0) + begin + write = 1'b0; + for(i=0;i<=PageSize;i=i+1) + begin + for(j=7;j>=0;j=j-1) + begin + if ((Data_in[(i*8)+(7-j)]) + !== 1'bX) + begin + Byte_slv[j] = + Data_in[(i*8)+(7-j)]; + end + end + WByte[i] = Byte_slv; + end + + if (data_cnt > (PageSize+1)*BYTE) + Byte_number = PageSize; + else + Byte_number = + ((data_cnt/8) - 1); + end + end + end + end + + QPP, + QPP4: + begin + if (data_cnt >0) + begin + if ((data_cnt % 2) == 0) + begin + write = 1'b0; + quad_pg = 1'b0; + for(i=0;i<=PageSize;i=i+1) + begin + for(j=1;j>=0;j=j-1) + begin + Quad_slv = + quad_data_in[(i*2)+(1-j)]; + if (j==1) + Byte_slv[7:4] = Quad_slv; + else if (j==0) + Byte_slv[3:0] = Quad_slv; + end + WByte[i] = Byte_slv; + end + if (data_cnt > (PageSize+1)*2) + Byte_number = PageSize; + else + Byte_number = ((data_cnt/2)-1); + end + end + end + + ABWR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 32) + begin + write = 1'b0; + for(j=0;j<=31;j=j+1) + begin + AutoBoot_reg_in[j] = Data_in[31-j]; + end + end + end + end + + BRWR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + begin + write = 1'b0; + for(j=0;j<=7;j=j+1) + begin + Bank_Addr_reg_in[j] = Data_in[7-j]; + end + end + end + end + + ASPP: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 16) + begin + write = 1'b0; + for(j=0;j<=15;j=j+1) + begin + ASP_reg_in[j] = Data_in[15-j]; + end + end + end + end + + DYBWR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + begin + write = 1'b0; + for(j=0;j<=7;j=j+1) + begin + DYBAR_in[j] = Data_in[7-j]; + end + end + end + end + + PNVDLR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + begin + write = 1'b0; + for(j=0;j<=7;j=j+1) + begin + NVDLR_reg_in[j] = Data_in[7-j]; + end + end + end + end + + WVDLR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + begin + write = 1'b0; + for(j=0;j<=7;j=j+1) + begin + VDLR_reg_in[j] = Data_in[7-j]; + end + end + end + end + + PASSP: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 64) + begin + write = 1'b0; + for(j=1;j<=8;j=j+1) + begin + for(k=1;k<=8;k=k+1) + begin + Password_reg_in[j*8-k] = + Data_in[8*(j-1)+k-1]; + end + end + end + end + end + + PASSU: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 64) + begin + write = 1'b0; + for(j=1;j<=8;j=j+1) + begin + for(k=1;k<=8;k=k+1) + begin + PASS_TEMP[j*8-k] = + Data_in[8*(j-1)+k-1]; + end + end + end + end + end + endcase + end + end + end + end + +/////////////////////////////////////////////////////////////////////////////// +// Timing control for the Page Program +/////////////////////////////////////////////////////////////////////////////// + time pob; + time elapsed_pgm; + time start_pgm; + time duration_pgm; + event pdone_event; + + always @(rising_edge_PSTART) + begin + if ((Instruct == PP) || (Instruct == PP4) || (Instruct == OTPP) || + (Instruct == QPP) || (Instruct == QPP4)) + if (PageSize == 255) + begin + pob = tdevice_PP_256; + end + else + begin + pob = tdevice_PP_512; + end + else + pob = tdevice_BP; + if ((rising_edge_PSTART) && PDONE) + begin + elapsed_pgm = 0; + duration_pgm = pob; + PDONE = 1'b0; + ->pdone_event; + start_pgm = $time; + end + end + + always @(posedge PGSUSP) + begin + if (PGSUSP && (~PDONE)) + begin + disable pdone_process; + elapsed_pgm = $time - start_pgm; + duration_pgm = pob - elapsed_pgm; + PDONE = 1'b0; + end + end + + always @(posedge PGRES) + begin + start_pgm = $time; + ->pdone_event; + end + + always @(pdone_event) + begin:pdone_process + PDONE = 1'b0; + #duration_pgm PDONE = 1'b1; + end + +/////////////////////////////////////////////////////////////////////////////// +// Timing control for the Write Status Register +/////////////////////////////////////////////////////////////////////////////// + time wob; + always @(posedge WSTART) + begin:wdone_process + wob = tdevice_WRR; + if (WSTART && WDONE) + begin + WDONE = 1'b0; + #wob WDONE = 1'b1; + end + end + +/////////////////////////////////////////////////////////////////////////////// +// Reset Timing +/////////////////////////////////////////////////////////////////////////////// + + time startlo; + time starthi; + time durationlo; + time durationhi; + + always @(negedge RSTNeg_in or Instruct) + begin + if (~RSTNeg_in) + begin + RST = 1'b1; + #200000 RST = 1'b0; // 200 ns + end + else if (Instruct == RESET) + begin + Reseted = 1'b0; + #10000 Reseted = 1'b1; // 10 ns + end + end + + always @(RST_in or rising_edge_Reseted) // Reset done,program terminated + begin + if ((RST_in && ~RST) || (rising_edge_Reseted)) + disable pdone_process; + disable edone_process; + disable wdone_process; + PDONE = 1'b1; + EDONE = 1'b1; + WDONE = 1'b1; + end + +/////////////////////////////////////////////////////////////////////////////// +// Timing control for the Bulk Erase +/////////////////////////////////////////////////////////////////////////////// + time seo; + time beo; + event edone_event; + time elapsed_ers; + time start_ers; + time duration_ers; + + always @(rising_edge_ESTART) + begin + if (UniformSec) + begin + seo = tdevice_SE256; + end + else + begin + seo = tdevice_SE64; + end + beo = tdevice_BE; + if ((rising_edge_ESTART) && EDONE) + begin + if (Instruct == BE) + begin + duration_ers = beo; + end + else + begin + duration_ers = seo; + end + elapsed_ers = 0; + EDONE = 1'b0; + ->edone_event; + start_ers = $time; + end + end + + always @(posedge ESUSP) + begin + if (ESUSP && (~EDONE)) + begin + disable edone_process; + elapsed_ers = $time - start_ers; + duration_ers = seo - elapsed_ers; + EDONE = 1'b0; + end + end + + always @(posedge ERES) + begin + if (ERES && (~EDONE)) + begin + start_ers = $time; + ->edone_event; + end + end + + always @(edone_event) + begin : edone_process + EDONE = 1'b0; + #duration_ers EDONE = 1'b1; + end + + /////////////////////////////////////////////////////////////////// + // Process for clock frequency determination + /////////////////////////////////////////////////////////////////// + always @(posedge SCK_ipd) + begin : clock_period + if (SCK_ipd) + begin + SCK_cycle = $time - prev_SCK; + prev_SCK = $time; + end + end + +// ///////////////////////////////////////////////////////////////////////// +// // Main Behavior Process +// // combinational process for next state generation +// ///////////////////////////////////////////////////////////////////////// + + reg rising_edge_PDONE = 1'b0; + reg rising_edge_EDONE = 1'b0; + reg rising_edge_WDONE = 1'b0; + reg falling_edge_write = 1'b0; + reg falling_edge_PPBERASE_in = 1'b0; + reg falling_edge_PASSULCK_in = 1'b0; + + integer i; + integer j; + + always @(rising_edge_PoweredUp or falling_edge_write or + falling_edge_RSTNeg or rising_edge_PDONE or rising_edge_WDONE or + rising_edge_EDONE or ERSSUSP_out_event or rising_edge_RSTNeg or + PRGSUSP_out_event or rising_edge_CSNeg_ipd or rising_edge_RST_out + or falling_edge_PPBERASE_in or falling_edge_PASSULCK_in) + begin: StateGen1 + + integer sect; + + if (rising_edge_PoweredUp) + begin + if (ABE == 1 && RPME !== 0 ) + begin + next_state = AUTOBOOT; + read_cnt = 0; + byte_cnt = 1; + read_addr = {AutoBoot_reg[31:9], 9'b0}; + start_delay = AutoBoot_reg[8:1]; + start_autoboot = 0; + ABSD = AutoBoot_reg[8:1]; + end + else + next_state = IDLE; + end + else + begin + if (RST_out == 1'b0) + next_state = current_state; + else if (falling_edge_write && Instruct == RESET) + begin + if (ABE == 1 && RPME !== 0) + begin + read_cnt = 0; + byte_cnt = 1; + read_addr = {AutoBoot_reg[31:9], 9'b0}; + start_delay = AutoBoot_reg[8:1]; + ABSD = AutoBoot_reg[8:1]; + start_autoboot = 0; + next_state = AUTOBOOT; + end + else + next_state = IDLE; + end + else + begin + case (current_state) + RESET_STATE : + begin + if (rising_edge_RST_out) + begin + if (ABE == 1 && RPME!== 0) + begin + next_state = AUTOBOOT; + read_cnt = 0; + byte_cnt = 1; + read_addr = {AutoBoot_reg[31:9],9'b0}; + start_delay = AutoBoot_reg[8:1]; + start_autoboot = 0; + ABSD = AutoBoot_reg[8:1]; + end + else + next_state = IDLE; + end + end + + IDLE : + begin + if (falling_edge_write && RdPswdProtMode == 0) + begin + if (Instruct == WRR && WEL == 1 && BAR_ACC == 0 + && (((~(SRWD == 1 && ~WPNeg_in))&& ~QUAD) || QUAD)) + // can not execute if HPM is entered or + // if WEL bit is zero + if (((TBPROT==1 && Config_reg1_in[5]==1'b0) || + (TBPARM==1 && Config_reg1_in[2]==1'b0) || + (BPNV ==1 && Config_reg1_in[3]==1'b0)) && + cfg_write) + begin + $display ("WARNING: Changing value of "); + $display ("Configuration Register OTP "); + $display ("bit from 1 to 0 is not"); + $display ("allowed!!!"); + end + else + begin + next_state = WRITE_SR; + end + else if (Instruct == WRR && BAR_ACC == 1) + begin + // Write to the lower address bits of the BAR + if (P_ERR == 0 && E_ERR == 0) + begin + next_state = IDLE; + end + end + else if ((Instruct == PP || Instruct == QPP || + Instruct == PP4 || Instruct == QPP4) && + WEL == 1) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + if (Sec_Prot[sect]== 0 && PPB_bits[sect]== 1 && + DYB_bits[sect]== 1) + begin + next_state = PAGE_PG; + end + end + else if (Instruct==OTPP && WEL==1 && FREEZE==0) + begin + if (((((Address>=16'h0010 && Address<=16'h0013) + ||(Address>=16'h0020 && Address<=16'h00FF)) + && LOCK_BYTE1[Address/32] == 1) || + ((Address>=16'h0100 && Address<=16'h01FF) + && LOCK_BYTE2[(Address-16'h0100)/32]==1) || + ((Address>=16'h0200 && Address<=16'h02FF) + && LOCK_BYTE3[(Address-16'h0200)/32]==1) || + ((Address>=16'h0300 && Address<=16'h03FF) + && LOCK_BYTE4[(Address-16'h0300)/32] == 1)) + && (Address + Byte_number <= OTPHiAddr)) + next_state = OTP_PG; + end + else if ((Instruct == SE || Instruct == SE4) + && WEL == 1) + begin + ReturnSectorID(sect,Address); + if (UniformSec || (TopBoot && sect < 510) || + (BottomBoot && sect > 31)) + begin + if (Sec_Prot[sect]== 0 && PPB_bits[sect]== 1 + && DYB_bits[sect]== 1) + next_state = SECTOR_ERS; + end + else if ((TopBoot && sect >= 510) || + (BottomBoot && sect <= 31)) + begin + if (Sec_ProtSE == 32 && ASP_ProtSE == 32) + //Sector erase command is applied to a + //64 KB range that includes 4 KB sectors. + next_state = SECTOR_ERS; + end + end + else if ((Instruct == P4E || Instruct == P4E4) + && WEL == 1) + begin + if (UniformSec || (TopBoot && sect < 510) || + (BottomBoot && sect > 31)) + begin + $display("The instruction is applied to"); + $display("a sector that is larger than"); + $display("4 KB."); + $display("Instruction is ignored!!!"); + end + else + begin + if (Sec_Prot[sect]== 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + next_state = SECTOR_ERS; + end + end + else if (Instruct == BE && WEL == 1 && + (Status_reg1[4]== 0 && Status_reg1[3]== 0 && + Status_reg1[2]== 0)) + next_state = BULK_ERS; + else if (Instruct == ABWR && WEL == 1) + //Autoboot Register Write Command + next_state = AUTOBOOT_PG; + else if (Instruct == BRWR) + //Bank Register Write Command + next_state = IDLE; + else if (Instruct == ASPP && WEL == 1) + begin + //ASP Register Program Command + if (~(ASPOTPFLAG)) + next_state = ASP_PG; + end + else if (Instruct == PLBWR && WEL == 1 && + RdPswdProtEnable == 0) + next_state = PLB_PG; + else if (Instruct == PASSP && WEL == 1) + begin + if (~(PWDMLB== 0 && PSTMLB== 1)) + next_state = PASS_PG; + end + else if (Instruct == PASSU && WEL && ~WIP) + next_state = PASS_UNLOCK; + else if (Instruct == PPBP && WEL == 1) + next_state <= PPB_PG; + else if (Instruct == PPBERS && WEL && PPBOTP) + next_state <= PPB_ERS; + else if (Instruct == DYBWR && WEL == 1) + next_state = DYB_PG; + else if (Instruct == PNVDLR && WEL == 1) + next_state = NVDLR_PG; + else + next_state = IDLE; + end + if (falling_edge_write && RdPswdProtMode == 1 && ~WIP) + begin + if (Instruct == PASSU) + next_state = PASS_UNLOCK; + end + end + + AUTOBOOT : + begin + if (rising_edge_CSNeg_ipd) + next_state = IDLE; + end + + WRITE_SR : + begin + if (rising_edge_WDONE) + next_state = IDLE; + end + + PAGE_PG : + begin + if (PRGSUSP_out_event && PRGSUSP_out == 1) + next_state = PG_SUSP; + else if (rising_edge_PDONE) + next_state = IDLE; + end + + PG_SUSP : + begin + if (falling_edge_write) + begin + if (Instruct == PGRS) + next_state = PAGE_PG; + end + end + + OTP_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + BULK_ERS : + begin + if (rising_edge_EDONE) + next_state = IDLE; + end + + SECTOR_ERS : + begin + if (ERSSUSP_out_event && ERSSUSP_out == 1) + next_state = ERS_SUSP; + else if (rising_edge_EDONE) + next_state = IDLE; + end + + ERS_SUSP : + begin + if (falling_edge_write) + begin + if ((Instruct == PP || Instruct == QPP || + Instruct == PP4 || Instruct == QPP4) && + WEL == 1) + begin + if ((PARAM_REGION && + SectorSuspend != Address/(SecSize+1)) || + (~PARAM_REGION && SectorSuspend != + Address/(SecSize+1)+30*b_act)) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + if (PPB_bits[sect]== 1 && + DYB_bits[sect]== 1) + begin + next_state = ERS_SUSP_PG; + end + end + end + else if (Instruct == DYBWR && WEL == 1) + next_state = DYB_PG; + else if (Instruct == ERRS) + next_state = SECTOR_ERS; + end + end + + ERS_SUSP_PG : + begin + if (rising_edge_PDONE) + next_state = ERS_SUSP; + else if (PRGSUSP_out_event && PRGSUSP_out == 1) + next_state = ERS_SUSP_PG_SUSP; + end + + ERS_SUSP_PG_SUSP : + begin + if (rising_edge_PDONE) + next_state = ERS_SUSP; + if (falling_edge_write) + begin + if (Instruct == PGRS) + begin + next_state = ERS_SUSP_PG; + end + end + end + + PASS_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + PASS_UNLOCK : + begin + if (falling_edge_PASSULCK_in) + next_state = IDLE; + end + + PPB_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + PPB_ERS : + begin + if (falling_edge_PPBERASE_in) + next_state = IDLE; + end + + AUTOBOOT_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + PLB_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + DYB_PG : + begin + if (rising_edge_PDONE) + if (ES) + next_state = ERS_SUSP; + else + next_state = IDLE; + end + + ASP_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + NVDLR_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + endcase + end + end + end + + /////////////////////////////////////////////////////////////////////////// + //FSM Output generation and general functionality + /////////////////////////////////////////////////////////////////////////// + reg rising_edge_read_out = 1'b0; + reg Instruct_event = 1'b0; + reg change_addr_event = 1'b0; + reg current_state_event = 1'b0; + reg rising_edge_DP_out = 1'b0; + + integer WData [0:511]; + integer WOTPData; + integer Addr; + integer Addr_tmp; + + always @(Instruct_event) + begin + read_cnt = 0; + byte_cnt = 1; + rd_fast = 1'b1; + dual = 1'b0; + rd_slow = 1'b0; + any_read = 1'b0; + end + + always @(rising_edge_read_out) + begin + if (rising_edge_read_out == 1'b1) + begin + if (PoweredUp == 1'b1) + begin + oe_z = 1'b1; + #1000 oe_z = 1'b0; + oe = 1'b1; + #1000 oe = 1'b0; + end + end + end + + always @(change_addr_event) + begin + if (change_addr_event) + begin + read_addr = Address; + end + end + + always @(posedge PASSACC_out) + begin + Status_reg1[0] = 1'b0; //WIP + PASSACC_in = 1'b0; + end + + always @(Instruct or posedge start_autoboot or oe or current_state_event or + falling_edge_write or posedge PDONE or posedge WDONE or oe_z or + posedge EDONE or ERSSUSP_out or rising_edge_Reseted or + rising_edge_PoweredUp or rising_edge_CSNeg_ipd or PRGSUSP_out or + Address) + begin: Functionality + integer i,j; + integer sect; + + if (rising_edge_PoweredUp) + begin + //the default condition after power-up + //The Bank Address Register is loaded to all zeroes + Bank_Addr_reg = 8'h0; + //The Configuration Register FREEZE bit is cleared. + Config_reg1[0] = 0; + //The WEL bit is cleared. + Status_reg1[1] = 0; + //When BPNV is set to '1'. the BP2-0 bits in Status Register are + //volatile and will be reset binary 111 after power-on reset + if (BPNV == 1 && LOCK == 0 && FREEZE == 0 ) + begin + Status_reg1[4] = 1'b0;// BP2 + Status_reg1[3] = 1'b0;// BP1 + Status_reg1[2] = 1'b0;// BP0 + BP_bits = {Status_reg1[4],Status_reg1[3],Status_reg1[2]}; + change_BP = 1'b1; + #1000 change_BP = 1'b0; + end + + //As shipped from the factory, all devices default ASP to the + //Persistent Protection mode, with all sectors unprotected, + //when power is applied. The device programmer or host system must + //then choose which sector protection method to use. + //For Persistent Protection mode, PPBLOCK defaults to "1" + PPBL[0] = 1'b1; + + //All the DYB power-up in the unprotected state + DYB_bits = {542{1'b1}}; + + end + + if (Instruct == RESET) + begin + //EXTADD is cleared to “0” + Bank_Addr_reg[7] = 1'b0; + //P_ERR bit is cleared + Status_reg1[6] = 1'b0; + //E_ERR bit is cleared + Status_reg1[5] = 1'b0; + //The WEL bit is cleared. + Status_reg1[1] = 1'b0; + //The WIP bit is cleared. + Status_reg1[0] = 1'b0; + //The ES bit is cleared. + Status_reg2[1] = 1'b0; + //The PS bit is cleared. + Status_reg2[0] = 1'b0; + //When BPNV is set to '1'. the BP2-0 bits in Status + //Register are volatile and will be reseted after + //reset command + if (BPNV == 1 && LOCK== 0 && FREEZE == 0) + begin + Status_reg1[4] = 1'b1; + Status_reg1[3] = 1'b1; + Status_reg1[2] = 1'b1; + + BP_bits = {Status_reg1[4],Status_reg1[3], + Status_reg1[2]}; + change_BP = 1'b1; + #1000 change_BP = 1'b0; + end + end + + case (current_state) + IDLE : + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + ASP_ProtSE = 0; + Sec_ProtSE = 0; + + if (BottomBoot) + begin + for (j=31;j>=0;j=j-1) + begin + if (PPB_bits[j] == 1 && DYB_bits[j] == 1) + begin + ASP_ProtSE = ASP_ProtSE + 1; + end + if (Sec_Prot[j] == 0) + begin + Sec_ProtSE = Sec_ProtSE + 1; + end + end + end + else if (TopBoot) + begin + for (j=541;j>=510;j=j-1) + begin + if (PPB_bits[j] == 1 && DYB_bits[j] == 1) + begin + ASP_ProtSE = ASP_ProtSE + 1; + end + if (Sec_Prot[j] == 0) + begin + Sec_ProtSE = Sec_ProtSE + 1; + end + end + end + + if (falling_edge_write && RdPswdProtMode == 1) + begin + if(Instruct == PASSU) + begin + if (~WIP) + begin + PASSULCK_in = 1; + Status_reg1[0] = 1'b1; //WIP + end + else + begin + $display ("The PASSU command cannot be accepted"); + $display (" any faster than once every 100us"); + end + end + else if (Instruct == CLSR) + begin + //The Clear Status Register Command resets bit SR1[5] + //(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + Status_reg1[5] = 0; + Status_reg1[6] = 0; + end + end + + if (falling_edge_write && RdPswdProtMode == 0) + begin + read_cnt = 0; + byte_cnt = 1; + if (Instruct == WREN) + Status_reg1[1] = 1'b1; + else if (Instruct == WRDI) + Status_reg1[1] = 0; + else if ((Instruct == WRR) && WEL == 1 && WDONE == 1 && + BAR_ACC == 0) + begin + if (((~(SRWD == 1 && ~WPNeg_in))&& ~QUAD) || QUAD) + begin + if (((TBPROT==1 && Config_reg1_in[5]==1'b0) || + (TBPARM==1 && Config_reg1_in[2]==1'b0) || + (BPNV ==1 && Config_reg1_in[3]==1'b0)) && + cfg_write) + begin + // P_ERR bit is set to 1 + Status_reg1[6] = 1'b1; + end + else + begin + // can not execute if Hardware Protection Mode + // is entered or if WEL bit is zero + WSTART = 1'b1; + WSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + end + else + Status_reg1[1] = 0; + end + else if ((Instruct == PP || Instruct == PP4) && WEL ==1 && + PDONE == 1 ) + begin + ReturnSectorID(sect,Address); + if (Sec_Prot[sect] == 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 0; + PGRES = 0; + INITIAL_CONFIG = 1; + Status_reg1[0] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + //P_ERR bit will be set when the user attempts to + //to program within a protected main memory sector + Status_reg1[6] = 1'b1; //P_ERR + Status_reg1[1] = 1'b0; //WEL + end + end + else if ((Instruct == QPP || Instruct == QPP4) && WEL ==1 && + PDONE == 1 ) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + if (Sec_Prot[sect] == 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 0; + PGRES = 0; + INITIAL_CONFIG = 1; + Status_reg1[0] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + //P_ERR bit will be set when the user attempts to + //to program within a protected main memory sector + Status_reg1[6] = 1'b1; //P_ERR + Status_reg1[1] = 1'b0; //WEL + end + end + else if (Instruct == OTPP && WEL == 1) + begin + // As long as the FREEZE bit remains cleared to a logic + // '0' the OTP address space is programmable. + if (FREEZE == 0) + begin + if (((((Address>= 16'h0010 && Address<= 16'h0013) || + (Address >= 16'h0020 && Address <= 16'h00FF)) + && LOCK_BYTE1[Address/32] == 1) || + ((Address >= 16'h0100 && Address <= 16'h01FF) + && LOCK_BYTE2[(Address-16'h0100)/32] == 1) || + ((Address >= 16'h0200 && Address <= 16'h02FF) + && LOCK_BYTE3[(Address-16'h0200)/32] == 1) || + ((Address >= 16'h0300 && Address <= 16'h03FF) + && LOCK_BYTE4[(Address-16'h0300)/32] == 1)) && + (Address + Byte_number <= OTPHiAddr)) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else if ((Address < 8'h10 || (Address > 8'h13 && + Address < 8'h20) || Address > 12'h3FF )) + begin + Status_reg1[6] = 1'b1;//P_ERR + Status_reg1[1] = 1'b0;//WEL + if (Address < 8'h20) + begin + $display ("Given address is "); + $display ("in reserved address range"); + end + else if (Address > 12'h3FF) + begin + $display ("Given address is "); + $display ("out of OTP address range"); + end + end + else + begin + //P_ERR bit will be set when the user attempts to + // to program within locked OTP region + Status_reg1[6] = 1'b1;//P_ERR + Status_reg1[1] = 1'b0;//WEL + end + end + else + begin + //P_ERR bit will be set when the user attempts to + //to program within locked OTP region + Status_reg1[6] = 1'b1;//P_ERR + Status_reg1[1] = 1'b0;//WEL + end + end + else if ((Instruct == SE || Instruct == SE4) && WEL == 1) + begin + ReturnSectorID(sect,Address); + if (UniformSec || (TopBoot && sect < 510) || + (BottomBoot && sect > 31)) + begin + SectorSuspend = sect; + PARAM_REGION = 0; + if (Sec_Prot[sect] == 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + ESTART = 1'b1; + ESTART <= #5 1'b0; + ESUSP = 0; + ERES = 0; + INITIAL_CONFIG = 1; + Status_reg1[0] = 1'b1; + Addr = Address; + end + else + begin + //E_ERR bit will be set when the user attempts to + //erase an individual protected main memory sector + Status_reg1[5] = 1'b1;//E_ERR + Status_reg1[1] = 1'b0;//WEL + end + end + else if ((TopBoot && sect >= 510) || + (BottomBoot && sect <= 31)) + begin + if (Sec_ProtSE == 32 && ASP_ProtSE == 32) + //Sector erase command is applied to a 64 KB range + //that includes 4 KB sectors + begin + if (TopBoot) + begin + SectorSuspend = 510 + (541 - sect)/16; + end + else + begin + SectorSuspend = sect/16; + end + PARAM_REGION = 1; + ESTART = 1'b1; + ESTART <= #5 1'b0; + ESUSP = 0; + ERES = 0; + INITIAL_CONFIG = 1; + Status_reg1[0] = 1'b1; + Addr = Address; + end + else + begin + //E_ERR bit will be set when the user attempts to + //erase an individual protected main memory sector + Status_reg1[5] = 1'b1;//E_ERR + Status_reg1[1] = 1'b0;//WEL + end + end + end + else if ((Instruct == P4E || Instruct == P4E4) && WEL == 1) + begin + ReturnSectorID(sect,Address); + if (UniformSec || (TopBoot && sect < 510) || + (BottomBoot && sect > 31)) + begin + Status_reg1[1] = 1'b0;//WEL + end + else + begin + if (Sec_Prot[sect] == 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + //A P4E instruction applied to a sector + //that has been Write Protected through the + //Block Protect Bits or ASP will not be + //executed and will set the E_ERR status + begin + ESTART = 1'b1; + ESTART <= #5 1'b0; + ESUSP = 0; + ERES = 0; + INITIAL_CONFIG = 1; + Status_reg1[0] = 1'b1; + Addr = Address; + end + else + begin + //E_ERR bit will be set when the user attempts to + //erase an individual protected main memory sector + Status_reg1[5] = 1'b1;//E_ERR + Status_reg1[1] = 1'b0;//WEL + end + end + end + else if (Instruct == BE && WEL == 1) + begin + if (Status_reg1[4]== 0 && Status_reg1[3]== 0 && + Status_reg1[2]== 0) + begin + ESTART = 1'b1; + ESTART <= #5 1'b0; + ESUSP = 0; + ERES = 0; + INITIAL_CONFIG = 1; + Status_reg1[0] = 1'b1; + end + else + begin + //The Bulk Erase command will not set E_ERR if a + //protected sector is found during the command + //execution. + Status_reg1[1] = 1'b0;//WEL + end + end + else if (Instruct == PASSP && WEL == 1) + begin + if (~(PWDMLB== 0 && PSTMLB== 1)) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else + begin + $display ("Password programming is not allowed"); + $display (" in Password Protection Mode."); + end + end + else if (Instruct == PASSU && WEL) + begin + if (~WIP) + begin + PASSULCK_in = 1; + Status_reg1[0] = 1'b1; //WIP + end + else + begin + $display ("The PASSU command cannot be accepted"); + $display (" any faster than once every 100us"); + end + end + else if (Instruct == BRWR) + begin + Bank_Addr_reg[7] = Bank_Addr_reg_in[7]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + if(Bank_Addr_reg_in[1] == 1) + begin + $display ("WARNING: Changing values of "); + $display ("Bank Address Register"); + $display ("BA25 is not allowed!!!"); + end + end + else if (Instruct == WRR && BAR_ACC == 1) + begin + // Write to the lower address bits of the BAR + if (P_ERR == 0 && E_ERR == 0) + begin + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + if(Bank_Addr_reg_in[1] == 1) + begin + $display ("WARNING: Changing values of "); + $display ("Bank Address Register"); + $display ("BA25 is not allowed!!!"); + end + end + end + else if (Instruct == ASPP && WEL == 1) + begin + if (~(ASPOTPFLAG)) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + $display ("Once the Protection Mode is selected,"); + $display ("no further changes to the ASP "); + $display ("register is allowed."); + end + end + else if (Instruct == ABWR && WEL == 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == PPBP && WEL == 1) + begin + ReturnSectorID(sect,Address); + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == PPBERS && WEL == 1) + begin + if (PPBOTP) + begin + PPBERASE_in = 1'b1; + Status_reg1[0] = 1'b1; + end + else + begin + Status_reg1[5] = 1'b1; + end + end + else if (Instruct == PLBWR && WEL == 1 && + RdPswdProtEnable == 0) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == DYBWR && WEL == 1) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == PNVDLR && WEL == 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == WVDLR && WEL == 1) + begin + VDLR_reg = VDLR_reg_in; + Status_reg1[1] = 1'b0; + end + else if (Instruct == CLSR) + begin + //The Clear Status Register Command resets bit SR1[5] + //(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + Status_reg1[5] = 0; + Status_reg1[6] = 0; + end + + if (Instruct == BRAC && P_ERR == 0 && E_ERR == 0) + begin + BAR_ACC = 1; + end + else + begin + BAR_ACC = 0; + end + end + else if (oe_z) + begin + if (Instruct == READ || Instruct == RD4 || + Instruct == RES || + (Instruct == DLPRD && RdPswdProtMode == 0)) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else if (Instruct == DDRDIOR || Instruct == DDRDIOR4 || + ((Instruct == DDRQIOR || Instruct == DDRQIOR4) + && QUAD)) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + ((Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4) + && QUAD)) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + else if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == READ || Instruct == RD4 || + Instruct == FSTRD || Instruct == FSTRD4 || + Instruct == DDRFR || Instruct == DDRFR4 ) + begin + //Read Memory array + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + if (bus_cycle_state == DUMMY_BYTES + && VDLR_reg != 8'b00000000) + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) is enabled + // Optional DLP + if (VDLR_reg != 8'b00000000 && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + read_addr_tmp = read_addr; + SecAddr = read_addr/(SecSize+1) ; + Sec_addr = read_addr - SecAddr*(SecSize+1); + SecAddr = ReturnSectorIDRdPswdMd(TBPROT); + read_addr = Sec_addr + SecAddr*(SecSize+1); + if (RdPswdProtMode == 0) + begin + read_addr = read_addr_tmp; + end + if (Mem[read_addr] !== -1) + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + end + else + begin + SOut_zd = 8'bx; + end + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 ) + begin + //Read Memory array + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + if (VDLR_reg != 8'b00000000 && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + read_addr_tmp = read_addr; + SecAddr = read_addr/(SecSize+1) ; + Sec_addr = read_addr - SecAddr*(SecSize+1); + SecAddr = ReturnSectorIDRdPswdMd(TBPROT); + read_addr = Sec_addr + SecAddr*(SecSize+1); + if (RdPswdProtMode == 0) + read_addr = read_addr_tmp; + + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if ((Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4 ) + && QUAD) + begin + //Read Memory array + if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (bus_cycle_state == DUMMY_BYTES) + begin + if ((Instruct == DDRQIOR || Instruct == DDRQIOR4) + && QUAD) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) is enabled + // Optional DLP + if (VDLR_reg != 8'b00000000 && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + HOLDNegOut_zd = data_out[7-read_cnt]; + WPNegOut_zd = data_out[7-read_cnt]; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + read_addr_tmp = read_addr; + SecAddr = read_addr/(SecSize+1) ; + Sec_addr = read_addr - SecAddr*(SecSize+1); + SecAddr = ReturnSectorIDRdPswdMd(TBPROT); + read_addr = Sec_addr + SecAddr*(SecSize+1); + if (RdPswdProtMode == 0) + read_addr = read_addr_tmp; + + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == OTPR) + begin + if(read_addr>=OTPLoAddr && read_addr<=OTPHiAddr + && RdPswdProtMode == 0) + begin + //Read OTP Memory array + rd_fast = 1'b1; + rd_slow = 1'b0; + data_out[7:0] = OTPMem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + else if ((read_addr > OTPHiAddr)||(RdPswdProtMode==1)) + begin + //OTP Read operation will not wrap to the + //starting address after the OTP address is at + //its maximum or Read Password Protection Mode + //is selected instead, the data beyond the + //maximum OTP address will be undefined. + SOut_zd = 1'bX; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (Instruct == REMS) + begin + //Read Manufacturer and Device ID + if (read_addr % 2 == 0) + begin + data_out[7:0] = Manuf_ID; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + else + begin + data_out[7:0] = DeviceID; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = 0; + end + end + end + else if (Instruct == RDID) + begin + ident_out = CFI_array_tmp; + if(read_cnt < 648) + begin + SOut_zd = ident_out[647-read_cnt]; + read_cnt = read_cnt + 1; + end + else + begin + //Continued shifting of output beyond the end of + //the defined ID-CFI address space will + //provide undefined data. + SOut_zd = 1'bX; + end + end + else if (Instruct == RES) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + data_out = ESignature; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == DLPRD && RdPswdProtMode == 0) + begin + //Read DLP + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = VDLR_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == ABRD && RdPswdProtMode == 0) + begin + //Read AutoBoot register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = AutoBoot_reg[31-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 32) + read_cnt = 0; + end + else if (Instruct == BRRD && RdPswdProtMode == 0) + begin + //Read Bank Address Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = Bank_Addr_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == ASPRD && RdPswdProtMode == 0) + begin + //Read ASP Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = ASP_reg[15-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 16) + read_cnt = 0; + end + else if (Instruct == PASSRD && RdPswdProtMode == 0) + begin + //Read Password Register + if (~(PWDMLB == 0 && PSTMLB == 1)) + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = + Password_reg[(8*byte_cnt-1)-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + byte_cnt = byte_cnt + 1; + if (byte_cnt == 9) + byte_cnt = 1; + end + end + end + else if (Instruct == PLBRD) + begin + //Read PPB Lock Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = PPBL[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == DYBRD) + begin + //Read DYB Access Register + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + DYBAR[7:0] = 8'bXXXXXXXX; + + if (RdPswdProtMode == 0) + begin + if (DYB_bits[sect] == 1) + DYBAR[7:0] = 8'hFF; + else + begin + DYBAR[7:0] = 8'h0; + end + end + SOut_zd = DYBAR[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == PPBRD) + begin + //Read PPB Access Register + ReturnSectorID(sect,Address); + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + PPBAR[7:0] = 8'bXXXXXXXX; + if (RdPswdProtMode == 0) + begin + if (PPB_bits[sect] == 1) + PPBAR[7:0] = 8'hFF; + else + begin + PPBAR[7:0] = 8'h0; + end + end + SOut_zd = PPBAR[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + end + + AUTOBOOT: + begin + if (start_autoboot == 1) + begin + if (oe) + begin + any_read = 1'b1; + if (QUAD == 1) + begin + if (ABSD > 0) //If ABSD > 0, + begin //max SCK frequency is 104MHz + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else // If ABSD = 0, max SCK frequency is 50 MHz + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + else + begin + if (ABSD > 0) //If ABSD > 0, + begin //max SCK frequency is 133MHz + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + else // If ABSD = 0, max SCK frequency is 50 MHz + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + end + else if (oe_z) + begin + if (QUAD == 1) + begin + if (ABSD > 0) //If ABSD > 0, + begin //max SCK frequency is 104MHz + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else // If ABSD = 0, max SCK frequency is 50 MHz + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + end + else + begin + if (ABSD > 0) //If ABSD > 0, + begin //max SCK frequency is 133MHz + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + else // If ABSD = 0, max SCK frequency is 50 MHz + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + end + end + + WRITE_SR: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (WDONE == 1) + begin + Status_reg1[0] = 1'b0; //WIP + Status_reg1[1] = 1'b0; //WEL + //SRWD bit + Status_reg1[7] = Status_reg1_in[7]; //MSB first + + if (LOCK == 0) + begin + if (FREEZE == 0) + //The Freeze Bit, when set to 1, locks the current + //state of the BP2-0 bits in Status Register, + //the TBPROT and TBPARM bits in the Config Register + //As long as the FREEZE bit remains cleared to logic + //'0', the other bits of the Configuration register + //including FREEZE are writeable. + begin + Status_reg1[4] = Status_reg1_in[4];//BP2 + Status_reg1[3] = Status_reg1_in[3];//BP1 + Status_reg1[2] = Status_reg1_in[2];//BP0 + + BP_bits = {Status_reg1[4],Status_reg1[3], + Status_reg1[2]}; + if (TBPROT == 1'b0 && INITIAL_CONFIG == 1'b0) + begin + Config_reg1[5] = Config_reg1_in[5];//TBPROT + end + if (TBPARM == 1'b0 && INITIAL_CONFIG == 1'b0 && + tmp_char2 == "0") + begin + Config_reg1[2] = Config_reg1_in[2];//TBPARM + change_TBPARM = 1'b1; + #1000 change_TBPARM = 1'b0; + end + change_BP = 1'b1; + #1000 change_BP = 1'b0; + end + end + + Config_reg1[7] = Config_reg1_in[7];//LC1 + Config_reg1[6] = Config_reg1_in[6];//LC0 + Config_reg1[1] = Config_reg1_in[1];//QUAD + + if (FREEZE == 1'b0) + begin + Config_reg1[0] = Config_reg1_in[0];//FREEZE + end + + if (WRLOCKENABLE== 1'b1 && LOCK == 1'b0) + begin + Config_reg1[4] = Config_reg1_in[4];//LOCK + WRLOCKENABLE = 1'b0; + end + if (BPNV == 1'b0) + begin + Config_reg1[3] = Config_reg1_in[3];//BPNV + end + end + end + + PAGE_PG : + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == PAGE_PG) + begin + if (~PDONE) + begin + ADDRHILO_PG(AddrLo, AddrHi, Addr); + cnt = 0; + + for (i=0;i<=wr_cnt;i=i+1) + begin + new_int = WData[i]; + old_int = Mem[Addr + i - cnt]; + if (new_int > -1) + begin + new_bit = new_int; + if (old_int > -1) + begin + old_bit = old_int; + for(j=0;j<=7;j=j+1) + begin + if (~old_bit[j]) + new_bit[j]=1'b0; + end + new_int=new_bit; + end + WData[i]= new_int; + end + else + begin + WData[i] = -1; + end + + Mem[Addr + i - cnt] = - 1; + if ((Addr + i) == AddrHi) + begin + Addr = AddrLo; + cnt = i + 1; + end + end + end + cnt = 0; + end + + if (PDONE) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + quad_pg = 0; + for (i=0;i<=wr_cnt;i=i+1) + begin + Mem[Addr_tmp + i - cnt] = WData[i]; + if ((Addr_tmp + i) == AddrHi) + begin + Addr_tmp = AddrLo; + cnt = i + 1; + end + end + end + + if (Instruct) + begin + if (Instruct == PGSP && ~PRGSUSP_in) + begin + if (~RES_TO_SUSP_MIN_TIME) + begin + PGSUSP = 1'b1; + PGSUSP <= #5 1'b0; + PRGSUSP_in = 1'b1; + if (RES_TO_SUSP_TYP_TIME) + begin + $display("Typical periods are needed for ", + "Program to progress to completion"); + end + end + else + begin + $display("Minimum for tPRS is not satisfied! ", + "PGSP command is ignored"); + end + end + end + end + + PG_SUSP: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + + if (PRGSUSP_out && PRGSUSP_in) + begin + PRGSUSP_in = 1'b0; + //The RDY/BSY bit in the Status Register will indicate that + //the device is ready for another operation. + Status_reg1[0] = 1'b0; + //The Program Suspend (PS) bit in the Status Register will + //be set to the logical “1” state to indicate that the + //program operation has been suspended. + Status_reg2[0] = 1'b1; + PDONE = 1'b1; + end + + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == BRRD) + begin + //Read Bank Address Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = Bank_Addr_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + //Read Array Operations + else if (Instruct == READ || Instruct == RD4 || + Instruct == FSTRD || Instruct == FSTRD4 || + Instruct == DDRFR || Instruct == DDRFR4 ) + begin + //Read Memory array + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + if (pgm_page != read_addr / (PageSize+1)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + + end + end + else + begin + SOut_zd = 8'bxxxxxxxx; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 ) + begin + //Read Memory array + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (pgm_page != read_addr / (PageSize+1)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4 ) + begin + //Read Memory array + if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (pgm_page != read_addr / (PageSize+1)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if ((Instruct == DDRQIOR + || Instruct == DDRQIOR4) && QUAD) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + HOLDNegOut_zd= data_out[7-read_cnt]; + WPNegOut_zd = data_out[7-read_cnt]; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + HOLDNegOut_zd = 1'bx; + WPNegOut_zd = 1'bx; + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + end + else if (oe_z) + begin + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (falling_edge_write) + begin + if (Instruct == BRWR) + begin + Bank_Addr_reg[7] = Bank_Addr_reg_in[7]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + if(Bank_Addr_reg_in[1] == 1) + begin + $display ("WARNING: Changing values of "); + $display ("Bank Address Register"); + $display ("BA25 is not allowed!!!"); + end + end + else if (Instruct == WRR && BAR_ACC == 1) + begin + // Write to the lower address bits of the BAR + if (P_ERR == 0 && E_ERR == 0) + begin + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + if(Bank_Addr_reg_in[1] == 1) + begin + $display ("WARNING: Changing values of "); + $display ("Bank Address Register"); + $display ("BA25 is not allowed!!!"); + end + end + end + else if (Instruct == PGRS) + begin + Status_reg2[0] = 1'b0; + Status_reg1[0] = 1'b1; + PGRES = 1'b1; + PGRES <= #5 1'b0; + RES_TO_SUSP_MIN_TIME = 1'b1; + RES_TO_SUSP_MIN_TIME <= #60000 1'b0;//60 ns + RES_TO_SUSP_TYP_TIME = 1'b1; + RES_TO_SUSP_TYP_TIME <= #100000000 1'b0;//100us + end + + if (Instruct == BRAC && P_ERR == 0 && E_ERR == 0 && + RdPswdProtMode == 0) + begin + BAR_ACC = 1; + end + else + begin + BAR_ACC = 0; + end + end + end + + ERS_SUSP_PG_SUSP: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + + if (PRGSUSP_out && PRGSUSP_in) + begin + PRGSUSP_in = 1'b0; + //The RDY/BSY bit in the Status Register will indicate that + //the device is ready for another operation. + Status_reg1[0] = 1'b0; + //The Program Suspend (PS) bit in the Status Register will + //be set to the logical “1” state to indicate that the + //program operation has been suspended. + Status_reg2[0] = 1'b1; + end + + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == BRRD) + begin + //Read Bank Address Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = Bank_Addr_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + //Read Array Operations + else if (Instruct == READ || Instruct == RD4 || + Instruct == FSTRD || Instruct == FSTRD4 || + Instruct == DDRFR || Instruct == DDRFR4 ) + begin + //Read Memory array + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + if ((SectorSuspend != read_addr/(SecSize+1)) && + (pgm_page != read_addr / (PageSize+1))) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + + end + end + else + begin + SOut_zd = 8'bxxxxxxxx; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 ) + begin + //Read Memory array + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if ((SectorSuspend != read_addr/(SecSize+1)) && + (pgm_page != read_addr / (PageSize+1))) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4 ) + begin + //Read Memory array + if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if ((SectorSuspend != read_addr/(SecSize+1)) && + (pgm_page != read_addr / (PageSize+1))) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if ((Instruct == DDRQIOR + || Instruct == DDRQIOR4) && QUAD) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + HOLDNegOut_zd =data_out[7-read_cnt]; + WPNegOut_zd = data_out[7-read_cnt]; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + HOLDNegOut_zd = 1'bx; + WPNegOut_zd = 1'bx; + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + end + else if (oe_z) + begin + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (falling_edge_write) + begin + if (Instruct == BRWR) + begin + Bank_Addr_reg[7] = Bank_Addr_reg_in[7]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + if(Bank_Addr_reg_in[1] == 1) + begin + $display ("WARNING: Changing values of "); + $display ("Bank Address Register"); + $display ("BA25 is not allowed!!!"); + end + end + else if (Instruct == WRR && BAR_ACC == 1) + begin + // Write to the lower address bits of the BAR + if (P_ERR == 0 && E_ERR == 0) + begin + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + if(Bank_Addr_reg_in[1] == 1) + begin + $display ("WARNING: Changing values of "); + $display ("Bank Address Register"); + $display ("BA25 is not allowed!!!"); + end + end + end + else if (Instruct == PGRS) + begin + Status_reg2[0] = 1'b0; + Status_reg1[0] = 1'b1; + PGRES = 1'b1; + PGRES <= #5 1'b0; + RES_TO_SUSP_MIN_TIME = 1'b1; + RES_TO_SUSP_MIN_TIME <= #60000 1'b0;//60 ns + RES_TO_SUSP_TYP_TIME = 1'b1; + RES_TO_SUSP_TYP_TIME <= #100000000 1'b0;//100us + end + + if (Instruct == BRAC && P_ERR == 0 && E_ERR == 0 && + RdPswdProtMode == 0) + begin + BAR_ACC = 1; + end + else + begin + BAR_ACC = 0; + end + end + end + + OTP_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == OTP_PG) + begin + if (~PDONE) + begin + if (Address + wr_cnt <= OTPHiAddr) + begin + for (i=0;i<=wr_cnt;i=i+1) + begin + new_int = WData[i]; + old_int = OTPMem[Addr + i]; + if (new_int > -1) + begin + new_bit = new_int; + if (old_int > -1) + begin + old_bit = old_int; + for(j=0;j<=7;j=j+1) + begin + if (~old_bit[j]) + new_bit[j] = 1'b0; + end + new_int = new_bit; + end + WData[i] = new_int; + end + else + begin + WData[i] = -1; + end + OTPMem[Addr + i] = -1; + end + end + else + begin + $display ("Programming will reach over "); + $display ("address limit of OTP array"); + end + end + end + + if (PDONE) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + for (i=0;i<=wr_cnt;i=i+1) + begin + OTPMem[Addr + i] = WData[i]; + end + LOCK_BYTE1 = OTPMem[16]; + LOCK_BYTE2 = OTPMem[17]; + LOCK_BYTE3 = OTPMem[18]; + LOCK_BYTE4 = OTPMem[19]; + end + end + + SECTOR_ERS: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == SECTOR_ERS) + begin + if (~EDONE) + begin + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = -1; + end + end + end + + if (EDONE == 1) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = MaxData; + end + end + else if (Instruct == ERSP && ~ERSSUSP_in) + begin + ESUSP = 1'b1; + ESUSP <= #5 1'b0; + ERSSUSP_in = 1'b1; + if (RES_TO_SUSP_TYP_TIME) + begin + $display("Typical periods are needed for ", + "Program to progress to completion"); + end + end + end + + BULK_ERS: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == BULK_ERS) + begin + if (~EDONE) + begin + for (i=0;i<=AddrRANGE;i=i+1) + begin + ReturnSectorID(sect,i); + if (PPB_bits[sect] == 1 && DYB_bits[sect] == 1) + begin + Mem[i] = -1; + end + end + + end + end + + if (EDONE == 1) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + for (i=0;i<=AddrRANGE;i=i+1) + begin + ReturnSectorID(sect,i); + if (PPB_bits[sect] == 1 && DYB_bits[sect] == 1) + begin + Mem[i] = MaxData; + end + end + end + end + + ERS_SUSP: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (ERSSUSP_out == 1) + begin + ERSSUSP_in = 0; + //The Erase Suspend (ES) bit in the Status Register will + //be set to the logical “1” state to indicate that the + //erase operation has been suspended. + Status_reg2[1] = 1'b1; + //The WIP bit in the Status Register will indicate that + //the device is ready for another operation. + Status_reg1[0] = 1'b0; + end + + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == DYBRD) + begin + //Read DYB Access Register + ReturnSectorID(sect,Address); + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (DYB_bits[sect] == 1) + DYBAR[7:0] = 8'hFF; + else + begin + DYBAR[7:0] = 8'h0; + end + SOut_zd = DYBAR[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == BRRD) + begin + //Read Bank Address Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = Bank_Addr_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == PPBRD) + begin + //Read PPB Access Register + ReturnSectorID(sect,Address); + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + PPBAR[7:0] = 8'bXXXXXXXX; + if (RdPswdProtMode == 0) + begin + if (PPB_bits[sect] == 1) + PPBAR[7:0] = 8'hFF; + else + begin + PPBAR[7:0] = 8'h0; + end + end + SOut_zd = PPBAR[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == READ || Instruct == RD4 || + Instruct == FSTRD || Instruct == FSTRD4 || + Instruct == DDRFR || Instruct == DDRFR4 ) + begin + //Read Memory array + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + if ((PARAM_REGION && + SectorSuspend != read_addr/(SecSize+1)) || + (~PARAM_REGION && + SectorSuspend != read_addr/(SecSize+1)+30*b_act)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + SOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 ) + begin + //Read Memory array + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if ((PARAM_REGION && + SectorSuspend != read_addr/(SecSize+1)) || + (~PARAM_REGION && + SectorSuspend != read_addr/(SecSize+1)+30*b_act)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4 ) + begin + //Read Memory array + if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if ((PARAM_REGION && + SectorSuspend != read_addr/(SecSize+1)) || + (~PARAM_REGION && + SectorSuspend != read_addr/(SecSize+1)+30*b_act)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if ((Instruct == DDRQIOR + || Instruct == DDRQIOR4) && QUAD) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + HOLDNegOut_zd= data_out[7-read_cnt]; + WPNegOut_zd = data_out[7-read_cnt]; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + HOLDNegOut_zd = 1'bx; + WPNegOut_zd = 1'bx; + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + end + else if (oe_z) + begin + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (falling_edge_write) + begin + if ((Instruct == PP || Instruct == PP4) && WEL == 1) + begin + if ((PARAM_REGION && + SectorSuspend != Address/(SecSize+1)) || + (~PARAM_REGION && + SectorSuspend != Address/(SecSize+1)+30*b_act)) + begin + ReturnSectorID(sect,Address); + if (Sec_Prot[sect] == 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 0; + PGRES = 0; + Status_reg1[0] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + end + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + end + end + else if ((Instruct == QPP || Instruct == QPP4) && WEL == 1) + begin + if ((PARAM_REGION && + SectorSuspend != Address/(SecSize+1)) || + (~PARAM_REGION && + SectorSuspend != Address/(SecSize+1)+30*b_act)) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + + if (Sec_Prot[sect] == 0 + && PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 0; + PGRES = 0; + Status_reg1[0] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + end + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + end + end + else if (Instruct == WREN) + Status_reg1[1] = 1'b1; + else if (Instruct == CLSR) + begin + //The Clear Status Register Command resets bit SR1[5] + //(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + Status_reg1[5] = 0; + Status_reg1[6] = 0; + end + else if (Instruct == BRWR) + begin + Bank_Addr_reg[7] = Bank_Addr_reg_in[7]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + if(Bank_Addr_reg_in[1] == 1) + begin + $display ("WARNING: Changing values of "); + $display ("Bank Address Register"); + $display ("BA25 is not allowed!!!"); + end + end + else if (Instruct == WRR && BAR_ACC == 1) + begin + // Write to the lower address bits of the BAR + if (P_ERR == 0 && E_ERR == 0) + begin + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + if(Bank_Addr_reg_in[1] == 1) + begin + $display ("WARNING: Changing values of "); + $display ("Bank Address Register"); + $display ("BA25 is not allowed!!!"); + end + end + end + else if (Instruct == DYBWR && WEL == 1) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == ERRS) + begin + Status_reg2[1] = 1'b0; + Status_reg1[0] = 1'b1; + if (BottomBoot) + begin + if (PARAM_REGION) + begin + Addr = SectorSuspend*(SecSize+1); + end + else + begin + Addr = (SectorSuspend-30)*(SecSize+1); + end + end + else + begin + Addr = SectorSuspend*(SecSize+1); + end + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + ERES = 1'b1; + ERES <= #5 1'b0; + RES_TO_SUSP_TYP_TIME = 1'b1; + RES_TO_SUSP_TYP_TIME <= #100000000 1'b0;//100us + end + + if (Instruct == BRAC && P_ERR == 0 && E_ERR == 0 && + RdPswdProtMode == 0) + begin + BAR_ACC = 1; + end + else + begin + BAR_ACC = 0; + end + end + end + + ERS_SUSP_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == ERS_SUSP_PG) + begin + if (~PDONE) + begin + ADDRHILO_PG(AddrLo, AddrHi, Addr); + cnt = 0; + for (i=0;i<=wr_cnt;i=i+1) + begin + new_int = WData[i]; + old_int = Mem[Addr + i - cnt]; + if (new_int > -1) + begin + new_bit = new_int; + if (old_int > -1) + begin + old_bit = old_int; + for(j=0;j<=7;j=j+1) + begin + if (~old_bit[j]) + new_bit[j] = 1'b0; + end + new_int = new_bit; + end + WData[i] = new_int; + end + else + begin + WData[i] = -1; + end + + if ((Addr + i) == AddrHi) + begin + Addr = AddrLo; + cnt = i + 1; + end + end + end + cnt =0; + end + + if(PDONE == 1) + begin + Status_reg1[0] = 1'b0;//WIP + Status_reg1[1] = 1'b0;//WEL + for (i=0;i<=wr_cnt;i=i+1) + begin + Mem[Addr_tmp + i - cnt] = WData[i]; + if ((Addr_tmp + i) == AddrHi ) + begin + Addr_tmp = AddrLo; + cnt = i + 1; + end + end + end + + if (Instruct) + begin + if (Instruct == PGSP && ~PRGSUSP_in) + begin + if (~RES_TO_SUSP_MIN_TIME) + begin + PGSUSP = 1'b1; + PGSUSP <= #5 1'b0; + PRGSUSP_in = 1'b1; + if (RES_TO_SUSP_TYP_TIME) + begin + $display("Typical periods are needed for ", + "Program to progress to completion"); + end + end + else + begin + $display("Minimum for tPRS is not satisfied! ", + "PGSP command is ignored"); + end + end + end + end + + PASS_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + new_pass = Password_reg_in; + old_pass = Password_reg; + for (i=0;i<=63;i=i+1) + begin + if (old_pass[j] == 0) + new_pass[j] = 0; + end + + if (PDONE == 1) + begin + Password_reg = new_pass; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + PASS_UNLOCK: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PASS_TEMP == Password_reg) + begin + PASS_UNLOCKED = 1'b1; + end + else + begin + PASS_UNLOCKED = 1'b0; + end + if (PASSULCK_out == 1'b1) + begin + if ((PASS_UNLOCKED == 1'b1) && (~PWDMLB)) + begin + PPBL[0] = 1'b1; + Status_reg1[0] = 1'b0; //WIP + end + else + begin + Status_reg1[6] = 1'b1; + $display ("Incorrect Password"); + PASSACC_in = 1'b1; + end + Status_reg1[1] = 1'b0; + PASSULCK_in = 1'b0; + end + end + + PPB_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + if (PPB_LOCK !== 0) + begin + PPB_bits[sect]= 1'b0; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + else + begin + Status_reg1[5] = 1'b0; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + end + + PPB_ERS: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PPBERASE_out == 1'b1) + begin + if ((PPB_LOCK !== 0) && PPBOTP) + begin + PPB_bits = {542{1'b1}}; + end + else + begin + Status_reg1[5] = 1'b1; + end + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + PPBERASE_in = 1'b0; + end + end + + AUTOBOOT_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + AutoBoot_reg = AutoBoot_reg_in; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + PLB_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + PPBL[0] = 1'b0; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + DYB_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + DYBAR = DYBAR_in; + if (DYBAR == 8'hFF) + begin + DYB_bits[sect]= 1'b1; + end + else if (DYBAR == 8'h00) + begin + DYB_bits[sect]= 1'b0; + end + else + begin + Status_reg1[6] = 1'b1; + end + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + ASP_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + + if (RPME == 1'b0 && ASP_reg_in[5] == 1'b1) + begin + Status_reg1[6] = 1'b1; //P_ERR + $display("RPME bit is allready programmed"); + end + else + begin + ASP_reg[5] = ASP_reg_in[5];//RPME + end + + if (PPBOTP == 1'b0 && ASP_reg_in[3] == 1'b1) + begin + Status_reg1[6] = 1'b1; //P_ERR + $display("PPBOTP bit is allready programmed"); + end + else + begin + ASP_reg[3] = ASP_reg_in[3];//PPBOTP + end + + if (PWDMLB == 1'b1 && PSTMLB == 1'b1) + begin + if (ASP_reg_in[2] == 1'b0 && ASP_reg_in[1] == 1'b0) + begin + $display("ASPR[2:1] = 00 Illegal condition"); + Status_reg1[6] = 1'b1; //P_ERR + end + else + begin + if (ASP_reg_in[2]!==1'b1 || ASP_reg_in[1]!==1'b1) + begin + ASPOTPFLAG = 1'b1; + end + ASP_reg[2] = ASP_reg_in[2];//PWDMLB + ASP_reg[1] = ASP_reg_in[1];//PSTMLB + end + end + + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + NVDLR_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + if (NVDLR_reg == 0) + begin + NVDLR_reg = NVDLR_reg_in; + VDLR_reg = NVDLR_reg_in; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + else + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; //P_ERR + $display("NVDLR bits allready programmed"); + end + end + end + + RESET_STATE: + begin + //the default condition hardware reset + //The Bank Address Register is loaded to all zeroes + Bank_Addr_reg = 8'h0; + if (BPNV && ~LOCK && ~FREEZE) + begin + Status_reg1[2] = 1'b1;// BP0 + Status_reg1[3] = 1'b1;// BP1 + Status_reg1[4] = 1'b1;// BP2 + BP_bits = 3'b111; + change_BP = 1'b1; + #1000 change_BP = 1'b0; + end + //Resets the volatile bits in the Status register 1 + Status_reg1[6] = 1'b0; + Status_reg1[5] = 1'b0; + Status_reg1[1] = 1'b0; + Status_reg1[0] = 1'b0; + //Resets the volatile bits in the Status register 2 + Status_reg2[1] = 1'b0; + Status_reg2[0] = 1'b0; + //Resets the volatile bits in the Configuration register 1 + Config_reg1[0] = 1'b0; + //On reset cycles the data pattern reverts back + //to what is in the NVDLR + VDLR_reg = NVDLR_reg; + dlp_act = 1'b0; + //Loads the Program Buffer with all ones + for(i=0;i<=511;i=i+1) + begin + WData[i] = MaxData; + end + if (~PWDMLB) + PPBL[0] = 1'b0; + else + PPBL[0] = 1'b1; + end + + endcase + + //Output Disable Control + if (CSNeg_ipd ) + begin + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + end + end + + assign fast_rd = rd_fast; + assign rd = rd_slow; + assign ddrd = ddr; + assign fast_ddr = ddr_fast; + + always @(change_TBPARM, posedge PoweredUp) + begin + if (tmp_char2 == "0") + begin + if (TBPARM == 0) + begin + BottomBoot = 1; + b_act = 1; + end + else + begin + TopBoot = 1; + BottomBoot = 0; + b_act = 0; + end + end + else if (tmp_char2 == "1") + begin + UniformSec = 1; + end + end + + always @(posedge change_BP) + begin + case (Status_reg1[4:2]) + + 3'b000: + begin + Sec_Prot[541:0] = {542{1'b0}}; + end + 3'b001: + begin + if (tmp_char2 == "1") + begin + if (~TBPROT) + begin + Sec_Prot[SecNum256:(SecNum256+1)*63/64] = 2'b11; + Sec_Prot[(SecNum256+1)*63/64-1 : 0] = 126'h0; + end + else + begin + Sec_Prot[(SecNum256+1)/64-1 : 0] = 2'b11; + Sec_Prot[SecNum256 : (SecNum256+1)/64] = 126'h0; + end + end + else if (tmp_char2 == "0" && TBPARM == 1) + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64:(SecNum64-29)*63/64] = {38{1'b1}}; + Sec_Prot[(SecNum64-29)*63/64-1 : 0] = 504'h0; + end + else + begin + Sec_Prot[(SecNum64-29)/64-1 : 0] = {8{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/64] = 534'h0; + end + end + else + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64:(SecNum64-29)*63/64+30] = {8{1'b1}}; + Sec_Prot[(SecNum64-29)*63/64+29 : 0] = 534'h0; + end + else + begin + Sec_Prot[(SecNum64-29)/64+29 : 0] = {38{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/64+30] = 504'h0; + end + end + end + + 3'b010: + begin + if (tmp_char2 == "1") + begin + if (~TBPROT) + begin + Sec_Prot[SecNum256 : (SecNum256+1)*31/32] = {4{1'b1}}; + Sec_Prot[(SecNum256+1)*31/32-1 : 0] = 124'h0; + end + else + begin + Sec_Prot[(SecNum256+1)/32-1 : 0] = {4{1'b1}}; + Sec_Prot[SecNum256 : (SecNum256+1)/32] = 124'h0; + end + end + else if (tmp_char2 == "0" && TBPARM == 1) + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64 : (SecNum64-29)*31/32] = {46{1'b1}}; + Sec_Prot[(SecNum64-29)*31/32-1 : 0] = 496'h0; + end + else + begin + Sec_Prot[(SecNum64-29)/32-1 : 0] = {16{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/32] = 526'h0; + end + end + else + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64:(SecNum64-29)*31/32+30] = {16{1'b1}}; + Sec_Prot[(SecNum64-29)*31/32+29 : 0] = 526'h0; + end + else + begin + Sec_Prot[(SecNum64-29)/32+29 : 0] = {46{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/32+30] = 496'h0; + end + end + end + + 3'b011: + begin + if (tmp_char2 == "1") + begin + if (~TBPROT) + begin + Sec_Prot[SecNum256 : (SecNum256+1)*15/16] = 8'hFF; + Sec_Prot[(SecNum256+1)*15/16-1 : 0] = 120'h0; + end + else + begin + Sec_Prot[(SecNum256+1)/16-1 : 0] = 8'hFF; + Sec_Prot[SecNum256 : (SecNum256+1)/16] = 120'h0; + end + end + else if (tmp_char2 == "0" && TBPARM == 1) + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64 : (SecNum64-29)*15/16] = {62{1'b1}}; + Sec_Prot[(SecNum64-29)*15/16-1 : 0] = 480'h0; + end + else + begin + Sec_Prot[(SecNum64-29)/16-1 : 0] = {32{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/16] = 510'h0; + end + end + else + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64 : (SecNum64-29)*15/16+30]={32{1'b1}}; + Sec_Prot[(SecNum64-29)*15/16+29 : 0] = 510'h0; + end + else + begin + Sec_Prot[(SecNum64-29)/16+29 : 0] ={62{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/16+30] = 480'h0; + end + end + end + + 3'b100: + begin + if (tmp_char2 == "1") + begin + if (~TBPROT) + begin + Sec_Prot[SecNum256 : (SecNum256+1)*7/8] = {16{1'b1}}; + Sec_Prot[(SecNum256+1)*7/8-1 : 0] = 112'h0; + end + else + begin + Sec_Prot[(SecNum256+1)/8-1 : 0] = {16{1'b1}}; + Sec_Prot[SecNum256 : (SecNum256+1)/8] = 112'h0; + end + end + else if (tmp_char2 == "0" && TBPARM == 1) + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64 : (SecNum64-29)*7/8] = {94{1'b1}}; + Sec_Prot[(SecNum64-29)*7/8-1 : 0] = 448'h0; + end + else + begin + Sec_Prot[(SecNum64-29)/8-1 : 0] = {64{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/8] = 478'h0; + end + end + else + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64 : (SecNum64-29)*7/8+30] ={64{1'b1}}; + Sec_Prot[(SecNum64-29)*7/8+29 : 0] = 478'h0; + end + else + begin + Sec_Prot[(SecNum64-29)/8+29 : 0] = {94{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/8+30] = 448'h0; + end + end + end + + 3'b101: + begin + if (tmp_char2 == "1") + begin + if (~TBPROT) + begin + Sec_Prot[SecNum256 : (SecNum256+1)*3/4] = {32{1'b1}}; + Sec_Prot[(SecNum256+1)*3/4-1 : 0] = 96'h0; + end + else + begin + Sec_Prot[(SecNum256+1)/4-1 : 0] = {32{1'b1}}; + Sec_Prot[SecNum256 : (SecNum256+1)/4] = 96'h0; + end + end + else if (tmp_char2 == "0" && TBPARM == 1) + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64 : (SecNum64-29)*3/4] = {158{1'b1}}; + Sec_Prot[(SecNum64-29)*3/4-1 : 0] = 384'h0; + end + else + begin + Sec_Prot[(SecNum64-29)/4-1 : 0] = {128{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/4] = 414'h0; + end + end + else + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64 : (SecNum64-29)*3/4+30] = {128{1'b1}}; + Sec_Prot[(SecNum64-29)*3/4+29 : 0] = 414'h0; + end + else + begin + Sec_Prot[(SecNum64-29)/4+29 : 0] = {158{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/4+30] = 384'h0; + end + end + end + + 3'b110: + begin + if (tmp_char2 == "1") + begin + if (~TBPROT) + begin + Sec_Prot[SecNum256 : (SecNum256+1)/2] = {64{1'b1}}; + Sec_Prot[(SecNum256+1)/2-1 : 0] = 64'h0; + end + else + begin + Sec_Prot[(SecNum256+1)/2-1 : 0] = {64{1'b1}}; + Sec_Prot[SecNum256 : (SecNum256+1)/2] = 64'h0; + end + end + else if (tmp_char2 == "0" && TBPARM == 1) + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64 : (SecNum64-29)/2] = {286{1'b1}}; + Sec_Prot[(SecNum64-29)/2-1 : 0] = 256'h0; + end + else + begin + Sec_Prot[(SecNum64-29)/2-1 : 0] = {256{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/2] = 286'h0; + end + end + else + begin + if (~TBPROT) + begin + Sec_Prot[SecNum64 : (SecNum64-29)/2+30] = {256{1'b1}}; + Sec_Prot[(SecNum64-29)/2+29 : 0] = 286'h0; + end + else + begin + Sec_Prot[(SecNum64-29)/2+29 : 0] = {286{1'b1}}; + Sec_Prot[SecNum64 : (SecNum64-29)/2+30] = 256'h0; + end + end + end + + 3'b111: + begin + Sec_Prot[SecNum64:0] = {542{1'b1}}; + end + endcase + end + + always @(SOut_zd or HOLDNeg_in or SIOut_zd) + begin + if (HOLDNeg_in == 0 && ~QUAD) + begin + hold_mode = 1'b1; + SIOut_z = 1'bZ; + SOut_z = 1'bZ; + end + else + begin + if (hold_mode == 1) + begin + SIOut_z <= #(tpd_HOLDNeg_SO) SIOut_zd; + SOut_z <= #(tpd_HOLDNeg_SO) SOut_zd; + hold_mode = #(tpd_HOLDNeg_SO) 1'b0; + end + else + begin + SIOut_z = SIOut_zd; + SOut_z = SOut_zd; + hold_mode = 1'b0; + end + end + end + + //////////////////////////////////////////////////////////////////////// + // autoboot control logic + //////////////////////////////////////////////////////////////////////// + always @(rising_edge_SCK_ipd or current_state_event) + begin + if(current_state == AUTOBOOT) + begin + if (rising_edge_SCK_ipd) + begin + if (start_delay > 0) + start_delay = start_delay - 1; + end + + if (start_delay == 0) + begin + start_autoboot = 1; + end + end + end + + //////////////////////////////////////////////////////////////////////// + // functions & tasks + //////////////////////////////////////////////////////////////////////// + // Procedure FDDR_DPL + task Return_DLP; + input integer Instruct; + input integer EHP; + input integer Latency_code; + input integer dummy_cnt; + inout dlp_act; + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + if (EHP) + begin + if (Latency_code == 1) + dlp_act = 1'b1; + else if (Latency_code == 2 && dummy_cnt >= 1) + dlp_act = 1'b1; + else if(Latency_code == 3 || Latency_code == 0) + begin + dlp_act = 1'b0; + $display("Warning at", $time); + $display("Inappropriate latency is set during DPL mode"); + end + end + else + begin + if (Latency_code == 3) + dlp_act = 1'b1; + else if (Latency_code == 0 && dummy_cnt >= 1) + dlp_act = 1'b1; + else if(Latency_code == 1 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if(Latency_code == 2 && dummy_cnt >= 3) + dlp_act = 1'b1; + end + end + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + if (EHP) + begin + if (Latency_code == 1 && dummy_cnt >= 1) + dlp_act = 1'b1; + else if (Latency_code == 2 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if( Latency_code == 3 || Latency_code == 0) + begin + dlp_act = 1'b0; + $display("Warning at", $time); + $display("Inappropriate latency is set during DPL mode"); + end + end + else + begin + if (Latency_code == 3) + dlp_act = 1'b0; + else if (Latency_code == 0 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if (Latency_code == 1 && dummy_cnt >= 3) + dlp_act = 1'b1; + else if(Latency_code == 2 && dummy_cnt >= 4) + dlp_act = 1'b1; + end + end + if ((Instruct == DDRQIOR || Instruct == DDRQIOR4) && QUAD) + begin + if (EHP) + begin + if (Latency_code == 0 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if (Latency_code == 1 && dummy_cnt >= 3) + dlp_act = 1'b1; + else if (Latency_code == 2 && dummy_cnt >= 4) + dlp_act = 1'b1; + else if( Latency_code == 3) + begin + dlp_act = 1'b0; + $display("Warning at", $time); + $display("Inappropriate latency is"); + $display("set during DPL mode"); + end + end + else + begin + if (Latency_code == 0 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if (Latency_code == 1 && dummy_cnt >= 3) + dlp_act = 1'b1; + else if (Latency_code == 2 && dummy_cnt >= 4) + dlp_act = 1'b1; + else if( Latency_code == 3) + begin + dlp_act = 1'b0; + $display("Warning at", $time); + $display("Inappropriate latency is"); + $display("set during DPL mode"); + end + end + end + end + endtask + + function integer ReturnSectorIDRdPswdMd; + input reg TBPROT; + begin + if(TBPROT == 0) + begin + ReturnSectorIDRdPswdMd = 0; + end + else + begin + if (UniformSec) + begin + ReturnSectorIDRdPswdMd = SecNum256; + end + else + begin + ReturnSectorIDRdPswdMd = 511; + end + end + end + endfunction + + // Procedure ADDRHILO_SEC + task ADDRHILO_SEC; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer sector; + begin + if (tmp_char2 == "0") + begin + if (TBPARM == 0) + begin + if (Addr/(SecSize64+1) <= 1 && + (Instruct == P4E || Instruct == P4E4)) //4KB Sectors + begin + sector = Addr/(SecSize4+1); + AddrLOW = sector*(SecSize4+1); + AddrHIGH = sector*(SecSize4+1) + SecSize4; + end + else + begin + sector = Addr/(SecSize64+1); + AddrLOW = sector*(SecSize64+1); + AddrHIGH = sector*(SecSize64+1) + SecSize64; + end + end + else + begin + if (Addr/(SecSize64+1) >= 510 && + (Instruct == P4E || Instruct == P4E4)) //4KB Sectors + begin + sector = 510 + (Addr-(SecSize64+1)*510)/(SecSize4+1); + AddrLOW = 510*(SecSize64+1)+(sector-510)*(SecSize4+1); + AddrHIGH = 510*(SecSize64+1)+ + (sector-510)*(SecSize4+1) + SecSize4; + end + else + begin + sector = Addr/(SecSize64+1); + AddrLOW = sector*(SecSize64+1); + AddrHIGH = sector*(SecSize64+1) + SecSize64; + end + end + end + else if (tmp_char2 == "1") + begin + sector = Addr/(SecSize256+1); + AddrLOW = sector*(SecSize256+1); + AddrHIGH = sector*(SecSize256+1) + SecSize256; + end + end + endtask + + // Procedure ADDRHILO_PG + task ADDRHILO_PG; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer page; + begin + page = Addr / (PageSize + 1); + AddrLOW = page * (PageSize + 1); + AddrHIGH = page * (PageSize + 1) + PageSize; + end + endtask + + // Procedure ReturnSectorID + task ReturnSectorID; + inout sect; + input Address; + integer sect; + integer Address; + integer conv; + begin + if (tmp_char2 == "0") + begin + conv = Address / (SecSize64+1); + if (BottomBoot) + begin + if (conv <= 1) //4KB Sectors + begin + sect = Address/(SecSize4+1); + end + else + begin + sect = conv + 30; + end + end + else if (TopBoot) + begin + if (conv >= 510) //4KB Sectors + begin + sect = 510 + (Address-(SecSize64+1)*510)/(SecSize4+1); + end + else + begin + sect = conv; + end + end + end + else + begin + sect = Address/(SecSize256+1); + end + end + endtask + + always @(PPBL[0], ASP_reg) + begin + if (PPBL[0] == 0 && PWDMLB == 0 && RPME == 0 && RdPswdProtEnable) + begin + RdPswdProtMode = 1; + AutoBoot_reg[0] = 0;//AUTOBOOT is disabled when Read Password + end //Protection is enabled + else + begin + RdPswdProtMode = 0; + end + end + + /////////////////////////////////////////////////////////////////////////// + // edge controll processes + /////////////////////////////////////////////////////////////////////////// + + always @(posedge PoweredUp) + begin + rising_edge_PoweredUp = 1; + #1000 rising_edge_PoweredUp = 0; + end + + always @(posedge SCK_ipd) + begin + rising_edge_SCK_ipd = 1'b1; + #1000 rising_edge_SCK_ipd = 1'b0; + end + + always @(negedge SCK_ipd) + begin + falling_edge_SCK_ipd = 1'b1; + #1000 falling_edge_SCK_ipd = 1'b0; + end + + always @(posedge read_out) + begin + rising_edge_read_out = 1'b1; + #1000 rising_edge_read_out = 1'b0; + end + + always @(negedge write) + begin + falling_edge_write = 1; + #1000 falling_edge_write = 0; + end + + always @(posedge PRGSUSP_out) + begin + PRGSUSP_out_event = 1; + #1000 PRGSUSP_out_event = 0; + end + + always @(posedge ERSSUSP_out) + begin + ERSSUSP_out_event = 1; + #1000 ERSSUSP_out_event = 0; + end + + always @(posedge CSNeg_ipd) + begin + rising_edge_CSNeg_ipd = 1'b1; + #1000 rising_edge_CSNeg_ipd = 1'b0; + end + + always @(negedge CSNeg_ipd) + begin + falling_edge_CSNeg_ipd = 1'b1; + #1000 falling_edge_CSNeg_ipd = 1'b0; + end + + always @(negedge RSTNeg_in) + begin + falling_edge_RSTNeg = 1'b1; + #50000 falling_edge_RSTNeg = 1'b0; + end + + always @(posedge RSTNeg_in) + begin + rising_edge_RSTNeg = 1'b1; + #10000 rising_edge_RSTNeg = 1'b0; + end + + always @(negedge RST) + begin + falling_edge_RST = 1'b1; + #10000 falling_edge_RST = 1'b0; + end + + always @(posedge RST) + begin + rising_edge_RST = 1'b1; + #1000 rising_edge_RST = 1'b0; + end + + always @(posedge PDONE) + begin + rising_edge_PDONE = 1'b1; + #1000 rising_edge_PDONE = 1'b0; + end + + always @(posedge WDONE) + begin + rising_edge_WDONE = 1'b1; + #1000 rising_edge_WDONE = 1'b0; + end + + always @(posedge WSTART) + begin + rising_edge_WSTART = 1'b1; + #1000 rising_edge_WSTART = 1'b0; + end + + always @(posedge EDONE) + begin + rising_edge_EDONE = 1'b1; + #1000 rising_edge_EDONE = 1'b0; + end + + always @(posedge ESTART) + begin + rising_edge_ESTART = 1'b1; + #1000 rising_edge_ESTART = 1'b0; + end + + always @(posedge PSTART) + begin + rising_edge_PSTART = 1'b1; + #1000 rising_edge_PSTART = 1'b0; + end + + always @(posedge Reseted) + begin + rising_edge_Reseted = 1'b1; + #1000 rising_edge_Reseted = 1'b0; + end + + always @(negedge PASSULCK_in) + begin + falling_edge_PASSULCK_in = 1'b1; + #1000 falling_edge_PASSULCK_in = 1'b0; + end + + always @(negedge PPBERASE_in) + begin + falling_edge_PPBERASE_in = 1'b1; + #1000 falling_edge_PPBERASE_in = 1'b0; + end + + always @(Instruct) + begin + Instruct_event = 1'b1; + #1000 Instruct_event = 1'b0; + end + + always @(change_addr) + begin + change_addr_event = 1'b1; + #1000 change_addr_event = 1'b0; + end + + always @(next_state) + begin + next_state_event = 1'b1; + #1000 next_state_event = 1'b0; + end + + always @(current_state) + begin + current_state_event = 1'b1; + #1000 current_state_event = 1'b0; + end + + always @(posedge RST_out) + begin + rising_edge_RST_out = 1'b1; + #1000 rising_edge_RST_out = 1'b0; + end + +endmodule \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl256s/model/s25fl256s.vhd b/lib/models/memory/flash/serial/S25fl256s/model/s25fl256s.vhd new file mode 100644 index 0000000..e53efb8 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl256s/model/s25fl256s.vhd @@ -0,0 +1,7222 @@ +------------------------------------------------------------------------------- +-- File Name: s25fl256s.vhd +------------------------------------------------------------------------------- +-- Copyright (C) 2012 Spansion, LLC. +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 V.Mancev 09 Nov 26 Inital Release +-- V1.1 V.Mancev 10 Mar 04 addr_cnt for second read in +-- high performance read continuous +-- mode can change its value only +-- when CSNeg = '0' +-- V1.2 V.Mancev 10 July 28 During the QUAD mode HOLD# input +-- is not monitored for its normal +-- function +-- V1.3 V.Mancev 10 Oct 15 Latest datasheet aligned +-- V1.4 V.Mancev 10 Oct 21 Hybrid configuration added +-- V1.5 V.Mancev 10 Nov 12 QUAD Program operation during Erase +-- Suspend is added +-- Warning for Resume to Suspend time +-- is added +-- During Erase Suspend, after Program +-- operation is completed, WEL bit is +-- cleared +-- Implemetation of Software Reset is +-- Changed +-- V1.6 V. Mancev 11 July 04 Latest datasheet aligned +-- V1.7 V. Mancev 11 Nov 18 Time tHO is changed to 1 ns +-- (customer's request) +-- BRWR instruction is corrected +-- V1.8 S.Petrovic 12 Aug 28 QPP Instruction is allowed on +-- previously programmed page +-- +------------------------------------------------------------------------------- +-- PART DESCRIPTION: +-- +-- Library: FLASH +-- Technology: FLASH MEMORY +-- Part: S25FL256S +-- +-- Description: 256 Megabit Serial Flash Memory +-- +------------------------------------------------------------------------------- +-- Comments : +-- For correct simulation, simulator resolution should be set to 1 ps +-- A device ordering (trim) option determines whether a feature is enabled +-- or not, or provide relevant parameters: +-- -15th character in TimingModel determines if enhanced high +-- performance option is available +-- (0,2,3,R,A,B,C,D) EHPLC +-- (Y,Z,S,T,K,L) Security EHPLC +-- (4,6,7,8,9,Q) HPLC +-- -15th character in TimingModel determines if RESET# input +-- is available +-- (R,A,B,C,D,Q.6,7,K,L,S,T,M,N,U,V) RESET# is available +-- (0,2,3,4,8,9,Y.Z.W,X) RESET# is tied to the inactive +-- state,inside the package. +-- -16th character in TimingModel determines Sector and Page Size: +-- (0) Sector Size = 64 kB; Page Size = 256 bytes +-- Hybrid Top/Bottom sector size architecture +-- (1) Sector Size = 256 kB; Page Size = 512 bytes +-- Uniform sector size architecture +-- +-------------------------------------------------------------------------------- +-- Known Bugs: +-- +-------------------------------------------------------------------------------- +LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; + USE STD.textio.ALL; + USE IEEE.VITAL_timing.ALL; + USE IEEE.VITAL_primitives.ALL; + +LIBRARY FMF; USE FMF.gen_utils.ALL; + USE FMF.conversions.ALL; +------------------------------------------------------------------------------- +-- ENTITY DECLARATION +------------------------------------------------------------------------------- +ENTITY s25fl256s IS + GENERIC ( + --------------------------------------------------------------------------- + -- TIMING GENERICS: + --------------------------------------------------------------------------- + -- tipd delays: interconnect path delays (delay between components) + -- There should be one for each IN or INOUT pin in the port list + -- They are given default values of zero delay. + tipd_SCK : VitalDelayType01 := VitalZeroDelay01; + tipd_SI : VitalDelayType01 := VitalZeroDelay01; + tipd_SO : VitalDelayType01 := VitalZeroDelay01; + + tipd_CSNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_HOLDNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_RSTNeg : VitalDelayType01 := VitalZeroDelay01; + + -- tpd delays: propagation delays (pin-to-pin delay within a component) + tpd_SCK_SO_normal : VitalDelayType01Z := UnitDelay01Z; -- tV, tHO + tpd_CSNeg_SO : VitalDelayType01Z := UnitDelay01Z; -- tDIS + tpd_HOLDNeg_SO : VitalDelayType01Z := UnitDelay01Z;-- + tpd_RSTNeg_SO : VitalDelayType01Z := UnitDelay01Z;-- + -- DDR operation values + tpd_SCK_SO_DDR : VitalDelayType01Z := UnitDelay01Z;--tV(66MHz) + + -- tsetup values: setup times + -- setup time is minimum time before the referent signal edge the + -- input should be stable + tsetup_CSNeg_SCK_normal_noedge_posedge + : VitalDelayType := UnitDelay; -- tCSS / + tsetup_CSNeg_SCK_DDR_noedge_posedge + : VitalDelayType := UnitDelay; -- tCSS / + tsetup_SI_SCK_normal_noedge_posedge: VitalDelayType + := UnitDelay; -- tSU:DAT / + tsetup_WPNeg_CSNeg : VitalDelayType := UnitDelay; -- tWPS \ + tsetup_HOLDNeg_SCK : VitalDelayType := UnitDelay; + tsetup_RSTNeg_CSNeg : VitalDelayType := UnitDelay; -- tRP + -- DDR operation values + tsetup_SI_SCK_DDR_noedge_posedge: VitalDelayType + := UnitDelay; -- tSU / + tsetup_SI_SCK_DDR_noedge_negedge: VitalDelayType + := UnitDelay; -- tSU \ + + -- thold values: hold times + -- hold time is minimum time the input should be present stable + -- after the referent signal edge + thold_CSNeg_SCK_normal_noedge_posedge + : VitalDelayType := UnitDelay; -- tCSH / + thold_CSNeg_SCK_DDR_noedge_posedge + : VitalDelayType := UnitDelay; -- tCSH / + thold_SI_SCK_normal_noedge_posedge: VitalDelayType + := UnitDelay; -- tHD:DAT / + thold_WPNeg_CSNeg : VitalDelayType := UnitDelay; -- tWPH / + thold_HOLDNeg_SCK : VitalDelayType := UnitDelay; -- + thold_CSNeg_RSTNeg : VitalDelayType := UnitDelay; -- tRPH + -- DDR operation values + thold_SI_SCK_DDR_noedge_posedge: VitalDelayType + := UnitDelay; -- tHD / + thold_SI_SCK_DDR_noedge_negedge: VitalDelayType + := UnitDelay; -- tHD \ + + --tpw values: pulse width + tpw_SCK_serial_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_dual_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_fast_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_quadpg_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_serial_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_SCK_dual_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_SCK_fast_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_SCK_quadpg_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_CSNeg_read_posedge : VitalDelayType := UnitDelay; -- tCS + tpw_CSNeg_pgers_posedge : VitalDelayType := UnitDelay; -- tCS + tpw_RSTNeg_negedge : VitalDelayType := UnitDelay; -- tRP + tpw_RSTNeg_posedge : VitalDelayType := UnitDelay; -- tRS + -- DDR operation values + tpw_SCK_DDR_posedge : VitalDelayType := UnitDelay; -- tWH(66MHz) + tpw_SCK_DDR_negedge : VitalDelayType := UnitDelay; -- tWL(66Hz) + + -- tperiod min (calculated as 1/max freq) + tperiod_SCK_serial_rd : VitalDelayType := UnitDelay; --fSCK=50MHz + tperiod_SCK_fast_rd : VitalDelayType := UnitDelay; --fSCK=133MHz + tperiod_SCK_dual_rd : VitalDelayType := UnitDelay; --fSCK=104MHz + tperiod_SCK_quadpg : VitalDelayType := UnitDelay; --fSCK=80MHz + -- DDR operation values + tperiod_SCK_DDR_rd : VitalDelayType := UnitDelay; --fSCK=66MHz + + -- tdevice values: values for internal delays + --timing values that are internal to the model and not associated + --with any port. + -- Page Program Operation (Page Size 256) + tdevice_PP256 : VitalDelayType := 550 us; --tPP + -- Page Program Operation (Page Size 512) + tdevice_PP512 : VitalDelayType := 750 us; --tPP + -- Typical Byte Programming Time + tdevice_BP : VitalDelayType := 400 us; --tBP + -- Sector Erase Operation(256KB Sectors) + tdevice_SE256 : VitalDelayType := 1875 ms; --tSE + -- Sector Erase Operation(64KB Sectors) + tdevice_SE64 : VitalDelayType := 650 ms; --tSE + -- Bulk Erase Operation + tdevice_BE : VitalDelayType := 330 sec; --tBE + -- WRR Cycle Time + tdevice_WRR : VitalDelayType := 200 ms; --tW + -- Erase Suspend/Erase Resume Time + tdevice_ERSSUSP : VitalDelayType := 40 us; --tESL + -- Program Suspend/Program Resume Time + tdevice_PRGSUSP : VitalDelayType := 40 us; -- + -- VCC (min) to CS# Low + tdevice_PU : VitalDelayType := 300 us; --tPU + -- PPB Erase Time + tdevice_PPBERASE :VitalDelayType := 15 ms; -- + -- Password Unlock Time + tdevice_PASSULCK :VitalDelayType := 1 us; -- + -- Password Unlock Time + tdevice_PASSACC :VitalDelayType := 100 us; + + --------------------------------------------------------------------------- + -- CONTROL GENERICS: + --------------------------------------------------------------------------- + -- generic control parameters + InstancePath : STRING := DefaultInstancePath; + TimingChecksOn : BOOLEAN := DefaultTimingChecks; + MsgOn : BOOLEAN := DefaultMsgOn; + XOn : BOOLEAN := DefaultXon; + -- memory file to be loaded + mem_file_name : STRING := "s25fl256s.mem"; + otp_file_name : STRING := "s25fl256sOTP.mem"; + + UserPreload : BOOLEAN := FALSE; --TRUE; + LongTimming : BOOLEAN := TRUE; + + -- For FMF SDF technology file usage + TimingModel : STRING + ); + PORT ( + -- Data Inputs/Outputs + SI : INOUT std_ulogic := 'U'; -- serial data input/IO0 + SO : INOUT std_ulogic := 'U'; -- serial data output/IO1 + -- Controls + SCK : IN std_ulogic := 'U'; -- serial clock input + CSNeg : IN std_ulogic := 'U'; -- chip select input + RSTNeg : IN std_ulogic := 'U'; -- hardware reset pin + WPNeg : INOUT std_ulogic := 'U'; -- write protect input/IO2 + HOLDNeg : INOUT std_ulogic := 'U' -- hold input/IO3 + ); + + ATTRIBUTE VITAL_LEVEL0 of s25fl256s : ENTITY IS TRUE; +END s25fl256s; + +------------------------------------------------------------------------------- +-- ARCHITECTURE DECLARATION +------------------------------------------------------------------------------- +ARCHITECTURE vhdl_behavioral of s25fl256s IS + ATTRIBUTE VITAL_LEVEL0 OF vhdl_behavioral : ARCHITECTURE IS TRUE; + + --------------------------------------------------------------------------- + -- CONSTANT AND SIGNAL DECLARATION + --------------------------------------------------------------------------- + --Declaration of constants - memory characteristics + -- The constant declared here are used to enable the creation of models + -- of memories within a family with a minimum amount of editing + + CONSTANT PartID : STRING := "s25fl256s"; + CONSTANT MaxData : NATURAL := 16#FF#; --255; + CONSTANT MemSize : NATURAL := 16#1FFFFFF#; --256Mbyte + CONSTANT SecSize256 : NATURAL := 16#3FFFF#; --256KB + CONSTANT SecSize64 : NATURAL := 16#FFFF#; --64KB + CONSTANT SecSize4 : NATURAL := 16#FFF#; --4KB + CONSTANT SecNum64 : NATURAL := 541; + CONSTANT SecNum256 : NATURAL := 127; + CONSTANT PageNum64 : NATURAL := 16#3FFFF#; + CONSTANT PageNum256 : NATURAL := 16#FFFF#; + CONSTANT AddrRANGE : NATURAL := 16#1FFFFFF#; + CONSTANT HiAddrBit : NATURAL := 31; + CONSTANT OTPSize : NATURAL := 1023; + CONSTANT OTPLoAddr : NATURAL := 16#000#; + CONSTANT OTPHiAddr : NATURAL := 16#3FF#; + CONSTANT BYTE : NATURAL := 8; + + --Manufacturer Identification + CONSTANT Manuf_ID : NATURAL := 16#01#; + CONSTANT DeviceID : NATURAL := 16#18#; + --Electronic Signature + CONSTANT ESignature : NATURAL := 16#18#; + --Device ID + --Manufacturer Identification && Memory Type && Memory Capacity + CONSTANT Jedec_ID : NATURAL := 16#01#; -- first byte of Device ID + CONSTANT DeviceID1 : NATURAL := 16#02#; + CONSTANT DeviceID2 : NATURAL := 16#19#; + CONSTANT ExtendedBytes : NATURAL := 16#4D#; + CONSTANT ExtendedID64 : NATURAL := 16#01#; + CONSTANT ExtendedID256 : NATURAL := 16#00#; + CONSTANT DieRev : NATURAL := 16#00#; + CONSTANT MaskRev : NATURAL := 16#00#; + + -- Declaration of signals that will hold the delayed values of ports + SIGNAL SI_ipd : std_ulogic := 'U'; + SIGNAL SO_ipd : std_ulogic := 'U'; + SIGNAL SCK_ipd : std_ulogic := 'U'; + SIGNAL CSNeg_ipd : std_ulogic := 'U'; + SIGNAL RSTNeg_ipd : std_ulogic := 'U'; + SIGNAL WPNeg_ipd : std_ulogic := 'U'; + SIGNAL HOLDNeg_ipd : std_ulogic := 'U'; + SIGNAL HOLDNeg_pullup : std_ulogic := 'U'; + SIGNAL WPNeg_pullup : std_ulogic := 'U'; + SIGNAL RSTNeg_pullup : std_ulogic := 'U'; + + -- internal delays + SIGNAL PP256_in : std_ulogic := '0'; + SIGNAL PP256_out : std_ulogic := '0'; + SIGNAL PP512_in : std_ulogic := '0'; + SIGNAL PP512_out : std_ulogic := '0'; + SIGNAL BP_in : std_ulogic := '0'; + SIGNAL BP_out : std_ulogic := '0'; + SIGNAL SE64_in : std_ulogic := '0'; + SIGNAL SE64_out : std_ulogic := '0'; + SIGNAL SE256_in : std_ulogic := '0'; + SIGNAL SE256_out : std_ulogic := '0'; + SIGNAL BE_in : std_ulogic := '0'; + SIGNAL BE_out : std_ulogic := '0'; + SIGNAL WRR_in : std_ulogic := '0'; + SIGNAL WRR_out : std_ulogic := '0'; + SIGNAL ERSSUSP_in : std_ulogic := '0'; + SIGNAL ERSSUSP_out : std_ulogic := '0'; + SIGNAL PRGSUSP_in : std_ulogic := '0'; + SIGNAL PRGSUSP_out : std_ulogic := '0'; + SIGNAL PU_in : std_ulogic := '0'; + SIGNAL PU_out : std_ulogic := '0'; + SIGNAL RST_in : std_ulogic := '0';-- Hardware Reset Timeout + SIGNAL RST_out : std_ulogic := '1';-- + SIGNAL PPBERASE_in : std_ulogic := '0'; + SIGNAL PPBERASE_out : std_ulogic := '0'; + SIGNAL PASSULCK_in : std_ulogic := '0'; + SIGNAL PASSULCK_out : std_ulogic := '0'; + SIGNAL PASSACC_in : std_ulogic := '0'; + SIGNAL PASSACC_out : std_ulogic := '0'; + + FUNCTION ReturnSectorIDRdPswdMd(TBPROT : std_logic) RETURN NATURAL IS + VARIABLE result : NATURAL; + BEGIN + IF TBPROT = '0' THEN + result := 0; + ELSE + IF (TimingModel(16) = '1') THEN + result := SecNum256; + ELSE + result := 511; + END IF; + END IF; + RETURN result; + END ReturnSectorIDRdPswdMd; + +BEGIN + + --------------------------------------------------------------------------- + -- Internal Delays + --------------------------------------------------------------------------- + -- Artificial VITAL primitives to incorporate internal delays + -- Because a tdevice generics is used, there must be a VITAL_primitives + -- assotiated with them + PP256 :VitalBuf(PP256_out, PP256_in, (tdevice_PP256 ,UnitDelay)); + PP512 :VitalBuf(PP512_out, PP512_in, (tdevice_PP512 ,UnitDelay)); + BP :VitalBuf(BP_out, BP_in, (tdevice_BP ,UnitDelay)); + SE64 :VitalBuf(SE64_out, SE64_in, (tdevice_SE64 ,UnitDelay)); + SE256 :VitalBuf(SE256_out, SE256_in, (tdevice_SE256 ,UnitDelay)); + BE :VitalBuf(BE_out, BE_in, (tdevice_BE ,UnitDelay)); + WRR :VitalBuf(WRR_out, WRR_in, (tdevice_WRR ,UnitDelay)); + ERSSUSP :VitalBuf(ERSSUSP_out, ERSSUSP_in, (tdevice_ERSSUSP ,UnitDelay)); + PRGSUSP :VitalBuf(PRGSUSP_out, PRGSUSP_in, (tdevice_PRGSUSP ,UnitDelay)); + PU :VitalBuf(PU_out, PU_in, (tdevice_PU ,UnitDelay)); + PPBERASE :VitalBuf(PPBERASE_out,PPBERASE_in,(tdevice_PPBERASE,UnitDelay)); + PASSULCK :VitalBuf(PASSULCK_out,PASSULCK_in,(tdevice_PASSULCK,UnitDelay)); + PASSACC :VitalBuf(PASSACC_out, PASSACC_in, (tdevice_PASSACC ,UnitDelay)); + + --------------------------------------------------------------------------- + -- Wire Delays + --------------------------------------------------------------------------- + WireDelay : BLOCK + BEGIN + + w_1 : VitalWireDelay (SI_ipd, SI, tipd_SI); + w_2 : VitalWireDelay (SO_ipd, SO, tipd_SO); + w_3 : VitalWireDelay (SCK_ipd, SCK, tipd_SCK); + w_4 : VitalWireDelay (CSNeg_ipd, CSNeg, tipd_CSNeg); + w_5 : VitalWireDelay (RSTNeg_ipd, RSTNeg, tipd_RSTNeg); + w_6 : VitalWireDelay (WPNeg_ipd, WPNeg, tipd_WPNeg); + w_7 : VitalWireDelay (HOLDNeg_ipd, HOLDNeg, tipd_HOLDNeg); + + END BLOCK; + + --------------------------------------------------------------------------- + -- Main Behavior Block + --------------------------------------------------------------------------- + Behavior: BLOCK + + PORT ( + SIIn : IN std_ulogic := 'U'; + SIOut : OUT std_ulogic := 'U'; + SOIn : IN std_logic := 'U'; + SOut : OUT std_logic := 'U'; + SCK : IN std_ulogic := 'U'; + CSNeg : IN std_ulogic := 'U'; + RSTNeg : IN std_ulogic := 'U'; + HOLDNegIn : IN std_ulogic := 'U'; + HOLDNegOut : OUT std_ulogic := 'U'; + WPNegIn : IN std_ulogic := 'U'; + WPNegOut : OUT std_ulogic := 'U' + ); + + PORT MAP ( + SIIn => SI_ipd, + SIOut => SI, + SOIn => SO_ipd, + SOut => SO, + SCK => SCK_ipd, + CSNeg => CSNeg_ipd, + RSTNeg => RSTNeg_ipd, + HOLDNegIn => HOLDNeg_ipd, + HOLDNegOut => HOLDNeg, + WPNegIn => WPNeg_ipd, + WPNegOut => WPNeg + ); + + -- State Machine : State_Type + TYPE state_type IS (IDLE, + RESET_STATE, + AUTOBOOT, + WRITE_SR, + PAGE_PG, + OTP_PG, + PG_SUSP, + SECTOR_ERS, + BULK_ERS, + ERS_SUSP, + ERS_SUSP_PG, + ERS_SUSP_PG_SUSP, + PASS_PG, + PASS_UNLOCK, + PPB_PG, + PPB_ERS, + AUTOBOOT_PG, + ASP_PG, + PLB_PG, + DYB_PG, + NVDLR_PG + ); + + -- Instruction Type + TYPE instruction_type IS ( NONE, + WREN, -- Write Enable + WRDI, -- Write Disable + WRR, -- Write Register + READ, -- Read Normal (3Byte Address) + RD4, -- Read Normal (4Byte +) + OTPR, -- OTP Read + RDSR, -- Read Status Register 1 + RDSR2, -- Read Status Register 2 + RDCR, -- Read Configuration Register 1 + REMS, -- Read ID (SST) + RDID, -- Read ID JEDEC + RES, -- Read ID + FSTRD, -- Fast Read (3Byte Address) + FSTRD4, -- Fast Read (4Byte +) + DDRFR, -- Fast Read DDR (3Byte Address) + DDRFR4, -- Fast Read DDR (4Byte +) + DOR, -- Read Dual Out (3Byte Address) + DOR4, -- Read Dual Out (4Byte +) + DIOR, -- Read Dual I/O (3Byte Address) + DIOR4, -- Read Dual I/O (4Byte +) + DDRDIOR, -- Read DDR Dual I/O (3Byte) + DDRDIOR4, -- Read DDR Dual I/O (4Byte +) + QOR, -- Read Quad Out (3Byte Address) + QOR4, -- Read Quad Out (4Byte +) + QIOR, -- Read Quad I/O (3Byte Address) + QIOR4, -- Read Quad I/O (4Byte +) + DDRQIOR, -- Read DDR Quad I/O (3Byte) + DDRQIOR4, -- Read DDR Quad I/O (4Byte +) + PP, -- Program Page (3Byte Address) + PP4, -- Program Page (4Byte +) + QPP, -- Quad Page Program (3Byte) + QPP4, -- Quad Page Program (4Byte +) + OTPP, -- OTP Program + PGSP, -- Program Suspend + PGRS, -- Program Resume + BE, -- Bulk Erase + SE, -- Erase 128/256KB (3Byte) + SE4, -- Erase 128/256KB (4Byte +) + P4E, -- 4KB-sector Erase (3Byte Addr) + P4E4, -- 4KB-sector Erase (4Byte Addr) + ERSP, -- Erase Suspend + ERRS, -- Erase Resume + ABRD, -- AutoBoot Register Read + ABWR, -- AutoBoot Register Write + BRRD, -- Bank Register Read + BRWR, -- Bank Register Write + BRAC, -- Bank Register Access + DLPRD, -- Read Data Learning Pattern + PNVDLR, -- Program NVDLP Reg + WVDLR, -- Write Volatile DLP Reg + ASPRD, -- ASP Read + ASPP, -- ASP Program + DYBRD, -- DYB Read + DYBWR, -- DYB Write + PPBRD, -- PPB Read + PPBP, -- PPB Program + PPBERS, -- PPB Erase + PLBWR, -- PPB Lock Bit Write + PLBRD, -- PPB Lock Bit Read + PASSRD, -- Password Read + PASSP, -- Password Program + PASSU, -- Password Unlock + RESET, -- Reset + MBR, -- Mode Bit Reset + MPM, -- Multi-I/O-High Perf Mode + CLSR -- Clear Status Register + ); + + TYPE WByteType IS ARRAY (0 TO 511) OF INTEGER RANGE -1 TO MaxData; + -- Flash Memory Array + TYPE MemArray IS ARRAY (0 TO AddrRANGE) OF INTEGER RANGE -1 TO MaxData; + -- OTP Memory Array + TYPE OTPArray IS ARRAY (OTPLoAddr TO OTPHiAddr) OF INTEGER + RANGE -1 TO MaxData; + --CFI Array (Common Flash Interface Query codes) + TYPE CFItype IS ARRAY (16#00# TO 16#55#) OF + INTEGER RANGE -1 TO 16#FF#; + ----------------------------------------------------------------------- + -- memory declaration + ----------------------------------------------------------------------- + -- Memory + SHARED VARIABLE Mem : MemArray := (OTHERS => MaxData); + -- OTP Sector + SHARED VARIABLE OTPMem : OTPArray := (OTHERS => MaxData); + --CFI Array + SHARED VARIABLE CFI_array : CFItype := (OTHERS => 0); + -- Programming Buffer + SIGNAL WByte : WByteType := (OTHERS => MaxData); + + -- states + SIGNAL current_state : state_type; + SIGNAL next_state : state_type; + + SIGNAL Instruct : instruction_type; + --zero delay signal + SIGNAL SOut_zd : std_logic := 'Z'; + SIGNAL SIOut_zd : std_logic := 'Z'; + SIGNAL HOLDNegOut_zd : std_logic := 'Z'; + SIGNAL WPNegOut_zd : std_logic := 'Z'; + --HOLD delay on output data + SIGNAL SOut_z : std_logic := 'Z'; + SIGNAL SIOut_z : std_logic := 'Z'; + -- powerup + SIGNAL PoweredUp : std_logic := '0'; + + ----------------------------------------------------------------------- + -- Registers + ----------------------------------------------------------------------- + -- *** Status Register 1 *** + SHARED VARIABLE Status_reg1 : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Status_reg1_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Status Register Write Disable Bit + ALIAS SRWD :std_logic IS Status_reg1(7); + -- Status Register Programming Error Bit + ALIAS P_ERR :std_logic IS Status_reg1(6); + -- Status Register Erase Error Bit + ALIAS E_ERR :std_logic IS Status_reg1(5); + -- Status Register Block Protection Bits + ALIAS BP2 :std_logic IS Status_reg1(4); + ALIAS BP1 :std_logic IS Status_reg1(3); + ALIAS BP0 :std_logic IS Status_reg1(2); + -- Status Register Write Enable Latch Bit + ALIAS WEL :std_logic IS Status_reg1(1); + -- Status Register Write In Progress Bit + ALIAS WIP :std_logic IS Status_reg1(0); + + -- *** Status Register 2 *** + SHARED VARIABLE Status_reg2 : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Status_reg2_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Status Register Write Enable Latch Bit + ALIAS ES :std_logic IS Status_reg2(1); + -- Status Register Write In Progress Bit + ALIAS PS :std_logic IS Status_reg2(0); + + -- *** Configuration Register 1 *** + SHARED VARIABLE Config_reg1 : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Config_reg1_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Latency code + ALIAS LC1 :std_logic IS Config_reg1(7); + ALIAS LC0 :std_logic IS Config_reg1(6); + -- Configuration Register TBPROT bit + ALIAS TBPROT :std_logic IS Config_reg1(5); + -- Configuration Register LOCK bit + ALIAS LOCK :std_logic IS Config_reg1(4); + -- Configuration Register BPNV bit + ALIAS BPNV :std_logic IS Config_reg1(3); + -- Configuration Register TBPARM bit + ALIAS TBPARM :std_logic IS Config_reg1(2); + -- Configuration Register QUAD bit + ALIAS QUAD :std_logic IS Config_reg1(1); + -- Configuration Register FREEZE bit + ALIAS FREEZE :std_logic IS Config_reg1(0); + + -- *** VDLR Register *** + SHARED VARIABLE VDLR_reg : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL VDLR_reg_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- *** NVDLR Register *** + SHARED VARIABLE NVDLR_reg : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL NVDLR_reg_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- *** AutoBoot Register *** + SHARED VARIABLE AutoBoot_reg : std_logic_vector(31 downto 0) + := (others => '0'); + SIGNAL AutoBoot_reg_in : std_logic_vector(31 downto 0) + := (others => '0'); + --AutoBoot Enable Bit + ALIAS ABE :std_logic IS AutoBoot_reg(0); + + -- *** Bank Address Register *** + SHARED VARIABLE Bank_Addr_reg : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Bank_Addr_reg_in : std_logic_vector(7 downto 0) + := (others => '0'); + --Bank Address Register EXTADD bit + ALIAS EXTADD :std_logic IS Bank_Addr_reg(7); + + -- *** ASP Register *** + SHARED VARIABLE ASP_reg : std_logic_vector(15 downto 0); + SIGNAL ASP_reg_in : std_logic_vector(15 downto 0) + := (others => '1'); + --Read Password Mode Enable Bit + ALIAS RPME :std_logic IS ASP_reg(5); + --PPB OTP Bit + ALIAS PPBOTP :std_logic IS ASP_reg(3); + -- Password Protection Mode Lock Bit + ALIAS PWDMLB :std_logic IS ASP_reg(2); + --Persistent Protection Mode Lock Bit + ALIAS PSTMLB :std_logic IS ASP_reg(1); + + -- *** Password Register *** + SHARED VARIABLE Password_reg : std_logic_vector(63 downto 0) + := (others => '1'); + SIGNAL Password_reg_in : std_logic_vector(63 downto 0) + := (others => '1'); + -- *** PPB Lock Register *** + SHARED VARIABLE PPBL : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL PPBL_in : std_logic_vector(7 downto 0) + := (others => '0'); + --Persistent Protection Mode Lock Bit + ALIAS PPB_LOCK : std_logic IS PPBL(0); + SIGNAL PPB_LOCK_temp : std_ulogic := '0'; + + -- *** PPB Access Register *** + SHARED VARIABLE PPBAR : std_logic_vector(7 downto 0) + := (others => '1'); + SIGNAL PPBAR_in : std_logic_vector(7 downto 0) + := (others => '1'); + -- PPB_bits(Sec) + SHARED VARIABLE PPB_bits : std_logic_vector(SecNum64 downto 0) + := (OTHERS => '1'); + -- *** DYB Access Register *** + SHARED VARIABLE DYBAR : std_logic_vector(7 downto 0) + := (others => '1'); + SIGNAL DYBAR_in : std_logic_vector(7 downto 0) + := (others => '1'); + -- DYB(Sec) + SHARED VARIABLE DYB_bits : std_logic_vector(SecNum64 downto 0); + + -- The Lock Protection Registers for OTP Memory space + SHARED VARIABLE LOCK_BYTE1 :std_logic_vector(7 downto 0); + SHARED VARIABLE LOCK_BYTE2 :std_logic_vector(7 downto 0); + SHARED VARIABLE LOCK_BYTE3 :std_logic_vector(7 downto 0); + SHARED VARIABLE LOCK_BYTE4 :std_logic_vector(7 downto 0); + + --Command Register + SIGNAL write : std_logic := '0'; + SIGNAL cfg_write : std_logic := '0'; + SIGNAL read_out : std_logic := '0'; + + SIGNAL rd : boolean := false; + SIGNAL dual : boolean := false; + SIGNAL fast_rd : boolean := true; + SIGNAL ddr : boolean := false; + SIGNAL any_read : boolean := false; + + SIGNAL quadpg : boolean := false; + + SIGNAL oe : boolean := false; + SIGNAL oe_z : boolean := false; + + SHARED VARIABLE hold_mode : boolean := false; + + -- Memory Array Configuration + SIGNAL BottomBoot : boolean := false; + SIGNAL TopBoot : boolean := false; + SIGNAL UniformSec : boolean := false; + + --FSM control signals + SIGNAL PDONE : std_logic := '1'; --Page Prog. Done + SIGNAL PSTART : std_logic := '0'; --Start Page Programming + SIGNAL PGSUSP : std_logic := '0'; --Suspend Program + SIGNAL PGRES : std_logic := '0'; --Resume Program + + SIGNAL RES_TO_SUSP_MIN_TIME : std_logic := '0';--Resume to Suspend Flag + SIGNAL RES_TO_SUSP_TYP_TIME : std_logic := '0';--Resume to Suspend Flag + + SIGNAL WDONE : std_logic := '1'; --Write operation Done + SIGNAL WSTART : std_logic := '0'; --Start Write operation + + SIGNAL ESTART : std_logic := '0'; --Start Erase operation + SIGNAL EDONE : std_logic := '1'; --Erase operation Done + SIGNAL ESUSP : std_logic := '0'; --Suspend Erase + SIGNAL ERES : std_logic := '0'; --Resume Erase + + --reset timing + SIGNAL RST : std_logic := '0'; + SIGNAL Reseted : std_logic := '0'; --Reset Timing Control + --Lock Bit is enabled for customer programming + SIGNAL WRLOCKENABLE : BOOLEAN := TRUE; + --Flag that mark if ASP Register is allready programmed + SIGNAL ASPOTPFLAG : BOOLEAN := FALSE; + SIGNAL ASP_INIT : NATURAL RANGE 0 TO 1; + SIGNAL INITIAL_CONFIG : std_logic := '0'; + + SHARED VARIABLE PageSize : NATURAL := 0 ; + SHARED VARIABLE PageNum : NATURAL := 0 ; + SHARED VARIABLE SecNum : NATURAL := 0 ; + SHARED VARIABLE SecNumMax : NATURAL := 0 ; + SHARED VARIABLE SecSize : NATURAL := 0 ; + SHARED VARIABLE b_act : NATURAL := 0 ; + + SHARED VARIABLE ASP_ProtSE : NATURAL := 0; + SHARED VARIABLE Sec_ProtSE : NATURAL := 0; + + SHARED VARIABLE SecAddr : NATURAL RANGE 0 TO SecNum64:= 0; + + SHARED VARIABLE Sec_addr : NATURAL := 0; + + SHARED VARIABLE Page_addr : NATURAL; + SHARED VARIABLE pgm_page : NATURAL; + + --Flag for Password unlock command + SIGNAL PASS_UNLOCKED : boolean := FALSE; + SIGNAL PASS_TEMP : std_logic_vector(63 downto 0) + := (others => '1'); + + SHARED VARIABLE DOUBLE : BOOLEAN := FALSE; + SHARED VARIABLE EHP : BOOLEAN := FALSE; + + SHARED VARIABLE read_cnt : NATURAL := 0; + SHARED VARIABLE byte_cnt : NATURAL := 1; + SHARED VARIABLE read_addr : NATURAL RANGE 0 TO AddrRANGE ; + SHARED VARIABLE read_addr_tmp : NATURAL RANGE 0 TO AddrRANGE ; + + SHARED VARIABLE start_delay : NATURAL RANGE 0 TO 7; + SHARED VARIABLE ABSD : NATURAL RANGE 0 TO 7; + SIGNAL start_autoboot : std_logic := '0'; + + SIGNAL change_addr : std_logic := '0'; + SIGNAL Address : NATURAL RANGE 0 TO AddrRANGE := 0; + SIGNAL SectorSuspend : NATURAL RANGE 0 TO SecNum64 := 0; + + -- Sector address + SIGNAL SA : NATURAL RANGE 0 TO SecNum64 := 0; + + -- Sector is protect if Sec_Prot(SecNum) = '1' + SHARED VARIABLE Sec_Prot : std_logic_vector(SecNum64 downto 0) := + (OTHERS => '0'); + + SIGNAL change_TBPARM : std_logic := '0'; + + SIGNAL change_BP : std_logic := '0'; + SHARED VARIABLE BP_bits : std_logic_vector(2 downto 0) := "000"; + + SHARED VARIABLE CFI_array_tmp : std_logic_vector(647 downto 0); + + SIGNAL Byte_number : NATURAL RANGE 0 TO 511 := 0; + + TYPE bus_cycle_type IS (STAND_BY, + OPCODE_BYTE, + ADDRESS_BYTES, + DUMMY_BYTES, + MODE_BYTE, + DATA_BYTES + ); + SHARED VARIABLE bus_cycle_state : bus_cycle_type; + -- switch between Data bytes and Dummy bytes + SHARED VARIABLE DummyBytes_act : X01 := '0'; + SIGNAL dummy_cnt_act_temp : NATURAL := 0; + SIGNAL dummy_cnt_act : NATURAL := 0; + --Read Password Protection Mode Active flag + SIGNAL RdPswdProtMode : std_ulogic := '0'; + --Read Password Protection Mode Support flag + SIGNAL RdPswdProtEnable : std_ulogic := '0'; + SIGNAL BAR_ACC : std_ulogic := '0'; + + SHARED VARIABLE Latency_code : NATURAL RANGE 0 TO 7; + SHARED VARIABLE opcode_cnt : NATURAL := 0; + SHARED VARIABLE addr_cnt : NATURAL := 0; + SHARED VARIABLE mode_cnt : NATURAL := 0; + SHARED VARIABLE dummy_cnt : NATURAL := 0; + SHARED VARIABLE data_cnt : NATURAL := 0; + + SHARED VARIABLE PARAM_REGION : BOOLEAN := FALSE; + + -- timing check violation + SIGNAL Viol : X01 := '0'; + + PROCEDURE ADDRHILO_SEC( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE Addr : NATURAL) IS + VARIABLE sector : NATURAL RANGE 0 TO 541; + BEGIN + + IF (TimingModel(16) = '0') THEN + IF TBPARM = '0' THEN + IF Addr/(SecSize64+1) <= 1 AND + (Instruct = P4E OR Instruct = P4E4) THEN --4KB Sectors + sector := Addr/(SecSize4+1); + AddrLOW := sector*(SecSize4+1); + AddrHIGH := sector*(SecSize4+1) + SecSize4; + ELSE + sector := Addr/(SecSize64+1); + AddrLOW := sector*(SecSize64+1); + AddrHIGH := sector*(SecSize64+1) + SecSize64; + END IF; + ELSE + IF Addr/(SecSize64+1) >= 510 AND + (Instruct = P4E OR Instruct = P4E4) THEN --4KB Sectors + sector := 510 + (Addr-(SecSize64+1)*510)/(SecSize4+1); + AddrLOW := 510*(SecSize64+1)+(sector-510)*(SecSize4+1); + AddrHIGH := 510*(SecSize64+1) + + (sector-510)*(SecSize4+1) + SecSize4; + ELSE + sector := Addr/(SecSize64+1); + AddrLOW := sector*(SecSize64+1); + AddrHIGH := sector*(SecSize64+1) + SecSize64; + END IF; + END IF; + ELSE + sector := Addr/(SecSize256+1); + AddrLOW := sector*(SecSize256+1); + AddrHIGH := sector*(SecSize256+1) + SecSize256; + END IF; + END ADDRHILO_SEC; + + PROCEDURE ADDRHILO_PG( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE Addr : NATURAL) IS + VARIABLE page : NATURAL RANGE 0 TO PageNum; + BEGIN + page := Addr/PageSize; + AddrLOW := Page*PageSize; + AddrHIGH := Page*PageSize + (PageSize-1); + END AddrHILO_PG; + + PROCEDURE ReturnSectorID( + VARIABLE result : INOUT NATURAL; + SIGNAL ADDR : NATURAL RANGE 0 TO AddrRANGE) IS + VARIABLE conv : NATURAL; + BEGIN + IF (TimingModel(16) = '0') THEN + conv := ADDR / (SecSize64+1); + IF BottomBoot = TRUE THEN + IF conv <= 1 THEN --4KB Sectors + result := ADDR/(SecSize4+1); + ELSE + result := conv + 30; + END IF; + ELSIF TopBoot = TRUE THEN + IF conv >= 510 THEN --4KB Sectors + result := 510 + (Addr-(SecSize64+1)*510)/(SecSize4+1); + ELSE + result := conv; + END IF; + END IF; + ELSE + result := ADDR/(SecSize256+1); + END IF; + END ReturnSectorID; + + BEGIN + --------------------------------------------------------------------------- + --Power Up time + --------------------------------------------------------------------------- + + PoweredUp <= '1' AFTER tdevice_PU; + + --------------------------------------------------------------------------- + --sector structure + --------------------------------------------------------------------------- + UniformSec <= TRUE WHEN (TimingModel(16) = '1') + ELSE FALSE; + + TimingModelSel: PROCESS + BEGIN + IF TimingModel(16) = '1' THEN + -- Sector Number/Sector Size + SecNumMax:= SecNum256; + SecNum := SecNum256; + SecSize := SecSize256; + -- 256B/512B Page Size + PageSize := 512; + PageNum := PageNum256; + ELSE + -- Sector Number/Sector Size + SecNumMax:= SecNum64; + SecNum := 511; + SecSize := SecSize64; + -- 256B/512B Page Size + PageSize := 256; + PageNum := PageNum64; + END IF; + --Enhanced High Performance Flag + IF (TimingModel(15) = '0' OR TimingModel(15) = '2' OR + TimingModel(15) = '3' OR TimingModel(15) = 'R' OR + TimingModel(15) = 'A' OR TimingModel(15) = 'B' OR + TimingModel(15) = 'C' OR TimingModel(15) = 'D' OR + TimingModel(15) = 'Y' OR TimingModel(15) = 'Z' OR + TimingModel(15) = 'S' OR TimingModel(15) = 'T' OR + TimingModel(15) = 'K' OR TimingModel(15) = 'L') THEN + EHP := TRUE; + IF (TimingModel(15) = 'Y' OR TimingModel(15) = 'Z' OR + TimingModel(15) = 'S' OR TimingModel(15) = 'T' OR + TimingModel(15) = 'K' OR TimingModel(15) = 'L') THEN + RdPswdProtEnable <= '1'; + END IF; + ELSIF (TimingModel(15) = '4' OR TimingModel(15) = '6' OR + TimingModel(15) = '7' OR TimingModel(15) = '8' OR + TimingModel(15) = '9' OR TimingModel(15) = 'Q') THEN + EHP := FALSE; + END IF; + + IF (TimingModel(15) ='0' OR TimingModel(15) ='2' OR + TimingModel(15) ='3' OR TimingModel(15) ='R' OR + TimingModel(15) ='A' OR TimingModel(15) ='B' OR + TimingModel(15) ='C' OR TimingModel(15) ='D' OR + TimingModel(15) ='4' OR TimingModel(15) ='6' OR + TimingModel(15) ='7' OR TimingModel(15) ='8' OR + TimingModel(15) ='9' OR TimingModel(15) ='Q') THEN + ASP_INIT <= 1; + ELSIF (TimingModel(15) ='Y' OR TimingModel(15) ='Z' OR + TimingModel(15) ='S' OR TimingModel(15) ='T' OR + TimingModel(15) ='K' OR TimingModel(15) ='L') THEN + ASP_INIT <= 0; + END IF; + WAIT; + END PROCESS; + + RSTtiming: PROCESS(RSTNeg_pullup,Instruct) + BEGIN + IF falling_edge(RSTNeg_pullup) THEN + RST <= '1', '0' AFTER 200 ns; + ELSIF Instruct = RESET THEN + Reseted <= '0', '1' AFTER 10 ns; + END IF; + END PROCESS; + + DUMMYcnt: PROCESS(dummy_cnt_act_temp) + BEGIN + dummy_cnt_act <= dummy_cnt_act_temp; + END PROCESS; + + ReadPasswordProtectionMode: PROCESS(PPB_LOCK_temp, + ASP_reg_in(2), ASP_reg_in(5)) + BEGIN + IF (PPB_LOCK = '0' AND PWDMLB = '0' AND RPME = '0' AND + RdPswdProtEnable = '1') THEN + RdPswdProtMode <= '1'; + ABE := '0'; + ELSE + RdPswdProtMode <= '0'; + END IF; + END PROCESS; + --------------------------------------------------------------------------- + -- autoboot control logic + --------------------------------------------------------------------------- + AutoBootControl: PROCESS(SCK_ipd, current_state) + BEGIN + IF (current_state = AUTOBOOT) THEN + IF rising_edge(SCK_ipd) THEN + IF (start_delay > 0) THEN + start_delay := start_delay - 1; + END IF; + END IF; + + IF (start_delay = 0) THEN + start_autoboot <= '1'; + ELSE + start_autoboot <= '0'; + END IF; + END IF; + END PROCESS; + + --------------------------------------------------------------------------- + -- VITAL Timing Checks Procedures + --------------------------------------------------------------------------- + VITALTimingCheck: PROCESS(SIIn, SOIn, SCK_ipd, CSNeg_ipd, RSTNeg_ipd, + HOLDNegIn, WPNegIn) + + -- Timing Check Variables + -- Setup/Hold Checks variables + VARIABLE Tviol_CSNeg_SCK_normal : X01 := '0'; + VARIABLE TD_CSNeg_SCK_normal : VitalTimingDataType; + + VARIABLE Tviol_CSNeg_SCK_DDR : X01 := '0'; + VARIABLE TD_CSNeg_SCK_DDR : VitalTimingDataType; + + VARIABLE Tviol_CSNeg_RSTNeg : X01 := '0'; + VARIABLE TD_CSNeg_RSTNeg : VitalTimingDataType; + + VARIABLE Tviol_SI_SCK : X01 := '0'; + VARIABLE TD_SI_SCK : VitalTimingDataType; + + VARIABLE Tviol_WPNeg_CSNeg_setup : X01 := '0'; + VARIABLE TD_WPNeg_CSNeg_setup : VitalTimingDataType; + + VARIABLE Tviol_WPNeg_CSNeg_hold : X01 := '0'; + VARIABLE TD_WPNeg_CSNeg_hold : VitalTimingDataType; + + VARIABLE Tviol_HOLDNeg_SCK : X01 := '0'; + VARIABLE TD_HOLDNeg_SCK : VitalTimingDataType; + + VARIABLE Tviol_SI_SCK_DDR_R : X01 := '0'; + VARIABLE TD_SI_SCK_DDR_R : VitalTimingDataType; + + VARIABLE Tviol_SI_SCK_DDR_F : X01 := '0'; + VARIABLE TD_SI_SCK_DDR_F : VitalTimingDataType; + + VARIABLE Tviol_RSTNeg_CSNeg : X01 := '0'; + VARIABLE TD_RSTNeg_CSNeg : VitalTimingDataType; + + --Pulse Width and Period Check Variables + VARIABLE Pviol_SCK_serial : X01 := '0'; + VARIABLE PD_SCK_serial : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_dual : X01 := '0'; + VARIABLE PD_SCK_dual : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_fast : X01 := '0'; + VARIABLE PD_SCK_fast : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_quadpg : X01 := '0'; + VARIABLE PD_SCK_quadpg : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_DDR : X01 := '0'; + VARIABLE PD_SCK_DDR : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_CSNeg_read : X01 := '0'; + VARIABLE PD_CSNeg_read : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_CSNeg_pgers : X01 := '0'; + VARIABLE PD_CSNeg_pgers : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_RSTNeg : X01 := '0'; + VARIABLE PD_RSTNeg : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_serial_rd : X01 := '0'; + VARIABLE PD_SCK_serial_rd : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_fast_rd : X01 := '0'; + VARIABLE PD_SCK_fast_rd : VitalPeriodDataType:=VitalPeriodDataInit; + + VARIABLE Pviol_SCK_dual_rd : X01 := '0'; + VARIABLE PD_SCK_dual_rd : VitalPeriodDataType:=VitalPeriodDataInit; + + VARIABLE Pviol_SCK_DDR_rd : X01 := '0'; + VARIABLE PD_SCK_DDR_rd : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_quad_pg : X01 := '0'; + VARIABLE PD_SCK_quad_pg : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Violation : X01 := '0'; + + BEGIN + --------------------------------------------------------------------------- + -- Timing Check Section + --------------------------------------------------------------------------- + IF (TimingChecksOn) THEN + + -- Setup/Hold Check between CS# and SCK + VitalSetupHoldCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_CSNeg_SCK_normal_noedge_posedge, + SetupLow => tsetup_CSNeg_SCK_normal_noedge_posedge, + HoldHigh => thold_CSNeg_SCK_normal_noedge_posedge, + HoldLow => thold_CSNeg_SCK_normal_noedge_posedge, + CheckEnabled => ddr = false, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_CSNeg_SCK_normal, + Violation => Tviol_CSNeg_SCK_normal + ); + + -- Setup/Hold Check between CS# and SCK + VitalSetupHoldCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_CSNeg_SCK_DDR_noedge_posedge, + SetupLow => tsetup_CSNeg_SCK_DDR_noedge_posedge, + HoldHigh => thold_CSNeg_SCK_DDR_noedge_posedge, + HoldLow => thold_CSNeg_SCK_DDR_noedge_posedge, + CheckEnabled => ddr, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_CSNeg_SCK_DDR, + Violation => Tviol_CSNeg_SCK_DDR + ); + + -- Hold Check between CSNeg and RSTNeg + VitalSetupHoldCheck ( + TestSignal => CSNeg, + TestSignalName => "CSNeg", + RefSignal => RSTNeg, + RefSignalName => "RSTNeg", + HoldHigh => thold_CSNeg_RSTNeg, + CheckEnabled => TRUE, + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_CSNeg_RSTNeg, + Violation => Tviol_CSNeg_RSTNeg + ); + + -- Setup/Hold Check between SI and SCK, serial mode + VitalSetupHoldCheck ( + TestSignal => SIIn, + TestSignalName => "SI", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_normal_noedge_posedge, + SetupLow => tsetup_SI_SCK_normal_noedge_posedge, + HoldHigh => thold_SI_SCK_normal_noedge_posedge, + HoldLow => thold_SI_SCK_normal_noedge_posedge, + CheckEnabled => NOT(DOUBLE) AND SIOut_z /= SIIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_SI_SCK, + Violation => Tviol_SI_SCK + ); + + -- Setup Check between WP# and CS# \ + VitalSetupHoldCheck ( + TestSignal => WPNegIn, + TestSignalName => "WP#", + RefSignal => CSNeg_ipd, + RefSignalName => "CS#", + SetupHigh => tsetup_WPNeg_CSNeg, + CheckEnabled => true, + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WPNeg_CSNeg_setup, + Violation => Tviol_WPNeg_CSNeg_setup + ); + + -- Hold Check between WP# and CS# / + VitalSetupHoldCheck ( + TestSignal => WPNegIn, + TestSignalName => "WP#", + RefSignal => CSNeg_ipd, + RefSignalName => "CS#", + HoldHigh => thold_WPNeg_CSNeg, + CheckEnabled => SRWD = '1' AND WEL = '1', + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WPNeg_CSNeg_hold, + Violation => Tviol_WPNeg_CSNeg_hold + ); + + -- Setup/Hold Check between HOLD# and SCK / + VitalSetupHoldCheck ( + TestSignal => HOLDNegIn, + TestSignalName => "HOLD#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupLow => tsetup_HOLDNeg_SCK, + SetupHigh => tsetup_HOLDNeg_SCK, + HoldLow => thold_HOLDNeg_SCK, + HoldHigh => thold_HOLDNeg_SCK, + CheckEnabled => QUAD = '0' + AND HOLDNegOut_zd /= HOLDNegIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_HOLDNeg_SCK, + Violation => Tviol_HOLDNeg_SCK + ); + + -- Setup/Hold Check between SI and SCK, DDR mode + VitalSetupHoldCheck ( + TestSignal => SIIn, + TestSignalName => "SI", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_DDR_noedge_posedge, + SetupLow => tsetup_SI_SCK_DDR_noedge_posedge, + HoldHigh => thold_SI_SCK_DDR_noedge_posedge, + HoldLow => thold_SI_SCK_DDR_noedge_posedge, + CheckEnabled => DOUBLE AND dual = false + AND SIOut_z /= SIIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_SI_SCK_DDR_R, + Violation => Tviol_SI_SCK_DDR_R + ); + + -- Setup/Hold Check between SI and SCK, DDR mode + VitalSetupHoldCheck ( + TestSignal => SIIn, + TestSignalName => "SI", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_DDR_noedge_negedge, + SetupLow => tsetup_SI_SCK_DDR_noedge_negedge, + HoldHigh => thold_SI_SCK_DDR_noedge_negedge, + HoldLow => thold_SI_SCK_DDR_noedge_negedge, + CheckEnabled => ddr AND dual = false + AND SIOut_z /= SIIn, + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_SI_SCK_DDR_F, + Violation => Tviol_SI_SCK_DDR_F + ); + + -- Setup Check between RSTNeg and SCK, DDR fast mode + VitalSetupHoldCheck ( + TestSignal => RSTNeg, + TestSignalName => "RSTNeg", + RefSignal => CSNeg, + RefSignalName => "CSNeg", + SetupHigh => tsetup_RSTNeg_CSNeg, + CheckEnabled => TRUE, + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_RSTNeg_CSNeg, + Violation => Tviol_RSTNeg_CSNeg + ); + + --Pulse Width and Period Check Variables + -- Pulse Width Check SCK for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_serial_negedge, + PulseWidthHigh => tpw_SCK_serial_posedge, + PeriodData => PD_SCK_serial, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_serial, + HeaderMsg => InstancePath & PartID, + CheckEnabled => rd); + + -- Pulse Width Check SCK for DUAL_READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_dual_negedge, + PulseWidthHigh => tpw_SCK_dual_posedge, + PeriodData => PD_SCK_dual, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_dual, + HeaderMsg => InstancePath & PartID, + CheckEnabled => dual); + + -- Pulse Width Check SCK for FAST_READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_fast_negedge, + PulseWidthHigh => tpw_SCK_fast_posedge, + PeriodData => PD_SCK_fast, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_fast, + HeaderMsg => InstancePath & PartID, + CheckEnabled => fast_rd ); + + -- Pulse Width Check SCK for QPP + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_quadpg_negedge, + PulseWidthHigh => tpw_SCK_quadpg_posedge, + PeriodData => PD_SCK_quadpg, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_quadpg, + HeaderMsg => InstancePath & PartID, + CheckEnabled => quadpg); + + -- Pulse Width Check CS# for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + PulseWidthHigh => tpw_CSNeg_read_posedge, + PeriodData => PD_CSNeg_read, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_CSNeg_read, + HeaderMsg => InstancePath & PartID, + CheckEnabled => any_read ); + + -- Pulse Width Check CS# for Program/Erase, serial mode + VitalPeriodPulseCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + PulseWidthHigh => tpw_CSNeg_pgers_posedge, + PeriodData => PD_CSNeg_pgers, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_CSNeg_pgers, + HeaderMsg => InstancePath & PartID, + CheckEnabled => NOT(any_read)); + + -- Pulse Width Check RSTNeg + VitalPeriodPulseCheck ( + TestSignal => RSTNeg_ipd, + TestSignalName => "RSTNeg", + PulseWidthLow => tpw_RSTNeg_negedge, + PulseWidthHigh => tpw_RSTNeg_posedge, + CheckEnabled => TRUE, + HeaderMsg => InstancePath & PartID, + PeriodData => PD_RSTNeg, + Violation => Pviol_RSTNeg + ); + + -- Pulse Width Check SCK for DDR READ + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_DDR_negedge, + PulseWidthHigh => tpw_SCK_DDR_posedge, + PeriodData => PD_SCK_DDR, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_DDR, + HeaderMsg => InstancePath & PartID, + CheckEnabled => ddr); + + -- Period Check SCK for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_serial_rd, + PeriodData => PD_SCK_serial_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_serial_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => rd ); + + -- Period Check SCK for FAST READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_fast_rd, + PeriodData => PD_SCK_fast_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_fast_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => fast_rd ); + + -- Period Check SCK for DUAL READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_dual_rd, + PeriodData => PD_SCK_dual_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_dual_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => dual ); + + -- Period Check SCK for QPP + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_quadpg, + PeriodData => PD_SCK_quad_pg, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_quad_pg, + HeaderMsg => InstancePath & PartID, + CheckEnabled => quadpg ); + + -- Period Check SCK for DDR READ + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_DDR_rd, + PeriodData => PD_SCK_DDR_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_DDR_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => ddr ); + + Violation := Tviol_CSNeg_SCK_normal OR + Tviol_CSNeg_SCK_DDR OR + Tviol_CSNeg_RSTNeg OR + Tviol_SI_SCK OR + Tviol_WPNeg_CSNeg_setup OR + Tviol_WPNeg_CSNeg_hold OR + Tviol_HOLDNeg_SCK OR + Tviol_SI_SCK_DDR_R OR + Tviol_SI_SCK_DDR_F OR + Tviol_RSTNeg_CSNeg OR + Pviol_SCK_serial OR + Pviol_SCK_dual OR + Pviol_SCK_fast OR + Pviol_SCK_quadpg OR + Pviol_CSNeg_read OR + Pviol_CSNeg_pgers OR + Pviol_SCK_DDR OR + Pviol_SCK_serial_rd OR + Pviol_SCK_fast_rd OR + Pviol_SCK_dual_rd OR + Pviol_SCK_quad_pg OR + Pviol_SCK_DDR_rd; + + Viol <= Violation; + + ASSERT Violation = '0' + REPORT InstancePath & partID & ": simulation may be" & + " inaccurate due to timing violations" + SEVERITY WARNING; + + END IF; + END PROCESS VITALTimingCheck; + + ---------------------------------------------------------------------------- + -- sequential process for FSM state transition + ---------------------------------------------------------------------------- + StateTransition : PROCESS(next_state, RST, PoweredUp, RST_out) + + BEGIN + IF PoweredUp = '1' THEN + IF RSTNeg_pullup = '1' and RST_out= '1' THEN + IF next_state'EVENT THEN + current_state <= next_state; + END IF; + ELSIF RSTNeg_pullup = '0' AND falling_edge(RST) THEN + --no state transition while RESET# low + current_state <= RESET_STATE; + RST_in <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END PROCESS StateTransition; + + Threset : PROCESS(RST_in) + BEGIN + IF rising_edge(RST_in) THEN + RST_out <= '0', '1' AFTER (thold_CSNeg_RSTNeg-200 ns); + END IF; + END PROCESS Threset; + + --------------------------------------------------------------------------- + -- Write cycle decode + --------------------------------------------------------------------------- + BusCycleDecode : PROCESS(SCK_ipd, CSNeg_ipd, HOLDNeg_pullup, SIIn, RST_out, + WPNeg_pullup) + + TYPE quad_data_type IS ARRAY (0 TO 1023) OF INTEGER RANGE 0 TO 15; + + VARIABLE bit_cnt : NATURAL := 0; + VARIABLE Data_in : std_logic_vector(4095 downto 0) + := (others => '0'); + + VARIABLE opcode : std_logic_vector(7 downto 0); + VARIABLE opcode_in : std_logic_vector(7 downto 0); + VARIABLE addr_bytes : std_logic_vector(31 downto 0); + VARIABLE hiaddr_bytes : std_logic_vector(31 downto 0); + VARIABLE Address_in : std_logic_vector(31 downto 0); + VARIABLE mode_bytes : std_logic_vector(7 downto 0); + VARIABLE mode_in : std_logic_vector(7 downto 0); + VARIABLE quad_data_in : quad_data_type; + VARIABLE quad_nybble : std_logic_vector(3 downto 0); + VARIABLE Quad_slv : std_logic_vector(3 downto 0); + VARIABLE Byte_slv : std_logic_vector(7 downto 0); + + VARIABLE CLK_PER : time; + VARIABLE LAST_CLK : time; + VARIABLE Check_freq : boolean := FALSE; + + BEGIN + + IF rising_edge(CSNeg_ipd) AND NOT(bus_cycle_state = DATA_BYTES) + AND NOT(bus_cycle_state = DUMMY_BYTES) THEN + bus_cycle_state := STAND_BY; + ELSE + CASE bus_cycle_state IS + WHEN STAND_BY => + IF falling_edge(CSNeg_ipd) THEN + Instruct <= NONE; + write <= '1'; + cfg_write <= '0'; + opcode_cnt:= 0; + addr_cnt := 0; + mode_cnt := 0; + dummy_cnt := 0; + dummy_cnt_act_temp <= dummy_cnt; + data_cnt := 0; + DOUBLE := FALSE; + CLK_PER := 0 ns; + LAST_CLK := 0 ns; + IF current_state = AUTOBOOT THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := OPCODE_BYTE; + END IF; + END IF; + + WHEN OPCODE_BYTE => + IF rising_edge(SCK_ipd) THEN + + Latency_code := to_nat(LC1 & LC0); + CLK_PER := NOW - LAST_CLK; + LAST_CLK := NOW; + IF Check_freq THEN + IF (CLK_PER < 20 ns AND Latency_code = 3) OR + (CLK_PER < 12.5 ns AND Latency_code = 0) OR + (CLK_PER < 11.1 ns AND Latency_code = 1) OR + (CLK_PER < 9.6 ns AND Latency_code = 2) THEN + ASSERT FALSE + REPORT "More wait states are required for " & + "this clock frequency value" + SEVERITY warning; + END IF; + END IF; + Check_freq := FALSE; + + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1') THEN + --One-byte of instruction opcode is shifted into the + --device on the SI serial input pin with the most + --significant bit (MSB) first.Each bit input on the + --SI serial input pin is latched on the rising edge of + --the SCK serial clock signal. + opcode_in(opcode_cnt) := SIIn; + opcode_cnt := opcode_cnt + 1; + IF opcode_cnt = BYTE THEN + --MSB first + FOR I IN 7 DOWNTO 0 LOOP + opcode(i) := opcode_in(7-i); + END LOOP; + + CASE opcode IS + WHEN "00000110" => --06h + Instruct <= WREN; + bus_cycle_state := DATA_BYTES; + WHEN "00000100" => --04h + Instruct <= WRDI; + bus_cycle_state := DATA_BYTES; + WHEN "00000001" => --01h + Instruct <= WRR; + bus_cycle_state := DATA_BYTES; + WHEN "00000011" => --03h + Instruct <= READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00010011" => --13h + Instruct <= RD4; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01001011" => --4Bh + Instruct <= OTPR; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00000101" => --05h + Instruct <= RDSR; + bus_cycle_state := DATA_BYTES; + WHEN "00000111" => --07h + Instruct <= RDSR2; + bus_cycle_state := DATA_BYTES; + WHEN "00110101" => --35h + Instruct <= RDCR; + bus_cycle_state := DATA_BYTES; + WHEN "10010000" => --90h + Instruct <= REMS; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10011111" => --9Fh + Instruct <= RDID; + bus_cycle_state := DATA_BYTES; + WHEN "10101011" => --ABh + Instruct <= RES; + bus_cycle_state := DUMMY_BYTES; + WHEN "00001011" => --0Bh + Instruct <= FSTRD; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00001100" => --0Ch + Instruct <= FSTRD4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00001101" => --0Dh + Instruct <= DDRFR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00001110" => --0Eh + Instruct <= DDRFR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00111011" => --3Bh + Instruct <= DOR; + Check_freq := TRUE; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00111100" => --3Ch + Instruct <= DOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "10111011" => --BBh + Instruct <= DIOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "10111100" => --BCh + Instruct <= DIOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "10111101" => --BDh + Instruct <= DDRDIOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "10111110" => --BEh + Instruct <= DDRDIOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "01101011" => --6Bh + Instruct <= QOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "01101100" => --6Ch + Instruct <= QOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "11101011" => --EBh + Instruct <= QIOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "11101100" => --ECh + Instruct <= QIOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "11101101" => --EDh + Instruct <= DDRQIOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "11101110" => --EEh + Instruct <= DDRQIOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00000010" => --02h + Instruct <= PP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00010010" => --12h + Instruct <= PP4; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00110010" => --32h + Instruct <= QPP; + bus_cycle_state := ADDRESS_BYTES; + quadpg <= TRUE; + WHEN "00111000" => --38h + Instruct <= QPP; + bus_cycle_state := ADDRESS_BYTES; + quadpg <= TRUE; + WHEN "00110100" => --34h + Instruct <= QPP4; + bus_cycle_state := ADDRESS_BYTES; + quadpg <= TRUE; + WHEN "01000010" => --42h + Instruct <= OTPP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10000101" => --85h + Instruct <= PGSP; + bus_cycle_state := DATA_BYTES; + WHEN "10001010" => --8Ah + Instruct <= PGRS; + bus_cycle_state := DATA_BYTES; + WHEN "11000111" => --C7h + Instruct <= BE; + bus_cycle_state := DATA_BYTES; + WHEN "01100000" => --60h + Instruct <= BE; + bus_cycle_state := DATA_BYTES; + WHEN "11011000" => --D8h + Instruct <= SE; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11011100" => --DCh + Instruct <= SE4; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00100000" => --20h + Instruct <= P4E; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00100001" => --21h + Instruct <= P4E4; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01110101" => --75h + Instruct <= ERSP; + bus_cycle_state := DATA_BYTES; + WHEN "01111010" => --7Ah + Instruct <= ERRS; + bus_cycle_state := DATA_BYTES; + WHEN "00010100" => --14h + Instruct <= ABRD; + bus_cycle_state := DATA_BYTES; + WHEN "00010101" => --15h + Instruct <= ABWR; + bus_cycle_state := DATA_BYTES; + WHEN "00010110" => --16h + Instruct <= BRRD; + bus_cycle_state := DATA_BYTES; + WHEN "00010111" => --17h + Instruct <= BRWR; + bus_cycle_state := DATA_BYTES; + WHEN "10111001" => --B9h + Instruct <= BRAC; + bus_cycle_state := DATA_BYTES; + WHEN "00101011" => --2Bh + Instruct <= ASPRD; + bus_cycle_state := DATA_BYTES; + WHEN "00101111" => --2Fh + Instruct <= ASPP; + bus_cycle_state := DATA_BYTES; + WHEN "11100000" => --E0h + Instruct <= DYBRD; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11100001" => --E1h + Instruct <= DYBWR; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11100010" => --E2h + Instruct <= PPBRD; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11100011" => --E3h + Instruct <= PPBP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11100100" => --E4h + Instruct <= PPBERS; + bus_cycle_state := DATA_BYTES; + WHEN "10100110" => --A6h + Instruct <= PLBWR; + bus_cycle_state := DATA_BYTES; + WHEN "10100111" => --A7h + Instruct <= PLBRD; + bus_cycle_state := DATA_BYTES; + WHEN "11100111" => --E7h + Instruct <= PASSRD; + bus_cycle_state := DATA_BYTES; + WHEN "11101000" => --E8h + Instruct <= PASSP; + bus_cycle_state := DATA_BYTES; + WHEN "11101001" => --E9h + Instruct <= PASSU; + bus_cycle_state := DATA_BYTES; + WHEN "11110000" => --F0h + Instruct <= RESET; + bus_cycle_state := DATA_BYTES; + WHEN "11111111" => --FFh + Instruct <= MBR; + bus_cycle_state := MODE_BYTE; + WHEN "01000001" => -- 41h + Instruct <= DLPRD; + bus_cycle_state := DATA_BYTES; + WHEN "01000011" => -- 43h + Instruct <= PNVDLR; + bus_cycle_state := DATA_BYTES; + WHEN "01001010" => -- 4Ah + Instruct <= WVDLR; + bus_cycle_state := DATA_BYTES; + WHEN "00110000" => --30h + Instruct <= CLSR; + bus_cycle_state := DATA_BYTES; + WHEN others => + null; + + END CASE; + END IF; + END IF; + END IF; + + WHEN ADDRESS_BYTES => + IF Instruct= DDRFR OR Instruct= DDRFR4 OR Instruct= DDRDIOR + OR Instruct = DDRDIOR4 OR Instruct = DDRQIOR OR + Instruct = DDRQIOR4 THEN + DOUBLE := TRUE; + ELSE + DOUBLE := FALSE; + END IF; + + IF (rising_edge(SCK_ipd) AND NOT(DOUBLE) AND + (CSNeg_ipd= '0')) THEN + IF (((Instruct=FSTRD AND EXTADD= '0' ) + OR (Instruct=DOR AND EXTADD= '0') + OR Instruct=OTPR) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) + OR (Instruct=QOR AND QUAD= '1' AND EXTADD='0') THEN + --Instruction + 3 Bytes Address + Dummy Byte + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 3*BYTE THEN + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 25) := "0000000"; + addr_bytes(24) := Bank_Addr_reg(0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF (Instruct=FSTRD OR Instruct=DOR OR + Instruct=QOR) THEN + IF (Latency_code = 3) THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF ((((Instruct=FSTRD4) OR (Instruct=DOR4) OR + ((Instruct=FSTRD) AND EXTADD= '1') OR + ((Instruct=DOR) AND EXTADD= '1')) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) OR + ((Instruct=QOR4) AND QUAD='1') OR + ((Instruct=QOR) AND QUAD='1' AND EXTADD='1')) THEN + --Instruction + 4 Bytes Address + Dummy Byte + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 4*BYTE THEN + FOR I IN 31 DOWNTO 0 LOOP + hiaddr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(hiaddr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF Latency_code = 3 THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := DUMMY_BYTES; + IF (DOUBLE AND NOT(hold_mode) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + ELSIF Instruct = DIOR AND EXTADD= '0' AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1') THEN + -- DUAL I/O High Performance Read (3Bytes Address) + IF SOIn /= 'Z' THEN + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt+1) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = (3*BYTE) / 2 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 25) := "0000000"; + addr_bytes(24) := Bank_Addr_reg(0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSE + bus_cycle_state := STAND_BY; + END IF; + ELSIF ((Instruct = DIOR4 OR + (Instruct = DIOR AND EXTADD= '1')) AND + ((HOLDNeg_pullup = '1' AND QUAD = '0') OR + QUAD = '1')) THEN + -- DUAL I/O High Performance Read (4Bytes Address) + IF SOIn /= 'Z' THEN + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt+1) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = (4*BYTE) / 2 THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + hiaddr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(hiaddr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSE + bus_cycle_state := STAND_BY; + END IF; + ELSIF (Instruct = QIOR AND EXTADD= '0') THEN + -- QUAD I/O High Performance Read (3Bytes Address) + IF QUAD = '1' THEN + IF SOIn /= 'Z' THEN + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = (3*BYTE) / 4 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 25) := "0000000"; + addr_bytes(24) := Bank_Addr_reg(0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + END IF; + ELSE + bus_cycle_state := STAND_BY; + END IF; + ELSIF (Instruct = QIOR4 OR + (Instruct = QIOR AND EXTADD= '1')) THEN + -- QUAD I/O High Performance Read (4Bytes Address) + IF QUAD = '1' THEN + IF SOIn /= 'Z' THEN + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = (4*BYTE) / 4 THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + hiaddr_bytes(31-i) + := Address_in(i); + END LOOP; + Address <= to_nat(hiaddr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + END IF; + ELSE + bus_cycle_state := STAND_BY; + END IF; + ELSIF (((Instruct = RD4 OR Instruct = PP4 OR + Instruct = SE4 OR Instruct = PPBRD OR + Instruct = DYBRD OR Instruct = DYBWR OR + Instruct = PPBP OR Instruct = P4E4 OR + (Instruct = READ AND EXTADD= '1' ) OR + (Instruct = PP AND EXTADD= '1' ) OR + (Instruct = P4E AND EXTADD= '1' ) OR + (Instruct = SE AND EXTADD= '1' )) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) + OR (QUAD ='1' AND (Instruct=QPP4 OR + (Instruct = QPP AND EXTADD= '1' ))))THEN + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 4*BYTE THEN + FOR I IN 31 DOWNTO 0 LOOP + hiaddr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(hiaddr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (((HOLDNeg_pullup='1' AND QUAD='0') + OR QUAD='1') AND EXTADD= '0') THEN + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 3*BYTE THEN + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 25) := "0000000"; + addr_bytes(24) := Bank_Addr_reg(0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF (SCK_ipd'EVENT AND DOUBLE AND addr_cnt /= 0 ) OR + (rising_edge(SCK_ipd) AND DOUBLE AND addr_cnt = 0 ) THEN + IF (Instruct=DDRFR AND EXTADD= '0' ) THEN + --Fast DDR Read Mode + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = 3*BYTE THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 25) := "0000000"; + addr_bytes(24) := Bank_Addr_reg(0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF (Instruct=DDRFR4 OR + (Instruct=DDRFR AND EXTADD= '1' )) THEN + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = 4*BYTE THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + addr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + ELSIF (Instruct= DDRDIOR AND EXTADD= '0' ) THEN + --Dual I/O DDR Read Mode + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt+1):= SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = (3*BYTE)/2 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 25) := "0000000"; + addr_bytes(24) := Bank_Addr_reg(0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF (Instruct=DDRDIOR4 OR + (Instruct=DDRDIOR AND EXTADD= '1' )) THEN + --Dual I/O DDR Read Mode + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt+1) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = (4*BYTE)/2 THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + addr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + ELSIF (Instruct=DDRQIOR AND EXTADD= '0' ) AND + QUAD = '1' THEN + --Quad I/O DDR Read Mode + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = (3*BYTE)/4 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 25) := "0000000"; + addr_bytes(24) := Bank_Addr_reg(0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 5 ns; + bus_cycle_state := MODE_BYTE; + END IF; + ELSIF QUAD = '1' AND (Instruct=DDRQIOR4 OR + (Instruct=DDRQIOR AND EXTADD= '1' )) THEN + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = (4*BYTE)/4 THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + addr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + END IF; + END IF; + + WHEN MODE_BYTE => + IF rising_edge(SCK_ipd) THEN + IF ((Instruct=DIOR OR Instruct = DIOR4) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) THEN + mode_in(2*mode_cnt) := SOIn; + mode_in(2*mode_cnt+1) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/2 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + IF Latency_code = 0 OR Latency_code = 3 THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF (Instruct=QIOR OR Instruct = QIOR4) + AND QUAD = '1' THEN + mode_in(4*mode_cnt) := HOLDNegIn; + mode_in(4*mode_cnt+1) := WPNegIn; + mode_in(4*mode_cnt+2) := SOIn; + mode_in(4*mode_cnt+3) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/4 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DUMMY_BYTES; + END IF; + ELSIF Instruct=DDRFR OR Instruct = DDRFR4 THEN + mode_in(2*mode_cnt) := SIIn; + ELSIF Instruct=DDRDIOR OR Instruct = DDRDIOR4 THEN + mode_in(4*mode_cnt) := SOIn; + mode_in(4*mode_cnt+1) := SIIn; + ELSIF (Instruct=DDRQIOR OR Instruct = DDRQIOR4) + AND QUAD = '1' THEN + mode_in(0) := HOLDNegIn; + mode_in(1) := WPNegIn; + mode_in(2) := SOIn; + mode_in(3) := SIIn; + END IF; + dummy_cnt := 0; + dummy_cnt_act_temp <= dummy_cnt; + ELSIF falling_edge(SCK_ipd) THEN + IF Instruct=DDRFR OR Instruct = DDRFR4 THEN + mode_in(2*mode_cnt+1) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/2 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + ELSIF Instruct=DDRDIOR OR Instruct = DDRDIOR4 THEN + mode_in(4*mode_cnt+2) := SOIn; + mode_in(4*mode_cnt+3) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/4 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + ELSIF (Instruct=DDRQIOR OR Instruct = DDRQIOR4) + AND QUAD = '1' THEN + mode_in(4) := HOLDNegIn; + mode_in(5) := WPNegIn; + mode_in(6) := SOIn; + mode_in(7) := SIIn; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + + WHEN DUMMY_BYTES => + IF rising_edge(SCK_ipd) THEN + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + IF (((Instruct=FSTRD OR Instruct=FSTRD4 OR + Instruct=DOR OR Instruct=DOR4 OR + Instruct=OTPR) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) OR + ((Instruct = QOR OR Instruct = QOR4) AND + QUAD = '1'))THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF dummy_cnt = BYTE THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct=DDRFR OR Instruct=DDRFR4) THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF EHP THEN + IF ((Latency_code = 3 AND dummy_cnt=1) OR + (Latency_code = 0 AND dummy_cnt=2) OR + (Latency_code = 1 AND dummy_cnt=4) OR + (Latency_code = 2 AND dummy_cnt=5)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + ELSE + IF ((Latency_code = 3 AND dummy_cnt = 4) OR + (Latency_code = 0 AND dummy_cnt = 5) OR + (Latency_code = 1 AND dummy_cnt = 6) OR + (Latency_code = 2 AND dummy_cnt = 7)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF Instruct=RES THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF dummy_cnt = 3*BYTE THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct = DIOR OR Instruct = DIOR4) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1') THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF EHP THEN + IF ((Latency_code = 1 AND dummy_cnt = 1) OR + (Latency_code = 2 AND dummy_cnt = 2)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + ELSE + IF ((Latency_code = 3 AND dummy_cnt = 4) OR + (Latency_code = 0 AND dummy_cnt = 4) OR + (Latency_code = 1 AND dummy_cnt = 5) OR + (Latency_code = 2 AND dummy_cnt = 6)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF EHP THEN + IF ((Latency_code = 3 AND dummy_cnt = 2) OR + (Latency_code = 0 AND dummy_cnt = 4) OR + (Latency_code = 1 AND dummy_cnt = 5) OR + (Latency_code = 2 AND dummy_cnt = 6)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + ELSE + IF ((Latency_code = 3 AND dummy_cnt = 4) OR + (Latency_code = 0 AND dummy_cnt = 6) OR + (Latency_code = 1 AND dummy_cnt = 7) OR + (Latency_code = 2 AND dummy_cnt = 8)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF ((Instruct = QIOR OR Instruct = QIOR4) AND + QUAD = '1') THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF ((Latency_code = 3 AND dummy_cnt = 1) OR + (Latency_code = 0 AND dummy_cnt = 4) OR + (Latency_code = 1 AND dummy_cnt = 4) OR + (Latency_code = 2 AND dummy_cnt = 5)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct = DDRQIOR OR Instruct = DDRQIOR4) + AND QUAD = '1' THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF ((Latency_code = 3 AND dummy_cnt = 3) OR + (Latency_code = 0 AND dummy_cnt = 6) OR + (Latency_code = 1 AND dummy_cnt = 7) OR + (Latency_code = 2 AND dummy_cnt = 8)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF falling_edge(SCK_ipd) THEN + IF NOT(hold_mode) THEN + IF (DOUBLE AND VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + + WHEN DATA_BYTES => + IF rising_edge(CSNeg_ipd) THEN + IF ((mode_bytes(7 downto 4) = "1010" AND + (Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QIOR OR Instruct = QIOR4)) OR + ((mode_bytes(7 downto 4) = + NOT(mode_bytes(3 downto 0))) AND + (Instruct = DDRFR OR Instruct = DDRFR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 OR + Instruct = DDRQIOR OR Instruct = DDRQIOR4))) THEN + bus_cycle_state := ADDRESS_BYTES; + ELSE + bus_cycle_state := STAND_BY; + END IF; + END IF; + IF falling_edge(SCK_ipd) AND CSNeg_ipd = '0' AND + NOT(DOUBLE) THEN + IF ((Instruct = READ OR Instruct=RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = RDSR OR Instruct = RDSR2 OR + Instruct = RDCR OR Instruct = OTPR OR + Instruct = DOR OR Instruct = DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = ABRD OR Instruct = BRRD OR + Instruct = ASPRD OR Instruct = DYBRD OR + Instruct = PPBRD OR + Instruct = PASSRD OR Instruct = RDID OR + Instruct = RES OR Instruct = REMS OR + Instruct = PLBRD OR Instruct = DLPRD) + AND ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) + OR (current_state = AUTOBOOT AND start_delay = 0)OR + ((Instruct=QOR OR Instruct=QIOR OR Instruct=QOR4 + OR Instruct= QIOR4) AND QUAD = '1') THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + ELSIF SCK_ipd'EVENT AND CSNeg_ipd = '0' AND DOUBLE THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + + IF rising_edge(SCK_ipd) THEN + IF QUAD = '1' AND (Instruct=QPP OR Instruct = QPP4)THEN + quad_nybble := HOLDNegIn & WPNegIn & SOIn & SIIn; + IF data_cnt > (PageSize*2-1) THEN + --In case of quad mode and QPP, + --if more than 512 bytes are sent to the device + FOR I IN 0 TO (PageSize*2-2) LOOP + quad_data_in(i) := quad_data_in(i+1); + END LOOP; + quad_data_in((PageSize*2-1)) := + to_nat(quad_nybble); + data_cnt := data_cnt +1; + ELSE + IF quad_nybble /= "ZZZZ" THEN + quad_data_in(data_cnt) := + to_nat(quad_nybble); + END IF; + data_cnt := data_cnt +1; + END IF; + ELSIF ((HOLDNeg_pullup='1' AND QUAD='0') + OR QUAD='1') THEN + IF data_cnt > (PageSize*8-1) THEN + --In case of serial mode and PP, + -- if more than 512 bytes are sent to the device + -- previously latched data are discarded and last + -- 512 data bytes are guaranteed to be programmed + -- correctly within the same page. + IF bit_cnt = 0 THEN + FOR I IN 0 TO ((PageSize-1)*BYTE - 1) LOOP + Data_in(i) := Data_in(i+8); + END LOOP; + END IF; + Data_in((PageSize-1)*BYTE + bit_cnt) := SIIn; + bit_cnt := bit_cnt + 1; + IF bit_cnt = 8 THEN + bit_cnt := 0; + END IF; + data_cnt := data_cnt + 1; + ELSE + Data_in(data_cnt) := SIIn; + data_cnt := data_cnt + 1; + bit_cnt := 0; + END IF; + END IF; + END IF; + + IF rising_edge(CSNeg_ipd) THEN + CASE Instruct IS + WHEN WREN | WRDI | BE | SE | SE4 | CLSR | RESET | + PPBP | PPBERS | PGSP | PGRS | ERSP | BRAC | + ERRS | P4E | P4E4 | PLBWR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') + OR QUAD='1') THEN + IF data_cnt = 0 THEN + write <= '0'; + END IF; + END IF; + + WHEN WRR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') + OR QUAD='1') THEN + IF ((data_cnt mod 8) = 0 AND data_cnt > 0) THEN + IF data_cnt = 8 THEN + --If CS# is driven high after eight + --cycle,only the Status Register is + --written to. + write <= '0'; + IF BAR_ACC = '0' THEN + FOR i IN 0 TO 7 LOOP + Status_reg1_in(i) <= + Data_in(7-i); + END LOOP; + ELSIF P_ERR = '0' AND E_ERR = '0' THEN + FOR i IN 0 TO 7 LOOP + Bank_Addr_reg_in(i) <= + Data_in(7-i); + END LOOP; + END IF; + ELSIF data_cnt = 16 THEN + --After the 16th cycle both the + --Status and Configuration Registers + --are written to. + write <= '0'; + IF BAR_ACC = '0' THEN + FOR i IN 0 TO 7 LOOP + cfg_write <= '1'; + FOR i IN 0 TO 7 LOOP + Status_reg1_in(i) <= + Data_in(7-i); + Config_reg1_in(i) <= + Data_in(15-i); + END LOOP; + END LOOP; + ELSIF P_ERR = '0' AND E_ERR = '0' THEN + FOR i IN 0 TO 7 LOOP + Bank_Addr_reg_in(i) <= + Data_in(7-i); + END LOOP; + END IF; + END IF; + END IF; + END IF; + + WHEN PP | PP4 | OTPP => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt > 0 THEN + IF (data_cnt mod 8) = 0 THEN + write <= '0'; + FOR I IN 0 TO (PageSize-1) LOOP + FOR J IN 7 DOWNTO 0 LOOP + IF Data_in((i*8) + (7-j)) + /= 'X' THEN + Byte_slv(j) := + Data_in((i*8) + (7-j)); + END IF; + END LOOP; + WByte(i) <= + to_nat(Byte_slv); + END LOOP; + IF data_cnt > PageSize*BYTE THEN + Byte_number <= PageSize-1; + ELSE + Byte_number <= data_cnt/8-1; + END IF; + END IF; + END IF; + END IF; + + WHEN QPP | QPP4=> + IF data_cnt > 0 THEN + IF data_cnt mod 2 = 0 THEN + quadpg <= FALSE; + write <= '0'; + FOR I IN 0 TO (PageSize-1) LOOP + FOR J IN 1 DOWNTO 0 LOOP + Quad_slv := + to_slv(quad_data_in((i*2) + + (1-j)),4); + + Byte_slv(4*j+3 DOWNTO 4*j) := + Quad_slv; + END LOOP; + WByte(i) <= to_nat(Byte_slv); + END LOOP; + IF data_cnt > PageSize*2 THEN + Byte_number <= PageSize-1; + ELSE + Byte_number <= data_cnt/2-1; + END IF; + END IF; + END IF; + + WHEN ABWR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 32 THEN + write <= '0'; + FOR J IN 0 TO 31 LOOP + AutoBoot_reg_in(J) <= + Data_in(31-J); + END LOOP; + END IF; + END IF; + + WHEN BRWR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 8 THEN + write <= '0'; + FOR J IN 0 TO 7 LOOP + Bank_Addr_reg_in(J) <= + Data_in(7-J); + END LOOP; + END IF; + END IF; + + WHEN ASPP => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 16 THEN + write <= '0'; + FOR J IN 0 TO 15 LOOP + ASP_reg_in(J) <= + Data_in(15-J); + END LOOP; + END IF; + END IF; + + WHEN DYBWR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 8 THEN + write <= '0'; + FOR J IN 0 TO 7 LOOP + DYBAR_in(J) <= + Data_in(7-J); + END LOOP; + END IF; + END IF; + + WHEN PNVDLR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 8 THEN + write <= '0'; + FOR J IN 0 TO 7 LOOP + NVDLR_reg_in(J) <= Data_in(7-J); + END LOOP; + END IF; + END IF; + + WHEN WVDLR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 8 THEN + write <= '0'; + FOR J IN 0 TO 7 LOOP + VDLR_reg_in(J) <= Data_in(7-J); + END LOOP; + END IF; + END IF; + + WHEN PASSP => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 64 THEN + write <= '0'; + FOR J IN 1 TO 8 LOOP + FOR K IN 1 TO 8 LOOP + Password_reg_in(J*8-K) <= + Data_in(8*(J-1)+K-1); + END LOOP; + END LOOP; + END IF; + END IF; + + WHEN PASSU => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 64 THEN + write <= '0'; + FOR J IN 1 TO 8 LOOP + FOR K IN 1 TO 8 LOOP + PASS_TEMP(J*8-K) <= + Data_in(8*(J-1)+K-1); + END LOOP; + END LOOP; + END IF; + END IF; + + WHEN others => + null; + + END CASE; + END IF; + END CASE; + END IF; + + END PROCESS BusCycleDecode; + + --------------------------------------------------------------------------- + -- Timing control for the Page Program + --------------------------------------------------------------------------- + ProgTime : PROCESS(PSTART, PGSUSP, PGRES, RST, Reseted) + VARIABLE pob : time; + VARIABLE elapsed : time; + VARIABLE start : time; + VARIABLE duration : time; + BEGIN + IF rising_edge(PSTART) AND PDONE = '1' THEN + IF Instruct = PP OR Instruct = PP4 OR Instruct = OTPP OR + Instruct = QPP OR Instruct = QPP4 THEN + IF PageSize = 256 THEN + pob := tdevice_PP256; + ELSE + pob := tdevice_PP512; + END IF; + ELSE + pob := tdevice_BP; + END IF; + elapsed := 0 ns; + start := NOW; + PDONE <= '0', '1' AFTER pob; + ELSIF PGSUSP'EVENT AND PGSUSP = '1' AND PDONE /= '1' THEN + elapsed := NOW - start; + duration := pob - elapsed; + PDONE <= '0'; + ELSIF PGRES'EVENT AND PGRES = '1' AND PDONE /= '1'THEN + start := NOW; + PDONE <= '0', '1' AFTER duration; + END IF; + + IF (RST'EVENT AND RST = '0') THEN + PDONE <= '1'; -- reset done, programing terminated + ELSIF rising_edge(Reseted) THEN + PDONE <= '1'; -- reset done, programing terminated + END IF; + + END PROCESS ProgTime; + + --------------------------------------------------------------------------- + -- Timing control for the Write Status Register + --------------------------------------------------------------------------- + WriteTime : PROCESS(WSTART) + VARIABLE wob : time; + BEGIN + IF LongTimming THEN + wob := tdevice_WRR; + ELSE + wob := tdevice_WRR / 100; + END IF; + IF rising_edge(WSTART) AND WDONE = '1' THEN + WDONE <= '0', '1' AFTER wob; + END IF; + + IF (RST'EVENT AND RST = '0') THEN + WDONE <= '1'; -- reset done, programing terminated + ELSIF rising_edge(Reseted) THEN + WDONE <= '1'; -- reset done, programing terminated + END IF; + + END PROCESS WriteTime; + + --------------------------------------------------------------------------- + -- Timing control for the Bulk Erase + --------------------------------------------------------------------------- + ErsTime : PROCESS(ESTART, ESUSP, ERES, RST, Reseted) + VARIABLE seo : time; + VARIABLE beo : time; + VARIABLE elapsed : time; + VARIABLE start : time; + VARIABLE duration : time; + BEGIN + IF LongTimming THEN + IF UniformSec THEN + seo := tdevice_SE256; + ELSE + seo := tdevice_SE64; + END IF; + beo := tdevice_BE; + ELSE + IF UniformSec THEN + seo := tdevice_SE256 / 1000; + ELSE + seo := tdevice_SE64 / 1000; + END IF; + beo := tdevice_BE / 1000; + END IF; + IF rising_edge(ESTART) AND EDONE = '1' THEN + IF Instruct = BE THEN + duration := beo; + ELSE --Instruct = SE OR SE4 OR P4E OR P4E4 + duration := seo; + END IF; + elapsed := 0 ns; + EDONE <= '0', '1' AFTER duration; + start := NOW; + ELSIF ESUSP'EVENT AND ESUSP = '1' AND EDONE /= '1' THEN + elapsed := NOW - start; + duration := duration - elapsed; + EDONE <= '0'; + ELSIF ERES'EVENT AND ERES = '1' AND EDONE /= '1' THEN + start := NOW; + EDONE <= '0', '1' AFTER duration; + END IF; + + IF (RST'EVENT AND RST = '0') THEN + EDONE <= '1'; -- reset done, eras terminated + ELSIF rising_edge(Reseted) THEN + EDONE <= '1'; -- reset done, erase terminated + END IF; + + END PROCESS ErsTime; + + CheckCEOnPowerUP :PROCESS(CSNeg_ipd) + BEGIN + IF (PoweredUp = '0' AND falling_edge(CSNeg_ipd)) THEN + REPORT InstancePath & partID & + ": Device is selected during Power Up" + SEVERITY WARNING; + END IF; + END PROCESS; + + --------------------------------------------------------------------------- + -- Main Behavior Process + -- combinational process for next state generation + --------------------------------------------------------------------------- + StateGen :PROCESS(PoweredUp, write, CSNeg_ipd, RSTNeg_pullup, WDONE, PDONE, + ERSSUSP_out, PRGSUSP_out, EDONE, RST_out, PPBERASE_in, + PASSULCK_in) + + VARIABLE sect : NATURAL RANGE 0 TO SecNum64; + + BEGIN + + IF rising_edge(PoweredUp) THEN + IF ABE = '1' AND RPME /= '0' THEN + --Autoboot is enabled and The Read Password feature is not enabled + next_state <= AUTOBOOT; + read_cnt := 0; + byte_cnt := 1; + read_addr := to_nat(AutoBoot_reg(31 DOWNTO 9)&"000000000"); + start_delay := to_nat(AutoBoot_reg(8 DOWNTO 1)); + ABSD := to_nat(AutoBoot_reg(8 DOWNTO 1)); + ELSE + next_state <= IDLE; + END IF; + ELSE + IF RST_out= '0' then + next_state <= current_state; + ELSIF falling_edge(write) AND Instruct = RESET THEN + IF ABE = '1' AND RPME /= '0' THEN + read_cnt := 0; + byte_cnt := 1; + read_addr := to_nat(AutoBoot_reg(31 DOWNTO 9)& + "000000000"); + start_delay:= to_nat(AutoBoot_reg(8 DOWNTO 1)); + ABSD := to_nat(AutoBoot_reg(8 DOWNTO 1)); + next_state <= AUTOBOOT; + ELSE + next_state <= IDLE; + END IF; + ELSE + CASE current_state IS + WHEN RESET_STATE => + IF rising_edge(RST_out) THEN + IF ABE = '1' AND RPME /= '0' + AND RdPswdProtMode = '0' THEN + next_state <= AUTOBOOT; + read_cnt := 0; + byte_cnt := 1; + read_addr := to_nat(AutoBoot_reg(31 DOWNTO 9)& + "000000000"); + start_delay := to_nat(AutoBoot_reg(8 DOWNTO 1)); + ABSD := to_nat(AutoBoot_reg(8 DOWNTO 1)); + ELSE + next_state <= IDLE; + END IF; + END IF; + + WHEN IDLE => + IF falling_edge(write) AND RdPswdProtMode = '0' THEN + IF (Instruct = WRR AND WEL = '1' AND BAR_ACC = '0') THEN + IF ((not(SRWD = '1' AND WPNeg_pullup = '0') AND + QUAD = '0') OR QUAD = '1') THEN + -- can not execute if HPM is entered + -- or if WEL bit is zero + IF ((TBPROT='1' AND Config_reg1_in(5)='0') OR + (TBPARM='1' AND Config_reg1_in(2)='0') OR + (BPNV ='1' AND Config_reg1_in(3)='0')) AND + cfg_write = '1' THEN + ASSERT cfg_write = '0' + REPORT "Changing value of Configuration " & + "Register OTP bit from 1 to 0 is " & + "not allowed!!!" + SEVERITY WARNING; + ELSE + next_state <= WRITE_SR; + END IF; + END IF; + ELSIF (Instruct = PP OR Instruct = QPP OR + Instruct = PP4 OR Instruct = QPP4) AND + WEL = '1' THEN + ReturnSectorID(sect,Address); + pgm_page := Address/(PageSize+1); + IF (Sec_Prot(sect) = '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + next_state <= PAGE_PG; + END IF; + ELSIF Instruct=OTPP AND WEL = '1' AND FREEZE = '0' THEN + IF ((((Address >= 16#10# AND Address <= 16#13#) OR + (Address >= 16#20# AND Address <= 16#FF#)) + AND LOCK_BYTE1(Address/32) = '1') OR + ((Address >= 16#100# AND Address <= 16#1FF#) + AND LOCK_BYTE2((Address-16#100#)/32) = '1') OR + ((Address >= 16#200# AND Address <= 16#2FF#) + AND LOCK_BYTE3((Address-16#200#)/32) = '1') OR + ((Address >= 16#300# AND Address <= 16#3FF#) + AND LOCK_BYTE4((Address-16#300#)/32) = '1')) AND + (Address + Byte_number <= OTPHiAddr) THEN + next_state <= OTP_PG; + END IF; + ELSIF (Instruct= SE OR Instruct= SE4) AND WEL = '1' THEN + ReturnSectorID(sect,Address); + IF UniformSec = TRUE OR + (TopBoot = TRUE AND sect < 510) OR + (BottomBoot = TRUE AND sect > 31) THEN + IF (Sec_Prot(sect) = '0' AND PPB_bits(sect)='1' + AND DYB_bits(sect)='1') THEN + next_state <= SECTOR_ERS; + END IF; + ELSIF (TopBoot = TRUE AND sect >= 510) OR + (BottomBoot = TRUE AND sect <= 31) THEN + IF Sec_ProtSE = 32 AND ASP_ProtSE = 32 THEN + --Sector erase command is applied to a 64 KB + --range that includes 4 KB sectors. + next_state <= SECTOR_ERS; + END IF; + END IF; + ELSIF (Instruct=P4E OR Instruct=P4E4) AND WEL='1' THEN + ReturnSectorID(sect,Address); + IF UniformSec = TRUE OR + (TopBoot = TRUE AND sect < 510) OR + (BottomBoot = TRUE AND sect > 31) THEN + --A P4E instruction applied to a sector that + --is larger than 4 KB will not be executed + --and will not set the E_ERR status. + REPORT "The instruction is applied to a "& + "sector that is larger than 4 KB. "& + "Instruction is ignored!!!" + SEVERITY warning; + ELSE + IF Sec_Prot(sect) = '0' AND PPB_bits(sect)='1' + AND DYB_bits(sect)='1' THEN + next_state <= SECTOR_ERS; + END IF; + END IF; + ELSIF Instruct = BE AND WEL = '1' AND + (BP0='0' AND BP1='0' AND BP2='0') THEN + next_state <= BULK_ERS; + ELSIF Instruct = ABWR AND WEL = '1' THEN + --Autoboot Register Write Command + next_state <= AUTOBOOT_PG; + ELSIF Instruct = ASPP AND WEL = '1' THEN + --ASP Register Program Command + IF not(ASPOTPFLAG) THEN + next_state <= ASP_PG; + END IF; + ELSIF Instruct = PLBWR AND WEL = '1' AND + RdPswdProtEnable = '0' THEN + next_state <= PLB_PG; + ELSIF Instruct = PASSP AND WEL = '1' THEN + IF not(PWDMLB='0' AND PSTMLB='1') THEN + next_state <= PASS_PG; + END IF; + ELSIF Instruct = PASSU AND WEL= '1' AND WIP= '0' THEN + next_state <= PASS_UNLOCK; + ELSIF Instruct = PPBP AND WEL = '1' THEN + next_state <= PPB_PG; + ELSIF (Instruct=PPBERS AND WEL='1' AND PPBOTP='1') THEN + next_state <= PPB_ERS; + ELSIF Instruct = DYBWR AND WEL = '1' THEN + next_state <= DYB_PG; + ELSIF Instruct = PNVDLR AND WEL = '1' THEN + next_state <= NVDLR_PG; + ELSE + next_state <= IDLE; + END IF; + END IF; + IF falling_edge(write) AND RdPswdProtMode = '1' AND + WIP = '0' THEN + IF Instruct = PASSU THEN + next_state <= PASS_UNLOCK; + END IF; + END IF; + + WHEN AUTOBOOT => + IF rising_edge(CSNeg_ipd) THEN + next_state <= IDLE; + END IF; + + WHEN WRITE_SR => + IF rising_edge(WDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PAGE_PG => + IF PRGSUSP_out'EVENT AND PRGSUSP_out = '1' THEN + next_state <= PG_SUSP; + ELSIF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PG_SUSP => + IF falling_edge(write) THEN + IF Instruct = PGRS THEN + next_state <= PAGE_PG; + ELSE + next_state <= PG_SUSP; + END IF; + ELSE + next_state <= PG_SUSP; + END IF; + + WHEN OTP_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN BULK_ERS => + IF rising_edge(EDONE) THEN + next_state <= IDLE; + END IF; + + WHEN SECTOR_ERS => + IF ERSSUSP_out'EVENT AND ERSSUSP_out = '1' THEN + next_state <= ERS_SUSP; + ELSIF rising_edge(EDONE) THEN + next_state <= IDLE; + END IF; + + WHEN ERS_SUSP => + IF falling_edge(write) THEN + IF (Instruct = PP OR Instruct = QPP OR + Instruct = PP4 OR Instruct = QPP4) AND + WEL = '1' THEN + IF (PARAM_REGION = TRUE AND + SectorSuspend /= Address/(SecSize+1)) OR + (PARAM_REGION = FALSE AND + SectorSuspend/=Address/(SecSize+1)+30*b_act) THEN + ReturnSectorID(sect,Address); + pgm_page := Address / (PageSize+1); + IF PPB_bits(sect)='1' AND + DYB_bits(sect)='1' THEN + next_state <= ERS_SUSP_PG; + END IF; + END IF; + ELSIF (Instruct = DYBWR AND WEL = '1') THEN + next_state <= DYB_PG; + ELSIF Instruct = ERRS THEN + next_state <= SECTOR_ERS; + ELSE + next_state <= ERS_SUSP; + END IF; + ELSE + next_state <= ERS_SUSP; + END IF; + + WHEN ERS_SUSP_PG => + IF PRGSUSP_out'EVENT AND PRGSUSP_out = '1' THEN + next_state <= ERS_SUSP_PG_SUSP; + ELSIF rising_edge(PDONE) THEN + next_state <= ERS_SUSP; + END IF; + + WHEN ERS_SUSP_PG_SUSP => + IF falling_edge(write) THEN + IF Instruct = PGRS THEN + next_state <= ERS_SUSP_PG; + ELSE + next_state <= ERS_SUSP_PG_SUSP; + END IF; + ELSE + next_state <= ERS_SUSP_PG_SUSP; + END IF; + + WHEN PASS_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PASS_UNLOCK => + IF falling_edge(PASSULCK_in) THEN + next_state <= IDLE; + END IF; + + WHEN PPB_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PPB_ERS => + IF falling_edge(PPBERASE_in) THEN + next_state <= IDLE; + END IF; + + WHEN AUTOBOOT_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PLB_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN DYB_PG => + IF rising_edge(PDONE) THEN + IF ES = '1' THEN + next_state <= ERS_SUSP; + ELSE + next_state <= IDLE; + END IF; + END IF; + + WHEN ASP_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN NVDLR_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + END CASE; + END IF; + END IF; + + END PROCESS StateGen; + + ReadEnable: PROCESS (read_out) + BEGIN + oe_z <= rising_edge(read_out) AND PoweredUp = '1'; + + IF read_out'EVENT AND read_out = '0' AND PoweredUp = '1' THEN + oe <= TRUE, FALSE AFTER 1 ns; + END IF; + END PROCESS ReadEnable; + + --------------------------------------------------------------------------- + --FSM Output generation and general funcionality + --------------------------------------------------------------------------- + Functional : PROCESS(write,current_state,start_autoboot,CSNeg_ipd, + HOLDNeg_pullup, Instruct, Address, WByte,change_addr, + PoweredUp, WPNeg_pullup, WDONE, PDONE, EDONE, + PRGSUSP_out,ERSSUSP_out, PASSACC_out, oe, oe_z) + + VARIABLE WData : WByteType:= (OTHERS => MaxData); + + VARIABLE AddrLo : NATURAL; + VARIABLE AddrHi : NATURAL; + VARIABLE Addr : NATURAL; + VARIABLE Addr_tmp : NATURAL; + + VARIABLE data_out : std_logic_vector(7 downto 0); + VARIABLE ident_out : std_logic_vector(647 downto 0); + + VARIABLE ExtendedID : NATURAL; + + VARIABLE old_bit : std_logic_vector(7 downto 0); + VARIABLE new_bit : std_logic_vector(7 downto 0); + VARIABLE old_int : INTEGER RANGE -1 to MaxData; + VARIABLE new_int : INTEGER RANGE -1 to MaxData; + VARIABLE old_pass : std_logic_vector(63 downto 0); + VARIABLE new_pass : std_logic_vector(63 downto 0); + VARIABLE wr_cnt : NATURAL RANGE 0 TO 511; + --Data Learning Pattern Enable + VARIABLE dlp_act : BOOLEAN := FALSE; + + VARIABLE sect : NATURAL RANGE 0 TO SecNum64; + VARIABLE cnt : NATURAL RANGE 0 TO 512 := 0; + + VARIABLE sec_tmp : NATURAL RANGE 0 TO SecNum64; + + BEGIN + + ----------------------------------------------------------------------- + -- Functionality Section + ----------------------------------------------------------------------- + + IF Instruct'EVENT THEN + read_cnt := 0; + byte_cnt := 1; + fast_rd <= true; + dual <= false; + rd <= false; + any_read <= false; + END IF; + + IF PASSACC_out'EVENT AND PASSACC_out = '1' THEN + WIP := '0'; + PASSACC_in <= '0'; + END IF; + + IF rising_edge(PoweredUp) THEN + --the default condition after power-up + --The Bank Address Register is loaded to all zeroes + Bank_Addr_reg := (others => '0'); + --The Configuration Register FREEZE bit is cleared. + FREEZE := '0'; + --The WEL bit is cleared. + WEL := '0'; + --When BPNV is set to '1'. the BP2-0 bits in Status Register are + --volatile and will be reset binary 111 after power-on reset + IF BPNV = '1' AND LOCK='0' AND FREEZE = '0' THEN + BP0 := '1'; + BP1 := '1'; + BP2 := '1'; + BP_bits := BP2 & BP1 & BP0; + change_BP <= '1', '0' AFTER 1 ns; + END IF; + --As shipped from the factory, all devices default ASP to the + --Persistent Protection mode, with all sectors unprotected, + --when power is applied. The device programmer or host system must + --then choose which sector protection method to use. + --For Persistent Protection mode, PPBLOCK defaults to "1" + PPB_LOCK := '1'; + PPB_LOCK_temp <= '1'; + DYB_bits := (OTHERS => '1'); + END IF; + + IF falling_edge(write) AND Instruct = RESET THEN + --The Configuration Register is set for Address mode + Bank_Addr_reg := (others => '0'); + --P_ERR bit is cleared + P_ERR := '0'; + --E_ERR bit is cleared + E_ERR := '0'; + --The WEL bit is cleared. + WEL := '0'; + --The WIP bit is cleared. + WIP := '0'; + --The ES bit is cleared. + ES := '0'; + --The PS bit is cleared. + PS := '0'; + + DummyBytes_act := '0'; + --When BPNV is set to '1'. the BP2-0 bits in Status + --Register are volatile and will be reseted after + --reset command + IF BPNV = '1' AND LOCK='0' AND FREEZE = '0' THEN + BP0 := '1'; + BP1 := '1'; + BP2 := '1'; + BP_bits := BP2 & BP1 & BP0; + change_BP <= '1', '0' AFTER 1 ns; + END IF; + END IF; + + IF change_addr'EVENT THEN + read_addr := Address; + END IF; + + CASE current_state IS + WHEN IDLE => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + ASP_ProtSE := 0; + Sec_ProtSE := 0; + PARAM_REGION := false; + IF falling_edge(write) AND RdPswdProtMode = '1' THEN + IF Instruct = PASSU THEN + IF WIP = '0' THEN + PASSULCK_in <= '1'; + ELSE + REPORT "The PASSU command cannot be accepted"& + " any faster than once every 100us" + SEVERITY WARNING; + END IF; + ELSIF Instruct = CLSR THEN + --The Clear Status Register Command resets bit SR1[5] + --(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + E_ERR := '0'; + P_ERR := '0'; + END IF; + END IF; + IF BottomBoot = TRUE THEN + FOR J IN 31 DOWNTO 0 LOOP + IF (PPB_bits(J)='1' AND DYB_bits(J)='1') THEN + ASP_ProtSE := ASP_ProtSE + 1; + END IF; + IF (Sec_Prot(J)='0') THEN + Sec_ProtSE := Sec_ProtSE + 1; + END IF; + END LOOP; + ELSIF TopBoot = TRUE THEN + FOR J IN 541 DOWNTO 510 LOOP + IF (PPB_bits(J)='1' AND DYB_bits(J)='1') THEN + ASP_ProtSE := ASP_ProtSE + 1; + END IF; + IF (Sec_Prot(J)='0') THEN + Sec_ProtSE := Sec_ProtSE + 1; + END IF; + END LOOP; + END IF; + IF falling_edge(write) AND RdPswdProtMode = '0' THEN + read_cnt := 0; + byte_cnt := 1; + IF Instruct = WREN THEN + WEL := '1'; + ELSIF Instruct = WRDI THEN + WEL := '0'; + ELSIF Instruct = WRR AND WEL = '1' AND BAR_ACC = '0' THEN + IF (not(SRWD = '1' AND WPNeg_pullup = '0') AND + QUAD ='0') OR QUAD ='1' THEN + -- can not execute if Hardware Protection Mode + -- is entered or if WEL bit is zero + + IF ((TBPROT='1' AND Config_reg1_in(5)='0') OR + (TBPARM='1' AND Config_reg1_in(2)='0') OR + (BPNV ='1' AND Config_reg1_in(3)='0')) AND + cfg_write = '1' THEN + P_ERR := '1'; + ELSE + WSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + END IF; + ELSE + WEL := '0'; + END IF; + ELSIF (Instruct = PP OR Instruct = PP4) AND WEL = '1' THEN + ReturnSectorID(sect,Address); + Addr := Address; + IF (Sec_Prot(sect) = '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + SA <= sect; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + P_ERR := '1'; + WEL := '0'; + END IF; + ELSIF (Instruct = QPP OR Instruct = QPP4) AND WEL = '1' THEN + ReturnSectorID(sect,Address); + Addr := Address; + pgm_page := Address/(PageSize+1); + IF (Sec_Prot(sect)= '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + SA <= sect; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + P_ERR := '1'; + WEL := '0'; + END IF; + ELSIF Instruct = OTPP AND WEL = '1' THEN + -- As long as the FREEZE bit remains cleared to a logic '0' + --the OTP address space is programmable. + IF FREEZE = '0' THEN + IF ((((Address >= 16#0010# AND Address <= 16#13#)OR + (Address >= 16#0020# AND Address <= 16#FF#)) + AND LOCK_BYTE1(Address/32) = '1') OR + ((Address >= 16#100# AND Address <= 16#1FF#) + AND LOCK_BYTE2((Address-16#100#)/32) = '1') OR + ((Address >= 16#200# AND Address <= 16#2FF#) + AND LOCK_BYTE3((Address-16#200#)/32) = '1') OR + ((Address >= 16#300# AND Address <= 16#3FF#) + AND LOCK_BYTE4((Address-16#300#)/32) = '1')) AND + (Address + Byte_number <= OTPHiAddr) THEN + PSTART <= '1', '0' AFTER 1 ns; + WIP := '1'; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSIF (Address < 16#0010# OR (Address > 16#0013# AND + Address < 16#0020#) OR Address > 16#3FF# ) THEN + P_ERR := '1'; + WEL := '0'; + IF Address < 16#0020# THEN + ASSERT false + REPORT "Given address is in" & + "reserved address range" + SEVERITY warning; + ELSIF Address > 16#3FF# THEN + ASSERT false + REPORT "Given address is out of" & + "OTP address range" + SEVERITY warning; + END IF; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSIF (Instruct = SE OR Instruct = SE4) AND WEL = '1' THEN + ReturnSectorID(sect,Address); + IF UniformSec = TRUE OR + (TopBoot = TRUE AND sect < 510) OR + (BottomBoot = TRUE AND sect > 31) THEN + SectorSuspend <= sect; + PARAM_REGION := FALSE; + IF (Sec_Prot(sect) = '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + Addr := Address; + ELSE + E_ERR := '1'; + WEL := '0'; + END IF; + ELSIF (TopBoot = TRUE AND sect >= 510) OR + (BottomBoot = TRUE AND sect <= 31) THEN + IF Sec_ProtSE = 32 AND ASP_ProtSE = 32 THEN + --Sector erase command is applied to a 64 KB range + --that includes 4 KB sectors + IF TopBoot = TRUE THEN + SectorSuspend <= 510 + (541 - sect)/16; + ELSE + SectorSuspend <= sect/16; + END IF; + PARAM_REGION := TRUE; + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + Addr := Address; + ELSE + E_ERR := '1'; + WEL := '0'; + END IF; + END IF; + ELSIF (Instruct = P4E OR Instruct = P4E4) AND WEL = '1' THEN + ReturnSectorID(sect,Address); + IF UniformSec = TRUE OR + (TopBoot = TRUE AND sect < 510) OR + (BottomBoot = TRUE AND sect > 31) THEN + WEL := '0'; + ELSE + IF (Sec_Prot(sect) = '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + --A P4E instruction applied to a sector + --that has been Write Protected through the + --Block Protect Bits or ASP will not be + --executed and will set the E_ERR status + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + Addr := Address; + ELSE + E_ERR := '1'; + WEL := '0'; + END IF; + END IF; + ELSIF Instruct = BE AND WEL = '1' THEN + IF (BP0='0' AND BP1='0' AND BP2='0') THEN + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + ELSE + --The Bulk Erase command will not set E_ERR if a + --protected sector is found during the command + --execution. + WEL := '0'; + END IF; + ELSIF Instruct = PASSP AND WEL = '1' THEN + IF not(PWDMLB='0' AND PSTMLB='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSE + REPORT "Password programming is not allowed" & + " in Password Protection Mode." + SEVERITY warning; + END IF; + ELSIF Instruct = PASSU AND WEL = '1' THEN + PASSULCK_in <= '1'; + ELSIF Instruct = BRWR THEN + Bank_Addr_reg(7) := Bank_Addr_reg_in(7); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + IF Bank_Addr_reg_in(1) = '1' THEN + REPORT "WARNING: Changing values of Bank Address" & + " Register BA25 is not allowed!!!" + SEVERITY warning; + END IF; + ELSIF Instruct = WRR AND BAR_ACC = '1' THEN + IF (P_ERR = '0' AND E_ERR = '0') THEN + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + IF Bank_Addr_reg_in(1) = '1' THEN + REPORT "WARNING: Changing values of Bank " & + "Address Register BA25 is not allowed!!!" + SEVERITY warning; + END IF; + END IF; + ELSIF Instruct = ASPP AND WEL = '1' THEN + IF not(ASPOTPFLAG) THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSE + WEL := '0'; + P_ERR := '1'; + REPORT "Once the Protection Mode is selected," & + "no further changes to the ASP register" & + "is allowed." + SEVERITY warning; + END IF; + ELSIF Instruct = ABWR AND WEL = '1' THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = PPBP AND WEL = '1' THEN + ReturnSectorID(sect,Address); + Addr := Address; + pgm_page := Address/(PageSize+1); + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = PPBERS AND WEL = '1' THEN + IF PPBOTP = '1' THEN + PPBERASE_in <= '1'; + WIP := '1'; + ELSE + E_ERR := '1'; + END IF; + ELSIF Instruct = PLBWR AND WEL = '1' AND + RdPswdProtEnable = '0' THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = DYBWR AND WEL = '1' THEN + ReturnSectorID(sect,Address); + Addr := Address; + pgm_page := Address/(PageSize+1); + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = PNVDLR AND WEL = '1' THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = WVDLR AND WEL = '1' THEN + VDLR_reg := VDLR_reg_in; + WEL := '0'; + ELSIF Instruct = CLSR THEN + --The Clear Status Register Command resets bit SR1[5] + --(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + E_ERR := '0'; + P_ERR := '0'; + END IF; + + IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' THEN + BAR_ACC <= '1'; + ELSE + BAR_ACC <= '0'; + END IF; + ELSIF oe_z THEN + IF Instruct = READ OR Instruct = RD4 OR + Instruct = RES OR Instruct = DLPRD THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSIF Instruct = DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + ELSIF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = READ OR Instruct = RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = DDRFR OR Instruct = DDRFR4 THEN + --Read Memory array + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + IF ((bus_cycle_state = DUMMY_BYTES OR + DummyBytes_act='1') AND VDLR_reg/="00000000") THEN + DummyBytes_act := '0'; + IF (Instruct = DDRFR OR Instruct = DDRFR4) THEN + IF EHP THEN + IF Latency_code = 1 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3 OR + Latency_code = 0) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + dlp_act := FALSE; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + read_addr_tmp := read_addr; + SecAddr := read_addr/(SecSize+1); + Sec_addr := read_addr - SecAddr*(SecSize+1); + SecAddr := ReturnSectorIDRdPswdMd(TBPROT); + read_addr := Sec_addr + SecAddr*(SecSize+1); + IF RdPswdProtMode = '0' THEN + read_addr := read_addr_tmp; + END IF; + IF Mem(read_addr) /= -1 THEN + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + ELSE + SOut_zd <= 'U'; + END IF; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct = DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + --Read Memory array + IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct = DDRDIOR OR Instruct = DDRDIOR4) THEN + IF EHP THEN + IF Latency_code = 0 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + read_addr_tmp := read_addr; + SecAddr := read_addr/(SecSize+1); + Sec_addr := read_addr - SecAddr*(SecSize+1); + SecAddr := ReturnSectorIDRdPswdMd(TBPROT); + read_addr := Sec_addr + SecAddr*(SecSize+1); + IF RdPswdProtMode = '0' THEN + read_addr := read_addr_tmp; + END IF; + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF (Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 OR + Instruct = DDRQIOR OR Instruct= DDRQIOR4) + AND QUAD = '1' THEN + --Read Memory array + IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF ((Instruct = DDRQIOR OR Instruct = DDRQIOR4) AND + QUAD = '1') THEN + IF EHP THEN + IF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + read_addr_tmp := read_addr; + SecAddr := read_addr/(SecSize+1); + Sec_addr := read_addr - SecAddr*(SecSize+1); + SecAddr := ReturnSectorIDRdPswdMd(TBPROT); + read_addr := Sec_addr + SecAddr*(SecSize+1); + IF RdPswdProtMode = '0' THEN + read_addr := read_addr_tmp; + END IF; + + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct = OTPR THEN + IF (read_addr>=OTPLoAddr) AND + (read_addr<=OTPHiAddr) AND RdPswdProtMode = '0' THEN + --Read OTP Memory array + fast_rd <= true; + rd <= false; + data_out := to_slv(OTPMem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + ELSIF (read_addr > OTPHiAddr) + OR RdPswdProtMode = '1' THEN + --OTP Read operation will not wrap to the + --starting address after the OTP address is at + --its maximum or Read Password Protection Mode + --is selected; instead, the data beyond the + --maximum OTP address will be undefined. + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF Instruct = REMS THEN + --Read Manufacturer and Device ID + IF read_addr MOD 2 = 0 THEN + data_out := to_slv(Manuf_ID,8); + SOut_zd <= data_out(7 - read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + ELSE + data_out := to_slv(DeviceID,8); + SOut_zd <= data_out(7 - read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := 0; + END IF; + END IF; + ELSIF Instruct = RDID THEN + IF UniformSec THEN + ExtendedID := ExtendedID256; + ELSE + ExtendedID := ExtendedID64; + END IF; + ident_out := CFI_array_tmp; + IF read_cnt < 648 THEN + SOut_zd <= ident_out(647-read_cnt); + read_cnt := read_cnt + 1; + ELSE + --Continued shifting of output beyond the end of + --the defined ID-CFI address space will provide + --undefined data. + SOut_zd <= 'U'; + END IF; + ELSIF Instruct = RES THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + data_out := to_slv(ESignature,8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = DLPRD THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + SOut_zd <= VDLR_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = ABRD THEN + --Read AutoBoot register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= AutoBoot_reg(31-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 32 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = BRRD THEN + --Read Bank Address Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Bank_Addr_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = ASPRD THEN + --Read ASP Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= ASP_reg(15-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 16 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = PASSRD THEN + --Read Password Register + IF not (PWDMLB='0' AND PSTMLB='1') THEN + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Password_reg((8*byte_cnt-1)-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + byte_cnt := byte_cnt + 1; + IF byte_cnt = 9 THEN + byte_cnt := 1; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 64 THEN + read_cnt := 0; + END IF; + IF read_cnt = 0 THEN + ASSERT false + REPORT "Verification of password is not " & + " allowed in Password Protection Mode." + SEVERITY warning; + END IF; + END IF; + ELSIF Instruct = PLBRD THEN + --Read PPB Lock Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= PPBL(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = DYBRD THEN + --Read DYB Access Register + ReturnSectorID(sect,Address); + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + DYBAR(7 downto 0) := "UUUUUUUU"; + IF RdPswdProtMode = '0' THEN + IF DYB_bits(sect) = '1' THEN + DYBAR(7 downto 0) := "11111111"; + ELSE + DYBAR(7 downto 0) := "00000000"; + END IF; + END IF; + SOut_zd <= DYBAR(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = PPBRD THEN + --Read PPB Access Register + ReturnSectorID(sect,Address); + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + PPBAR(7 downto 0) := "UUUUUUUU"; + IF RdPswdProtMode = '0' THEN + IF PPB_bits(sect) = '1' THEN + PPBAR(7 downto 0) := "11111111"; + ELSE + PPBAR(7 downto 0) := "00000000"; + END IF; + END IF; + SOut_zd <= PPBAR(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + + WHEN AUTOBOOT => + IF start_autoboot = '1' THEN + IF (oe) THEN + any_read <= true; + IF QUAD = '1' THEN + IF ABSD > 0 THEN --If ABSD > 0, + fast_rd <= false; --max SCK frequency is 104MHz + rd <= false; + dual <= true; + ddr <= false; + ELSE -- If ABSD = 0, max SCK frequency is 50 MHz + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + END IF; + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + ELSE + IF ABSD > 0 THEN --If ABSD > 0, + fast_rd <= true; --max SCK frequency is 133MHz + rd <= false; + dual <= false; + ddr <= false; + ELSE -- If ABSD = 0, max SCK frequency is 50 MHz + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + END IF; + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + END IF; + ELSIF oe_z THEN + IF QUAD = '1' THEN + IF ABSD > 0 THEN --If ABSD > 0, + fast_rd <= false; --max SCK frequency is 104MHz + rd <= false; + dual <= true; + ddr <= false; + ELSE -- If ABSD = 0, max SCK frequency is 50 MHz + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + END IF; + ELSE + IF ABSD > 0 THEN --If ABSD > 0, + fast_rd <= true; --max SCK frequency is 133MHz + rd <= false; + dual <= false; + ddr <= false; + ELSE -- If ABSD = 0, max SCK frequency is 50 MHz + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + END IF; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + END IF; + + WHEN WRITE_SR => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF WDONE = '1' THEN + WIP := '0'; + WEL := '0'; + SRWD := Status_reg1_in(7);--MSB first + + IF LOCK='0' THEN + IF FREEZE='0' THEN + --The Freeze Bit, when set to 1, locks the current + --state of the BP2-0 bits in Status Register, + --the TBPROT and TBPARM bits in the Config Register + --As long as the FREEZE bit remains cleared to logic + --'0', the other bits of the Configuration register + --including FREEZE are writeable. + BP2 := Status_reg1_in(4); + BP1 := Status_reg1_in(3); + BP0 := Status_reg1_in(2); + + BP_bits := BP2 & BP1 & BP0; + + IF TBPROT = '0' AND INITIAL_CONFIG = '0' THEN + TBPROT := Config_reg1_in(5); + END IF; + + IF (TBPARM = '0' AND INITIAL_CONFIG = '0' AND + TimingModel(16) = '0') THEN + TBPARM := Config_reg1_in(2); + change_TBPARM <= '1', '0' AFTER 1 ns; + END IF; + + change_BP <= '1', '0' AFTER 1 ns; + + LC1 := Config_reg1_in(7); + LC0 := Config_reg1_in(6); + QUAD := Config_reg1_in(1); + + IF FREEZE = '0' THEN + FREEZE := Config_reg1_in(0); + END IF; + + IF WRLOCKENABLE AND LOCK = '0' THEN + LOCK := Config_reg1_in(4); + WRLOCKENABLE <= false; + END IF; + + IF BPNV = '0' THEN + BPNV := Config_reg1_in(3); + END IF; + END IF; + END IF; + END IF; + + WHEN PAGE_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF falling_edge(PDONE) THEN + + ADDRHILO_PG(AddrLo, AddrHi, Addr); + cnt := 0; + + FOR i IN 0 TO wr_cnt LOOP + new_int := WData(i); + old_int := Mem(Addr + i - cnt); + IF new_int > -1 THEN + new_bit := to_slv(new_int,8); + IF old_int > -1 THEN + old_bit := to_slv(old_int,8); + FOR j IN 0 TO 7 LOOP + IF old_bit(j) = '0' THEN + new_bit(j) := '0'; + END IF; + END LOOP; + new_int := to_nat(new_bit); + END IF; + WData(i) := new_int; + ELSE + WData(i) := -1; + END IF; + + Mem(Addr + i - cnt) := -1; + + IF (Addr + i) = AddrHi THEN + Addr := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + cnt :=0; + END IF; + + IF PDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO wr_cnt LOOP + Mem(Addr_tmp + i - cnt) := WData(i); + IF (Addr_tmp + i) = AddrHi THEN + Addr_tmp := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + ELSIF Instruct = PGSP AND PRGSUSP_in = '0' THEN + IF RES_TO_SUSP_MIN_TIME = '0' THEN + PGSUSP <= '1', '0' AFTER 1 ns; + PRGSUSP_in <= '1'; + ASSERT RES_TO_SUSP_TYP_TIME = '0' + REPORT "Typical periods are needed for " & + "Program to progress to completion" + SEVERITY warning; + ELSE + ASSERT FALSE + REPORT "Minimum for tPRS is not satisfied! " & + "PGSP command is ignored" + SEVERITY warning; + END IF; + END IF; + + WHEN PG_SUSP => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF PRGSUSP_out = '1' AND PRGSUSP_in = '1' THEN + PRGSUSP_in <= '0'; + --The RDY/BSY bit in the Status Register will indicate that + --the device is ready for another operation. + WIP := '0'; + --The Program Suspend (PS) bit in the Status Register will + --be set to the logical “1” state to indicate that the + --program operation has been suspended. + PS := '1'; + END IF; + + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = BRRD THEN + --Read Bank Address Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Bank_Addr_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + --Read Array Operations + ELSIF Instruct = READ OR Instruct = RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = DDRFR OR Instruct = DDRFR4 THEN + --Read Memory array + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + + IF pgm_page /= read_addr/(PageSize+1) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRFR OR Instruct=DDRFR4) THEN + IF EHP THEN + IF Latency_code = 1 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3 OR + Latency_code = 0) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:= VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + read_cnt:=read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + --Read Memory array + IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF pgm_page /= read_addr/(PageSize+1) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRDIOR OR Instruct=DDRDIOR4) THEN + IF EHP THEN + IF Latency_code = 0 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency"& + " is set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:=VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + SIOut_zd<=data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF (Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 OR + Instruct = DDRQIOR OR Instruct= DDRQIOR4) + AND QUAD = '1' THEN + --Read Memory array + IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + + IF pgm_page /= read_addr/(PageSize+1) THEN + + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF EHP THEN + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + HOLDNegOut_zd <= 'U'; + WPNegOut_zd <= 'U'; + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + END IF; + ELSIF oe_z THEN + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + ELSIF falling_edge(write) THEN + IF Instruct = BRWR THEN + Bank_Addr_reg(7) := Bank_Addr_reg_in(7); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + IF Bank_Addr_reg_in(1) = '1' THEN + REPORT "WARNING: Changing values of Bank Address" & + " Register BA25 is not allowed!!!" + SEVERITY warning; + END IF; + ELSIF Instruct = WRR AND BAR_ACC = '1' THEN + -- Write to the lower address bits of the BAR + IF (P_ERR = '0' AND E_ERR = '0')THEN + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + IF Bank_Addr_reg_in(1) = '1' THEN + REPORT "WARNING: Changing values of Bank " & + "Address Register BA25 is not allowed!!!" + SEVERITY warning; + END IF; + END IF; + ELSIF Instruct = PGRS THEN + PGRES <= '1', '0' AFTER 5 ns; + PS := '0'; + WIP := '1'; + RES_TO_SUSP_MIN_TIME <= '1', '0' AFTER 60 ns; + RES_TO_SUSP_TYP_TIME <= '1', '0' AFTER 100 us; + END IF; + + IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' AND + RdPswdProtMode = '0' THEN + BAR_ACC <= '1'; + ELSE + BAR_ACC <= '0'; + END IF; + END IF; + + WHEN ERS_SUSP_PG_SUSP => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF PRGSUSP_out = '1' AND PRGSUSP_in = '1' THEN + PRGSUSP_in <= '0'; + --The RDY/BSY bit in the Status Register will indicate that + --the device is ready for another operation. + WIP := '0'; + --The Program Suspend (PS) bit in the Status Register will + --be set to the logical “1” state to indicate that the + --program operation has been suspended. + PS := '1'; + END IF; + + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = BRRD THEN + --Read Bank Address Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Bank_Addr_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + --Read Array Operations + ELSIF Instruct = READ OR Instruct = RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = DDRFR OR Instruct = DDRFR4 THEN + --Read Memory array + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + IF (SectorSuspend /= read_addr/(SecSize+1)+30*b_act AND + pgm_page /= read_addr/(PageSize+1)) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRFR OR Instruct=DDRFR4) THEN + IF EHP THEN + IF Latency_code = 1 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3 OR + Latency_code = 0) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:= VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + read_cnt:=read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + --Read Memory array + IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF (SectorSuspend /= read_addr/(SecSize+1)+30*b_act AND + pgm_page /= read_addr/(PageSize+1)) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRDIOR OR Instruct=DDRDIOR4) THEN + IF EHP THEN + IF Latency_code = 0 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency"& + " is set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:=VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + SIOut_zd<=data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF (Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 OR + Instruct = DDRQIOR OR Instruct= DDRQIOR4) + AND QUAD = '1' THEN + --Read Memory array + IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF (SectorSuspend /= read_addr/(SecSize+1)+30*b_act AND + pgm_page /= read_addr/(PageSize+1)) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF EHP THEN + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + HOLDNegOut_zd <= 'U'; + WPNegOut_zd <= 'U'; + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + END IF; + ELSIF oe_z THEN + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + ELSIF falling_edge(write) THEN + IF Instruct = BRWR THEN + Bank_Addr_reg(7) := Bank_Addr_reg_in(7); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + IF Bank_Addr_reg_in(1) = '1' THEN + REPORT "WARNING: Changing values of Bank Address" & + " Register BA25 is not allowed!!!" + SEVERITY warning; + END IF; + ELSIF Instruct = WRR AND BAR_ACC = '1' THEN + -- Write to the lower address bits of the BAR + IF (P_ERR = '0' AND E_ERR = '0')THEN + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + IF Bank_Addr_reg_in(1) = '1' THEN + REPORT "WARNING: Changing values of Bank " & + "Address Register BA25 is not allowed!!!" + SEVERITY warning; + END IF; + END IF; + ELSIF Instruct = PGRS THEN + PGRES <= '1', '0' AFTER 5 ns; + PS := '0'; + WIP := '1'; + RES_TO_SUSP_MIN_TIME <= '1', '0' AFTER 60 ns; + RES_TO_SUSP_TYP_TIME <= '1', '0' AFTER 100 us; + END IF; + + IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' AND + RdPswdProtMode = '0' THEN + BAR_ACC <= '1'; + ELSE + BAR_ACC <= '0'; + END IF; + END IF; + + WHEN OTP_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF Address + wr_cnt <= OTPHiAddr THEN + FOR i IN 0 TO wr_cnt LOOP + new_int := WData(i); + old_int := OTPMem(Addr + i); + IF new_int > -1 THEN + new_bit := to_slv(new_int,8); + IF old_int > -1 THEN + old_bit := to_slv(old_int,8); + FOR j IN 0 TO 7 LOOP + IF old_bit(j) = '0' THEN + new_bit(j) := '0'; + END IF; + END LOOP; + new_int := to_nat(new_bit); + END IF; + WData(i) := new_int; + ELSE + WData(i) := -1; + END IF; + + OTPMem(Addr + i) := -1; + END LOOP; + ELSE + ASSERT false + REPORT "Programming will reach over address limit"& + " of OTP array" + SEVERITY warning; + END IF; + + IF PDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO wr_cnt LOOP + OTPMem(Addr_tmp + i) := WData(i); + END LOOP; + LOCK_BYTE1 := to_slv(OTPMem(16#10#),8); + LOCK_BYTE2 := to_slv(OTPMem(16#11#),8); + LOCK_BYTE3 := to_slv(OTPMem(16#12#),8); + LOCK_BYTE4 := to_slv(OTPMem(16#13#),8); + END IF; + + WHEN SECTOR_ERS => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := -1; + END LOOP; + IF EDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := MaxData; + END LOOP; + ELSIF Instruct = ERSP AND ERSSUSP_in = '0' THEN + ESUSP <= '1', '0' AFTER 10 ns; + ERSSUSP_in <= '1'; + ASSERT RES_TO_SUSP_TYP_TIME = '0' + REPORT "Typical periods are needed for " & + "Program to progress to completion" + SEVERITY warning; + END IF; + + WHEN BULK_ERS => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF falling_edge(EDONE) THEN + FOR i IN 0 TO AddrRANGE LOOP + -- Sector ID calculation + IF TimingModel(16) = '0' THEN + sec_tmp := i / (SecSize64+1); + IF BottomBoot THEN + IF sec_tmp <= 1 THEN --4KB Sectors + sect := i/(SecSize4+1); + ELSE + sect := sec_tmp + 30; + END IF; + ELSIF TopBoot THEN + IF sec_tmp >= 510 THEN --4KB Sectors + sect := + 510+(i-(SecSize64+1)*510)/(SecSize4+1); + ELSE + sect := sec_tmp; + END IF; + END IF; + ELSE + sect := i/(SecSize256+1); + END IF; + IF PPB_bits(sect) = '1' AND DYB_bits(sect) = '1' THEN + Mem(i) := -1; + END IF; + END LOOP; + END IF; + + IF EDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO AddrRANGE LOOP + -- Sector ID calculation + IF TimingModel(16) = '0' THEN + sec_tmp := i / (SecSize64+1); + IF BottomBoot THEN + IF sec_tmp <= 1 THEN --4KB Sectors + sect := i/(SecSize4+1); + ELSE + sect := sec_tmp + 30; + END IF; + ELSIF TopBoot THEN + IF sec_tmp >= 510 THEN --4KB Sectors + sect := + 510+(i-(SecSize64+1)*510)/(SecSize4+1); + ELSE + sect := sec_tmp; + END IF; + END IF; + ELSE + sect := i/(SecSize256+1); + END IF; + IF PPB_bits(sect) = '1' AND DYB_bits(sect) = '1' THEN + Mem(i) := MaxData; + END IF; + END LOOP; + END IF; + + WHEN ERS_SUSP => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF ERSSUSP_out = '1' THEN + ERSSUSP_in <= '0'; + --The Erase Suspend (ES) bit in the Status Register will + --be set to the logical “1” state to indicate that the + --erase operation has been suspended. + ES := '1'; + --The WIP bit in the Status Register will indicate that + --the device is ready for another operation. + WIP := '0'; + END IF; + + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = DYBRD THEN + --Read DYB Access Register + ReturnSectorID(sect,Address); + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF DYB_bits(sect) = '1' THEN + DYBAR(7 downto 0) := "11111111"; + ELSE + DYBAR(7 downto 0) := "00000000"; + END IF; + SOut_zd <= DYBAR(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = BRRD THEN + --Read Bank Address Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Bank_Addr_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = PPBRD THEN + --Read PPB Access Register + ReturnSectorID(sect,Address); + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + PPBAR(7 downto 0) := "UUUUUUUU"; + IF RdPswdProtMode = '0' THEN + IF PPB_bits(sect) = '1' THEN + PPBAR(7 downto 0) := "11111111"; + ELSE + PPBAR(7 downto 0) := "00000000"; + END IF; + END IF; + SOut_zd <= PPBAR(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + --Read Array Operations + ELSIF Instruct = READ OR Instruct = RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = DDRFR OR Instruct = DDRFR4 THEN + --Read Memory array + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + + IF (PARAM_REGION = TRUE AND + SectorSuspend /= read_addr/(SecSize+1)) OR + (PARAM_REGION = FALSE AND + SectorSuspend /= read_addr/(SecSize+1)+30*b_act) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRFR OR Instruct=DDRFR4) THEN + IF EHP THEN + IF Latency_code = 1 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3 OR + Latency_code = 0) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:= VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + read_cnt:=read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + --Read Memory array + IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF (PARAM_REGION = TRUE AND + SectorSuspend /= read_addr/(SecSize+1)) OR + (PARAM_REGION = FALSE AND + SectorSuspend /= read_addr/(SecSize+1)+30*b_act) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRDIOR OR Instruct=DDRDIOR4) THEN + IF EHP THEN + IF Latency_code = 0 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency"& + " is set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:=VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + SIOut_zd<=data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF (Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 OR + Instruct = DDRQIOR OR Instruct= DDRQIOR4) + AND QUAD = '1' THEN + --Read Memory array + IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF (PARAM_REGION = TRUE AND + SectorSuspend /= read_addr/(SecSize+1)) OR + (PARAM_REGION = FALSE AND + SectorSuspend /= read_addr/(SecSize+1)+30*b_act) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF EHP THEN + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + HOLDNegOut_zd <= 'U'; + WPNegOut_zd <= 'U'; + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + + END IF; + END IF; + ELSIF oe_z THEN + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF falling_edge(write) THEN + IF (Instruct = PP OR Instruct = PP4) AND WEL = '1' THEN + IF (PARAM_REGION = TRUE AND + SectorSuspend /= Address/(SecSize+1)) OR + (PARAM_REGION = FALSE AND + SectorSuspend/=Address/(SecSize+1)+30*b_act) THEN + ReturnSectorID(sect,Address); + Addr := Address; + pgm_page := Address/(PageSize+1); + IF (Sec_Prot(sect) = '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + WIP := '1' ; + SA <= sect; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSIF (Instruct = QPP OR Instruct = QPP4) AND WEL = '1' THEN + IF (PARAM_REGION = TRUE AND + SectorSuspend /= Address/(SecSize+1)) OR + (PARAM_REGION = FALSE AND + SectorSuspend/=Address/(SecSize+1)+30*b_act) THEN + ReturnSectorID(sect,Address); + Addr := Address; + pgm_page := Address/(PageSize+1); + IF (Sec_Prot(sect)='0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + WIP := '1' ; + SA <= sect; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSIF Instruct = WREN THEN + WEL := '1'; + ELSIF Instruct = CLSR THEN + --The Clear Status Register Command resets bit SR1[5] + --(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + E_ERR := '0'; + P_ERR := '0'; + ELSIF Instruct = BRWR THEN + Bank_Addr_reg(7) := Bank_Addr_reg_in(7); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + IF Bank_Addr_reg_in(1) = '1' THEN + REPORT "WARNING: Changing values of Bank Address" & + " Register BA25 is not allowed!!!" + SEVERITY warning; + END IF; + ELSIF Instruct = WRR AND BAR_ACC = '1' THEN + -- Write to the lower address bits of the BAR + IF (P_ERR = '0' AND E_ERR = '0')THEN + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + IF Bank_Addr_reg_in(1) = '1' THEN + REPORT "WARNING: Changing values of Bank " & + "Address Register BA25 is not allowed!!!" + SEVERITY warning; + END IF; + END IF; + ELSIF Instruct = DYBWR AND WEL = '1' THEN + ReturnSectorID(sect,Address); + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = ERRS THEN + ERES <= '1', '0' AFTER 5 ns; + ES := '0'; + WIP := '1'; + IF BottomBoot = TRUE THEN + IF PARAM_REGION = TRUE THEN + Addr := SectorSuspend*(SecSize+1); + ELSE + Addr := (SectorSuspend-30)*(SecSize+1); + END IF; + ELSE + Addr := SectorSuspend*(SecSize+1); + END IF; + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + RES_TO_SUSP_TYP_TIME <= '1', '0' AFTER 100 us; + END IF; + + IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' AND + RdPswdProtMode = '0' THEN + BAR_ACC <= '1'; + ELSE + BAR_ACC <= '0'; + END IF; + END IF; + + WHEN ERS_SUSP_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + ADDRHILO_PG(AddrLo, AddrHi, Addr); + cnt := 0; + + FOR i IN 0 TO wr_cnt LOOP + new_int := WData(i); + old_int := Mem(Addr + i - cnt); + IF new_int > -1 THEN + new_bit := to_slv(new_int,8); + IF old_int > -1 THEN + old_bit := to_slv(old_int,8); + FOR j IN 0 TO 7 LOOP + IF old_bit(j) = '0' THEN + new_bit(j) := '0'; + END IF; + END LOOP; + new_int := to_nat(new_bit); + END IF; + WData(i) := new_int; + ELSE + WData(i) := -1; + END IF; + + IF (Addr + i) = AddrHi THEN + Addr := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + cnt :=0; + + IF PDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO wr_cnt LOOP + Mem(Addr_tmp + i - cnt) := WData(i); + IF (Addr_tmp + i) = AddrHi THEN + Addr_tmp := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + ELSIF Instruct = PGSP AND PRGSUSP_in = '0' THEN + PGSUSP <= '1', '0' AFTER 1 ns; + PRGSUSP_in <= '1'; + END IF; + + WHEN PASS_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + new_pass := Password_reg_in; + old_pass := Password_reg; + FOR j IN 0 TO 63 LOOP + IF old_pass(j) = '0' THEN + new_pass(j) := '0'; + END IF; + END LOOP; + + IF PDONE = '1' THEN + Password_reg := new_pass; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN PASS_UNLOCK => + WIP := '1'; + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PASS_TEMP = Password_reg THEN + PASS_UNLOCKED <= TRUE; + ELSE + PASS_UNLOCKED <= FALSE; + END IF; + + IF PASSULCK_out = '1' THEN + IF PASS_UNLOCKED AND PWDMLB = '0' THEN + PPB_LOCK := '1'; + PPB_LOCK_temp <= '1'; + WIP := '0'; + ELSE + P_ERR := '1'; + REPORT "Incorrect Password!" + SEVERITY warning; + PASSACC_in <= '1'; + END IF; + WEL := '0'; + PASSULCK_in <= '0'; + END IF; + + WHEN PPB_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + IF PPB_LOCK /= '0' THEN + PPB_bits(sect):= '0'; + WIP := '0'; + WEL := '0'; + ELSE + P_ERR := '0'; + WIP := '0'; + WEL := '0'; + END IF; + END IF; + + WHEN PPB_ERS => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PPBERASE_out = '1' THEN + IF PPB_LOCK /= '0' AND PPBOTP = '1' THEN + PPB_bits:= (OTHERS => '1'); + ELSE + E_ERR := '1'; + END IF; + WIP := '0'; + WEL := '0'; + PPBERASE_in <= '0'; + END IF; + + WHEN AUTOBOOT_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + AutoBoot_reg := AutoBoot_reg_in; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN PLB_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + PPB_LOCK := '0'; + PPB_LOCK_temp <= '0'; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN DYB_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + DYBAR := DYBAR_in; + IF DYBAR = "11111111" THEN + DYB_bits(sect):= '1'; + ELSIF DYBAR = "00000000" THEN + DYB_bits(sect):= '0'; + ELSE + P_ERR := '1'; + END IF; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN ASP_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + + IF (RPME = '0' AND ASP_reg_in(5) = '1') THEN + P_ERR := '1'; + REPORT "RPME bit is allready programmed" + SEVERITY warning; + ELSE + RPME := ASP_reg_in(5); + END IF; + + IF (PPBOTP = '0' AND ASP_reg_in(3) ='1') THEN + P_ERR := '1'; + REPORT "PPBOTP bit is allready programmed" + SEVERITY warning; + ELSE + PPBOTP := ASP_reg_in(3); + END IF; + + IF (PWDMLB = '1' AND PSTMLB = '1') THEN + IF (ASP_reg_in(2) = '0' AND ASP_reg_in(1) = '0') THEN + REPORT "ASPR[2:1] = 00 Illegal condition" + SEVERITY warning; + P_ERR := '1'; + ELSE + IF (ASP_reg_in(2) /= '1' OR + ASP_reg_in(1) /= '1') THEN + ASPOTPFLAG <= TRUE; + END IF; + PWDMLB := ASP_reg_in(2); + PSTMLB := ASP_reg_in(1); + END IF; + END IF; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN NVDLR_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + IF NVDLR_reg = "00000000" THEN + NVDLR_reg :=NVDLR_reg_in; + VDLR_reg := NVDLR_reg_in; + WIP := '0'; + WEL := '0'; + ELSE + WIP := '0'; + WEL := '0'; + P_ERR := '1'; + REPORT "NVDLR is allready programmed" + SEVERITY warning; + END IF; + END IF; + + WHEN RESET_STATE => + --the default condition hardware reset + --The Bank Address Register is loaded to all zeroes + Bank_Addr_reg := (others => '0'); + IF BPNV = '1' AND LOCK='0' AND FREEZE = '0' THEN + BP0 := '1'; + BP1 := '1'; + BP2 := '1'; + BP_bits := BP2 & BP1 & BP0; + change_BP <= '1', '0' AFTER 1 ns; + END IF; + --Resets the Status register 1 + P_ERR := '0'; + E_ERR := '0'; + WEL := '0'; + WIP := '0'; + --Resets the Status register 2 + ES := '0'; + PS := '0'; + --Resets the Configuration register 1 + FREEZE := '0'; + --On reset cycles the data pattern reverts back + --to what is in the NVDLR + VDLR_reg := NVDLR_reg; + dlp_act := FALSE; + --Loads the Program Buffer with all ones + WData := (OTHERS => MaxData); + + IF PWDMLB = '0' THEN + PPB_LOCK := '0'; + PPB_LOCK_temp <= '0'; + ELSE + PPB_LOCK := '1'; + PPB_LOCK_temp <= '1'; + END IF; + + END CASE; + + --Output Disable Control + IF (CSNeg_ipd = '1') THEN + SIOut_zd <= 'Z'; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + END IF; + + END PROCESS Functional; + + --------------------------------------------------------------------------- + -- CFI Process + --------------------------------------------------------------------------- + CFIPreload: PROCESS + + BEGIN + ------------------------------------------------------------------------ + --CFI array data + ------------------------------------------------------------------------ + -- Manufacturer and Device ID + CFI_array(16#00#) := 16#01#; + CFI_array(16#01#) := 16#02#; + CFI_array(16#02#) := 16#19#; + CFI_array(16#03#) := 16#00#; + IF TimingModel(16) = '0' THEN + CFI_array(16#04#) := 16#01#;--256B page + ELSIF TimingModel(16) = '1' THEN + CFI_array(16#04#) := 16#00#;--512B page + END IF; + CFI_array(16#05#) := 16#80#; + + CFI_array(16#06#) := 16#00#; + CFI_array(16#07#) := 16#00#; + CFI_array(16#08#) := 16#00#; + CFI_array(16#09#) := 16#00#; + CFI_array(16#0A#) := 16#00#; + CFI_array(16#0B#) := 16#00#; + CFI_array(16#0C#) := 16#00#; + CFI_array(16#0D#) := 16#00#; + CFI_array(16#0E#) := 16#00#; + CFI_array(16#0F#) := 16#00#; + --CFI Query Identification String + CFI_array(16#10#) := 16#51#; + CFI_array(16#11#) := 16#52#; + CFI_array(16#12#) := 16#59#; + CFI_array(16#13#) := 16#02#; + CFI_array(16#14#) := 16#00#; + CFI_array(16#15#) := 16#40#; + CFI_array(16#16#) := 16#00#; + CFI_array(16#17#) := 16#53#; + CFI_array(16#18#) := 16#46#; + CFI_array(16#19#) := 16#51#; + CFI_array(16#1A#) := 16#00#; + --CFI system interface string + CFI_array(16#1B#) := 16#27#; + CFI_array(16#1C#) := 16#36#; + CFI_array(16#1D#) := 16#00#; + CFI_array(16#1E#) := 16#00#; + CFI_array(16#1F#) := 16#06#; + IF TimingModel(16) = '0' THEN + CFI_array(16#20#) := 16#08#;--256B page + CFI_array(16#21#) := 16#08#;--64KB + ELSIF TimingModel(16) = '1' THEN + CFI_array(16#20#) := 16#09#;--512B page + CFI_array(16#21#) := 16#09#;--256KB + END IF; + + CFI_array(16#22#) := 16#10#; + CFI_array(16#23#) := 16#02#; + CFI_array(16#24#) := 16#02#; + CFI_array(16#25#) := 16#03#; + CFI_array(16#26#) := 16#03#; + --Device Geometry Definition + CFI_array(16#27#) := 16#19#; + CFI_array(16#28#) := 16#02#; + CFI_array(16#29#) := 16#01#; + IF TimingModel(16) = '0' THEN + CFI_array(16#2A#) := 16#08#;--256B page + ELSIF TimingModel(16) = '1' THEN + CFI_array(16#2A#) := 16#09#;--512B page + END IF; + CFI_array(16#2B#) := 16#00#; + IF TimingModel(16) = '1' THEN + CFI_array(16#2C#) := 16#01#; --Uniform Device + CFI_array(16#2D#) := 16#7F#; + CFI_array(16#2E#) := 16#00#; + CFI_array(16#2F#) := 16#00#; + CFI_array(16#30#) := 16#04#; + CFI_array(16#31#) := 16#FF#; + CFI_array(16#32#) := 16#FF#; + CFI_array(16#33#) := 16#FF#; + CFI_array(16#34#) := 16#FF#; + ELSE + CFI_array(16#2C#) := 16#02#; --Boot device + IF TBPARM = '1' THEN + CFI_array(16#2D#) := 16#FD#; + CFI_array(16#2E#) := 16#00#; + CFI_array(16#2F#) := 16#00#; + CFI_array(16#30#) := 16#01#; + CFI_array(16#31#) := 16#1F#; + CFI_array(16#32#) := 16#01#; + CFI_array(16#33#) := 16#10#; + CFI_array(16#34#) := 16#00#; + ELSE + CFI_array(16#2D#) := 16#1F#; + CFI_array(16#2E#) := 16#00#; + CFI_array(16#2F#) := 16#10#; + CFI_array(16#30#) := 16#00#; + CFI_array(16#31#) := 16#FD#; + CFI_array(16#32#) := 16#01#; + CFI_array(16#33#) := 16#00#; + CFI_array(16#34#) := 16#01#; + END IF; + END IF; + CFI_array(16#35#) := 16#FF#; + CFI_array(16#36#) := 16#FF#; + CFI_array(16#37#) := 16#FF#; + CFI_array(16#38#) := 16#FF#; + CFI_array(16#39#) := 16#FF#; + CFI_array(16#3A#) := 16#FF#; + CFI_array(16#3B#) := 16#FF#; + CFI_array(16#3C#) := 16#FF#; + CFI_array(16#3D#) := 16#FF#; + CFI_array(16#3E#) := 16#FF#; + CFI_array(16#3F#) := 16#FF#; + --CFI Primary Vendor-Specific Extended Query + CFI_array(16#40#) := 16#50#; + CFI_array(16#41#) := 16#52#; + CFI_array(16#42#) := 16#49#; + CFI_array(16#43#) := 16#31#; + CFI_array(16#44#) := 16#33#; + CFI_array(16#45#) := 16#21#; + CFI_array(16#46#) := 16#02#; + CFI_array(16#47#) := 16#01#; + CFI_array(16#48#) := 16#00#; + CFI_array(16#49#) := 16#08#; + CFI_array(16#4A#) := 16#00#; + CFI_array(16#4B#) := 16#01#; + CFI_array(16#4C#) := 16#00#; + CFI_array(16#4D#) := 16#00#; + CFI_array(16#4E#) := 16#00#; + CFI_array(16#4F#) := 16#07#; + CFI_array(16#50#) := 16#01#; + + CFI_array_tmp :=to_slv(CFI_array(16#00#), 8) & + to_slv(CFI_array(16#01#), 8) & + to_slv(CFI_array(16#02#), 8) & + to_slv(CFI_array(16#03#), 8) & + to_slv(CFI_array(16#04#), 8) & + to_slv(CFI_array(16#05#), 8) & + to_slv(CFI_array(16#06#), 8) & + to_slv(CFI_array(16#07#), 8) & + to_slv(CFI_array(16#08#), 8) & + to_slv(CFI_array(16#09#), 8) & + to_slv(CFI_array(16#0A#), 8) & + to_slv(CFI_array(16#0B#), 8) & + to_slv(CFI_array(16#0C#), 8) & + to_slv(CFI_array(16#0D#), 8) & + to_slv(CFI_array(16#0E#), 8) & + to_slv(CFI_array(16#0F#), 8) & + to_slv(CFI_array(16#10#), 8) & + to_slv(CFI_array(16#11#), 8) & + to_slv(CFI_array(16#12#), 8) & + to_slv(CFI_array(16#13#), 8) & + to_slv(CFI_array(16#14#), 8) & + to_slv(CFI_array(16#15#), 8) & + to_slv(CFI_array(16#16#), 8) & + to_slv(CFI_array(16#17#), 8) & + to_slv(CFI_array(16#18#), 8) & + to_slv(CFI_array(16#19#), 8) & + to_slv(CFI_array(16#1A#), 8) & + to_slv(CFI_array(16#1B#), 8) & + to_slv(CFI_array(16#1C#), 8) & + to_slv(CFI_array(16#1D#), 8) & + to_slv(CFI_array(16#1E#), 8) & + to_slv(CFI_array(16#1F#), 8) & + to_slv(CFI_array(16#20#), 8) & + to_slv(CFI_array(16#21#), 8) & + to_slv(CFI_array(16#22#), 8) & + to_slv(CFI_array(16#23#), 8) & + to_slv(CFI_array(16#24#), 8) & + to_slv(CFI_array(16#25#), 8) & + to_slv(CFI_array(16#26#), 8) & + to_slv(CFI_array(16#27#), 8) & + to_slv(CFI_array(16#28#), 8) & + to_slv(CFI_array(16#29#), 8) & + to_slv(CFI_array(16#2A#), 8) & + to_slv(CFI_array(16#2B#), 8) & + to_slv(CFI_array(16#2C#), 8) & + to_slv(CFI_array(16#2D#), 8) & + to_slv(CFI_array(16#2E#), 8) & + to_slv(CFI_array(16#2F#), 8) & + to_slv(CFI_array(16#30#), 8) & + to_slv(CFI_array(16#31#), 8) & + to_slv(CFI_array(16#32#), 8) & + to_slv(CFI_array(16#33#), 8) & + to_slv(CFI_array(16#34#), 8) & + to_slv(CFI_array(16#35#), 8) & + to_slv(CFI_array(16#36#), 8) & + to_slv(CFI_array(16#37#), 8) & + to_slv(CFI_array(16#38#), 8) & + to_slv(CFI_array(16#39#), 8) & + to_slv(CFI_array(16#3A#), 8) & + to_slv(CFI_array(16#3B#), 8) & + to_slv(CFI_array(16#3C#), 8) & + to_slv(CFI_array(16#3D#), 8) & + to_slv(CFI_array(16#3E#), 8) & + to_slv(CFI_array(16#3F#), 8) & + to_slv(CFI_array(16#40#), 8) & + to_slv(CFI_array(16#41#), 8) & + to_slv(CFI_array(16#42#), 8) & + to_slv(CFI_array(16#43#), 8) & + to_slv(CFI_array(16#44#), 8) & + to_slv(CFI_array(16#45#), 8) & + to_slv(CFI_array(16#46#), 8) & + to_slv(CFI_array(16#47#), 8) & + to_slv(CFI_array(16#48#), 8) & + to_slv(CFI_array(16#49#), 8) & + to_slv(CFI_array(16#4A#), 8) & + to_slv(CFI_array(16#4B#), 8) & + to_slv(CFI_array(16#4C#), 8) & + to_slv(CFI_array(16#4D#), 8) & + to_slv(CFI_array(16#4E#), 8) & + to_slv(CFI_array(16#4F#), 8) & + to_slv(CFI_array(16#50#), 8); + + WAIT; + + END PROCESS CFIPreload; + + AspRegInit: PROCESS(ASP_INIT) + BEGIN + IF ASP_INIT = 0 THEN + ASP_reg := to_slv(16#FE4F#,16); + ELSE + ASP_reg := to_slv(16#FE7F#,16); + END IF; + END PROCESS AspRegInit; + + TopBottom: PROCESS(change_TBPARM, PoweredUp) + BEGIN + IF (TimingModel(16)= '0') THEN + IF TBPARM = '0' THEN + BottomBoot <= TRUE; + b_act := 1; + ELSE + TopBoot <= TRUE; + BottomBoot <= FALSE; + b_act := 0; + END IF; + END IF; + END PROCESS TopBottom; + + Protect : PROCESS(change_BP) + BEGIN + IF rising_edge(change_BP) THEN + + CASE BP_bits IS + WHEN "000" => + Sec_Prot := (OTHERS => '0'); + WHEN "001" => + IF TBPROT = '0' THEN + Sec_Prot(SecNumMax downto ((SecNum+1)*63/64+30*b_act)) + := (OTHERS => '1'); + Sec_Prot(((SecNum+1)*63/64 + 30*b_act) - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/64 + 30*b_act - 1 downto 0) + := (OTHERS => '1'); + Sec_Prot(SecNumMax downto (SecNum+1)/64 + 30*b_act) + := (OTHERS => '0'); + END IF; + WHEN "010" => + IF TBPROT = '0' THEN + Sec_Prot(SecNumMax downto ((SecNum+1)*31/32+30*b_act)) + := (OTHERS => '1'); + Sec_Prot(((SecNum+1)*31/32+30*b_act) - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/32 + 30*b_act - 1 downto 0) + := (others => '1'); + Sec_Prot(SecNumMax downto (SecNum+1)/32 + 30*b_act) + := (OTHERS => '0'); + END IF; + WHEN "011" => + IF TBPROT = '0' THEN + Sec_Prot(SecNumMax downto ((SecNum+1)*15/16+30*b_act)) + := (OTHERS => '1'); + Sec_Prot(((SecNum+1)*15/16 + 30*b_act) - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/16 + 30*b_act - 1 downto 0) + := (OTHERS => '1'); + Sec_Prot(SecNumMax downto (SecNum+1)/16 + 30*b_act) + := (OTHERS => '0'); + END IF; + WHEN "100" => + IF TBPROT = '0' THEN + Sec_Prot(SecNumMax downto ((SecNum+1)*7/8 + 30*b_act)) + := (OTHERS => '1'); + Sec_Prot(((SecNum+1)*7/8 + 30*b_act) - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/8 + 30*b_act - 1 downto 0) + := (OTHERS => '1'); + Sec_Prot(SecNumMax downto (SecNum+1)/8 + 30*b_act) + := (OTHERS => '0'); + END IF; + WHEN "101" => + IF TBPROT = '0' THEN + Sec_Prot(SecNumMax downto ((SecNum+1)*3/4 + 30*b_act)) + := (OTHERS => '1'); + Sec_Prot(((SecNum+1)*3/4 + 30*b_act) - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/4 + 30*b_act - 1 downto 0) + := (OTHERS => '1'); + Sec_Prot(SecNumMax downto (SecNum+1)/4 + 30*b_act) + := (OTHERS => '0'); + END IF; + + WHEN "110" => + IF TBPROT = '0' THEN + Sec_Prot(SecNumMax downto ((SecNum+1)/2 + 30*b_act)) + := (OTHERS => '1'); + Sec_Prot(((SecNum+1)/2 + 30*b_act) - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/2 + 30*b_act - 1 downto 0) + := (OTHERS => '1'); + Sec_Prot(SecNumMax downto (SecNum+1)/2 + 30*b_act) + := (OTHERS => '0'); + END IF; + + WHEN OTHERS => + Sec_Prot := (OTHERS => '1'); + END CASE; + END IF; + END PROCESS Protect; + + HOLD_FRAME_ON_PO_ZD : PROCESS(SOut_zd, SIOut_zd, HOLDNeg_pullup) + BEGIN + IF (HOLDNeg_pullup = '0' AND QUAD /= '1') THEN + hold_mode := TRUE; + SIOut_z <= 'Z'; + SOut_z <= 'Z'; + ELSE + IF hold_mode THEN + SIOut_z <= SIOut_zd AFTER tpd_HOLDNeg_SO(trz0); + SOut_z <= SOut_zd AFTER tpd_HOLDNeg_SO(trz0); + hold_mode := FALSE; + ELSE + SIOut_z <= SIOut_zd; + SOut_z <= SOut_zd; + hold_mode := FALSE; + END IF; + END IF; + END PROCESS HOLD_FRAME_ON_PO_ZD; + + HOLD_PULL_UP : PROCESS(HOLDNegIn) + BEGIN + IF (QUAD = '0') THEN + IF (HOLDNegIn = 'Z') THEN + HOLDNeg_pullup <= '1'; + ELSE + HOLDNeg_pullup <= HOLDNegIn; + END IF; + END IF; + END PROCESS HOLD_PULL_UP; + + WP_PULL_UP : PROCESS(WPNegIn) + BEGIN + IF (QUAD = '0') THEN + IF (WPNegIn = 'Z') THEN + WPNeg_pullup <= '1'; + ELSE + WPNeg_pullup <= WPNegIn; + END IF; + END IF; + END PROCESS WP_PULL_UP; + + RST_PULL_UP : PROCESS(RSTNeg) + BEGIN + IF (RSTNeg = 'Z') THEN + RSTNeg_pullup <= '1'; + ELSE + RSTNeg_pullup <= RSTNeg; + END IF; + END PROCESS RST_PULL_UP; + + --------------------------------------------------------------------------- + ---- File Read Section - Preload Control + --------------------------------------------------------------------------- + MemPreload : PROCESS + + -- text file input variables + FILE mem_file : text is mem_file_name; + FILE otp_file : text is otp_file_name; + VARIABLE ind : NATURAL RANGE 0 TO AddrRANGE := 0; + VARIABLE otp_ind : NATURAL RANGE 16#000# TO 16#3FF# := 16#000#; + VARIABLE buf : line; + + BEGIN + --------------------------------------------------------------------------- + --s25fl256s memory preload file format +----------------------------------- + --------------------------------------------------------------------------- + -- / - comment + -- @aaaaaa - stands for address + -- dd -
is byte to be written at Mem(aaaaaa++) + -- (aaaaaa is incremented at every load) + -- only first 1-7 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + --------------------------------------------------------------------------- + + -- memory preload + IF (mem_file_name /= "none" AND UserPreload) THEN + ind := 0; + Mem := (OTHERS => MaxData); + WHILE (not ENDFILE (mem_file)) LOOP + READLINE (mem_file, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + IF ind > AddrRANGE THEN + ASSERT false + REPORT "Given preload address is out of" & + "memory address range" + SEVERITY warning; + ELSE + ind := h(buf(2 to 8)); --address + END IF; + ELSE + Mem(ind) := h(buf(1 to 2)); + IF ind < AddrRANGE THEN + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + --------------------------------------------------------------------------- + --s25fl256s_otp memory preload file format + --------------------------------------------------------------------------- + -- / - comment + -- @aaa - stands for address + -- dd -
is byte to be written at OTPMem(aaa++) + -- (aaa is incremented at every load) + -- only first 1-4 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + --------------------------------------------------------------------------- + + -- memory preload + IF (otp_file_name /= "none" AND UserPreload) THEN + otp_ind := 16#000#; + OTPMem := (OTHERS => MaxData); + WHILE (not ENDFILE (otp_file)) LOOP + READLINE (otp_file, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + IF otp_ind > 16#3FF# OR otp_ind < 16#000# THEN + ASSERT false + REPORT "Given preload address is out of" & + "OTP address range" + SEVERITY warning; + ELSE + otp_ind := h(buf(2 to 4)); --address + END IF; + ELSE + OTPMem(otp_ind) := h(buf(1 to 2)); + otp_ind := otp_ind + 1; + END IF; + END LOOP; + END IF; + + LOCK_BYTE1 := to_slv(OTPMem(16#10#),8); + LOCK_BYTE2 := to_slv(OTPMem(16#11#),8); + LOCK_BYTE3 := to_slv(OTPMem(16#12#),8); + LOCK_BYTE4 := to_slv(OTPMem(16#13#),8); + + WAIT; + END PROCESS MemPreload; + + ---------------------------------------------------------------------------- + -- Path Delay Section + ---------------------------------------------------------------------------- + + S_Out_PathDelay_Gen : PROCESS(SOut_z) + + VARIABLE SO_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => SOut, + OutSignalName => "SO", + OutTemp => SOut_z, + Mode => VitalTransport, + GlitchData => SO_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal), + PathCondition => NOT(ddr)), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR), + PathCondition => (ddr OR fast_rd)), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1'), + 3 => (InputChangeTime => HOLDNegIn'LAST_EVENT, + PathDelay => tpd_HOLDNeg_SO, + PathCondition => QUAD = '0') + ) + ); + END PROCESS; + + SI_Out_PathDelay : PROCESS(SIOut_z) + + VARIABLE SI_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => SIOut, + OutSignalName => "SI", + OutTemp => SIOut_z, + Mode => VitalTransport, + GlitchData => SI_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal), + PathCondition => dual AND NOT(ddr)), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR), + PathCondition => dual AND ddr), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1'), + 3 => (InputChangeTime => HOLDNegIn'LAST_EVENT, + PathDelay => tpd_HOLDNeg_SO, + PathCondition => dual AND QUAD = '0') + ) + ); + END PROCESS; + + HOLD_Out_PathDelay : PROCESS(HOLDNegOut_zd) + + VARIABLE HOLD_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => HOLDNegOut, + OutSignalName => "HOLDNeg", + OutTemp => HOLDNegOut_zd, + Mode => VitalTransport, + GlitchData => HOLD_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal), + PathCondition => dual AND not(ddr) AND QUAD = '1'), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR), + PathCondition => ddr AND QUAD = '1'), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND + HOLDNegOut_zd = 'Z' AND QUAD = '1') + ) + ); + END PROCESS; + + WP_Out_PathDelay : PROCESS(WPNegOut_zd) + + VARIABLE WP_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => WPNegOut, + OutSignalName => "WPNeg", + OutTemp => WPNegOut_zd, + Mode => VitalTransport, + GlitchData => WP_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal), + PathCondition => dual AND not(ddr) AND QUAD = '1'), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR), + PathCondition => ddr AND QUAD = '1'), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND + WPNegOut_zd = 'Z' AND QUAD = '1') + ) + ); + END PROCESS; + + END BLOCK behavior; +END vhdl_behavioral; \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl256s/model/s25fl256s_ver.ftm b/lib/models/memory/flash/serial/S25fl256s/model/s25fl256s_ver.ftm new file mode 100644 index 0000000..341b37c --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl256s/model/s25fl256s_ver.ftm @@ -0,0 +1,725 @@ + +FMF Timing for s25fl256s Parts + + +version: | author: | mod date: | changes made: + V1.0 R. Prokopovic 09 Nov 27 Initial release + V1.1 V.Mancev 10 Oct 20 Latest datasheet aligned + V1.2 B.Colakovic 11 June 29 Latest datasheet aligned + V1.3 V.Mancev 11 Nov 17 Time tHO is changed to 1 ns + +1ns +s25fl256s + +S25FL256SAGMFI000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR01_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR11_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR01_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR11_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI200_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI203_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI210_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI213_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI300_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI303_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI310_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI313_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV200_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV203_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV210_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV213_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV300_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV303_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV310_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV313_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for VIO=VCC=2.7V to 3.6V, CL=30pF + +(DELAY (ABSOLUTE + (COND ~ddr (IOPATH SCK SO (5.4:6.7:8) (5.4:6.7:8) (1) (5.4:6.7:8) (1) (5.4:6.7:8))) + (COND (ddr || rd_fast) (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && dual (IOPATH SCK SI (5.4:6.7:8) (5.4:6.7:8) (1) (5.4:6.7:8) (1) (5.4:6.7:8))) + (COND ddr && dual (IOPATH SCK SI (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND ~ddr && QUAD (IOPATH SCK HOLDNeg (5.4:6.7:8) (5.4:6.7:8) (1) (5.4:6.7:8) (1) (5.4:6.7:8))) + (COND ddr && QUAD (IOPATH SCK HOLDNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && QUAD (IOPATH SCK WPNeg (5.4:6.7:8) (5.4:6.7:8) (1) (5.4:6.7:8) (1) (5.4:6.7:8))) + (COND ddr && QUAD (IOPATH SCK WPNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && dual (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~QUAD (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND ~QUAD && dual (IOPATH HOLDNeg SI () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP CSNeg (COND sdr_rd SCK) (3)) + (SETUP CSNeg (COND ddr_rd SCK) (3)) + (SETUP SI (COND deg_sin(posedge SCK)) (3)) + (SETUP SI (COND ddro(posedge SCK)) (2)) + (SETUP SI (COND ddro(negedge SCK)) (2)) + (SETUP WPNeg (COND wr_prot(negedge CSNeg)) (20)) + (SETUP HOLDNeg (COND quad_rd (posedge SCK)) (3)) + (SETUP RSTNeg CSNeg (50)) + + (HOLD CSNeg (COND sdr_rd SCK) (3)) + (HOLD CSNeg (COND ddr_rd SCK) (3)) + (HOLD SI (COND deg_sin (posedge SCK)) (2)) + (HOLD SI (COND ddro (posedge SCK)) (2)) + (HOLD SI (COND ddro (negedge SCK)) (2)) + (HOLD WPNeg (COND wr_prot (posedge CSNeg)) (100)) + (HOLD HOLDNeg (COND quad_rd (posedge SCK)) (3)) + (HOLD CSNeg RSTNeg (35000)) + + (WIDTH (COND rd (posedge SCK)) (10)) + (WIDTH (COND rd (negedge SCK)) (10)) + (WIDTH (COND dual_rd (posedge SCK)) (4.8)) + (WIDTH (COND dual_rd (negedge SCK)) (4.8)) + (WIDTH (COND fast_rd (negedge SCK)) (3.75)) + (WIDTH (COND fast_rd (posedge SCK)) (3.75)) + (WIDTH (COND quadpg (posedge SCK)) (6.25)) + (WIDTH (COND quadpg (negedge SCK)) (6.25)) + (WIDTH (COND ddrd (posedge SCK)) (7.5)) + (WIDTH (COND ddrd (negedge SCK)) (7.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (7.52)) + (PERIOD (COND dual_rd SCK) (9.6)) + (PERIOD (COND quadpg SCK) (12.5)) + (PERIOD (COND ddrd SCK) (15)) +) + + + +S25FL256SAGMFI000_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI001_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI003_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR01_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR11_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV000_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV001_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV003_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR01_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR11_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI000_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI001_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI003_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV000_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV001_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV003_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI200_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI203_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI210_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI213_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI300_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI303_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI310_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI313_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV200_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV203_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV210_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV213_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV300_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV303_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV310_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV313_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=30pF + +(DELAY (ABSOLUTE + (COND ~ddr (IOPATH SCK SO (4.3:6.0:7.65) (4.3:6.0:7.65) (1) (4.3:6.0:7.65) (1) (4.3:6.0:7.65))) + (COND (ddr || rd_fast) (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && dual (IOPATH SCK SI (4.3:6.0:7.65) (4.3:6.0:7.65) (1) (4.3:6.0:7.65) (1) (4.3:6.0:7.65))) + (COND ddr && dual (IOPATH SCK SI (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND ~ddr && QUAD (IOPATH SCK HOLDNeg (4.3:6.0:7.65) (4.3:6.0:7.65) (1) (4.3:6.0:7.65) (1) (4.3:6.0:7.65))) + (COND ddr && QUAD (IOPATH SCK HOLDNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && QUAD (IOPATH SCK WPNeg (4.3:6.0:7.65) (4.3:6.0:7.65) (1) (4.3:6.0:7.65) (1) (4.3:6.0:7.65))) + (COND ddr && QUAD (IOPATH SCK WPNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && dual (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~QUAD (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND ~QUAD && dual (IOPATH HOLDNeg SI () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP CSNeg (COND sdr_rd SCK) (3)) + (SETUP CSNeg (COND ddr_rd SCK) (3)) + (SETUP SI (COND deg_sin(posedge SCK)) (3)) + (SETUP SI (COND ddro(posedge SCK)) (2)) + (SETUP SI (COND ddro(negedge SCK)) (2)) + (SETUP WPNeg (COND wr_prot(negedge CSNeg)) (20)) + (SETUP HOLDNeg (COND quad_rd (posedge SCK)) (3)) + (SETUP RSTNeg CSNeg (50)) + + (HOLD CSNeg (COND sdr_rd SCK) (3)) + (HOLD CSNeg (COND ddr_rd SCK) (3)) + (HOLD SI (COND deg_sin (posedge SCK)) (2)) + (HOLD SI (COND ddro (posedge SCK)) (2)) + (HOLD SI (COND ddro (negedge SCK)) (2)) + (HOLD WPNeg (COND wr_prot (posedge CSNeg)) (100)) + (HOLD HOLDNeg (COND quad_rd (posedge SCK)) (3)) + (HOLD CSNeg RSTNeg (35000)) + + (WIDTH (COND rd (posedge SCK)) (10)) + (WIDTH (COND rd (negedge SCK)) (10)) + (WIDTH (COND dual_rd (posedge SCK)) (4.8)) + (WIDTH (COND dual_rd (negedge SCK)) (4.8)) + (WIDTH (COND fast_rd (negedge SCK)) (3.75)) + (WIDTH (COND fast_rd (posedge SCK)) (3.75)) + (WIDTH (COND quadpg (posedge SCK)) (6.25)) + (WIDTH (COND quadpg (negedge SCK)) (6.25)) + (WIDTH (COND ddrd (posedge SCK)) (7.5)) + (WIDTH (COND ddrd (negedge SCK)) (7.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (7.52)) + (PERIOD (COND dual_rd SCK) (9.6)) + (PERIOD (COND quadpg SCK) (12.5)) + (PERIOD (COND ddrd SCK) (15)) +) + + + +S25FL256SAGMFI000_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI001_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI003_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR01_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR11_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV000_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV001_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV003_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR01_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR11_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI000_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI001_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI003_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV000_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV001_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV003_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI200_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI203_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI210_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI213_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI300_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI303_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI310_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI313_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV200_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV203_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV210_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV213_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV300_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV303_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV310_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV313_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=15pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND ~ddr (IOPATH SCK SO (4.5:5.5:6.5) (4.5:5.5:6.5) (1) (4.5:5.5:6.5) (1) (4.5:5.5:6.5))) + (COND (ddr || rd_fast) (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && dual (IOPATH SCK SI (4.5:5.5:6.5) (4.5:5.5:6.5) (1) (4.5:5.5:6.5) (1) (4.5:5.5:6.5))) + (COND ddr && dual (IOPATH SCK SI (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND ~ddr && QUAD (IOPATH SCK HOLDNeg (4.5:5.5:6.5) (4.5:5.5:6.5) (1) (4.5:5.5:6.5) (1) (4.5:5.5:6.5))) + (COND ddr && QUAD (IOPATH SCK HOLDNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && QUAD (IOPATH SCK WPNeg (4.5:5.5:6.5) (4.5:5.5:6.5) (1) (4.5:5.5:6.5) (1) (4.5:5.5:6.5))) + (COND ddr && QUAD (IOPATH SCK WPNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && dual (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~QUAD (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND ~QUAD && dual (IOPATH HOLDNeg SI () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP CSNeg (COND sdr_rd SCK) (3)) + (SETUP CSNeg (COND ddr_rd SCK) (3)) + (SETUP SI (COND deg_sin(posedge SCK)) (3)) + (SETUP SI (COND ddro(posedge SCK)) (2)) + (SETUP SI (COND ddro(negedge SCK)) (2)) + (SETUP WPNeg (COND wr_prot(negedge CSNeg)) (20)) + (SETUP HOLDNeg (COND quad_rd (posedge SCK)) (3)) + (SETUP RSTNeg CSNeg (50)) + + (HOLD CSNeg (COND sdr_rd SCK) (3)) + (HOLD CSNeg (COND ddr_rd SCK) (3)) + (HOLD SI (COND deg_sin (posedge SCK)) (2)) + (HOLD SI (COND ddro (posedge SCK)) (2)) + (HOLD SI (COND ddro (negedge SCK)) (2)) + (HOLD WPNeg (COND wr_prot (posedge CSNeg)) (100)) + (HOLD HOLDNeg (COND quad_rd (posedge SCK)) (3)) + (HOLD CSNeg RSTNeg (35000)) + + (WIDTH (COND rd (posedge SCK)) (10)) + (WIDTH (COND rd (negedge SCK)) (10)) + (WIDTH (COND dual_rd (posedge SCK)) (4.8)) + (WIDTH (COND dual_rd (negedge SCK)) (4.8)) + (WIDTH (COND fast_rd (negedge SCK)) (3.75)) + (WIDTH (COND fast_rd (posedge SCK)) (3.75)) + (WIDTH (COND quadpg (posedge SCK)) (6.25)) + (WIDTH (COND quadpg (negedge SCK)) (6.25)) + (WIDTH (COND ddrd (posedge SCK)) (7.5)) + (WIDTH (COND ddrd (negedge SCK)) (7.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (7.52)) + (PERIOD (COND dual_rd SCK) (9.6)) + (PERIOD (COND quadpg SCK) (12.5)) + (PERIOD (COND ddrd SCK) (15)) +) + + + +S25FL256SDPMFIR00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR01_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR11_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI200_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI203_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI210_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI213_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI300_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI303_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI310_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI313_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHIC00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHIC03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHIC10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHIC13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHID00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHID03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHID10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHID13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for Vcc range VCC=2.7V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND ~ddr (IOPATH SCK SO (1.5:8:14.5) (1.5:8:14.5) (1) (1.5:8:14.5) (1) (1.5:8:14.5))) + (COND (ddr || rd_fast) (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && dual (IOPATH SCK SI (1.5:8:14.5) (1.5:8:14.5) (1) (1.5:8:14.5) (1) (1.5:8:14.5))) + (COND ddr && dual (IOPATH SCK SI (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND ~ddr && QUAD (IOPATH SCK HOLDNeg (1.5:8:14.5) (1.5:8:14.5) (1) (1.5:8:14.5) (1) (1.5:8:14.5))) + (COND ddr && QUAD (IOPATH SCK HOLDNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && QUAD (IOPATH SCK WPNeg (1.5:8:14.5) (1.5:8:14.5) (1) (1.5:8:14.5) (1) (1.5:8:14.5))) + (COND ddr && QUAD (IOPATH SCK WPNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && dual (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~QUAD (IOPATH HOLDNeg SO () () (7:10.5:14) (7:10.5:14) (7:10.5:14) (7:10.5:14))) + (COND ~QUAD && dual (IOPATH HOLDNeg SI () () (7:10.5:14) (7:10.5:14) (7:10.5:14) (7:10.5:14))) + + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP CSNeg (COND sdr_rd SCK) (3)) + (SETUP CSNeg (COND ddr_rd SCK) (3)) + (SETUP SI (COND deg_sin(posedge SCK)) (5)) + (SETUP SI (COND ddro(posedge SCK)) (2)) + (SETUP SI (COND ddro(negedge SCK)) (2)) + (SETUP WPNeg (COND wr_prot(negedge CSNeg)) (20)) + (SETUP HOLDNeg (COND quad_rd (posedge SCK)) (5)) + (SETUP RSTNeg CSNeg (50)) + + (HOLD CSNeg (COND sdr_rd SCK) (3)) + (HOLD CSNeg (COND ddr_rd SCK) (3)) + (HOLD SI (COND deg_sin (posedge SCK)) (4)) + (HOLD SI (COND ddro (posedge SCK)) (2)) + (HOLD SI (COND ddro (negedge SCK)) (2)) + (HOLD WPNeg (COND wr_prot (posedge CSNeg)) (100)) + (HOLD HOLDNeg (COND quad_rd (posedge SCK)) (5)) + (HOLD CSNeg RSTNeg (35000)) + + (WIDTH (COND rd (posedge SCK)) (10)) + (WIDTH (COND rd (negedge SCK)) (10)) + (WIDTH (COND dual_rd (posedge SCK)) (7.5)) + (WIDTH (COND dual_rd (negedge SCK)) (7.5)) + (WIDTH (COND fast_rd (negedge SCK)) (7.5)) + (WIDTH (COND fast_rd (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (negedge SCK)) (7.5)) + (WIDTH (COND ddrd (posedge SCK)) (7.5)) + (WIDTH (COND ddrd (negedge SCK)) (7.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (15)) + (PERIOD (COND dual_rd SCK) (15)) + (PERIOD (COND quadpg SCK) (15)) + (PERIOD (COND ddrd SCK) (15)) +) + + + +S25FL256SDPMFIR00_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR01_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR03_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR10_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR11_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR13_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI000_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI001_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI003_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI010_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI011_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI013_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI200_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI203_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI210_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI213_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI300_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI303_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI310_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI313_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHIC00_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHIC03_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHIC10_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHIC13_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHID00_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHID03_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHID10_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHID13_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for Vcc range VCC=2.7V to 3.6V, CL=15pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND ~ddr (IOPATH SCK SO (2:7:12) (2:7:12) (1) (2:7:12) (1) (2:7:12))) + (COND (ddr || rd_fast) (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && dual (IOPATH SCK SI (2:7:12) (2:7:12) (1) (2:7:12) (1) (2:7:12))) + (COND ddr && dual (IOPATH SCK SI (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND ~ddr && QUAD (IOPATH SCK HOLDNeg (2:7:12) (2:7:12) (1) (2:7:12) (1) (2:7:12))) + (COND ddr && QUAD (IOPATH SCK HOLDNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && QUAD (IOPATH SCK WPNeg (2:7:12) (2:7:12) (1) (2:7:12) (1) (2:7:12))) + (COND ddr && QUAD (IOPATH SCK WPNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && dual (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~QUAD (IOPATH HOLDNeg SO () () (7:10.5:14) (7:10.5:14) (7:10.5:14) (7:10.5:14))) + (COND ~QUAD && dual (IOPATH HOLDNeg SI () () (7:10.5:14) (7:10.5:14) (7:10.5:14) (7:10.5:14))) + + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP CSNeg (COND sdr_rd SCK) (3)) + (SETUP CSNeg (COND ddr_rd SCK) (3)) + (SETUP SI (COND deg_sin(posedge SCK)) (5)) + (SETUP SI (COND ddro(posedge SCK)) (2)) + (SETUP SI (COND ddro(negedge SCK)) (2)) + (SETUP WPNeg (COND wr_prot(negedge CSNeg)) (20)) + (SETUP HOLDNeg (COND quad_rd (posedge SCK)) (5)) + (SETUP RSTNeg CSNeg (50)) + + (HOLD CSNeg (COND sdr_rd SCK) (3)) + (HOLD CSNeg (COND ddr_rd SCK) (3)) + (HOLD SI (COND deg_sin (posedge SCK)) (4)) + (HOLD SI (COND ddro (posedge SCK)) (2)) + (HOLD SI (COND ddro (negedge SCK)) (2)) + (HOLD WPNeg (COND wr_prot (posedge CSNeg)) (100)) + (HOLD HOLDNeg (COND quad_rd (posedge SCK)) (5)) + (HOLD CSNeg RSTNeg (35000)) + + (WIDTH (COND rd (posedge SCK)) (10)) + (WIDTH (COND rd (negedge SCK)) (10)) + (WIDTH (COND dual_rd (posedge SCK)) (7.5)) + (WIDTH (COND dual_rd (negedge SCK)) (7.5)) + (WIDTH (COND fast_rd (negedge SCK)) (7.5)) + (WIDTH (COND fast_rd (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (negedge SCK)) (7.5)) + (WIDTH (COND ddrd (posedge SCK)) (7.5)) + (WIDTH (COND ddrd (negedge SCK)) (7.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (15)) + (PERIOD (COND dual_rd SCK) (15)) + (PERIOD (COND quadpg SCK) (15)) + (PERIOD (COND ddrd SCK) (15)) +) + + \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl256s/model/s25fl256s_vhd.ftm b/lib/models/memory/flash/serial/S25fl256s/model/s25fl256s_vhd.ftm new file mode 100644 index 0000000..fa35d87 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl256s/model/s25fl256s_vhd.ftm @@ -0,0 +1,781 @@ + +FMF Timing for s25fl256s Parts + + +version: | author: | mod date: | changes made: + V1.0 V.Mancev 09 Nov 26 Initial release + V1.1 V.Mancev 11 July 04 Latest datasheet aligned + V1.2 V.Mancev 11 Nov 17 Time tHO is changed to 1 ns + +1ns +s25fl256s + +S25FL256SAGMFI000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR01_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR11_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR01_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR11_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI200_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI203_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI210_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI213_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI300_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI303_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI310_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI313_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV200_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV203_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV210_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV213_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV300_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV303_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV310_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV313_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for VCC=2.7V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND normal (IOPATH SCK SO (5.4:6.7:8) (5.4:6.7:8) (1) (5.4:6.7:8) (1) (5.4:6.7:8))) + (COND DDR (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP (COND normal CSNeg) (posedge SCK) (3)) + (SETUP (COND DDR CSNeg) (posedge SCK) (3)) + (SETUP (COND normal SI) (posedge SCK) (3)) + (SETUP WPNeg CSNeg (20)) + (SETUP HOLDNeg SCK (3)) + (SETUP RSTNeg CSNeg (50)) + (SETUP (COND DDR SI) (posedge SCK) (2)) + (SETUP (COND DDR SI) (negedge SCK) (2)) + + (HOLD (COND normal CSNeg) (posedge SCK) (3)) + (HOLD (COND DDR CSNeg) (posedge SCK) (3)) + (HOLD (COND normal SI) (posedge SCK) (2)) + (HOLD WPNeg CSNeg (100)) + (HOLD HOLDNeg SCK (3)) + (HOLD CSNeg RSTNeg (35000)) + (HOLD (COND DDR SI) (posedge SCK) (2)) + (HOLD (COND DDR SI) (negedge SCK) (2)) + + (WIDTH (COND serial (posedge SCK)) (10)) + (WIDTH (COND serial (negedge SCK)) (10)) + (WIDTH (COND dual (posedge SCK)) (4.8)) + (WIDTH (COND dual (negedge SCK)) (4.8)) + (WIDTH (COND fast (negedge SCK)) (3.75)) + (WIDTH (COND fast (posedge SCK)) (3.75)) + (WIDTH (COND quadpg (posedge SCK)) (6.25)) + (WIDTH (COND quadpg (negedge SCK)) (6.25)) + (WIDTH (COND DDR (posedge SCK)) (7.5)) + (WIDTH (COND DDR (negedge SCK)) (7.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgers (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND serial_rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (7.52)) + (PERIOD (COND dual_rd SCK) (9.6)) + (PERIOD (COND quadpg SCK) (12.5)) + (PERIOD (COND DDR_rd SCK) (15)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP256) (DELAY (ABSOLUTE (DEVICE(183e3:366e3:550e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP512) (DELAY (ABSOLUTE (DEVICE(250e3:500e3:750e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BP) (DELAY (ABSOLUTE (DEVICE(133e3:266e3:400e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE64) (DELAY (ABSOLUTE (DEVICE(217e6:434e6:650e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE256) (DELAY (ABSOLUTE (DEVICE(625e6:1250e6:1875e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(33e9:66e9:330e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WRR) (DELAY (ABSOLUTE(DEVICE(200e6:200e6:200e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300e3:300e3:300e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PRGSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/ERSSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PPBERASE) (DELAY (ABSOLUTE (DEVICE(15e6:15e6:15e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSULCK) (DELAY (ABSOLUTE (DEVICE(1000:1000:1000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSACC) (DELAY (ABSOLUTE (DEVICE(100e3:100e3:100e3) ) ) ) + + + +S25FL256SAGMFI000_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI001_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI003_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR01_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR11_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV000_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV001_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV003_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR01_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR11_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI000_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI001_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI003_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV000_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV001_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV003_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI200_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI203_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI210_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI213_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI300_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI303_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI310_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI313_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV200_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV203_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV210_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV213_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV300_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV303_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV310_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV313_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL00_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL03_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND normal (IOPATH SCK SO (4.3:6.0:7.65) (4.3:6.0:7.65) (1) (4.3:6.0:7.65) (1) (4.3:6.0:7.65))) + (COND DDR (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP (COND normal CSNeg) (posedge SCK) (3)) + (SETUP (COND DDR CSNeg) (posedge SCK) (3)) + (SETUP (COND normal SI) (posedge SCK) (3)) + (SETUP WPNeg CSNeg (20)) + (SETUP HOLDNeg SCK (3)) + (SETUP RSTNeg CSNeg (50)) + (SETUP (COND DDR SI) (posedge SCK) (2)) + (SETUP (COND DDR SI) (negedge SCK) (2)) + + (HOLD (COND normal CSNeg) (posedge SCK) (3)) + (HOLD (COND DDR CSNeg) (posedge SCK) (3)) + (HOLD (COND normal SI) (posedge SCK) (2)) + (HOLD WPNeg CSNeg (100)) + (HOLD HOLDNeg SCK (3)) + (HOLD CSNeg RSTNeg (35000)) + (HOLD (COND DDR SI) (posedge SCK) (2)) + (HOLD (COND DDR SI) (negedge SCK) (2)) + + (WIDTH (COND serial (posedge SCK)) (10)) + (WIDTH (COND serial (negedge SCK)) (10)) + (WIDTH (COND dual (posedge SCK)) (4.8)) + (WIDTH (COND dual (negedge SCK)) (4.8)) + (WIDTH (COND fast (negedge SCK)) (3.75)) + (WIDTH (COND fast (posedge SCK)) (3.75)) + (WIDTH (COND quadpg (posedge SCK)) (6.25)) + (WIDTH (COND quadpg (negedge SCK)) (6.25)) + (WIDTH (COND DDR (posedge SCK)) (7.5)) + (WIDTH (COND DDR (negedge SCK)) (7.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgers (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND serial_rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (7.52)) + (PERIOD (COND dual_rd SCK) (9.6)) + (PERIOD (COND quadpg SCK) (12.5)) + (PERIOD (COND DDR_rd SCK) (15)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP256) (DELAY (ABSOLUTE (DEVICE(183e3:366e3:550e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP512) (DELAY (ABSOLUTE (DEVICE(250e3:500e3:750e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BP) (DELAY (ABSOLUTE (DEVICE(133e3:266e3:400e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE64) (DELAY (ABSOLUTE (DEVICE(217e6:434e6:650e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE256) (DELAY (ABSOLUTE (DEVICE(625e6:1250e6:1875e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(33e9:66e9:330e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WRR) (DELAY (ABSOLUTE(DEVICE(200e6:200e6:200e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300e3:300e3:300e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PRGSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/ERSSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PPBERASE) (DELAY (ABSOLUTE (DEVICE(15e6:15e6:15e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSULCK) (DELAY (ABSOLUTE (DEVICE(1000:1000:1000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSACC) (DELAY (ABSOLUTE (DEVICE(100e3:100e3:100e3) ) ) ) + + + +S25FL256SAGMFI000_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI001_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI003_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFI013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR01_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR11_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFIR13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV000_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV001_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV003_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFV013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR01_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR11_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGMFVR13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI000_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI001_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI003_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFI013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV000_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV001_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV003_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGNFV013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI200_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI203_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI210_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI213_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI300_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI303_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI310_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHI313_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIA13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIB13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIC13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHID13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV200_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV203_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV210_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV213_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV300_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV303_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV310_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHV313_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVA13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVB13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVC13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHVD13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIY13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIZ13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIS13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIT13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIK13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL00_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL03_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SAGBHIL13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=15pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND normal (IOPATH SCK SO (4.5:5.5:6.5) (4.5:5.5:6.5) (1) (4.5:5.5:6.5) (1) (4.5:5.5:6.5))) + (COND DDR (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP (COND normal CSNeg) (posedge SCK) (3)) + (SETUP (COND DDR CSNeg) (posedge SCK) (3)) + (SETUP (COND normal SI) (posedge SCK) (3)) + (SETUP WPNeg CSNeg (20)) + (SETUP HOLDNeg SCK (3)) + (SETUP RSTNeg CSNeg (50)) + (SETUP (COND DDR SI) (posedge SCK) (2)) + (SETUP (COND DDR SI) (negedge SCK) (2)) + + (HOLD (COND normal CSNeg) (posedge SCK) (3)) + (HOLD (COND DDR CSNeg) (posedge SCK) (3)) + (HOLD (COND normal SI) (posedge SCK) (2)) + (HOLD WPNeg CSNeg (100)) + (HOLD HOLDNeg SCK (3)) + (HOLD CSNeg RSTNeg (35000)) + (HOLD (COND DDR SI) (posedge SCK) (2)) + (HOLD (COND DDR SI) (negedge SCK) (2)) + + (WIDTH (COND serial (posedge SCK)) (10)) + (WIDTH (COND serial (negedge SCK)) (10)) + (WIDTH (COND dual (posedge SCK)) (4.8)) + (WIDTH (COND dual (negedge SCK)) (4.8)) + (WIDTH (COND fast (negedge SCK)) (3.75)) + (WIDTH (COND fast (posedge SCK)) (3.75)) + (WIDTH (COND quadpg (posedge SCK)) (6.25)) + (WIDTH (COND quadpg (negedge SCK)) (6.25)) + (WIDTH (COND DDR (posedge SCK)) (7.5)) + (WIDTH (COND DDR (negedge SCK)) (7.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgers (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND serial_rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (7.52)) + (PERIOD (COND dual_rd SCK) (9.6)) + (PERIOD (COND quadpg SCK) (12.5)) + (PERIOD (COND DDR_rd SCK) (15)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP256) (DELAY (ABSOLUTE (DEVICE(183e3:366e3:550e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP512) (DELAY (ABSOLUTE (DEVICE(250e3:500e3:750e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BP) (DELAY (ABSOLUTE (DEVICE(133e3:266e3:400e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE64) (DELAY (ABSOLUTE (DEVICE(217e6:434e6:650e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE256) (DELAY (ABSOLUTE (DEVICE(625e6:1250e6:1875e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(33e9:66e9:330e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WRR) (DELAY (ABSOLUTE(DEVICE(200e6:200e6:200e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300e3:300e3:300e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PRGSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/ERSSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PPBERASE) (DELAY (ABSOLUTE (DEVICE(15e6:15e6:15e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSULCK) (DELAY (ABSOLUTE (DEVICE(1000:1000:1000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSACC) (DELAY (ABSOLUTE (DEVICE(100e3:100e3:100e3) ) ) ) + + + +S25FL256SDPMFIR00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR01_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR11_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI000_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI001_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI003_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI200_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI203_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI210_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI213_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI300_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI303_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI310_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI313_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHIC00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHIC03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHIC10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHIC13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHID00_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHID03_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHID10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHID13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND normal (IOPATH SCK SO (1.5:8:14.5) (1.5:8:14.5) (1) (1.5:8:14.5) (1) (1.5:8:14.5))) + (COND DDR (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + (IOPATH HOLDNeg SO () () (10:12:14) (10:12:14) (10:12:14) (10:12:14)) + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP (COND normal CSNeg) (posedge SCK) (3)) + (SETUP (COND DDR CSNeg) (posedge SCK) (3)) + (SETUP (COND normal SI) (posedge SCK) (5)) + (SETUP WPNeg CSNeg (20)) + (SETUP HOLDNeg SCK (5)) + (SETUP RSTNeg CSNeg (50)) + (SETUP (COND DDR SI) (posedge SCK) (2)) + (SETUP (COND DDR SI) (negedge SCK) (2)) + + (HOLD (COND normal CSNeg) (posedge SCK) (3)) + (HOLD (COND DDR CSNeg) (posedge SCK) (3)) + (HOLD (COND normal SI) (posedge SCK) (4)) + (HOLD WPNeg CSNeg (100)) + (HOLD HOLDNeg SCK (5)) + (HOLD CSNeg RSTNeg (35000)) + (HOLD (COND DDR SI) (posedge SCK) (2)) + (HOLD (COND DDR SI) (negedge SCK) (2)) + + (WIDTH (COND serial (posedge SCK)) (10)) + (WIDTH (COND serial (negedge SCK)) (10)) + (WIDTH (COND dual (posedge SCK)) (7.5)) + (WIDTH (COND dual (negedge SCK)) (7.5)) + (WIDTH (COND fast (negedge SCK)) (7.5)) + (WIDTH (COND fast (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (negedge SCK)) (7.5)) + (WIDTH (COND DDR (posedge SCK)) (7.5)) + (WIDTH (COND DDR (negedge SCK)) (7.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgers (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND serial_rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (15)) + (PERIOD (COND dual_rd SCK) (15)) + (PERIOD (COND quadpg SCK) (15)) + (PERIOD (COND DDR_rd SCK) (15)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP256) (DELAY (ABSOLUTE (DEVICE(183e3:366e3:550e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP512) (DELAY (ABSOLUTE (DEVICE(250e3:500e3:750e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BP) (DELAY (ABSOLUTE (DEVICE(133e3:266e3:400e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE64) (DELAY (ABSOLUTE (DEVICE(217e6:434e6:650e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE256) (DELAY (ABSOLUTE (DEVICE(625e6:1250e6:1875e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(33e9:66e9:330e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WRR) (DELAY (ABSOLUTE(DEVICE(200e6:200e6:200e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300e3:300e3:300e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PRGSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/ERSSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PPBERASE) (DELAY (ABSOLUTE (DEVICE(15e6:15e6:15e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSULCK) (DELAY (ABSOLUTE (DEVICE(1000:1000:1000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSACC) (DELAY (ABSOLUTE (DEVICE(100e3:100e3:100e3) ) ) ) + + + +S25FL256SDPMFIR00_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR01_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR03_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR10_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR11_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPMFIR13_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI000_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI001_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI003_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI010_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI011_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPNFI013_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI200_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI203_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI210_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI213_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI300_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI303_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI310_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHI313_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHIC00_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHIC03_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHIC10_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHIC13_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHID00_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHID03_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHID10_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL256SDPBHID13_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=15pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND normal (IOPATH SCK SO (2:7:12) (2:7:12) (1) (2:7:12) (1) (2:7:12))) + (COND DDR (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + (IOPATH HOLDNeg SO () () (10:12:14) (10:12:14) (10:12:14) (10:12:14)) + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP (COND normal CSNeg) (posedge SCK) (3)) + (SETUP (COND DDR CSNeg) (posedge SCK) (3)) + (SETUP (COND normal SI) (posedge SCK) (5)) + (SETUP WPNeg CSNeg (20)) + (SETUP HOLDNeg SCK (5)) + (SETUP RSTNeg CSNeg (50)) + (SETUP (COND DDR SI) (posedge SCK) (2)) + (SETUP (COND DDR SI) (negedge SCK) (2)) + + (HOLD (COND normal CSNeg) (posedge SCK) (3)) + (HOLD (COND DDR CSNeg) (posedge SCK) (3)) + (HOLD (COND normal SI) (posedge SCK) (4)) + (HOLD WPNeg CSNeg (100)) + (HOLD HOLDNeg SCK (5)) + (HOLD CSNeg RSTNeg (35000)) + (HOLD (COND DDR SI) (posedge SCK) (2)) + (HOLD (COND DDR SI) (negedge SCK) (2)) + + (WIDTH (COND serial (posedge SCK)) (10)) + (WIDTH (COND serial (negedge SCK)) (10)) + (WIDTH (COND dual (posedge SCK)) (7.5)) + (WIDTH (COND dual (negedge SCK)) (7.5)) + (WIDTH (COND fast (negedge SCK)) (7.5)) + (WIDTH (COND fast (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (negedge SCK)) (7.5)) + (WIDTH (COND DDR (posedge SCK)) (7.5)) + (WIDTH (COND DDR (negedge SCK)) (7.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgers (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND serial_rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (15)) + (PERIOD (COND dual_rd SCK) (15)) + (PERIOD (COND quadpg SCK) (15)) + (PERIOD (COND DDR_rd SCK) (15)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP256) (DELAY (ABSOLUTE (DEVICE(183e3:366e3:550e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP512) (DELAY (ABSOLUTE (DEVICE(250e3:500e3:750e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BP) (DELAY (ABSOLUTE (DEVICE(133e3:266e3:400e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE64) (DELAY (ABSOLUTE (DEVICE(217e6:434e6:650e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE256) (DELAY (ABSOLUTE (DEVICE(625e6:1250e6:1875e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(33e9:66e9:330e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WRR) (DELAY (ABSOLUTE(DEVICE(200e6:200e6:200e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300e3:300e3:300e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PRGSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/ERSSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PPBERASE) (DELAY (ABSOLUTE (DEVICE(15e6:15e6:15e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSULCK) (DELAY (ABSOLUTE (DEVICE(1000:1000:1000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSACC) (DELAY (ABSOLUTE (DEVICE(100e3:100e3:100e3) ) ) ) + + \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl256s/utilities/CreateSDF/mk_sdf.cmd b/lib/models/memory/flash/serial/S25fl256s/utilities/CreateSDF/mk_sdf.cmd new file mode 100644 index 0000000..f6d6cc7 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl256s/utilities/CreateSDF/mk_sdf.cmd @@ -0,0 +1,10 @@ +SET sdffile_suffix .sdf +SET use_global_timing_dir false +SET timingfile_dir /user/USERNAME/CreateSDF +SET timingfile_suffix .ftm +SET time_scale 1ns +SET local_path . +SET vendor MODELSIM_HOME +SET diagnostics on +SET vhdl_file testbench.vhd +SET lwb false diff --git a/lib/models/memory/flash/serial/S25fl256s/utilities/CreateSDF/mk_sdf_204.pl b/lib/models/memory/flash/serial/S25fl256s/utilities/CreateSDF/mk_sdf_204.pl new file mode 100644 index 0000000..5f2f2b8 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl256s/utilities/CreateSDF/mk_sdf_204.pl @@ -0,0 +1,462 @@ +#!/usr/local/bin/perl +# +# mk_sdf : Perl replacement for C mk_sdf +# +# Copyright (C) 2000, 1999 Free Model Foundry; http:/vhdl.org/fmf/ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# Author : R. Munden +# Date : 20001115 +# Version : 2.0.4 +# +# Revision history: +# 2.0: 19990702 +# o Intial release of perl version +# 2.0.1: 19990722 +# o fixed problem with . in path for TimingModels +# 2.0.2: 20000616 +# o changed instance search to work with Mentor +# 2.0.3: 20001115 +# o changed to parse ":" without leading space +# o fixed problem with . in path for TimingModels again +# 2.0.4: 20030405 +# o chaged SDF version to 3.0 +# +################################################################# +# +# command line arguments: + +# ARGV[0] - name of VHDL netlist + +# global variables: + +# %component_list - list of instance names by component name +# %instance_isin - list architectures by instances contained therein +# %instance_comp - list of component names by instance name +# %comp_lib - library each component (by name) is configured to +# @instance_list - array of all instance names in design in order found + +$version = "2.0.4"; +$design_name = ''; +$timing_dir = ''; +$diags = "off"; + +%keywords = (architecture => 1, + component => 1, + timingmodel => 1); + +# INPUT files +$CMD = "mk_sdf.cmd"; +$VHD = ''; # name of VHDL netlist + +# OUTPUT files +$RFV = "/tmp/short.vhd"; # reformatted VHDL +$sdf_file = ''; # name of SDF file + +&read_cmd_file; +&get_names; +&reformat; + +open INPUT, $RFV; +@lines = ; +close INPUT; + +$current_architecture = ""; + +foreach $line (@lines) +{ + @words = split / /, $line; + foreach $word (@words) + { + $keywords{$word} == "1" and do { &$word(@words);}; + if ($component_list{$word}) + { + $line =~ /(.+) : $word/ and do { + if ($1 !~ /for/) { # instantiation found + $component_list{$word} = $component_list{$word} . $1; + push (@instance_list, $1); + $instance_name = $1; + } + }; + $instance_comp{$1} = $word; + $instance_isin{$1} = $current_architecture; + if ( $diags ne off ) { + print "reading instance $instance_name: $word in $current_architecture\n"; + } + $line =~ /for all : $word use entity (.+)/ and do + { + @config = split(/\./, $1); + $comp_lib{$word} = $config[0];}; + } + } +} +if ( $diags ne off ) { + print "finished with netlist\n\n"; +} + +&begin_sdf; +&build_paths; +&close_sdf; +`rm $RFV`; + +print "$time\n"; + +sub architecture +{ + $current_architecture = $_[3]; + push (@architectures, $current_architecture); +} + +sub component +{ + if ($_[0] ne "end") + { + $name = $_[1]; + $arch_list{$current_architecture} = + $arch_list{$current_architecture} . " " . $name; + unless ($component_list{$name}) { $component_list{$name} = " ";} + } +} + +sub timingmodel +{ + $line =~ /timingmodel => \"(.+)\"/ and do { + $model = $1; + $model_name{$instance_name} = $model; + }; +} + +sub begin_sdf +{ + if ( $diags ne off ) { + print "writing SDF boilerplate\n"; + } + $time = localtime; + if (open(SDF, ">$sdf_file") !=1) { die "can't open $sdf_file\n";} + print "Opening $sdf_file\n"; + print SDF "(DELAYFILE\n"; + print SDF " (SDFVERSION \"3.0\")\n"; + print SDF " (DESIGN \"$design_name\")\n"; + print SDF " (DATE \"$time\")\n"; + print SDF " (VENDOR \"Free Model Foundry\")\n"; + print SDF " (PROGRAM \"SDF timing utility(tm)\")\n"; + print SDF " (VERSION \"$version\")\n"; + print SDF " (DIVIDER /)\n"; + print SDF " (VOLTAGE)\n"; + print SDF " (PROCESS)\n"; + print SDF " (TEMPERATURE)\n"; + print SDF " (TIMESCALE 1ns)\n"; +} + +sub build_paths +{ + foreach $instance_list (@instance_list) + { + @instance = $instance_list; + foreach $instance (@instance) + { + if ( $diags ne off ) { + print "working on $instance\n"; + } + if ($gtd =~ /true/i) { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; +# $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}./$timing_dir"; + } else { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; + } + $timing_file = "$path/$instance_comp{$instance}_vhd.ftm"; + $timing_file =~ s/\s//; + if ( $diags ne off ) { + print "$instance should be in $timing_file\n"; + } + if (-e $timing_file) { + if ($model_name{$instance} ne "") { + print SDF " (CELL\n"; + print SDF " (CELLTYPE \"$instance_comp{$instance}\")\n"; + $inst = $instance; + $full_inst = $instance; + while ($component_list{$instance_isin{$inst}}) { + $full_inst = "$component_list{$instance_isin{$inst}}/$full_inst"; + $full_inst =~ s/\s+//; + $inst = $component_list{$instance_isin{$inst}}; + $inst =~ s/\s+//; +# print SDF " (INSTANCE $component_list{$instance_isin{$instance}}/$instance)\n"; + } + print SDF " (INSTANCE $full_inst)\n"; + &add_timing; + } + } else { + if ( $diags ne off ) { + print "$timing_file not found!\n"; + } + } + } + } +} + +sub add_timing +{ + $timing_found = "false"; + $part_found = "false"; +# unless ($lib_path{$comp_lib{$instance_comp{$instance}}}) + unless ($timing_file) + { + print "path to $timing_file not found\n"; + exit; + } + if ($gtd =~ /true/i) { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; +# $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}./$timing_dir"; + } else { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; + } + $timing_file = "$path/$instance_comp{$instance}_vhd.ftm"; + if (open(TF, "<$timing_file") !=1) { warn "can't open $timing_file\n"; } + if ( $diags ne off ) { + print "reading $timing_file\n"; + } + $section_found = "false"; + while () + { + next unless (/$model_name{$instance}/i || ($part_found eq "true")); + $part_found = "true"; + if ( $diags ne off ) { + print "found entry for $model_name{$instance}\n"; + } + next unless (//i || ($timing_found eq "true")); + $timing_found = "true"; + next if (//i); + if (/<\/timing>/i) + { + print SDF " )\n"; + $timing_found = "false"; + $part_found = "false"; + $section_found = "true"; + last; + } else { + if (/%LABEL%/) + { + if ($component_list{$instance_isin{$instance}}) + { + $_ =~ s/%LABEL%/$component_list{$instance_isin{$instance}}\/$instance/; + } else { + $_ =~ s/%LABEL%/$instance/; + } + } + print SDF $_; + } + } + unless ($section_found eq "true") { + print "$model_name not found\n"; + } +} + +sub close_sdf +{ + print SDF ")\n"; + print "closing $sdf_file\n"; + close(SDF); +} + +# read mk_sdf.cmd + +sub read_cmd_file { + + if (open(CMD, $CMD) !=1) { die "can't open $CMD\n"; } + while () { + chop; + @fields = ''; + @fields = split; + unless ($fields[0] =~ /#/) { + if ($fields[0] =~ /SET/) { + if ($fields[1] =~ /vhdl_file/) {$VHD = $fields[2]} + if ($fields[1] =~ /sdffile_suffix/) {$suffix = $fields[2]} + if ($fields[1] =~ /use_global_timing_dir/) {$gtd = $fields[2]} + if ($fields[1] =~ /timingfile_dir/) {$timing_dir = $fields[2]} + if ($fields[1] =~ /vendor/) {$vendor = $fields[2]} + if ($fields[1] =~ /diagnostics/) {$diags = $fields[2]} + } + } + } + if ( $diags ne off ) { + print "\nmk_sdf diagnostics on\n\n"; + print "vhdl_file $VHD\n"; + print "sdffile_suffix $suffix\n"; + print "use_global_timing_dir $gtd\n"; + print "timingfile_dir $timing_dir\n"; + print "vendor $vendor\n\n"; + } +} +# + +# get name of netlist + +sub get_names +{ + + if ($ARGV[0] ne "") { $VHD = "$ARGV[0]"; } + + if ($ARGV[1] eq "") + { + @name = split(/\./,$VHD); + $design_name = $name[0]; + } else { + $design_name = "$ARGV[1]"; + } + $sdf_file = $design_name . $suffix; + if ($gtd =~ /false/i) + { + if ($vendor =~ /modeltech/i) { &read_mti; } + if ($vendor =~ /cadence/i) { &read_cds; } + } + if ( $diags ne off ) { + print "design name is $design_name\n\n"; + } +} +# +################################################################ +# + +# reformat netlist + +sub reformat +{ + $entfound = false; + + if (open(VHD, $VHD) !=1) { die "can't open $VHD\n"; } + if (open(OUT, ">$RFV") !=1) { die "can't open $OUT\n"; } + + while () { + if (/^--|library|package/i) { next } + if (/--/) { # strip embeded comments + @line = split("--"); + $_ = $line[0]; + } + s/:/ : /g; + s/;/ ;/g; + s/\s+/ /g; # reduces spaces and tabs + s/^\s//g; # no leading spaces + if (/entity/i) { + $entfound = "true"; + } + chomp; + if ( $entfound eq true ) { + print OUT lc($_); + if (/;|is|begin/i) { print OUT "\n"; } + } + } + + close OUT; + if ( $diags ne off ) { + print "reformatted netlist written to $RFV\n\n"; + } + +} + +# read ModelTech's modelsim.ini file + +sub read_mti +{ + $lib_found = "false"; + if ($ENV{MODELPATH}) + { + $ini_file = "$ENV{MODELPATH}/../modelsim.ini"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + if ($lib_found eq "true") + { + chomp; + if (/\[.+\]/) { last; } + s/\s+//; + @lib_line = split(/=/); + $lib_line[1] =~ s/\/work//; + $lib_path{$lib_line[0]} = $lib_line[1]; + } elsif (/\[Library\]/i) + { + $lib_found = "true"; + next; + } + } + } else { + print "\$MODELPATH environment variable not found\n"; + } + $lib_found = "false"; + if (-e "modelsim.ini") + { + $ini_file = "modelsim.ini"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + if ($lib_found eq "true") + { + chomp; + if (/\[.+\]/) { last; } + s/\s+//; + @lib_line = split(/=/); + $lib_line[1] =~ s/\/work//; + $lib_path{$lib_line[0]} = $lib_line[1]; + } elsif (/\[Library\]/i) + { + $lib_found = "true"; + next; + } + } + } else { + print "local modelsim.ini file not found, may not be needed\n"; + } +} + +# read Cadence's cds.lib file + +sub read_cds +{ + if ($ENV{CDS_VHDL}) + { + $ini_file = "$ENV{CDS_VHDL}/files/cds.lib"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + chomp; + s/\s+/ /; + if (/define/i) + { + @lib_line = split; + $lib_path{$lib_line[1]} = $lib_line[2]; + } + } + } else { + print "\$CDS_VHDL environment variable not found\n"; + } + if (-e "cds.lib") + { + $ini_file = "cds.lib"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + chomp; + s/\s+/ /; + if (/define/i) + { + @lib_line = split; + $lib_path{$lib_line[1]} = $lib_line[2]; + } + } + } else { + print "local cds.lib file not found, may not be needed\n"; + } +} diff --git a/lib/models/memory/flash/serial/S25fl256s/utilities/CreateSDF/my_mem_vhd.ftm b/lib/models/memory/flash/serial/S25fl256s/utilities/CreateSDF/my_mem_vhd.ftm new file mode 100644 index 0000000..2fc35c2 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl256s/utilities/CreateSDF/my_mem_vhd.ftm @@ -0,0 +1,205 @@ + +FMF Timing for testbench Parts + + +version: | author: | mod date: | changes made: + V1.0 VHD2FTM 03 July 11 Initial release + +1ns +am29lv640m + +MY_MEM +AM29LV640MH90R +AM29LV640ML90R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (90:90:90) (90:90:90)) + (IOPATH A0 DQ1 (25:25:25) (25:25:25)) + (IOPATH CENeg DQ0 (85:85:85) (85:85:85) (11:11:11) (85:85:85) (11:11:11) (85:85:85)) + (IOPATH OENeg DQ0 (20:20:20) (20:20:20) (11:11:11) (20:20:20) (11:11:11) (20:20:20)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (90)) + (IOPATH WENeg RY (0) (90)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (90:90:90)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH101 +AM29LV640ML101 +AM29LV640MH101R +AM29LV640ML101R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (100:100:100) (100:100:100)) + (IOPATH A0 DQ1 (30:30:30) (30:30:30)) + (IOPATH CENeg DQ0 (95:95:95) (95:95:95) (11:11:11) (95:95:95) (11:11:11) (95:95:95)) + (IOPATH OENeg DQ0 (25:25:25) (25:25:25) (11:11:11) (25:25:25) (11:11:11) (25:25:25)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (100)) + (IOPATH WENeg RY (0) (100)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (100:100:100)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH112 +AM29LV640ML112 +AM29LV640MH112R +AM29LV640ML112R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (110:110:110) (110:110:110)) + (IOPATH A0 DQ1 (40:40:40) (40:40:40)) + (IOPATH CENeg DQ0 (105:105:105) (105:105:105) (11:11:11) (105:105:105) (11:11:11) (105:105:105)) + (IOPATH OENeg DQ0 (35:35:35) (35:35:35) (11:11:11) (35:35:35) (11:11:11) (35:35:35)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (110)) + (IOPATH WENeg RY (0) (110)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (110:110:110)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH120 +AM29LV640ML120 +AM29LV640MH120R +AM29LV640ML120R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (120:120:120) (120:120:120)) + (IOPATH A0 DQ1 (40:40:40) (40:40:40)) + (IOPATH CENeg DQ0 (115:115:115) (115:115:115) (11:11:11) (115:115:115) (11:11:11) (115:115:115)) + (IOPATH OENeg DQ0 (35:35:35) (35:35:35) (11:11:11) (35:35:35) (11:11:11) (35:35:35)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (120)) + (IOPATH WENeg RY (0) (120)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (120:120:120)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + diff --git a/lib/models/memory/flash/serial/S25fl256s/utilities/CreateSDF/testbench.sdf b/lib/models/memory/flash/serial/S25fl256s/utilities/CreateSDF/testbench.sdf new file mode 100644 index 0000000..02495dd --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl256s/utilities/CreateSDF/testbench.sdf @@ -0,0 +1,58 @@ +(DELAYFILE + (SDFVERSION "3.0") + (DESIGN "testbench") + (DATE "Wed Jan 28 15:15:41 2004") + (VENDOR "Free Model Foundry") + (PROGRAM "SDF timing utility(tm)") + (VERSION "2.0.4") + (DIVIDER /) + (VOLTAGE) + (PROCESS) + (TEMPERATURE) + (TIMESCALE 1ns) + (CELL + (CELLTYPE "my_mem") + (INSTANCE dut) + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (90:90:90) (90:90:90)) + (IOPATH A0 DQ1 (25:25:25) (25:25:25)) + (IOPATH CENeg DQ0 (85:85:85) (85:85:85) (11:11:11) (85:85:85) (11:11:11) (85:85:85)) + (IOPATH OENeg DQ0 (20:20:20) (20:20:20) (11:11:11) (20:20:20) (11:11:11) (20:20:20)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (90)) + (IOPATH WENeg RY (0) (90)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (90:90:90)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + ) +) diff --git a/lib/models/memory/flash/serial/S25fl256s/utilities/CreateSDF/testbench.vhd b/lib/models/memory/flash/serial/S25fl256s/utilities/CreateSDF/testbench.vhd new file mode 100644 index 0000000..c7d852a --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl256s/utilities/CreateSDF/testbench.vhd @@ -0,0 +1,1606 @@ +------------------------------------------------------------------------------ +-- File name : testbench_640.vhd +------------------------------------------------------------------------------- +-- Copyright (C) 2003 AMD. +-- +-- MODIFICATION HISTORY : +-- +-- version: | author: | mod date: | changes made: +-- V0.1 M.Marinkovic 11 July 03 Initial +-- v0.2 M.Marinkovic 28 Aug 03 Changed protected sector selection +-- +------------------------------------------------------------------------------- +-- PART DESCRIPTION: +-- +-- Description: +-- Generic test enviroment for verification of AMD flash memory +-- VITAL models.my_mem +-- +------------------------------------------------------------------------------- +-- Note: VHDL code formating not done +-- For High/Low sector protection selection change: +-- TimingModel constant and TimingModel generic value +-- +------------------------------------------------------------------------------- +LIBRARY IEEE; + USE IEEE.std_logic_1164.ALL; +--USE IEEE.VITAL_timing.ALL; +--USE IEEE.VITAL_primitives.ALL; + USE STD.textio.ALL; + +LIBRARY VITAL2000; + USE VITAL2000.vital_timing.ALL; + USE VITAL2000.vital_primitives.ALL; + +LIBRARY FMF; + USE FMF.gen_utils.ALL; + USE FMF.conversions.ALL; + + +LIBRARY work; + USE work.amd_tc_pkg.ALL; + +------------------------------------------------------------------------------- +-- ENTITY DECLARATION +------------------------------------------------------------------------------- +ENTITY testbench_640 IS +END testbench_640; + + +------------------------------------------------------------------------------- +-- ARCHITECTURE DECLARATION +------------------------------------------------------------------------------- +ARCHITECTURE vhdl_behavioral of testbench_640 IS + COMPONENT my_mem + GENERIC ( + -- tipd delays: interconnect path delays + tipd_A0 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A1 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A2 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A3 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A4 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A5 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A6 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A7 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A8 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A9 : VitalDelayType01 := VitalZeroDelay01; --address + tipd_A10 : VitalDelayType01 := VitalZeroDelay01; --lines + tipd_A11 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A12 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A13 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A14 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A15 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A16 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A17 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A18 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A19 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A20 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A21 : VitalDelayType01 := VitalZeroDelay01; -- + + tipd_DQ0 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ1 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ2 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ3 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ4 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ5 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ6 : VitalDelayType01 := VitalZeroDelay01; -- data + tipd_DQ7 : VitalDelayType01 := VitalZeroDelay01; -- lines + tipd_DQ8 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ9 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ10 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ11 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ12 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ13 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ14 : VitalDelayType01 := VitalZeroDelay01; -- + + tipd_DQ15 : VitalDelayType01 := VitalZeroDelay01; -- DQ15/A-1 + + tipd_CENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_OENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_RESETNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; --WP#/ACC + tipd_BYTENeg : VitalDelayType01 := VitalZeroDelay01; + + -- tpd delays + tpd_A0_DQ0 : VitalDelayType01 := UnitDelay01;--tACC + tpd_A0_DQ1 : VitalDelayType01 := UnitDelay01;--tPACC + tpd_CENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(tCE,tCE,tDF,-,tDF,-) + tpd_OENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(tOE,tOE,tDF,-,tDF,-) + tpd_RESETNeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(-,-,0,-,0,-) + tpd_CENeg_RY : VitalDelayType01 := UnitDelay01; --tBUSY + tpd_WENeg_RY : VitalDelayType01 := UnitDelay01; --tBUSY + + --tsetup values + tsetup_A0_CENeg : VitalDelayType := UnitDelay; --tAS edge \ + tsetup_A0_OENeg : VitalDelayType := UnitDelay; --tASO edge \ + tsetup_DQ0_CENeg : VitalDelayType := UnitDelay; --tDS edge / + + --thold values + thold_CENeg_RESETNeg: VitalDelayType := UnitDelay; --tRH edge / + thold_OENeg_WENeg : VitalDelayType := UnitDelay; --tOEH edge / + thold_A0_CENeg : VitalDelayType := UnitDelay; --tAH edge \ + thold_A0_OENeg : VitalDelayType := UnitDelay; --tAHT edge \ + thold_DQ0_CENeg : VitalDelayType := UnitDelay; --tDH edge / + thold_WENeg_OENeg : VitalDelayType := UnitDelay; --tGHWL edge / + + --tpw values: pulse width + tpw_RESETNeg_negedge: VitalDelayType := UnitDelay; --tRP + tpw_OENeg_posedge : VitalDelayType := UnitDelay; --tOEPH + tpw_WENeg_negedge : VitalDelayType := UnitDelay; --tWP + tpw_WENeg_posedge : VitalDelayType := UnitDelay; --tWPH + tpw_CENeg_negedge : VitalDelayType := UnitDelay; --tCP + tpw_CENeg_posedge : VitalDelayType := UnitDelay; --tCEPH + tpw_A0_negedge : VitalDelayType := UnitDelay; --tWC tRC + + + -- tdevice values: values for internal delays + --Effective Write Buffer Program Operation tWHWH1 + tdevice_WBPB : VitalDelayType := 11 us; + --Program Operation + tdevice_POB : VitalDelayType := 100 us; + --Sector Erase Operation tWHWH2 + tdevice_SEO : VitalDelayType := 500 ms; + --Timing Limit Exceeded + tdevice_HANG : VitalDelayType := 400 ms; --? + --program/erase suspend timeout + tdevice_START_T1 : VitalDelayType := 5 us; + --sector erase command sequence timeout + tdevice_CTMOUT : VitalDelayType := 50 us; + --device ready after Hardware reset(during embeded algorithm) + tdevice_READY : VitalDelayType := 20 us; --tReady + + -- generic control parameters + InstancePath : STRING := DefaultInstancePath; + TimingChecksOn : BOOLEAN := DefaultTimingChecks; + MsgOn : BOOLEAN := DefaultMsgOn; + XOn : BOOLEAN := DefaultXon; + -- memory file to be loaded + mem_file_name : STRING ;--:= "am29lv640m.mem"; + prot_file_name : STRING ;--:= "am29lv640m_prot.mem"; + secsi_file_name : STRING ;--:= "am29lv_secsi.mem"; + + UserPreload : BOOLEAN ;--:= TRUE; + LongTimming : BOOLEAN ;--:= TRUE; + + -- For FMF SDF technology file usage + TimingModel : STRING --:= "AM29LV640MH90R" + ); + PORT ( + A21 : IN std_logic := 'U'; -- + A20 : IN std_logic := 'U'; -- + A19 : IN std_logic := 'U'; -- + A18 : IN std_logic := 'U'; -- + A17 : IN std_logic := 'U'; -- + A16 : IN std_logic := 'U'; -- + A15 : IN std_logic := 'U'; -- + A14 : IN std_logic := 'U'; -- + A13 : IN std_logic := 'U'; --address + A12 : IN std_logic := 'U'; --lines + A11 : IN std_logic := 'U'; -- + A10 : IN std_logic := 'U'; -- + A9 : IN std_logic := 'U'; -- + A8 : IN std_logic := 'U'; -- + A7 : IN std_logic := 'U'; -- + A6 : IN std_logic := 'U'; -- + A5 : IN std_logic := 'U'; -- + A4 : IN std_logic := 'U'; -- + A3 : IN std_logic := 'U'; -- + A2 : IN std_logic := 'U'; -- + A1 : IN std_logic := 'U'; -- + A0 : IN std_logic := 'U'; -- + + DQ15 : INOUT std_logic := 'U'; -- DQ15/A-1 + DQ14 : INOUT std_logic := 'U'; -- + DQ13 : INOUT std_logic := 'U'; -- + DQ12 : INOUT std_logic := 'U'; -- + DQ11 : INOUT std_logic := 'U'; -- + DQ10 : INOUT std_logic := 'U'; -- + DQ9 : INOUT std_logic := 'U'; -- data + DQ8 : INOUT std_logic := 'U'; -- lines + DQ7 : INOUT std_logic := 'U'; -- + DQ6 : INOUT std_logic := 'U'; -- + DQ5 : INOUT std_logic := 'U'; -- + DQ4 : INOUT std_logic := 'U'; -- + DQ3 : INOUT std_logic := 'U'; -- + DQ2 : INOUT std_logic := 'U'; -- + DQ1 : INOUT std_logic := 'U'; -- + DQ0 : INOUT std_logic := 'U'; -- + + CENeg : IN std_logic := 'U'; + OENeg : IN std_logic := 'U'; + WENeg : IN std_logic := 'U'; + RESETNeg : IN std_logic := 'U'; + WPNeg : IN std_logic := 'U'; --WP#/ACC + BYTENeg : IN std_logic := 'U'; + RY : OUT std_logic := 'U' --RY/BY# + ); + END COMPONENT; + + FOR ALL: my_mem USE ENTITY WORK.my_mem(VHDL_BEHAVIORAL); + + --------------------------------------------------------------------------- + --memory configuration + --------------------------------------------------------------------------- + CONSTANT MaxData : NATURAL := 16#FF#; --255; + CONSTANT SecSize : NATURAL := 16#FFFF#; --65535 + CONSTANT SecSiSize : NATURAL := 255; + CONSTANT SecNum : NATURAL := 127; + CONSTANT HiAddrBit : NATURAL := 21; + --Address of the Protected Sector +-- CONSTANT ProtSecNum : NATURAL := SecNum; + + --------------------------------------------------------------------------- + --model configuration + --------------------------------------------------------------------------- + CONSTANT mem_file : STRING := "am29lv640m.mem"; + CONSTANT prot_file : STRING := "am29lv640m_prot.mem"; + CONSTANT secsi_file : STRING := "am29lv_secsi.mem"; + + CONSTANT UserPreload : boolean := TRUE; + CONSTANT DebugInfo : boolean := FALSE; + CONSTANT LongTimming : boolean := TRUE; + CONSTANT TimingModel : STRING := "MY_MEM"; + -- "AM29LV640MH90R";--High sect prot. + -- "AM29LV128ML93R";--Low sect. prot. + --------------------------------------------------------------------------- + SIGNAL ProtSecNum : NATURAL := SecNum ; + + --Flash Memory Array + TYPE SecType IS ARRAY (0 TO SecSize) OF + INTEGER RANGE -1 TO MaxData; + TYPE MemArray IS ARRAY (0 TO SecNum) OF + SecType; + + --Common Flash Interface Query codes + TYPE CFItype IS ARRAY (16#10# TO 16#50#) OF + NATURAL RANGE 0 TO 16#FF#; + + --SecSi Sector + TYPE SecSiType IS ARRAY ( 0 TO SecSiSize) OF + INTEGER RANGE -1 TO MaxData; + + --------------------------------------------------------------------------- + -- memory declaration + --------------------------------------------------------------------------- + -- -- Mem(SecAddr)(Address).... + SHARED VARIABLE Mem : MemArray := (OTHERS => (OTHERS=> MaxData)); + SHARED VARIABLE CFI_array : CFItype :=(OTHERS=>0); + SHARED VARIABLE SecSi : SecSiType :=(OTHERS=>0); + + --command sequence + SHARED VARIABLE cmd_seq : cmd_seq_type; + + SIGNAL status : status_type := none; + SIGNAL sts_check : std_logic_vector(7 downto 0); + + + SIGNAL check_err : std_logic := '0'; + SIGNAL ErrorInTest : std_logic := '0'; -- + ---------------------------------------------------------------------------- + --Personality module: + -- + -- instanciates the DUT module and adapts generic test signals to it + -- TBD: block port + ---------------------------------------------------------------------------- + --DUT port + SIGNAL T_DQ : std_logic_vector(15 downto 0) := (OTHERS=>'U'); + SIGNAL T_A : std_logic_vector(HiAddrBit downto 0) := (OTHERS=>'U'); + SIGNAL T_RESETNeg : std_logic := 'U'; + SIGNAL T_CENeg : std_logic := 'U'; + SIGNAL T_WENeg : std_logic := 'U'; + SIGNAL T_OENeg : std_logic := 'U'; + SIGNAL T_WPNeg : std_logic := 'U'; + SIGNAL T_BYTENeg : std_logic := 'U'; + SIGNAL T_RY : std_logic := 'U'; + + --------------------------------------------------------------------------- + -- + --------------------------------------------------------------------------- + --SecSi ProtectionStatus + SHARED VARIABLE FactoryProt : std_logic := '1'; + --Sector Protection Status + SHARED VARIABLE Sec_Prot : std_logic_vector (SecNum downto 0) := + (OTHERS => '0'); + SHARED VARIABLE Sect : NATURAL RANGE 0 TO SecNum := 0; + SHARED VARIABLE Addr : NATURAL RANGE 0 TO SecSize := 0; + SHARED VARIABLE WriteData : NATURAL RANGE 0 TO MaxData := 0; + + + --CONSTANT + --timming parameters + CONSTANT RESETNeg_pw : time := 500 ns; --tRP + + SIGNAL pwron : std_logic := '0'; + + SIGNAL Tseries : NATURAL; + SIGNAL Tcase : NATURAL; + + SHARED VARIABLE ts_cnt : NATURAL RANGE 1 TO 30:=1; -- testseries counter + SHARED VARIABLE tc_cnt : NATURAL RANGE 0 TO 10:=0; -- testcase counter + + + BEGIN + DUT : my_mem + GENERIC MAP ( + -- tipd delays: interconnect path delays + tipd_A0 => VitalZeroDelay01, -- + tipd_A1 => VitalZeroDelay01, -- + tipd_A2 => VitalZeroDelay01, -- + tipd_A3 => VitalZeroDelay01, -- + tipd_A4 => VitalZeroDelay01, -- + tipd_A5 => VitalZeroDelay01, -- + tipd_A6 => VitalZeroDelay01, -- + tipd_A7 => VitalZeroDelay01, -- + tipd_A8 => VitalZeroDelay01, -- + tipd_A9 => VitalZeroDelay01, --address + tipd_A10 => VitalZeroDelay01, --lines + tipd_A11 => VitalZeroDelay01, -- + tipd_A12 => VitalZeroDelay01, -- + tipd_A13 => VitalZeroDelay01, -- + tipd_A14 => VitalZeroDelay01, -- + tipd_A15 => VitalZeroDelay01, -- + tipd_A16 => VitalZeroDelay01, -- + tipd_A17 => VitalZeroDelay01, -- + tipd_A18 => VitalZeroDelay01, -- + tipd_A19 => VitalZeroDelay01, -- + tipd_A20 => VitalZeroDelay01, -- + tipd_A21 => VitalZeroDelay01, -- + + tipd_DQ0 => VitalZeroDelay01, -- + tipd_DQ1 => VitalZeroDelay01, -- + tipd_DQ2 => VitalZeroDelay01, -- + tipd_DQ3 => VitalZeroDelay01, -- + tipd_DQ4 => VitalZeroDelay01, -- + tipd_DQ5 => VitalZeroDelay01, -- + tipd_DQ6 => VitalZeroDelay01, -- data + tipd_DQ7 => VitalZeroDelay01, -- lines + tipd_DQ8 => VitalZeroDelay01, -- + tipd_DQ9 => VitalZeroDelay01, -- + tipd_DQ10 => VitalZeroDelay01, -- + tipd_DQ11 => VitalZeroDelay01, -- + tipd_DQ12 => VitalZeroDelay01, -- + tipd_DQ13 => VitalZeroDelay01, -- + tipd_DQ14 => VitalZeroDelay01, -- + + tipd_DQ15 => VitalZeroDelay01, -- DQ15/A-1 + + tipd_CENeg => VitalZeroDelay01, + tipd_OENeg => VitalZeroDelay01, + tipd_WENeg => VitalZeroDelay01, + tipd_RESETNeg => VitalZeroDelay01, + tipd_WPNeg => VitalZeroDelay01,--WP#/ACC + tipd_BYTENeg => VitalZeroDelay01, + + -- tpd delays + tpd_A0_DQ0 => UnitDelay01,--tACC + tpd_A0_DQ1 => UnitDelay01,--tPACC + tpd_CENeg_DQ0 => UnitDelay01Z, + --(tCE,tCE,tDF,-,tDF + tpd_OENeg_DQ0 => UnitDelay01Z, + --(tOE,tOE,tDF,-,tDF + tpd_RESETNeg_DQ0 => UnitDelay01Z, + --(-,-,0,-,0,-) + tpd_CENeg_RY => UnitDelay01, --tBUSY + tpd_WENeg_RY => UnitDelay01, --tBUSY + + --tsetup values + tsetup_A0_CENeg => UnitDelay, --tAS edge \ + tsetup_A0_OENeg => UnitDelay, --tASO edge \ + tsetup_DQ0_CENeg => UnitDelay, --tDS edge / + + --thold values + thold_CENeg_RESETNeg=> UnitDelay, --tRH edge / + thold_OENeg_WENeg => UnitDelay, --tOEH edge / + thold_A0_CENeg => UnitDelay, --tAH edge \ + thold_A0_OENeg => UnitDelay, --tAHT edge \ + thold_DQ0_CENeg => UnitDelay, --tDH edge / + thold_WENeg_OENeg => UnitDelay, --tGHVL edge / + + --tpw values: pulse width + tpw_RESETNeg_negedge=> UnitDelay, --tRP + tpw_OENeg_posedge => UnitDelay, --tOEPH + tpw_WENeg_negedge => UnitDelay, --tWP + tpw_WENeg_posedge => UnitDelay, --tWPH + tpw_CENeg_negedge => UnitDelay, --tCP + tpw_CENeg_posedge => UnitDelay, --tCEPH + tpw_A0_negedge => UnitDelay, --tWC tRC + -- tdevice values: values for internal delays + --Effective Write Buffer Program Operation tWHWH1 + tdevice_WBPB => 11 us, + --Program Operation + tdevice_POB => 100 us, + --Sector Erase Operation tWHWH2 + tdevice_SEO => 500 ms, + --Timing Limit Exceeded + tdevice_HANG => 400 ms, --? + --program/erase suspend timeout + tdevice_START_T1 => 5 us, + --sector erase command sequence timeout + tdevice_CTMOUT => 50 us, + --device ready after Hardware reset(during embeded algorithm) + tdevice_READY => 20 us, --tReady + + -- generic control parameters + InstancePath => DefaultInstancePath, + TimingChecksOn => TRUE,--DefaultTimingChecks, + MsgOn => DefaultMsgOn, + XOn => DefaultXon, + -- memory file to be loaded + mem_file_name => mem_file, + prot_file_name => prot_file , + secsi_file_name => secsi_file, + + UserPreload => UserPreload, + LongTimming => LongTimming, + -- For FMF SDF technology file usage + TimingModel => "AM29LV640MH90R" -- TimingModel + ) + PORT MAP( + A21 => T_A(21), -- + A20 => T_A(20), -- + A19 => T_A(19), -- + A18 => T_A(18), -- + A17 => T_A(17), -- + A16 => T_A(16), -- + A15 => T_A(15), -- + A14 => T_A(14), -- + A13 => T_A(13), --address + A12 => T_A(12), --lines + A11 => T_A(11), -- + A10 => T_A(10), -- + A9 => T_A(9), -- + A8 => T_A(8), -- + A7 => T_A(7), -- + A6 => T_A(6), -- + A5 => T_A(5),-- + A4 => T_A(4),-- + A3 => T_A(3), -- + A2 => T_A(2), -- + A1 => T_A(1), -- + A0 => T_A(0), -- + + DQ15 => T_DQ(15), -- DQ15/A-1 + DQ14 => T_DQ(14), -- + DQ13 => T_DQ(13), -- + DQ12 => T_DQ(12), -- + DQ11 => T_DQ(11), -- + DQ10 => T_DQ(10), -- + DQ9 => T_DQ(9), -- data + DQ8 => T_DQ(8), -- lines + DQ7 => T_DQ(7), -- + DQ6 => T_DQ(6), -- + DQ5 => T_DQ(5), -- + DQ4 => T_DQ(4), -- + DQ3 => T_DQ(3), -- + DQ2 => T_DQ(2), -- + DQ1 => T_DQ(1), -- + DQ0 => T_DQ(0), -- + + CENeg => T_CENeg, + OENeg => T_OENeg, + WENeg => T_WENeg, + RESETNeg => T_RESETNeg, + WPNeg => T_WPNeg, --WP#/ACC + BYTENeg => T_BYTENeg, + RY => T_RY --RY/BY# + ); + + --------------------------------------------------------------------------- + --protected sector + --------------------------------------------------------------------------- + ProtSecNum <= SecNum WHEN TimingModel(11) = 'H' ELSE + 0 ;-- WHEN TimingModel = "AM29LV128ML93R" + + pwron <= '0', '1' after 1 ns; + +--At the end of the simulation, if ErrorInTest='0' there were no errors +err_ctrl : PROCESS ( check_err ) + BEGIN + IF check_err = '1' THEN + ErrorInTest <= '1'; + END IF; + END PROCESS err_ctrl; + +tb :PROCESS + + -------------------------------------------------------------------------- + --= PROCEDURE to select TC + -- can be modified to read TC list from file, or to generate random list + -------------------------------------------------------------------------- + PROCEDURE Pick_TC + (Model : IN STRING := "AM29LV640MH90R" ) + IS + BEGIN + IF TC_cnt < tc(TS_cnt) THEN + TC_cnt := TC_cnt+1; + ELSE + TC_cnt:=1; + IF TS_cnt<30 THEN + TS_cnt := TS_cnt+1; + ELSE + -- end test + IF ErrorInTest='0' THEN + REPORT "Test Ended without errors" + SEVERITY note; + ELSE + REPORT "There were errors in test" + SEVERITY note; + END IF; + WAIT; + END IF; + END IF; + END PROCEDURE Pick_TC; + + --------------------------------------------------------------------------- + --bus commands, device specific implementation + --------------------------------------------------------------------------- + TYPE bus_type IS (bus_idle, + bus_standby, --CE# deasseretd, others are don't care + bus_enable, --CE# asserted, others deasserted + bus_output_disable, + bus_reset, + bus_write, + bus_read); + + --bus drive for specific command sequence cycle + PROCEDURE bus_cycle( + bus_cmd :IN bus_type := bus_idle; + byte :IN boolean ; + data :IN INTEGER RANGE -2 TO MaxData := -2; -- -1 for all Z + dataHi :IN INTEGER RANGE -2 TO MaxData := -2; -- -2 for ignore + sector :IN INTEGER RANGE -1 TO SecNum := -1; -- -1 for ignore addr + address :IN NATURAL RANGE 0 TO SecSize := 0; + disable :IN boolean := false; + violate :IN boolean := false; + tm :IN TIME := 10 ns) + IS + + VARIABLE tmp : std_logic_vector(15 downto 0); + BEGIN + + IF data=-1 THEN -- HiZ + T_DQ(7 downto 0) <= (OTHERS => 'Z'); + END IF; + + IF (NOT byte)THEN --word access + IF dataHi=-1 THEN -- HiZ + T_DQ(15 downto 8) <= (OTHERS => 'Z'); + END IF; + T_BYTENeg <= '1'; + ELSE --byte access + T_BYTENeg <= '0'; + T_DQ(14 downto 8) <= (OTHERS => 'Z'); + END IF; + + IF sector > -1 THEN + T_A(HiAddrBit downto 15) <= to_slv(sector, HiAddrbit-14); + tmp := to_slv(address, 16); + IF byte THEN + T_A(14 downto 0) <= tmp(15 downto 1); + T_DQ(15) <= tmp(0); + ELSE + T_A(14 downto 0) <= tmp(14 downto 0); + END IF; + + END IF; + + wait for 1 ns; + + CASE bus_cmd IS + WHEN bus_output_disable => + T_OENeg <= '1'; + WAIT FOR 20 ns; + + WHEN bus_idle => + T_RESETNeg <= '1'; + T_WENeg <= '1'; + T_CENeg <= '1'; + T_OENeg <= '1'; + IF disable THEN + T_WPNeg <= '0'; + ELSE + T_WPNeg <= '1'; + END IF; + WAIT FOR 30 ns; + + WHEN bus_standby => + T_CENeg <= '1'; + WAIT FOR 30 ns; + + WHEN bus_reset => + T_RESETNeg <= '0', '1' AFTER tm ; + -- WAIT FOR 500 ns should follow this bus cmd for reset to + --complete + WAIT FOR 30 ns; + + WHEN bus_enable => + T_WENeg <= '1' AFTER 50 ns; --- + T_CENeg <= '0' AFTER 50 ns; --- + T_OENeg <= '1' AFTER 30 ns; --- + + WAIT FOR tm ; + + WHEN bus_write => + T_OENeg <= '1' ;-- AFTER 5 ns; + T_CENeg <= '0' AFTER 10 ns ; + T_WENeg <= '0' AFTER 20 ns; + + IF data>-1 THEN + T_DQ(7 downto 0) <= to_slv(data,8); + END IF; + IF NOT byte THEN + IF dataHi>-1 THEN + T_DQ(15 downto 8) <= to_slv(dataHi,8); + END IF; + END IF; + + IF violate THEN + T_WENeg <= '1'; + WAIT FOR 50 ns; + T_WENeg <= '0', '1' AFTER tm; + WAIT FOR 50 ns; + ELSE + WAIT FOR 100 ns; + END IF; + + WHEN bus_read => + + T_CENeg <= '0' ; + T_WENeg <= '1'AFTER 10 ns; + IF NOT disable THEN + T_OENeg <= '0' AFTER 15 ns; + ELSE + T_OENeg <= '1'; + END IF; + + IF NOT byte THEN + T_DQ(15 downto 8) <= (OTHERS => 'Z'); + END IF; + T_DQ(7 downto 0) <= (OTHERS => 'Z'); + + WAIT FOR 100 ns; + + -- T_OENeg <= '1' ; ----------- + + END CASE; + + + END PROCEDURE; + + + --------------------------------------------------------------------------- + --procedure to decode commands into specific bus command sequence + --------------------------------------------------------------------------- + PROCEDURE cmd_dc + ( command : IN cmd_rec ) + IS + VARIABLE D_hi : NATURAL ;--RANGE 0 to MaxData; + VARIABLE D_lo : NATURAL RANGE 0 to MaxData; + VARIABLE Addr : NATURAL RANGE 0 to SecSize :=0; + VARIABLE Addrfix : NATURAL RANGE 0 to SecSize/2:=0; + VARIABLE Sect : INTEGER RANGE -1 to SecNum :=0; + VARIABLE slv_1, slv_2 : std_logic_vector(7 downto 0); + VARIABLE byte : boolean; + VARIABLE i : NATURAL; + BEGIN + CASE command.cmd IS + WHEN idle => + bus_cycle(bus_cmd => bus_idle, + byte => command.byte, + disable => command.aux=disable); + + WHEN h_reset => + bus_cycle(bus_cmd => bus_reset, + byte => command.byte, + tm => command.wtime); + + WHEN rd => + bus_cycle(bus_cmd => bus_enable, + byte => command.byte, + data => -1, + sector => command.sect, + address => command.addr, + tm => 90 ns); + + bus_cycle(bus_cmd => bus_read, + byte => command.byte, + data => -1, + dataHi => -1, + sector => command.sect, + address => command.addr, + disable => command.aux=disable); + + bus_cycle(bus_cmd => bus_output_disable, + byte => command.byte); + + WHEN rd_page => + bus_cycle(bus_cmd => bus_enable, + byte => command.byte, + data => -1, + sector => 0, + address => 0, + tm => 90 ns); + + Addr := command.addr; + Sect := command.sect; + byte := command.byte; + ---- 08July---- + WAIT FOR 10 ns; + -------------- + i := 0; + WHILE i < command.d_hi LOOP + + IF command.wtime > 0 ns THEN + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + --byte toggle mode + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + byte := false; + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + Addrfix := Addr /2; + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + --word read; + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addrfix); + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + byte := true; + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 30 ns); + + --first byte read + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addr); + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + i := i +3; + wait for 10 ns; ------- + ELSE + byte := command.byte; + END IF; + --second byte read in byte toggle mode + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addr); + + + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + i := i +1; + WAIT FOR 10 ns; + END LOOP; + bus_cycle(bus_cmd => bus_output_disable, + byte => command.byte); + + + + WHEN w_cycle => + + D_lo := 16#AA# ; --first command data + Addr := 16#AAA#; --first command byte address + D_hi := 16#55#; --second command data + Addrfix := 16#555#; --second command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + Addrfix := 16#2AA#; --second command byte address + END IF; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_lo, + dataHi => 0, + sector => 0, + address => Addr, + violate => command.aux=violate, + tm => command.wtime); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_hi, + dataHi => 0, + sector => 0, + address => Addrfix); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_reset | w_prog | w_erase | w_unlock | + w_autoselect | w_enter_sec => + Addr := 16#AAA#; + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + + CASE command.cmd IS + WHEN w_reset => + d_lo := 16#F0#; + WHEN w_prog => + d_lo := 16#A0#; + WHEN w_erase => + d_lo := 16#80#; + WHEN w_unlock => + d_lo := 16#20#; + WHEN w_autoselect => + d_lo := 16#90#; + WHEN w_enter_sec => + d_lo := 16#88#; + WHEN OTHERS => + d_lo := 0; + END CASE; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => d_lo, + dataHi => 0, + sector => 0, + address => Addr); + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + + WHEN w_unlock_reset => + Addr := 16#AAA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#90#, + dataHi => 0, + sector => 0, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#F0#, + dataHi => 0, + sector => 0, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + WHEN w_chip_ers => + Addr := 16#AAA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#10#, + dataHi => 0, + sector => 0, + Address => Addr); + FOR i IN 0 TO SecNum LOOP + IF Sec_Prot(i)/='1' THEN + mem(i) := (OTHERS=>16#FF#); + END IF; + END LOOP; + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_cfi => + Addr := 16#AA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#55#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#98#, + dataHi => 0, + sector => 0, + Address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + + WHEN w_suspend => + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#B0#, + dataHi => 0, + sector => -1); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + WHEN w_resume => + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#30#, + dataHi => 0, + sector => -1); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_data => + + D_hi := command.d_hi MOD 16#100#; + D_lo := command.d_lo ; + Addr := command.addr; + Sect := command.sect; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_lo, + dataHi => D_hi, + sector => Sect, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + IF NOT command.byte THEN + Addr := Addr*2; + END IF; + + --write value(s) in default mem + IF status = erase_active AND Sec_Prot(Sect)/='1'THEN + --sector should be erased + mem(Sect) := (OTHERS=>16#FF#); + + ELSIF status = erase_na AND Sec_Prot(Sect)/='1'THEN + --sector erase terminated = data integrity violated + mem(Sect) := (OTHERS=>-1); + + ELSIF status = readX AND Sec_Prot(Sect)/='1' THEN + mem(Sect)(Addr) := -1; + IF NOT command.byte THEN + mem(Sect)(Addr+1) := -1; + END IF; + + -- Write to Secure Silicon Sector Region + ELSIF status = rd_SecSi AND FactoryProt/='1' THEN + slv_1 := to_slv(d_lo,8); + IF SecSi(Addr)>-1 THEN + slv_2 := to_slv(SecSi(Addr),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + SecSi(Addr) := to_nat(slv_1); + IF NOT command.byte THEN + slv_1 := to_slv(d_hi,8); + IF SecSi(Addr+1)>-1 THEN + slv_2 := to_slv(SecSi(Addr+1),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + SecSi(Addr+1) := to_nat(slv_1); + END IF; + + ELSIF status=buff_wr_busy THEN + --Write to Buffer command cycle + null; + + ELSIF status=erase_na THEN + --sector erase command sequence violation + null; + + -- Write to Flash Memory Array + ELSIF status /= err AND Sec_Prot(Sect)/='1'THEN + slv_1 := to_slv(d_lo,8); + IF mem(Sect)(Addr)>-1 THEN + slv_2 := to_slv(mem(Sect)(Addr),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + mem(Sect)(Addr) := to_nat(slv_1); + IF NOT command.byte THEN + slv_1 := to_slv(d_hi,8); + IF mem(Sect)(Addr+1)>-1 THEN + slv_2 := to_slv(mem(Sect)(Addr+1),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + mem(Sect)(Addr+1) := to_nat(slv_1); + END IF; + END IF; + + + WHEN wt => + WAIT FOR command.wtime; + + WHEN wt_rdy => + IF T_RY/='1' THEN + WAIT UNTIL rising_edge(T_RY) FOR command.wtime; + END IF; + + WHEN wt_bsy => + IF T_RY='1' THEN + WAIT UNTIL falling_edge(T_RY) FOR command.wtime; + END IF; + + WHEN OTHERS => null; + END CASE; + END PROCEDURE; + + + VARIABLE cmd_cnt : NATURAL; + VARIABLE command : cmd_rec; -- + +BEGIN + Pick_TC (Model => "AM29LV640MH90R" ); + + Tseries <= ts_cnt ; + Tcase <= tc_cnt ; + + Generate_TC + (Model => "AM29LV640MH90R" , + Series => ts_cnt, + TestCase => tc_cnt, + command_seq => cmd_seq); + + + cmd_cnt := 1; + WHILE cmd_seq(cmd_cnt).cmd/=done LOOP + command:= cmd_seq(cmd_cnt); + IF command.sect = -1 THEN + command.sect := ProtSecNum; + END IF; + status <= command.status; + sts_check<= to_slv(command.d_lo,8); --used only for toggle/status check + cmd_dc(command); + cmd_cnt :=cmd_cnt +1; + + END LOOP; + +END PROCESS tb; + +--process to monitor WP# +PROCESS(T_WPNeg) +VARIABLE reg : std_logic; +BEGIN + IF falling_edge(T_WPNeg) THEN + reg := Sec_Prot(ProtSecNum); + Sec_Prot(ProtSecNum) := '1'; + ELSIF rising_edge(T_WPNeg) THEN + Sec_Prot(ProtSecNum) := reg; + END IF; +END PROCESS; + +-------------------------------------------------------------------------------- +-- Checker process, +-- Bus transition extractor: when bus cycle is read samples addr and data +-- Transition checker : verifies correct read data using default memory +-------------------------------------------------------------------------------- +checker: PROCESS + VARIABLE RAddr : NATURAL; + VARIABLE RSect : NATURAL; + VARIABLE longread : boolean; + VARIABLE shortread : boolean; + VARIABLE toggle : boolean:=false; + VARIABLE toggle_sts : std_logic_vector(7 downto 0); + +BEGIN +-- Transition extractor + IF (T_CENeg='0'AND T_OENeg='0'AND T_WENeg='1') THEN + IF T_BYTENeg='1' THEN + RAddr := to_nat(T_A(14 downto 0)&'0'); + ELSE + RAddr := to_nat(T_A(14 downto 0)&T_DQ(15)); + END IF; + RSect := to_nat(T_A(HiAddrBit downto 15)); + + shortread:= false; + longread := false; + + --DUT specific timing + IF (T_CENeg'EVENT OR T_WENeg'EVENT OR T_A(HiAddrBit downto 2)'EVENT)AND -- + (status=read OR status=rd_cfi OR status=rd_secsi) THEN --OR status=readX) + longread := true; + CASE TimingModel IS + WHEN "AM29LV640MH90R" | + "AM29LV640ML90R" => WAIT FOR 95 ns; +-- WHEN "AM29LV640MH101" | +-- "AM29LV640ML101" => WAIT FOR 105 ns; +-- WHEN "AM29LV640MH101R" | +-- "AM29LV640ML101R" => WAIT FOR 105 ns; +-- WHEN "AM29LV640MH112" | +-- "AM29LV640ML112" => WAIT FOR 115 ns; +-- WHEN "AM29LV640MH112R" | +-- "AM29LV640ML112R" => WAIT FOR 115 ns; +-- WHEN "AM29LV640MH120" | +-- "AM29LV640ML120" => WAIT FOR 125 ns; +-- WHEN "AM29LV640MH120R" | +-- "AM29LV640ML120R" => WAIT FOR 125 ns; + WHEN OTHERS => + REPORT "Timing model NOT supported : "&TimingModel + SEVERITY error; + END CASE; + + ELSIF T_A(1 downto 0)'EVENT OR + (T_DQ(15)'EVENT AND T_BYTENeg='0')OR + (T_BYTENeg'EVENT) OR + T_OENeg'EVENT OR + (status/=read AND status/=rd_cfi AND + status/=rd_secsi) THEN --AND status/=readX) + shortread:=true; + CASE TimingModel IS + WHEN "AM29LV640MH90R" | + "AM29LV640ML90R" => WAIT FOR 30 ns; +-- WHEN "AM29LV640MH101" | +-- "AM29LV640ML101" => WAIT FOR 40 ns; +-- WHEN "AM29LV640MH101R" | +-- "AM29LV640ML101R" => WAIT FOR 40 ns; +-- WHEN "AM29LV640MH112" | +-- "AM29LV640ML112" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH112R" | +-- "AM29LV640ML112R" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH120" | +-- "AM29LV640ML120" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH120R" | +-- "AM29LV640ML120R" => WAIT FOR 45 ns; + WHEN OTHERS => + REPORT "Timing model NOT supported : "&TimingModel + SEVERITY error; + END CASE; + + END IF; + + + + --Checker + IF longread OR shortread THEN + + CASE status IS + WHEN none => + toggle := false; + + -- read memory array data + WHEN read => + toggle := false; + Check_read ( + DQ => T_DQ, + D_lo => mem(RSect)(RAddr), + D_hi => mem(RSect)(RAddr+1), + Byte => T_BYTENeg, + check_err=> check_err); + + -- read secure silicon region + WHEN rd_secsi => + toggle := false; + Check_SecSi ( + DQ => T_DQ, + D_lo => SecSi(RAddr), + D_hi => SecSi(RAddr+1), + Byte => T_BYTENeg, + check_err=>check_err); + + + --read CFI query codes + WHEN rd_cfi => + RAddr := to_nat(T_A(14 downto 0)); --x16 addressing + toggle := false; + Check_CFI ( + DQ => T_DQ, + D_lo => CFI_array(RAddr) , + D_hi => 0 , + Byte => T_BYTENeg, + check_err=>check_err); + + + + -- read Autoselect codes + WHEN rd_AS => + RAddr := to_nat(T_A(14 downto 0)); --x16 addressing + toggle := false; + Check_AS ( + DQ => T_DQ, + addr => RAddr, + ProtSecNum=>ProtSecNum, + secProt => Sec_Prot(RSect), + FactoryProt=>FactoryProt , + Byte => T_BYTENeg, + AS_E => to_slv(16#0C#,8), + AS_F => to_slv(1,8), + + check_err=>check_err); + + + WHEN rd_HiZ => + toggle:=false; + Check_Z ( + DQ => T_DQ, + check_err=>check_err); + + + + WHEN readX => + toggle:=false; + Check_X ( + DQ => T_DQ, + check_err=>check_err); + + + WHEN erase_na | erase_active => + IF toggle THEN + Check_Erase ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN ers_susp_e => + IF toggle THEN + Check_Ers_Susp ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + +-- + + WHEN ers_susp_prog_na | ers_susp_prog => + IF toggle THEN + Check_Ers_Susp_Prog ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + +-- + + WHEN prog_na | prog_active => + IF toggle THEN + Check_Progr ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN buff_wr_busy | buff_wr_N_busy => + IF toggle THEN + Check_Buff_Busy ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN buff_abort => + IF toggle THEN + Check_Abort ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + WHEN OTHERS => null; + END CASE; + + -- get firs data for toggle check + CASE status IS + WHEN prog_active | prog_na | + erase_active | erase_na | + ers_susp_e | + ers_susp_prog | ers_susp_prog_na | + buff_wr_busy | buff_wr_N_busy | + buff_abort | get_toggle => + + IF (NOT toggle) OR (status=get_toggle) THEN + toggle:=true; + toggle_sts := T_DQ(7 downto 0); + END IF; + + WHEN OTHERS => null; + END CASE; + + + END IF; + + END IF; + + WAIT ON T_A, T_CENeg, T_OENeg, T_WENeg, T_DQ(15), T_BYTENeg; + +END PROCESS checker; + + +default: PROCESS + -- text file input variables + FILE mem_f : text is mem_file; + FILE prot_f : text is prot_file; + FILE secsi_f : text is secsi_file; + + VARIABLE S_ind : NATURAL RANGE 0 TO SecNum:= 0; + VARIABLE ind : NATURAL RANGE 0 TO SecSize:= 0; + VARIABLE buf : line; + +BEGIN + --Preload Control + ----------------------------------------------------------------------- + -- File Read Section + ----------------------------------------------------------------------- + IF UserPreload THEN + --- Sector protection preload + IF (prot_file /= "none" ) THEN + ind := 0; + FactoryProt := '0'; + Sec_Prot := (OTHERS => '0'); + WHILE (not ENDFILE (prot_f)) LOOP + READLINE (prot_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 3)); --address + ELSE + IF ind > SecNum THEN + --SecSi Factory protect preload + IF buf(1)='1' THEN + FactoryProt := '1'; + END IF; + ELSE + -- Standard Sector prload + IF buf(1)='1' THEN + Sec_Prot(ind):= '1'; + END IF; + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + -- Secure Silicon Sector Region preload + IF (SecSi_file /= "none" ) THEN + SecSi := (OTHERS => MaxData); + ind := 0; + WHILE (not ENDFILE (SecSi_f)) LOOP + READLINE (SecSi_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 3)); --address + ELSE + IF ind <= SecSiSize THEN + SecSi(ind) := h(buf(1 TO 2)); + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + --- Memory Preload + IF (mem_file /= "none" ) THEN + ind := 0; + Mem := (OTHERS => (OTHERS => MaxData)); + -- load sector 0 + WHILE (not ENDFILE (mem_f)) LOOP + READLINE (mem_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 5)); --address + ELSE + IF ind <= SecSize THEN + Mem(0)(ind) := h(buf(1 to 2)); + ind := ind + 1; + END IF; + END IF; + END LOOP; + -- load other sectors + FOR i IN 1 TO SecNum LOOP + Mem(i) := Mem(0); + END LOOP; + END IF; + + END IF; + ----------------------------------------------------------------------- + --CFI array data / AM29LV640MH90R !!! DEVICE SPECIFIC + ----------------------------------------------------------------------- + --CFI query identification string + -- !!!!!! WORD ADDRESSES (x16) - for x8 addressing double addr + --CFI query identification string + CFI_array(16#10#) := 16#51#; + CFI_array(16#11#) := 16#52#; + CFI_array(16#12#) := 16#59#; + CFI_array(16#13#) := 16#02#; + CFI_array(16#14#) := 16#00#; + CFI_array(16#15#) := 16#40#; + CFI_array(16#16#) := 16#00#; + CFI_array(16#17#) := 16#00#; + CFI_array(16#18#) := 16#00#; + CFI_array(16#19#) := 16#00#; + CFI_array(16#1A#) := 16#00#; + --system interface string + CFI_array(16#1B#) := 16#27#; + CFI_array(16#1C#) := 16#36#; + CFI_array(16#1D#) := 16#00#; + CFI_array(16#1E#) := 16#00#; + CFI_array(16#1F#) := 16#07#; + CFI_array(16#20#) := 16#07#; + CFI_array(16#21#) := 16#0A#; + CFI_array(16#22#) := 16#00#; + CFI_array(16#23#) := 16#01#; + CFI_array(16#24#) := 16#05#; + CFI_array(16#25#) := 16#04#; + CFI_array(16#26#) := 16#00#; + --device geometry definition + CFI_array(16#27#) := 16#17#; + CFI_array(16#28#) := 16#02#; + CFI_array(16#29#) := 16#00#; + CFI_array(16#2A#) := 16#05#; + CFI_array(16#2B#) := 16#00#; + CFI_array(16#2C#) := 16#01#; + CFI_array(16#2D#) := 16#7F#; + CFI_array(16#2E#) := 16#00#; + CFI_array(16#2F#) := 16#00#; + CFI_array(16#30#) := 16#01#; + CFI_array(16#31#) := 16#00#; + CFI_array(16#32#) := 16#00#; + CFI_array(16#33#) := 16#00#; + CFI_array(16#34#) := 16#00#; + CFI_array(16#35#) := 16#00#; + CFI_array(16#36#) := 16#00#; + CFI_array(16#37#) := 16#00#; + CFI_array(16#38#) := 16#00#; + CFI_array(16#39#) := 16#00#; + CFI_array(16#3A#) := 16#00#; + CFI_array(16#3B#) := 16#00#; + CFI_array(16#3C#) := 16#00#; + --primary vendor-specific extended query + CFI_array(16#40#) := 16#50#; + CFI_array(16#41#) := 16#52#; + CFI_array(16#42#) := 16#49#; + CFI_array(16#43#) := 16#31#; + CFI_array(16#44#) := 16#33#; + CFI_array(16#45#) := 16#08#; + CFI_array(16#46#) := 16#02#; + CFI_array(16#47#) := 16#01#; + CFI_array(16#48#) := 16#01#; + CFI_array(16#49#) := 16#04#; + CFI_array(16#4A#) := 16#00#; + CFI_array(16#4B#) := 16#00#; + CFI_array(16#4C#) := 16#01#; + CFI_array(16#4D#) := 16#B5#; + CFI_array(16#4E#) := 16#C5#; + IF TimingModel(11) = 'L' THEN + CFI_array(16#4F#) := 16#04#; + ELSE + CFI_array(16#4F#) := 16#05#; --uniform sectors top protect + END IF; + CFI_array(16#50#) := 16#01#; + + WAIT; + +END PROCESS default; + + + +END vhdl_behavioral; + diff --git a/lib/models/memory/flash/serial/S25fl256s/utilities/conversions.vhd b/lib/models/memory/flash/serial/S25fl256s/utilities/conversions.vhd new file mode 100644 index 0000000..e5fc0d6 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl256s/utilities/conversions.vhd @@ -0,0 +1,1035 @@ +-------------------------------------------------------------------------------- +-- File Name: conversions_p.vhd +-------------------------------------------------------------------------------- +-- Copyright (C) 1997, 1998, 2001 Free Model Foundry; http://eda.org/fmf/ +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License version 2 as +-- published by the Free Software Foundation. +-- +-- This package was written by SEVA Technologies, Inc. and donated to the FMF. +-- www.seva.com +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 R. Steele 97 DEC 05 Added header and formatting to SEVA file +-- V1.1 R. Munden 98 NOV 28 Corrected some comments +-- Corrected function b +-- V1.2 R. Munden 01 MAY 27 Corrected function to_nat for weak values +-- and combined into a single file +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; + +-------------------------------------------------------------------------------- +-- CONVERSION FUNCTION SELECTION TABLES +-------------------------------------------------------------------------------- +-- +-- FROM TO: std_logic_vector std_logic natural time string +-- -----------------|---------------|---------|---------|---------|----------- +-- std_logic_vector | N/A | N/A | to_nat | combine | see below +-- std_logic | N/A | N/A | to_nat | combine | see below +-- natural | to_slv | to_sl | N/A | to_time | see below +-- time | N/A | N/A | to_nat | N/A | to_time_str +-- hex string | h | N/A | h | combine | N/A +-- decimal string | d | N/A | d | combine | N/A +-- octal string | o | N/A | o | combine | N/A +-- binary string | b | N/A | b | combine | N/A +-- -----------------|---------------|---------|---------|---------|----------- +-- +-- FROM TO: hex string decimal string octal string binary string +-- -----------------|------------|-------------|------------|---------------- +-- std_logic_vector | to_hex_str | to_int_str | to_oct_str | to_bin_str +-- std_logic | N/A | N/A | N/A | to_bin_str +-- natural | to_hex_str | to_int_str | to_oct_str | to_bin_str +-- -----------------|------------|-------------|------------|---------------- +-- +-------------------------------------------------------------------------------- + +PACKAGE conversions IS + + ---------------------------------------------------------------------------- + -- the conversions in this package are not guaranteed to be synthesizable. + -- + -- others functions available + -- fill creates a variable length string of the fill character + -- + -- + -- + -- input parameters of type natural or integer can be in the form: + -- normal -> 8, 99, 4_237 + -- base#value# -> 2#0101#, 16#fa4C#, 8#6_734# + -- with exponents(x10) -> 8e4, 16#2e#E4 + -- + -- input parameters of type string can be in the form: + -- "99", "4_237", "0101", "1010_1010" + -- + -- for bit/bit_vector <-> std_logic/std_logic_vector conversions use + -- package std_logic_1164 + -- to_bit(std_logic) + -- to_bitvector(std_logic_vector) + -- to_stdlogic(bit) + -- to_stdlogicvector(bit_vector) + -- + -- for "synthesizable" signed/unsigned/std_logic_vector/integer + -- conversions use + -- package std_logic_arith + -- conv_integer(signed/unsigned) + -- conv_unsigned(integer/signed,size) + -- conv_signed(integer/unsigned,size) + -- conv_std_logic_vector(integer/signed/unsigned,size) + -- + -- for "synthesizable" std_logic_vector -> integer conversions use + -- package std_logic_unsigned/std_logic_signed + -- + -- conv_integer(std_logic_vector) + -- + -- type1'(expression of type2) + -- + -- most conversions have 4 parmeters: + -- x : value to be converted + -- rtn_len : size of the return value + -- justify : justify value 'left' or 'right', default is right + -- basespec : print the base of the value - 'yes'/'no', default is yes + -- + -- Typical ways to call these functions: + -- simple, all defaults used + -- to_bin_str(x) + -- x will be converted to a string of minimum size with a + -- base specification appended for clarity + -- if x is 10101 then return is b"10101" + -- + -- to control size of return string + -- to_hex_str(x, + -- 6) + -- length of string returned will be 6 characters + -- value will be right justified in the field + -- if x is 10101 then return is ....h"15" + -- where '.' represents a blank + -- if 'rtn_len' parm defaults or is set to 0 then + -- return string will always be minimum size + -- + -- to left justify and suppress base specification + -- to_int_str(x, + -- 6, + -- justify => left, + -- basespec => yes) + -- length of return string will be 6 characters + -- the base specification will be suppressed + -- if x is 10101 then return is 21.... + -- where '.' represents a blank + -- + -- other usage notes + -- + -- if rtn_len less than or equal to x'length then ignore + -- rtn_len and return string of x'length + -- the 'justify' parm is effectively ignored in this case + -- + -- if rtn_len greater than x'length then return string + -- of rtn_len with blanks based on 'justify' parm + -- + -- these routines do not handle negative numbers + ---------------------------------------------------------------------------- + + type justify_side is (left, right); + type b_spec is (no , yes); + + -- std_logic_vector to binary string + function to_bin_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- std_logic to binary string + function to_bin_str(x : std_logic; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to binary string + function to_bin_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to hex string + function to_hex_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to hex string + function to_hex_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to octal string + function to_oct_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to octal string + function to_oct_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- natural to integer string + function to_int_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to integer string + function to_int_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- time to string + function to_time_str (x : time) + return string; + + -- add characters to a string + function fill (fill_char : character := '*'; + rtn_len : integer := 1) + return string; + -- usage: + -- fill + -- returns * + -- fill(' ',10) + -- returns .......... when '.' represents a blank + -- fill(lf) or fill(ht) + -- returns line feed character or tab character respectively + + -- std_logic_vector to natural + function to_nat (x : std_logic_vector) + return natural; + + -- std_logic to natural + function to_nat (x : std_logic) + return natural; + + -- time to natural + function to_nat (x : time) + return natural; + + -- hex string to std_logic_vector + function h (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or a,A to f,F + -- or x,X,z,Z,u,U,-,w,W, result will be 0 + + -- decimal string to std_logic_vector + function d (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- octal string to std_logic_vector + function o (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 7 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- binary string to std_logic_vector + function b (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 1 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- hex string to natural + function h (x : string) + return natural; + -- if x is other than characters 0 to 9 or a,A to f,F, result will be 0 + + -- decimal string to natural + function d (x : string) + return natural; + -- if x is other than characters 0 to 9, result will be 0 + + -- octal string to natural + function o (x : string) + return natural; + -- if x is other than characters 0 to 7, result will be 0 + + -- binary string to natural + function b (x : string) + return natural; + -- if x is other than characters 0 to 1, result will be 0 + + -- natural to std_logic_vector + function to_slv (x : natural; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than sizeof(x), result will be truncated on the left + -- see note above regarding possible formats for x + + -- natural to std_logic + function to_sl (x : natural) + return std_logic; + + -- natural to time + function to_time (x : natural) + return time; + -- see note above regarding possible formats for x + +END conversions; +-- +-------------------------------------------------------------------------------- +-- + +PACKAGE BODY conversions IS + + -- private declarations for this package + type basetype is (binary, octal, decimal, hex); + + function max(x,y: integer) return integer is + begin + if x > y then return x; else return y; end if; + end max; + + function min(x,y: integer) return integer is + begin + if x < y then return x; else return y; end if; + end min; + + -- consider function sizeof for string/slv/???, return natural + + -- function size(len: natural) return natural is + -- begin + -- if len=0 then + -- return 31; + -- else return len; + -- end if; + -- end size; + + function nextmultof (x : positive; + size : positive) return positive is + begin + case x mod size is + when 0 => return size * x/size; + when others => return size * (x/size + 1); + end case; + end nextmultof; + + function rtn_base (base : basetype) return character is + begin + case base is + when binary => return 'b'; + when octal => return 'o'; + when decimal => return 'd'; + when hex => return 'h'; + end case; + end rtn_base; + + function format (r : string; + base : basetype; + rtn_len : natural ; + justify : justify_side; + basespec : b_spec) return string is + variable int_rtn_len : integer; + begin + if basespec=yes then + int_rtn_len := rtn_len - 3; + else + int_rtn_len := rtn_len; + end if; + if int_rtn_len <= r'length then + case basespec is + when no => return r ; + when yes => return rtn_base(base) & '"' & r & '"'; + end case; + else + case justify is + when left => + case basespec is + when no => + return r & fill(' ',int_rtn_len - r'length); + when yes => + return rtn_base(base) & '"' & r & '"' & + fill(' ',int_rtn_len - r'length); + end case; + when right => + case basespec is + when no => + return fill(' ',int_rtn_len - r'length) & r ; + when yes => + return fill(' ',int_rtn_len - r'length) & + rtn_base(base) & '"' & r & '"'; + end case; + end case; + end if; + end format; + + -- convert numeric string of any base to natural + function cnvt_base (x : string; + inbase : natural range 2 to 16) return natural is + -- assumes x is an unsigned number string of base 'inbase' + -- values larger than natural'high are not supported + variable r,t : natural := 0; + variable place : positive := 1; + begin + for i in x'reverse_range loop + case x(i) is + when '0' => t := 0; + when '1' => t := 1; + when '2' => t := 2; + when '3' => t := 3; + when '4' => t := 4; + when '5' => t := 5; + when '6' => t := 6; + when '7' => t := 7; + when '8' => t := 8; + when '9' => t := 9; + when 'a'|'A' => t := 10; + when 'b'|'B' => t := 11; + when 'c'|'C' => t := 12; + when 'd'|'D' => t := 13; + when 'e'|'E' => t := 14; + when 'f'|'F' => t := 15; + when '_' => t := 0; -- ignore these characters + place := place / inbase; + when others => + assert false + report lf & + "CNVT_BASE found input value larger than base: " & lf & + "Input value: " & x(i) & + " Base: " & to_int_str(inbase) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + if t / inbase > 1 then -- invalid value for base + assert false + report lf & + "CNVT_BASE found input value larger than base: " & lf & + "Input value: " & x(i) & + " Base: " & to_int_str(inbase) & lf & + "converting input to integer 0" + severity warning; + return 0; + else + r := r + (t * place); + place := place * inbase; + end if; + end loop; + return r; + end cnvt_base; + + function extend (x : std_logic; + len : positive) return std_logic_vector is + variable v : std_logic_vector(1 to len) := (others => x); + begin + return v; + end extend; + + + -- implementation of public declarations + + function to_bin_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + + variable int : std_logic_vector(1 to x'length):=x; + variable r : string(1 to x'length):=(others=>'$'); + begin + for i in int'range loop + r(i to i) := to_bin_str(int(i),basespec=>no); + end loop; + return format (r,binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_bin_str(x : std_logic; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable r : string(1 to 1); + begin + case x is + when '0' => r(1) := '0'; + when '1' => r(1) := '1'; + when 'U' => r(1) := 'U'; + when 'X' => r(1) := 'X'; + when 'Z' => r(1) := 'Z'; + when 'W' => r(1) := 'W'; + when 'H' => r(1) := 'H'; + when 'L' => r(1) := 'L'; + when '-' => r(1) := '-'; + end case; + return format (r,binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_bin_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 2 to 32 := 32; + variable r : string(2 to 32):=(others=>'$'); + begin + if int = 0 then + return format ("0",binary,rtn_len,justify,basespec); + end if; + + while int > 0 loop + case int rem 2 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when others => + assert false report lf & "TO_BIN_STR, shouldn't happen" + severity failure; + return "$"; + null; + end case; + int := int / 2; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 32),binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_hex_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + -- will return x'length/4 + variable nxt : positive := nextmultof(x'length,4); + variable int : std_logic_vector(1 to nxt):= (others => '0'); + variable ptr : positive range 1 to (nxt/4)+1 := 1; + variable r : string(1 to nxt/4):=(others=>'$'); + subtype slv4 is std_logic_vector(1 to 4); + begin + int(nxt-x'length+1 to nxt) := x; + if nxt-x'length > 0 and x(x'left) /= '1' then + int(1 to nxt-x'length) := extend(x(x'left),nxt-x'length); + end if; + for i in int'range loop + next when i rem 4 /= 1; + case slv4'(int(i to i+3)) is + when "0000" => r(ptr) := '0'; + when "0001" => r(ptr) := '1'; + when "0010" => r(ptr) := '2'; + when "0011" => r(ptr) := '3'; + when "0100" => r(ptr) := '4'; + when "0101" => r(ptr) := '5'; + when "0110" => r(ptr) := '6'; + when "0111" => r(ptr) := '7'; + when "1000" => r(ptr) := '8'; + when "1001" => r(ptr) := '9'; + when "1010" => r(ptr) := 'A'; + when "1011" => r(ptr) := 'B'; + when "1100" => r(ptr) := 'C'; + when "1101" => r(ptr) := 'D'; + when "1110" => r(ptr) := 'E'; + when "1111" => r(ptr) := 'F'; + when "ZZZZ" => r(ptr) := 'Z'; + when "WWWW" => r(ptr) := 'W'; + when "LLLL" => r(ptr) := 'L'; + when "HHHH" => r(ptr) := 'H'; + when "UUUU" => r(ptr) := 'U'; + when "XXXX" => r(ptr) := 'X'; + when "----" => r(ptr) := '-'; + when others => + assert false + report lf & + "TO_HEX_STR found illegal value: " & + to_bin_str(int(i to i+3)) & lf & + "converting input to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr + 1; + end loop; + return format (r,hex,rtn_len,justify,basespec); + end to_hex_str; + + function to_hex_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 20 := 20; + variable r : string(1 to 20):=(others=>'$'); + begin + if x=0 then return format ("0",hex,rtn_len,justify,basespec); end if; + while int > 0 loop + case int rem 16 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when 8 => r(ptr) := '8'; + when 9 => r(ptr) := '9'; + when 10 => r(ptr) := 'A'; + when 11 => r(ptr) := 'B'; + when 12 => r(ptr) := 'C'; + when 13 => r(ptr) := 'D'; + when 14 => r(ptr) := 'E'; + when 15 => r(ptr) := 'F'; + when others => + assert false report lf & "TO_HEX_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 16; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 20),hex,rtn_len,justify,basespec); + end to_hex_str; + + function to_oct_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + -- will return x'length/3 + variable nxt : positive := nextmultof(x'length,3); + variable int : std_logic_vector(1 to nxt):= (others => '0'); + variable ptr : positive range 1 to (nxt/3)+1 := 1; + variable r : string(1 to nxt/3):=(others=>'$'); + subtype slv3 is std_logic_vector(1 to 3); + begin + int(nxt-x'length+1 to nxt) := x; + if nxt-x'length > 0 and x(x'left) /= '1' then + int(1 to nxt-x'length) := extend(x(x'left),nxt-x'length); + end if; + for i in int'range loop + next when i rem 3 /= 1; + case slv3'(int(i to i+2)) is + when "000" => r(ptr) := '0'; + when "001" => r(ptr) := '1'; + when "010" => r(ptr) := '2'; + when "011" => r(ptr) := '3'; + when "100" => r(ptr) := '4'; + when "101" => r(ptr) := '5'; + when "110" => r(ptr) := '6'; + when "111" => r(ptr) := '7'; + when "ZZZ" => r(ptr) := 'Z'; + when "WWW" => r(ptr) := 'W'; + when "LLL" => r(ptr) := 'L'; + when "HHH" => r(ptr) := 'H'; + when "UUU" => r(ptr) := 'U'; + when "XXX" => r(ptr) := 'X'; + when "---" => r(ptr) := '-'; + when others => + assert false + report lf & + "TO_OCT_STR found illegal value: " & + to_bin_str(int(i to i+2)) & lf & + "converting input to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr + 1; + end loop; + return format (r,octal,rtn_len,justify,basespec); + end to_oct_str; + + function to_oct_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 20 := 20; + variable r : string(1 to 20):=(others=>'$'); + begin + if x=0 then return format ("0",octal,rtn_len,justify,basespec); end if; + while int > 0 loop + case int rem 8 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when others => + assert false report lf & "TO_OCT_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 8; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 20),octal,rtn_len,justify,basespec); + end to_oct_str; + + function to_int_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 32 := 32; + variable r : string(1 to 32):=(others=>'$'); + begin + if x=0 then return format ("0",hex,rtn_len,justify,basespec); + else + while int > 0 loop + case int rem 10 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when 8 => r(ptr) := '8'; + when 9 => r(ptr) := '9'; + when others => + assert false report lf & "TO_INT_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 10; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 32),decimal,rtn_len,justify,basespec); + end if; + end to_int_str; + + function to_int_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string is + begin + return to_int_str(to_nat(x),rtn_len,justify,basespec); + end to_int_str; + + + function to_time_str (x : time) + return string is + begin + return to_int_str(to_nat(x),basespec=>no) & " ns"; + end to_time_str; + + function fill (fill_char : character := '*'; + rtn_len : integer := 1) + return string is + variable r : string(1 to max(rtn_len,1)) := (others => fill_char); + variable len : integer; + begin + if rtn_len < 2 then -- always returns at least 1 fill char + len := 1; + else + len := rtn_len; + end if; + return r(1 to len); + end fill; + + function to_nat(x : std_logic_vector) return natural is + -- assumes x is an unsigned number, lsb on right, + -- more than 31 bits are truncated on left + variable t : std_logic_vector(1 to x'length) := x; + variable int : std_logic_vector(1 to 31) := (others => '0'); + variable r : natural := 0; + variable place : positive := 1; + begin + if x'length < 32 then + int(max(32-x'length,1) to 31) := t(1 to x'length); + else -- x'length >= 32 + int(1 to 31) := t(x'length-30 to x'length); + end if; + for i in int'reverse_range loop + case int(i) is + when '1' | 'H' => r := r + place; + when '0' | 'L' => null; + when others => + assert false + report lf & + "TO_NAT found illegal value: " & to_bin_str(int(i)) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + exit when i=1; + place := place * 2; + end loop; + return r; + end to_nat; + + function to_nat (x : std_logic) + return natural is + begin + case x is + when '0' => return 0 ; + when '1' => return 1 ; + when others => + assert false + report lf & + "TO_NAT found illegal value: " & to_bin_str(x) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + end to_nat; + + function to_nat (x : time) + return natural is + begin + return x / 1 ns; + end to_nat; + + function h(x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or a,A to f,F or + -- x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length*4,rtn_len); + variable ptr : integer range -3 to size := size; + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr-3 to ptr) := "0000"; + when '1' => r(ptr-3 to ptr) := "0001"; + when '2' => r(ptr-3 to ptr) := "0010"; + when '3' => r(ptr-3 to ptr) := "0011"; + when '4' => r(ptr-3 to ptr) := "0100"; + when '5' => r(ptr-3 to ptr) := "0101"; + when '6' => r(ptr-3 to ptr) := "0110"; + when '7' => r(ptr-3 to ptr) := "0111"; + when '8' => r(ptr-3 to ptr) := "1000"; + when '9' => r(ptr-3 to ptr) := "1001"; + when 'a'|'A' => r(ptr-3 to ptr) := "1010"; + when 'b'|'B' => r(ptr-3 to ptr) := "1011"; + when 'c'|'C' => r(ptr-3 to ptr) := "1100"; + when 'd'|'D' => r(ptr-3 to ptr) := "1101"; + when 'e'|'E' => r(ptr-3 to ptr) := "1110"; + when 'f'|'F' => r(ptr-3 to ptr) := "1111"; + when 'U' => r(ptr-3 to ptr) := "UUUU"; + when 'X' => r(ptr-3 to ptr) := "XXXX"; + when 'Z' => r(ptr-3 to ptr) := "ZZZZ"; + when 'W' => r(ptr-3 to ptr) := "WWWW"; + when 'H' => r(ptr-3 to ptr) := "HHHH"; + when 'L' => r(ptr-3 to ptr) := "LLLL"; + when '-' => r(ptr-3 to ptr) := "----"; + when '_' => ptr := ptr + 4; + when others => + assert false + report lf & + "O conversion found illegal input character: " & + int(i) & lf & "converting character to '----'" + severity warning; + r(ptr-3 to ptr) := "----"; + end case; + ptr := ptr - 4; + end loop; + return r(size-rtn_len+1 to size); + end h; + + function d (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than binary length of x, result will be truncated on + -- the left + -- if x is other than characters 0 to 9, result will be 0 + begin + return to_slv(cnvt_base(x,10),rtn_len); + end d; + + function o (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length*3, result will be truncated on the left + -- if x is other than characters 0 to 7 or or x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length*3,rtn_len); + variable ptr : integer range -2 to size := size; + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr-2 to ptr) := "000"; + when '1' => r(ptr-2 to ptr) := "001"; + when '2' => r(ptr-2 to ptr) := "010"; + when '3' => r(ptr-2 to ptr) := "011"; + when '4' => r(ptr-2 to ptr) := "100"; + when '5' => r(ptr-2 to ptr) := "101"; + when '6' => r(ptr-2 to ptr) := "110"; + when '7' => r(ptr-2 to ptr) := "111"; + when 'U' => r(ptr-2 to ptr) := "UUU"; + when 'X' => r(ptr-2 to ptr) := "XXX"; + when 'Z' => r(ptr-2 to ptr) := "ZZZ"; + when 'W' => r(ptr-2 to ptr) := "WWW"; + when 'H' => r(ptr-2 to ptr) := "HHH"; + when 'L' => r(ptr-2 to ptr) := "LLL"; + when '-' => r(ptr-2 to ptr) := "---"; + when '_' => ptr := ptr + 3; + when others => + assert false + report lf & + "O conversion found illegal input character: " & + int(i) & lf & "converting character to '---'" + severity warning; + r(ptr-2 to ptr) := "---"; + end case; + ptr := ptr - 3; + end loop; + return r(size-rtn_len+1 to size); + end o; + + function b (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length, result will be truncated on the left + -- if x is other than characters 0 to 1 or x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length,rtn_len); + variable ptr : integer range 0 to size+1 := size; -- csa + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr) := '0'; + when '1' => r(ptr) := '1'; + when 'U' => r(ptr) := 'U'; + when 'X' => r(ptr) := 'X'; + when 'Z' => r(ptr) := 'Z'; + when 'W' => r(ptr) := 'W'; + when 'H' => r(ptr) := 'H'; + when 'L' => r(ptr) := 'L'; + when '-' => r(ptr) := '-'; + when '_' => ptr := ptr + 1; + when others => + assert false + report lf & + "B conversion found illegal input character: " & + int(i) & lf & "converting character to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr - 1; + end loop; + return r(size-rtn_len+1 to size); + end b; + + function h (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 9 + -- a,A to f,F + -- blanks, underscore + begin + return cnvt_base(x,16); + end h; + + function d (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 9 + -- blanks, underscore + begin + return cnvt_base(x,10); + end d; + + function o (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 7 + -- blanks, underscore + begin + return cnvt_base(x,8); + end o; + + function b (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 1 + -- blanks, underscore + begin + return cnvt_base(x,2); + end b; + + function to_slv(x : natural; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than sizeof(x), result will be truncated on the left + variable int : natural := x; + variable ptr : positive := 32; + variable r : std_logic_vector(1 to 32) := (others=>'0'); + begin + while int > 0 loop + case int rem 2 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when others => + assert false report lf & "TO_SLV, shouldn't happen" + severity failure; + return "0"; + end case; + int := int / 2; + ptr := ptr - 1; + end loop; + return r(33-rtn_len to 32); + end to_slv; + + function to_sl(x : natural) + return std_logic is + variable r : std_logic := '0'; + begin + case x is + when 0 => null; + when 1 => r := '1'; + when others => + assert false + report lf & + "TO_SL found illegal input character: " & + to_int_str(x) & lf & "converting character to '-'" + severity warning; + return '-'; + end case; + return r; + end to_sl; + + function to_time (x: natural) return time is + begin + return x * 1 ns; + end to_time; + +END conversions; diff --git a/lib/models/memory/flash/serial/S25fl256s/utilities/gen_utils.vhd b/lib/models/memory/flash/serial/S25fl256s/utilities/gen_utils.vhd new file mode 100644 index 0000000..65c0e77 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl256s/utilities/gen_utils.vhd @@ -0,0 +1,144 @@ +-------------------------------------------------------------------------------- +-- File name: gen_utils.vhd +-------------------------------------------------------------------------------- +-- Copyright (C) 1996, 1998, 2001 Free Model Foundry; http://eda.org/fmf/ +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License version 2 as +-- published by the Free Software Foundation. +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 R. Steele 96 SEP 26 Initial release +-- V1.1 REV3 97 Feb 27 Added Xon and MsgOn generics +-- V1.2 R. Steele 97 APR 16 Changed wired-or to wired-and +-- V1.3 R. Steele 97 APR 16 Added diff. receiver table +-- V1.4 R. Munden 98 APR 13 Added GenParity and CheckParity +-- V1.5 R. Munden 01 NOV 24 Added UnitDelay01ZX +-- +-------------------------------------------------------------------------------- +LIBRARY IEEE; USE IEEE.std_Logic_1164.ALL; + USE IEEE.VITAL_primitives.ALL; + USE IEEE.VITAL_timing.ALL; + +PACKAGE gen_utils IS + + ---------------------------------------------------------------------------- + -- Result map for Wired-and output values (open collector) + ---------------------------------------------------------------------------- + CONSTANT STD_wired_and_rmap : VitalResultMapType := ('U','X','0','Z'); + + ---------------------------------------------------------------------------- + -- Table for computing a single signal from a differential receiver input + -- pair. + ---------------------------------------------------------------------------- + CONSTANT diff_rec_tab : VitalStateTableType := ( + + ------INPUTS--|-PREV-|-OUTPUT---- + -- A ANeg | Aint | Aint' -- + --------------|------|----------- + ( 'X', '-', '-', 'X'), -- A unknown + ( '-', 'X', '-', 'X'), -- A unknown + ( '1', '-', 'X', '1'), -- Recover from 'X' + ( '0', '-', 'X', '0'), -- Recover from 'X' + ( '/', '0', '0', '1'), -- valid diff. rising edge + ( '1', '\', '0', '1'), -- valid diff. rising edge + ( '\', '1', '1', '0'), -- valid diff. falling edge + ( '0', '/', '1', '0'), -- valid diff. falling edge + ( '-', '-', '-', 'S') -- default + ); -- end of VitalStateTableType definition + + + ---------------------------------------------------------------------------- + -- Default Constants + ---------------------------------------------------------------------------- + CONSTANT UnitDelay : VitalDelayType := 1 ns; + CONSTANT UnitDelay01 : VitalDelayType01 := (1 ns, 1 ns); + CONSTANT UnitDelay01Z : VitalDelayType01Z := (others => 1 ns); + CONSTANT UnitDelay01ZX : VitalDelayType01ZX := (others => 1 ns); + + CONSTANT DefaultInstancePath : STRING := "*"; + CONSTANT DefaultTimingChecks : BOOLEAN := FALSE; + CONSTANT DefaultTimingModel : STRING := "UNIT"; + CONSTANT DefaultXon : BOOLEAN := TRUE; + CONSTANT DefaultMsgOn : BOOLEAN := TRUE; + + -- Older VITAL generic being phased out + CONSTANT DefaultXGeneration : BOOLEAN := TRUE; + + ------------------------------------------------------------------- + -- Generate Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION GenParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic_vector; + + ------------------------------------------------------------------- + -- Check Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION CheckParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic; -- '0' - Parity Error + +END gen_utils; + +PACKAGE BODY gen_utils IS + + function XOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 403 + variable result: STD_LOGIC; + begin + result := '0'; + for i in ARG'range loop + result := result xor ARG(i); + end loop; + return result; + end; + ------------------------------------------------------------------- + -- Generate Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION GenParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic_vector + IS + VARIABLE I: NATURAL; + VARIABLE Result: std_logic_vector (Data'Length - 1 DOWNTO 0); + BEGIN + I := 0; + WHILE (I < SIZE) LOOP + Result(I+7 DOWNTO I) := Data(I+7 downto I); + Result(I+8) := XOR_REDUCE( Data(I+7 downto I) ) XOR ODDEVEN; + I := I + 9; + END LOOP; + RETURN Result; + END GenParity; + + ------------------------------------------------------------------- + -- Check Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION CheckParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic -- '0' - Parity Error + IS + VARIABLE I: NATURAL; + VARIABLE Result: std_logic; + BEGIN + I := 0; Result := '1'; + WHILE (I < SIZE) LOOP + Result := Result AND + NOT (XOR_REDUCE( Data(I+8 downto I) ) XOR ODDEVEN); + I := I + 9; + END LOOP; + RETURN Result; + END CheckParity; + +END gen_utils; diff --git a/lib/models/memory/flash/serial/S25fl512s/Model_Manual_English.pdf b/lib/models/memory/flash/serial/S25fl512s/Model_Manual_English.pdf new file mode 100644 index 0000000..954c3f6 Binary files /dev/null and b/lib/models/memory/flash/serial/S25fl512s/Model_Manual_English.pdf differ diff --git a/lib/models/memory/flash/serial/S25fl512s/Model_Manual_Japanese.pdf b/lib/models/memory/flash/serial/S25fl512s/Model_Manual_Japanese.pdf new file mode 100644 index 0000000..de2f909 Binary files /dev/null and b/lib/models/memory/flash/serial/S25fl512s/Model_Manual_Japanese.pdf differ diff --git a/lib/models/memory/flash/serial/S25fl512s/model/model_release_history.txt b/lib/models/memory/flash/serial/S25fl512s/model/model_release_history.txt new file mode 100644 index 0000000..aeea7de --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl512s/model/model_release_history.txt @@ -0,0 +1,380 @@ +########################################## +Date (DD/MM/YYYY) - 16.11.2009 + +Model name - S25FL256S + +Vendor - Spansion (www.spansion.com) + +Publication ID - S25FL128 256 512 01GS MRS Rev0 98 + +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Ranko Prokopovic + r-prokopovic@hdl-dh.com +########################################## +########################################## +INITIAL RELEASE + +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2009-11-16-1.tar.gz +# Release Date (DD/MM/YYYY) => 16/11/2009 +# Release Version => 1.0 + +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Ranko Prokopovic + r-prokopovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2009-11-19-2.tar.gz +# Release Date (DD/MM/YYYY) => 19/11/2009 +# Release Version => 1.1 + +# Corrections: +# 1.Negative tests which show how model behaves when reset pulse +# width is less than specified and when write and erase operations are interrupted . +# with reset signal are interrupted with reset signal are added. +# 2.Implementation of Continuous Read Mode +# 3.After 8 clock cycles for instruction, first address bit is latched on the next +# rising edge of clock. + +# Files modified +-s25fl512s.vhd +-testbench_s25fl512s_vhdl.vhd +-spansion_tc_pkg.vhd +-s25fl512s.ftm +-s25fl512s_vhdl.sdf +-s25fl512s.v +-testbench_s25fl512s_verilog.vhd +-s25fl512s.ftmv +-s25fl512s_verilog.sdf +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2010-03-04-1.tar.gz +# Release Date (DD/MM/YYYY) => 04/03/2010 +# Release Version => 1.2 + +# Corrections: +# 1.Array variable WByte in sensitivity list is replaced with signal WB_flag to enable +# compilation in NCSim +# 2.addr_cnt for second read in high performance read continuous mode can change its +# value only when CSNeg = '0' + +# Files modified +-s25fl512s.v +-s25fl512s.vhd +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2010-04-15-1.tar.gz +# Release Date (DD/MM/YYYY) => 15/04/2010 +# Release Version => 1.3 + +# Corrections: +# 1.HOLD mode corrected +# 2.Condition for PP operation corrected + +# Files modified +-s25fl512s.v +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2010-05-21-1.tar.gz +# Release Date (DD/MM/YYYY) => 21/05/2010 +# Release Version => 1.4 + +# Corrections: +# 1.SRWD bit assignment is corrected +# 2.Condition for WRR command in write_cycle_decode section is corrected +# 3.Blocking assignments for signals WSTART and PSTART are replaced with +# nonblocking assignments +# 4.Conditions in Page Program section are fixed +# + +# Files modified +-s25fl512s.v +-s25fl512s.vhd +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2010-05-25-1.tar.gz +# Release Date (DD/MM/YYYY) => 25/05/2010 +# Release Version => 1.5 + +# Corrections: +# 1. Timing control sections for Program and Erase operation are changed +# 2. Conditions in Page Program section are fixed +# + +# Files modified +-s25fl512s.v +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2010-06-03-2.tar.gz +# Release Date (DD/MM/YYYY) => 03/06/2010 +# Release Version => 1.6 + +# Corrections: +# 1. bus_cycle_state section for PGSP command is fixed +# + +# Files modified +-s25fl512s.v +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2010-07-28-1.tar.gz +# Release Date (DD/MM/YYYY) => 28/07/2010 +# Release Version => 1.7 + +# Corrections: +# 1. During the QUAD mode HOLD# input is not monitored for its normal function +# 2. Internal pull-up resistors for HOLD# and WP# inputs are implemented + +# Files modified +-s25fl512s.v +-s25fl512s.vhd +########################################## +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2010-08-24-1.tar.gz +# Release Date (DD/MM/YYYY) => 24/08/2010 +# Release Version => 1.8 + +# Corrections: +# 1. All redundant signals are removed from BusCycle process + +# Files modified +-s25fl512s.v +-s25fl512s.vhd +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Branislav Colakovic + b-colakovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2010-10-14-1.tar.gz +# Release Date (DD/MM/YYYY) => 14/10/2010 +# Release Version => 1.9 + +# Corrections: +# 1. Latest datasheet aligned (VERILOG files only) + +# Files modified +-spansion_tc_pkg.vhd +-s25fl512s.v +-testbench_s25fl512s_verilog.vhd +-s25fl512s.ftmv +-s25fl512s_verilog.sdf +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Branislav Colakovic + b-colakovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2010-10-20-1.tar.gz +# Release Date (DD/MM/YYYY) => 20/10/2010 +# Release Version => 2.0 + +# Corrections: +# 1. Latest datasheet aligned (VHDL files added) + +# Files modified +-s25fl512s.vhd +-testbench_s25fl512s_vhdl.vhd +-s25fl512s.ftm +-s25fl512s_vhdl.sdf +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2010-10-22-2.tar.gz +# Release Date (DD/MM/YYYY) => 22/10/2010 +# Release Version => 2.1 + +# Corrections: +# 1. Latest datasheet aligned (VHDL files added) + +# Files modified +-s25fl512s.vhd +-testbench_s25fl512s_vhdl.vhd +-s25fl512s.ftm +-s25fl512s_verilog.sdf +-s25fl512s.v +-s25fl512s.sv +-testbench_s25fl512s_verilog.vhd +-s25fl512s.ftmv +-s25fl512s_vhdl.sdf +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2010-11-05-1.tar.gz +# Release Date (DD/MM/YYYY) => 05/11/2010 +# Release Version => 2.2 + +# Corrections: +# 1. Latest datasheet aligned + +# Files modified +-spansion_tc_pkg.vhd +-s25fl512s.vhd +-testbench_s25fl512s_vhdl.vhd +-s25fl512s.v +-s25fl512s.sv +-testbench_s25fl512s_verilog.vhd +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Ranko Prokopovic + r-prokopovic@hdl-dh.com + Hana Dimitrijevic + h-dimitrijevic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2010-11-15-1.tar.gz +# Release Date (DD/MM/YYYY) => 15/11/2010 +# Release Version => 2.3 + +# Corrections: +# 1. QUAD Program operation during Erase Suspend is added +# 2. Warning for Resume to Suspend time is added +# 3. During Erase Suspend, after Program operation is completed, WEL bit is cleared +# 4. Implementation of Software Reset is Changed +# 5. ADDRHILO_PG procedure corrected + +# Files modified +-spansion_tc_pkg.vhd +-s25fl512s.v +-s25fl512s.vhd +########################################## +########################################## +VITAL model author - Snezana Petrovic + s-petrovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2011-04-18-1.tar.gz +# Release Date (DD/MM/YYYY) => 18/04/2011 +# Release Version => 2.4 + +# Corrections: +- corrected timing for internal signal rising_edge_CSNeg_ipd + +# Files modified +-s25fl512s.v +-s25fl512s.sv +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Branislav Colakovic + b-colakovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2011-07-11-1.tar.gz +# Release Date (DD/MM/YYYY) => 11/07/2011 +# Release Version => 2.5 + +# Corrections: +- Latest Datasheet Aligned + +# Files modified +-s25fl512s.v +-s25fl512s.vhd +-testbench_s25fl512s_verilog.vhd +-testbench_s25fl512s_vhdl.vhd +-spansion_tc_pkg.vhd +-s25fl512s.ftmv +-s25fl512s.ftm +-s25fl512s_verilog.sdf +-s25fl512s_vhdl.sdf +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Branislav Colakovic + b-colakovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2011-07-15-2.tar.gz +# Release Date (DD/MM/YYYY) => 15/07/2011 +# Release Version => 2.6 + +# Corrections: +- Optimization issue is fixed +- Timingmodel is corrected + +# Files modified +-s25fl512s.v +-s25fl512s.sv +-testbench_s25fl512s_vhdl.vhd +-testbench_s25fl512s_verilog.vhd +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com + Branislav Colakovic + b-colakovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2011-07-22-1.tar.gz +# Release Date (DD/MM/YYYY) => 22/07/2011 +# Release Version => 2.7 + +# Corrections: +- Timing check issue is fixed +- Correction for P4E and P4E4 instructions + +# Files modified +-s25fl512s.v +-s25fl512s.sv +-s25fl512s.vhd +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2011-11-18-1.tar.gz +# Release Date (DD/MM/YYYY) => 18/11/2011 +# Release Version => 2.8 + +# Corrections: +- Time tHO is changed to 1 ns (customer's request) +- Setting of Device protection mode is modified (customer's request) +- BRWR instruction is corrected + +# Files modified +-s25fl512s.v +-s25fl512s.vhd +-testbench_s25fl512s_verilog.vhd +-testbench_s25fl512s_vhdl.vhd +-s25fl512s.ftmv +-s25fl512s.ftm +-s25fl512s_verilog.sdf +-s25fl512s_vhdl.sdf +########################################## +########################################## +VITAL model author - Snezana Petrovic + s-petrovic@hdl-dh.com +########################################## +# Release Label => vital-amd-serial-s25fl-REL-s25fl512s-2012-06-02-1.tar.gz +# Release Date (DD/MM/YYYY) => 02/06/2012 +# Release Version => 2.9 + +# Corrections: +- OPP instruction is allowed in previously programmed page + +# Files modified +-s25fl512s.v +-s25fl512s.sv +-s25fl512s.vhd +-testbench_s25fl512s_verilog.vhd +-testbench_s25fl512s_vhdl.vhd +-spansion_tc_pkg.vhd + +########################################## \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl512s/model/s25fl512s.sv b/lib/models/memory/flash/serial/S25fl512s/model/s25fl512s.sv new file mode 100644 index 0000000..1e25c19 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl512s/model/s25fl512s.sv @@ -0,0 +1,8080 @@ +/////////////////////////////////////////////////////////////////////////////// +// File name : s25fl512s.sv +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2011 Spansion, LLC. +// +// MODIFICATION HISTORY : +// +// version: | author: | mod date: | changes made: +// V1.0 V.Mancev 19 Nov 09 Initial +// R.Prokopovic +// V1.1 V.Mancev 04 Mar 10 addr_cnt for second read in +// high performance read continuous +// mode can change its value only +// when CSNeg = '0' +// V1.2 V.Mancev 23 Mar 10 During read operations read_out +// signal changes its value in +// shorter interval +// V1.3 V.Mancev 12 Apr 10 HOLD mode corrected +// Condition for PP operation +// corrected +// V1.4 V.Mancev 20 May 10 SRWD bit assignment is corrected +// Condition for WRR command in +// write_cycle _decode section is +// corrected +// Blocking assignments for signals +// WSTART and PSTART are replaced +// with nonblocking assignments +// Conditions in Page Program +// section are fixed +// V1.5 V.Mancev 25 May 10 Conditions in programming +// sections are fixed +// Timing control sections for +// Program and Erase operation are +// changed +// V1.6 V.Mancev 03 June 10 bus_cycle_state section for +// PGSP command is fixed +// V1.7 V.Mancev 28 July 10 During the QUAD mode HOLD# input +// is not monitored for its normal +// function +// write cycle decode section is +// changed +// V1.8 B.Colakovic 24 Aug 10 All redundant signals are +// removed from BusCycle process +// V1.9 V.Mancev 05 Nov 10 Latest datasheet aligned +// B.Colakovic +// V2.0 H.Dimitrijevic 15 Nov 10 QUAD Program operation during +// Erase Suspend is added. +// Warning for Resume to Suspend +// time is added. +// During Erase Suspend, after +// Program operation is completed, +// WEL bit is cleared. +// Implemetation of Software Reset +// is Changed. +// V2.1 S.Petrovic 18 Apr 11 Corrected timing in always block +// that generates +// rising_edge_CSNeg_ipd +// V2.2 V.Mancev 11 July 11 Latest datasheet aligned +// B.Colakovic +// V2.3 B.Colakovic 15 July 11 Optimization issue is fixed +// V2.4 V.Mancev 22 July 11 Timing check issue is fixed +// B.Colakovic +// V2.5 V. Mancev 18 Nov 11 Time tHO is changed to 1 ns +// (customer's request) +// BRWR instruction is corrected +// V2.6 S.Petrovic 02 Jun 12 QPP Instruction is allowed on +// previously programmed page +/////////////////////////////////////////////////////////////////////////////// +// PART DESCRIPTION: +// +// Library: FLASH +// Technology: FLASH MEMORY +// Part: S25FL512S +// +// Description: 512 Megabit Serial Flash Memory +// +////////////////////////////////////////////////////////////////////////////// +// Comments : +// For correct simulation, simulator resolution should be set to 1 ps +// A device ordering (trim) option determines whether a feature is enabled +// or not, or provide relevant parameters: +// -15th character in TimingModel determines if enhanced high +// performance option is available +// (0,2,3,R,A,B,C,D) EHPLC +// (Y,Z,S,T,K,L) Security EHPLC +// (4,6,7,8,9,Q) HPLC +// -15th character in TimingModel determines if RESET# input +// is available +// (R,A,B,C,D,Q.6,7,K,L,S,T,M,N,U,V) RESET# is available +// (0,2,3,4,8,9,Y.Z.W,X) RESET# is tied to the inactive +// state,inside the package. +////////////////////////////////////////////////////////////////////////////// +// Known Bugs: +// +////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// MODULE DECLARATION // +////////////////////////////////////////////////////////////////////////////// +`timescale 1 ps/1 ps + +module s25fl512s + ( + // Data Inputs/Outputs + SI , + SO , + // Controls + SCK , + CSNeg , + RSTNeg , + WPNeg , + HOLDNeg + +); + +/////////////////////////////////////////////////////////////////////////////// +// Port / Part Pin Declarations +/////////////////////////////////////////////////////////////////////////////// + + inout SI ; + inout SO ; + + input SCK ; + input CSNeg ; + input RSTNeg ; + inout HOLDNeg ; + inout WPNeg ; + + // interconnect path delay signals + wire SCK_ipd ; + wire SI_ipd ; + wire SO_ipd ; + + wire SI_in ; + assign SI_in = SI_ipd ; + + wire SI_out ; + assign SI_out = SI ; + + wire SO_in ; + assign SO_in = SO_ipd ; + + wire SO_out ; + assign SO_out = SO ; + + wire CSNeg_ipd ; + wire HOLDNeg_ipd ; + wire WPNeg_ipd ; + wire RSTNeg_ipd ; + + wire HOLDNeg_in ; + //Internal pull-up + assign HOLDNeg_in = (HOLDNeg_ipd === 1'bx) ? 1'b1 : HOLDNeg_ipd; + + wire HOLDNeg_out ; + assign HOLDNeg_out = HOLDNeg ; + + wire WPNeg_in ; + //Internal pull-up + assign WPNeg_in = (WPNeg_ipd === 1'bx) ? 1'b1 : WPNeg_ipd; + + wire WPNeg_out ; + assign WPNeg_out = WPNeg ; + + wire RSTNeg_in ; + //Internal pull-up + assign RSTNeg_in = (RSTNeg_ipd === 1'bx) ? 1'b1 : RSTNeg_ipd; + + // internal delays + reg PP_in ; + reg PP_out ; + reg BP_in ; + reg BP_out ; + reg SE_in ; + reg SE_out ; + reg BE_in ; + reg BE_out ; + reg WRR_in ; + reg WRR_out ; + reg ERSSUSP_in ; + reg ERSSUSP_out ; + reg PRGSUSP_in ; + reg PRGSUSP_out ; + reg PU_in ; + reg PU_out ; + reg RST_in ; + reg RST_out ; + reg PPBERASE_in ; + reg PPBERASE_out; + reg PASSULCK_in ; + reg PASSULCK_out; + reg PASSACC_in ; + reg PASSACC_out; + + // event control registers + reg PRGSUSP_out_event; + reg ERSSUSP_out_event; + reg Reseted_event; + reg SCK_ipd_event; + reg next_state_event; + + reg rising_edge_PoweredUp; + reg rising_edge_Reseted; + reg rising_edge_PASSULCK_in; + reg rising_edge_RES_out; + reg rising_edge_PSTART; + reg rising_edge_WSTART; + reg rising_edge_ESTART; + reg rising_edge_RSTNeg; + reg rising_edge_RST; + reg falling_edge_RSTNeg; + reg falling_edge_RST; + reg rising_edge_RST_out; + reg rising_edge_CSNeg_ipd = 1'b0; + reg falling_edge_CSNeg_ipd = 1'b0; + reg rising_edge_SCK_ipd = 1'b0; + reg falling_edge_SCK_ipd = 1'b0; + + reg RST ; + + reg SOut_zd = 1'bZ ; + reg SOut_z = 1'bZ ; + + wire SI_z ; + wire SO_z ; + + reg SIOut_zd = 1'bZ ; + reg SIOut_z = 1'bZ ; + + reg WPNegOut_zd = 1'bZ ; + reg HOLDNegOut_zd = 1'bZ ; + + assign SI_z = SIOut_z; + assign SO_z = SOut_z; + + parameter UserPreload = 1; + parameter mem_file_name = "none";//"s25fl512s.mem"; + parameter otp_file_name = "s25fl512sOTP.mem";//"none"; + + parameter TimingModel = "DefaultTimingModel"; + + parameter PartID = "s25fl512s"; + parameter MaxData = 255; + parameter MemSize = 28'h3FFFFFF; + parameter SecSize = 20'h3FFFF; + parameter SecNum = 255; + parameter PageNum = 17'h1FFFF; + parameter AddrRANGE = 28'h3FFFFFF; + parameter HiAddrBit = 31; + parameter OTPSize = 1023; + parameter OTPLoAddr = 12'h000; + parameter OTPHiAddr = 12'h3FF; + parameter BYTE = 8; + + // Manufacturer Identification + parameter Manuf_ID = 8'h01; + parameter DeviceID = 8'h19; + // Electronic Signature + parameter ESignature = 8'h19; + // Device ID + //Manufacturer Identification && Memory Type && Memory Capacity + parameter Jedec_ID = 8'h01; + parameter DeviceID1 = 8'h02; + parameter DeviceID2 = 8'h20; + parameter ExtendedBytes = 8'h4D; + parameter ExtendedID = 8'h00; + parameter DieRev = 8'h00; + parameter MaskRev = 8'h00; + + integer PageSize = 511; + + integer EHP; //Enhanced High Performance Mode active + + integer BAR_ACC = 0; //Bank Register Access active + + //varaibles to resolve architecture used + reg [24*8-1:0] tmp_timing;//stores copy of TimingModel + reg [7:0] tmp_char1;//Define EHPLC or HPLC Mode + integer found = 1'b0; + + // If speedsimulation is needed uncomment following line + +// `define SPEEDSIM; + + // powerup + reg PoweredUp; + + // FSM control signals + reg PDONE ; + reg PSTART ; + reg PGSUSP ; + reg PGRES ; + + reg RES_TO_SUSP_MIN_TIME; + reg RES_TO_SUSP_TYP_TIME; + + reg WDONE ; + reg WSTART ; + + reg EDONE ; + reg ESTART ; + reg ESUSP ; + reg ERES ; + + reg Reseted ; + + // Lock Bit is enabled for customer programming + reg WRLOCKENABLE = 1'b1; + // Flag that mark if ASP Register is allready programmed + reg ASPOTPFLAG = 1'b0; + + //Flag for Password unlock command + reg PASS_UNLOCKED = 1'b0; + reg [63:0] PASS_TEMP = 64'hFFFFFFFFFFFFFFFF; + + reg QUADRD = 1'b0; + reg INITIAL_CONFIG = 1'b0; + reg CHECK_FREQ = 1'b0; + + // Programming buffer + integer WByte[0:511]; + // CFI array + integer CFI_array[8'h00:8'h50]; + // OTP Memory Array + integer OTPMem[OTPLoAddr:OTPHiAddr]; + // Flash Memory Array + + // Registers + // VDLR Register + reg[7:0] VDLR_reg = 8'h00; + reg[7:0] VDLR_reg_in = 8'h00; + // NVDLR Register + reg[7:0] NVDLR_reg = 8'h00; + reg[7:0] NVDLR_reg_in = 8'h00; + reg dlp_act = 1'b0; + + // Status Register 1 + reg[7:0] Status_reg1 = 8'h00; + reg[7:0] Status_reg1_in = 8'h00; + + wire SRWD ; + wire P_ERR; + wire E_ERR; + wire [2:0]BP; + wire WEL; + wire WIP; + assign SRWD = Status_reg1[7]; + assign P_ERR = Status_reg1[6]; + assign E_ERR = Status_reg1[5]; + assign BP = Status_reg1[4:2]; + assign WEL = Status_reg1[1]; + assign WIP = Status_reg1[0]; + + // Status Register 2 + reg[7:0] Status_reg2 = 8'h00; + reg[7:0] Status_reg2_in = 8'h00; + + wire ES ; + wire PS ; + assign ES = Status_reg2[1]; + assign PS = Status_reg2[0]; + + // Configuration Register 1 + reg[7:0] Config_reg1 = 8'h00; + reg[7:0] Config_reg1_in = 8'h00; + + wire LC1 ; + wire LC0 ; + wire TBPROT ; + wire LOCK ; + wire BPNV ; + wire QUAD ; + wire FREEZE ; + assign LC1 = Config_reg1[7]; + assign LC0 = Config_reg1[6]; + assign TBPROT = Config_reg1[5]; + assign LOCK = Config_reg1[4]; + assign BPNV = Config_reg1[3]; + assign QUAD = Config_reg1[1]; + assign FREEZE = Config_reg1[0]; + + // Autoboot Register + reg[31:0] AutoBoot_reg = 32'h00000000; + reg[31:0] AutoBoot_reg_in = 32'h00000000; + + wire ABE; + assign ABE = AutoBoot_reg[0]; + + // Bank Address Register + reg [7:0] Bank_Addr_reg = 8'h00; + reg [7:0] Bank_Addr_reg_in = 8'h00; + + wire EXTADD; + wire BA25; + wire BA24; + + assign EXTADD = Bank_Addr_reg[7]; + assign BA25 = Bank_Addr_reg[1]; + assign BA24 = Bank_Addr_reg[0]; + + // ASP Register + reg[15:0] ASP_reg; + reg[15:0] ASP_reg_in; + + wire RPME ; + wire PPBOTP ; + wire PWDMLB ; + wire PSTMLB ; + assign RPME = ASP_reg[5]; + assign PPBOTP = ASP_reg[3]; + assign PWDMLB = ASP_reg[2]; + assign PSTMLB = ASP_reg[1]; + + // Password register + reg[63:0] Password_reg = 64'hFFFFFFFFFFFFFFFF; + reg[63:0] Password_reg_in = 64'hFFFFFFFFFFFFFFFF; + + // PPB Lock Register + reg[7:0] PPBL = 8'h00; + reg[7:0] PPBL_in = 8'h00; + + wire PPB_LOCK ; + assign PPB_LOCK = PPBL[0]; + + // PPB Access Register + reg[7:0] PPBAR = 8'hFF; + reg[7:0] PPBAR_in = 8'hFF; + + reg[SecNum:0] PPB_bits = {512{1'b1}}; + + // DYB Access Register + reg[7:0] DYBAR = 8'hFF; + reg[7:0] DYBAR_in = 8'hFF; + + reg[SecNum:0] DYB_bits = {512{1'b1}}; + + //The Lock Protection Registers for OTP Memory space + reg[7:0] LOCK_BYTE1; + reg[7:0] LOCK_BYTE2; + reg[7:0] LOCK_BYTE3; + reg[7:0] LOCK_BYTE4; + + // Command Register + reg write; + reg cfg_write; + reg read_out; + reg dual = 1'b0; + reg rd_fast = 1'b1; + reg rd_slow = 1'b0; + reg ddr = 1'b0; + reg ddr_fast = 1'b0; + reg hold_mode = 1'b0; + reg any_read = 1'b0; + reg quad_pg = 1'b0; + + wire rd ; + wire fast_rd ; + wire ddrd ; + wire fast_ddr ; + + wire quadpg ; + assign quadpg = quad_pg; + + wire RD_EQU_1; + assign RD_EQU_1 = any_read; + + wire RD_EQU_0; + assign RD_EQU_0 = ~any_read; + + reg change_BP = 0; + reg [2:0] BP_bits = 3'b0; + + reg DOUBLE = 1'b0; //Double Data Rate (DDR) flag + + reg RdPswdProtMode = 1'b0;//Read Password Protection Mode Active flag + reg RdPswdProtEnable = 1'b0;//Read Password Protection Mode Support flag + + integer Byte_number = 0; + + reg oe = 1'b0; + reg oe_z = 1'b0; + + reg [647:0] CFI_array_tmp ; + reg [7:0] CFI_tmp; + + integer start_delay; + reg start_autoboot; + integer ABSD; + + reg change_addr ; + integer Address = 0; + integer SectorSuspend = 0; + integer mem_data; + + //Sector and subsector addresses + integer SA = 0; + + // Sector is protect if Sec_Prot(SecNum) = '1' + reg [SecNum:0] Sec_Prot = 512'b0; + + // Page Number for QPP operations + reg[PageNum:0] QPP_page = 0; + + // timing check violation + reg Viol = 1'b0; + + integer WOTPByte; + integer AddrLo; + integer AddrHi; + + reg[7:0] old_bit, new_bit; + integer old_int, new_int; + reg[63:0] old_pass; + reg[63:0] new_pass; + integer wr_cnt; + integer cnt; + + integer read_cnt = 0; + integer byte_cnt = 1; + integer read_addr = 0; + integer read_addr_tmp = 0; + integer Sec_addr = 0; + integer SecAddr = 0; + integer SecAddrERS = 0; + + integer Page_addr = 0; + integer pgm_page = 0; + integer SecAddr_tmp; + + reg [SecNum : 0] corrupt_Sec; + reg [7:0] OutputD; + + reg[7:0] data_out; + reg[647:0] ident_out; + + time SCK_cycle = 0; + time prev_SCK; + time start_ddr; + time out_time; + time SCK_SO_DDR; +/////////////////////////////////////////////////////////////////////////////// +//Interconnect Path Delay Section +/////////////////////////////////////////////////////////////////////////////// + buf (SCK_ipd, SCK); + buf (SI_ipd, SI); + + buf (SO_ipd, SO); + buf (CSNeg_ipd, CSNeg); + buf (HOLDNeg_ipd, HOLDNeg); + buf (WPNeg_ipd, WPNeg); + buf (RSTNeg_ipd, RSTNeg); + +/////////////////////////////////////////////////////////////////////////////// +// Propagation delay Section +/////////////////////////////////////////////////////////////////////////////// + nmos (SI, SI_z , 1); + + nmos (SO, SO_z , 1); + nmos (HOLDNeg, HOLDNegOut_zd , 1); + nmos (WPNeg, WPNegOut_zd , 1); + + wire deg_pin; + wire deg_sin; + wire deg_holdin; + //VHDL VITAL CheckEnable equivalents + wire quad_rd; + assign quad_rd = deg_holdin && ~QUAD && (SIOut_z != 1'bz); + wire wr_prot; + assign wr_prot = SRWD && WEL && ~QUAD; + wire dual_rd; + assign dual_rd = dual ; + wire ddro; + assign ddro = ddr && ~dual ; + wire ddr_rd; + assign ddr_rd = PoweredUp && ddr; + wire sdr_rd; + assign sdr_rd = PoweredUp && ~ddr; + + memory_features memory_features_i0(); + +specify + // tipd delays: interconnect path delays , mapped to input port delays. + // In Verilog is not necessary to declare any tipd_ delay variables, + // they can be taken from SDF file + // With all the other delays real delays would be taken from SDF file + + // tpd delays + specparam tpd_SCK_SO_normal =1; + specparam tpd_CSNeg_SO =1; + specparam tpd_HOLDNeg_SO =1; + specparam tpd_RSTNeg_SO =1; + //DDR operation values + specparam tpd_SCK_SO_DDR =1; + + //tsetup values: setup times + specparam tsetup_CSNeg_SCK =1; + specparam tsetup_SI_SCK_normal =1; + specparam tsetup_WPNeg_CSNeg =1; + specparam tsetup_HOLDNeg_SCK =1; + specparam tsetup_RSTNeg_CSNeg =1; + // DDR operation values + specparam tsetup_SI_SCK_DDR =1; + specparam tsetup_SI_SCK_DDR_fast =1; + specparam tsetup_CSNeg_SCK_DDR =1; + + //thold values: hold times + specparam thold_CSNeg_SCK =1; + specparam thold_SI_SCK_normal =1; + specparam thold_WPNeg_CSNeg =1; + specparam thold_HOLDNeg_SCK =1; + specparam thold_CSNeg_RSTNeg =1; + // DDR operation values + specparam thold_SI_SCK_DDR =1; + specparam thold_SI_SCK_DDR_fast =1; + specparam thold_CSNeg_SCK_DDR =1; + + // tpw values: pulse width + specparam tpw_SCK_serial_posedge =1; + specparam tpw_SCK_dual_posedge =1; + specparam tpw_SCK_fast_posedge =1; + specparam tpw_SCK_quadpg_posedge =1; + specparam tpw_SCK_serial_negedge =1; + specparam tpw_SCK_dual_negedge =1; + specparam tpw_SCK_fast_negedge =1; + specparam tpw_SCK_quadpg_negedge =1; + specparam tpw_CSNeg_read_posedge =1; + specparam tpw_CSNeg_pgers_posedge =1; + specparam tpw_RSTNeg_negedge =1; + specparam tpw_RSTNeg_posedge =1; + // DDR operation values + specparam tpw_SCK_DDR_posedge =1; + specparam tpw_SCK_DDR_negedge =1; + + // tperiod min (calculated as 1/max freq) + specparam tperiod_SCK_serial_rd =1;// 50 MHz + specparam tperiod_SCK_fast_rd =1;//133 MHz + specparam tperiod_SCK_dual_rd =1;//104 MHz + specparam tperiod_SCK_quadpg =1;// 80 MHz + // DDR operation values + specparam tperiod_SCK_DDR_rd =1;// 66 MHz + + `ifdef SPEEDSIM + // Page Program Operation + specparam tdevice_PP_256 = 55e7;//tPP + // Page Program Operation + specparam tdevice_PP_512 = 75e7;//tPP + // Typical Byte Programming Time + specparam tdevice_BP = 4e8;//tBP + // Sector Erase Operation + specparam tdevice_SE = 1875e7;//tSE + // Bulk Erase Operation + specparam tdevice_BE = 460e9;//tBE + // WRR Cycle Time + specparam tdevice_WRR = 2e9;//tW + // Erase Suspend/Erase Resume Time + specparam tdevice_ERSSUSP = 40e6;//tESL + // Program Suspend/Program Resume Time + specparam tdevice_PRGSUSP = 40e6;// + // VCC (min) to CS# Low + specparam tdevice_PU = 3e8;//tPU + // PPB Erase Time + specparam tdevice_PPBERASE = 15e9;// + // Password Unlock Time + specparam tdevice_PASSULCK = 1e6;// + // Password Unlock to Password Unlock Time + specparam tdevice_PASSACC = 100e6; + `else + // Page Program Operation + specparam tdevice_PP_256 = 55e7;//tPP + // Page Program Operation + specparam tdevice_PP_512 = 75e7;//tPP + // Typical Byte Programming Time + specparam tdevice_BP = 4e8;//tBP + // Sector Erase Operation + specparam tdevice_SE = 1875e9;//tSE + // Bulk Erase Operation + specparam tdevice_BE = 460e12;//tBE + // WRR Cycle Time + specparam tdevice_WRR = 2e11;//tW + // Erase Suspend/Erase Resume Time + specparam tdevice_ERSSUSP = 40e6;//tESL + // Program Suspend/Program Resume Time + specparam tdevice_PRGSUSP = 40e6;// + // VCC (min) to CS# Low + specparam tdevice_PU = 3e8;//tPU + // PPB Erase Time + specparam tdevice_PPBERASE = 15e9;// + // Password Unlock Time + specparam tdevice_PASSULCK = 1e6;// + // Password Unlock to Password Unlock Time + specparam tdevice_PASSACC = 100e6; + `endif // SPEEDSIM + +/////////////////////////////////////////////////////////////////////////////// +// Input Port Delays don't require Verilog description +/////////////////////////////////////////////////////////////////////////////// +// Path delays // +/////////////////////////////////////////////////////////////////////////////// + if (~ddr) (SCK => SO) = tpd_SCK_SO_normal; + if (ddr || rd_fast) (SCK => SO) = tpd_SCK_SO_DDR; + + if (~ddr && dual) (SCK => SI) = tpd_SCK_SO_normal; + if ( ddr && dual) (SCK => SI) = tpd_SCK_SO_DDR; + + if (~ddr && QUAD)(SCK => HOLDNeg) = tpd_SCK_SO_normal; + if ( ddr && QUAD)(SCK => HOLDNeg) = tpd_SCK_SO_DDR; + if (~ddr && QUAD)(SCK => WPNeg) = tpd_SCK_SO_normal; + if ( ddr && QUAD)(SCK => WPNeg) = tpd_SCK_SO_DDR; + + if (CSNeg) (CSNeg => SO) = tpd_CSNeg_SO; + if (CSNeg && dual) (CSNeg => SI) = tpd_CSNeg_SO; + + if (CSNeg && QUAD) (CSNeg => HOLDNeg) = tpd_CSNeg_SO; + if (CSNeg && QUAD) (CSNeg => WPNeg) = tpd_CSNeg_SO; + + if (~QUAD) (HOLDNeg => SO) = tpd_HOLDNeg_SO; + if (~QUAD && dual) (HOLDNeg => SI) = tpd_HOLDNeg_SO; + + (RSTNeg => SO) = tpd_RSTNeg_SO; +/////////////////////////////////////////////////////////////////////////////// +// Timing Violation // +/////////////////////////////////////////////////////////////////////////////// + $setup ( CSNeg , posedge SCK &&& sdr_rd, + tsetup_CSNeg_SCK, Viol); + $setup ( CSNeg , posedge SCK &&& ddr_rd, + tsetup_CSNeg_SCK_DDR, Viol); + $setup ( SI , posedge SCK &&& deg_sin, + tsetup_SI_SCK_normal, Viol); + $setup ( WPNeg , negedge CSNeg &&& wr_prot, + tsetup_WPNeg_CSNeg, Viol); + $setup ( HOLDNeg , posedge SCK &&& quad_rd, + tsetup_HOLDNeg_SCK, Viol); + $setup ( SI , posedge SCK &&& ddro, + tsetup_SI_SCK_DDR, Viol); + $setup ( SI , negedge SCK &&& ddro, + tsetup_SI_SCK_DDR, Viol); + + $setup ( RSTNeg , negedge CSNeg, + tsetup_RSTNeg_CSNeg, Viol); + + $hold ( posedge SCK &&& sdr_rd , CSNeg, + thold_CSNeg_SCK, Viol); + $hold ( posedge SCK &&& ddr_rd , CSNeg, + thold_CSNeg_SCK_DDR, Viol); + $hold ( posedge SCK &&& deg_sin , SI , + thold_SI_SCK_normal, Viol); + $hold ( posedge CSNeg &&& wr_prot , WPNeg , + thold_WPNeg_CSNeg, Viol); + $hold ( posedge SCK &&& quad_rd , HOLDNeg , + thold_HOLDNeg_SCK, Viol); + $hold ( posedge SCK &&& ddro , SI, + thold_SI_SCK_DDR, Viol); + $hold ( negedge SCK &&& ddro , SI, + thold_SI_SCK_DDR, Viol); + + $hold ( negedge RSTNeg , CSNeg, + thold_CSNeg_RSTNeg, Viol); + + $width ( posedge SCK &&& rd , tpw_SCK_serial_posedge); + $width ( negedge SCK &&& rd , tpw_SCK_serial_negedge); + $width ( posedge SCK &&& dual_rd , tpw_SCK_dual_posedge); + $width ( negedge SCK &&& dual_rd , tpw_SCK_dual_negedge); + $width ( posedge SCK &&& fast_rd , tpw_SCK_fast_posedge); + $width ( negedge SCK &&& fast_rd , tpw_SCK_fast_negedge); + $width ( posedge SCK &&& ddrd , tpw_SCK_DDR_posedge); + $width ( negedge SCK &&& ddrd , tpw_SCK_DDR_negedge); + $width ( posedge SCK &&& quadpg , tpw_SCK_quadpg_posedge); + $width ( negedge SCK &&& quadpg , tpw_SCK_quadpg_negedge); + + $width ( posedge CSNeg &&& RD_EQU_1, tpw_CSNeg_read_posedge); + $width ( posedge CSNeg &&& RD_EQU_0, tpw_CSNeg_pgers_posedge); + $width ( negedge RSTNeg , tpw_RSTNeg_negedge); + $width ( posedge RSTNeg , tpw_RSTNeg_posedge); + + $period ( posedge SCK &&& rd , tperiod_SCK_serial_rd); + $period ( posedge SCK &&& fast_rd , tperiod_SCK_fast_rd); + $period ( posedge SCK &&& dual_rd , tperiod_SCK_dual_rd); + $period ( posedge SCK &&& quadpg , tperiod_SCK_quadpg); + $period ( posedge SCK &&& ddrd , tperiod_SCK_DDR_rd); + +endspecify + +/////////////////////////////////////////////////////////////////////////////// +// Main Behavior Block // +/////////////////////////////////////////////////////////////////////////////// +// FSM states + parameter IDLE = 5'd0; + parameter RESET_STATE = 5'd1; + parameter AUTOBOOT = 5'd2; + parameter WRITE_SR = 5'd3; + parameter PAGE_PG = 5'd4; + parameter OTP_PG = 5'd5; + parameter PG_SUSP = 5'd6; + parameter SECTOR_ERS = 5'd7; + parameter BULK_ERS = 5'd8; + parameter ERS_SUSP = 5'd9; + parameter ERS_SUSP_PG = 5'd10; + parameter ERS_SUSP_PG_SUSP= 5'd11; + parameter PASS_PG = 5'd12; + parameter PASS_UNLOCK = 5'd13; + parameter PPB_PG = 5'd14; + parameter PPB_ERS = 5'd15; + parameter AUTOBOOT_PG = 5'd16; + parameter ASP_PG = 5'd17; + parameter PLB_PG = 5'd18; + parameter DYB_PG = 5'd19; + parameter NVDLR_PG = 5'd20; + + reg [4:0] current_state; + reg [4:0] next_state; + +// Instruction type + parameter NONE = 7'd0; + parameter WRR = 7'd1; + parameter PP = 7'd2; + parameter READ = 7'd3; + parameter WRDI = 7'd4; + parameter RDSR = 7'd5; + parameter WREN = 7'd6; + parameter RDSR2 = 7'd7; + parameter FSTRD = 7'd8; + parameter FSTRD4 = 7'd9; + parameter DDRFR = 7'd10; + parameter DDRFR4 = 7'd11; + parameter PP4 = 7'd12; + parameter RD4 = 7'd13; + parameter ABRD = 7'd14; + parameter ABWR = 7'd15; + parameter BRRD = 7'd16; + parameter BRWR = 7'd17; + parameter P4E = 7'd18; + parameter P4E4 = 7'd19; + parameter ASPRD = 7'd20; + parameter ASPP = 7'd21; + parameter CLSR = 7'd22; + parameter QPP = 7'd23; + parameter QPP4 = 7'd24; + parameter RDCR = 7'd25; + parameter DOR = 7'd26; + parameter DOR4 = 7'd27; + parameter DLPRD = 7'd28; + parameter OTPP = 7'd29; + parameter PNVDLR = 7'd30; + parameter OTPR = 7'd31; + parameter WVDLR = 7'd32; + parameter BE = 7'd33; + parameter QOR = 7'd34; + parameter QOR4 = 7'd35; + parameter ERSP = 7'd36; + parameter ERRS = 7'd37; + parameter PGSP = 7'd38; + parameter PGRS = 7'd39; + parameter REMS = 7'd40; + parameter RDID = 7'd41; + parameter MPM = 7'd42; + parameter PLBWR = 7'd43; + parameter PLBRD = 7'd44; + parameter RES = 7'd45; + parameter DIOR = 7'd46; + parameter DIOR4 = 7'd47; + parameter DDRDIOR = 7'd48; + parameter DDRDIOR4 = 7'd49; + parameter SE = 7'd50; + parameter SE4 = 7'd51; + parameter DYBRD = 7'd52; + parameter DYBWR = 7'd53; + parameter PPBRD = 7'd54; + parameter PPBP = 7'd55; + parameter PPBERS = 7'd56; + parameter PASSRD = 7'd57; + parameter PASSP = 7'd58; + parameter PASSU = 7'd69; + parameter QIOR = 7'd70; + parameter QIOR4 = 7'd71; + parameter DDRQIOR = 7'd72; + parameter DDRQIOR4 = 7'd73; + parameter RESET = 7'd74; + parameter MBR = 7'd75; + parameter BRAC = 7'd76; + + reg [6:0] Instruct; + +//Bus cycle state + parameter STAND_BY = 3'd0; + parameter OPCODE_BYTE = 3'd1; + parameter ADDRESS_BYTES = 3'd2; + parameter DUMMY_BYTES = 3'd3; + parameter MODE_BYTE = 3'd4; + parameter DATA_BYTES = 3'd5; + + reg [2:0] bus_cycle_state; + + reg deq_pin; + always @(SO_in, SO_z) + begin + if (SO_in==SO_z) + deq_pin=1'b0; + else + deq_pin=1'b1; + end + // check when data is generated from model to avoid setuphold check in + // this occasion + assign deg_pin=deq_pin; + + reg deq_sin; + always @(SI_in, SIOut_z) + begin + if (SI_in==SIOut_z) + deq_sin=1'b0; + else + deq_sin=1'b1; + end + // check when data is generated from model to avoid setuphold check in + // this occasion + assign deg_sin=deq_sin + && (ddr == 1'b0) && (Instruct !== DDRFR) + && (Instruct !== DDRFR4) && (Instruct !== DDRDIOR) + && (Instruct !== DDRDIOR4) && (Instruct !== DDRQIOR) + && (Instruct !== DDRQIOR4) && (SIOut_z != 1'bz); + + reg deq_holdin; + always @(HOLDNeg_ipd, HOLDNegOut_zd) + begin + if (HOLDNeg_ipd==HOLDNegOut_zd) + deq_holdin=1'b0; + else + deq_holdin=1'b1; + end + // check when data is generated from model to avoid setuphold check in + // this occasion + assign deg_holdin=deq_holdin; + + //Power Up time; + initial + begin + PoweredUp = 1'b0; + #tdevice_PU PoweredUp = 1'b1; + end + + initial + begin : Init + write = 1'b0; + cfg_write = 1'b0; + read_out = 1'b0; + Address = 0; + change_addr = 1'b0; + cnt = 0; + RST = 1'b0; + RST_in = 1'b0; + RST_out = 1'b1; + PDONE = 1'b1; + PSTART = 1'b0; + PGSUSP = 1'b0; + PGRES = 1'b0; + PRGSUSP_in = 1'b0; + ERSSUSP_in = 1'b0; + RES_TO_SUSP_MIN_TIME = 1'b0; + RES_TO_SUSP_TYP_TIME = 1'b0; + + EDONE = 1'b1; + ESTART = 1'b0; + ESUSP = 1'b0; + ERES = 1'b0; + + WDONE = 1'b1; + WSTART = 1'b0; + + Reseted = 1'b0; + + Instruct = NONE; + bus_cycle_state = STAND_BY; + current_state = IDLE; + next_state = IDLE; + end + // constraint memory preload file parameters + parameter preload_line_width = 160; + parameter preload_address_width = 7; + parameter preload_data_width = 2; + + // preload dedicated declarations + reg [preload_line_width*8 : 1] scanf_str; + reg [8:1] fetch_char; + integer preload_iter; + integer preload_file; + integer scanf_address; + integer scanf_data; + + // initialize memory and load preload files if any + initial + begin: InitMemory + integer i; + + // memory region implicitly initialized + memory_features_i0.initialize_w(); + + if ((UserPreload) && !(mem_file_name == "none")) + begin + // Memory Preload + //s25fl512s.mem, memory preload file + // @aaaaaa - stands for address + // dd -
is byte to be written at Mem(aaaaaa++) + // (aaaaaa is incremented at every load) + scanf_address = 0; + preload_file = $fopen(mem_file_name, "r"); + + while($fgets(scanf_str, preload_file)) + begin + fetch_char = scanf_str + [preload_line_width * 8 : preload_line_width * 8 - 7]; + while (!fetch_char) + begin + scanf_str = scanf_str << 8; + fetch_char = scanf_str + [preload_line_width * 8 : preload_line_width * 8 - 7]; + end + + if ((fetch_char == "/") || (fetch_char == "\n")) + begin + // empty lines and comments not processed + end + else + begin + if (fetch_char == "@") + begin + scanf_address = 0; + for(preload_iter = 0; + preload_iter < preload_address_width; + preload_iter = preload_iter + 1) + begin + scanf_str = scanf_str << 8; + fetch_char = scanf_str[ + preload_line_width * 8 : + preload_line_width * 8 - 7 + ]; + scanf_address = scanf_address * 16; + if ((fetch_char >= "0")&&(fetch_char <= "9")) + scanf_address = + scanf_address + (fetch_char - "0"); + else if ((fetch_char >= "A")&&(fetch_char <= "F")) + scanf_address = + scanf_address + (fetch_char - "A") + 10; + else if ((fetch_char >= "a")&&(fetch_char <= "f")) + scanf_address = + scanf_address + (fetch_char - "a") + 10; + end + end + else + begin + scanf_data = 0; + for(preload_iter = 0; + preload_iter < preload_data_width; + preload_iter = preload_iter + 1) + begin + scanf_data = scanf_data * 16; + if ((fetch_char >= "0") && (fetch_char <= "9")) + scanf_data = scanf_data + (fetch_char - "0"); + else if ((fetch_char >= "A")&&(fetch_char <= "F")) + scanf_data = + scanf_data + (fetch_char - "A") + 10; + else if ((fetch_char >= "a")&&(fetch_char <= "f")) + scanf_data = + scanf_data + (fetch_char - "a") + 10; + scanf_str = scanf_str << 8; + fetch_char = scanf_str[ + preload_line_width * 8 : + preload_line_width * 8-7 + ]; + end + if (scanf_data !== MaxData) + begin + if (scanf_address <= AddrRANGE) + begin + memory_features_i0.write_mem_w(scanf_address, + scanf_data); + end + else + $display("Memory address out of range."); + end + scanf_address++; + end + end + end + $fclose(preload_file); + end + + for (i=OTPLoAddr;i<=OTPHiAddr;i=i+1) + begin + OTPMem[i] = MaxData; + end + + if (UserPreload && !(otp_file_name == "none")) + begin + //s25fl512s_otp memory file + // / - comment + // @aaaaaa - stands for address within last defined + // sector + // dd -
is byte to be written at OTPMem(aaa++) + // (aa is incremented at every load) + // only first 1-4 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + $readmemh(otp_file_name,OTPMem); + end + + LOCK_BYTE1[7:0] = OTPMem[16]; + LOCK_BYTE2[7:0] = OTPMem[17]; + LOCK_BYTE3[7:0] = OTPMem[18]; + LOCK_BYTE4[7:0] = OTPMem[19]; + end + + // initialize memory and load preload files if any + initial + begin: InitTimingModel + integer i; + integer j; + //UNIFORM OR HYBRID arch model is used + //assumptions: + //1. TimingModel has format as S25FL128SXXXXXXXX_X_XXpF + //it is important that 16-th character from first one is "0" or "1" + //2. TimingModel does not have more then 24 characters + tmp_timing = TimingModel;//copy of TimingModel + + i = 23; + while ((i >= 0) && (found != 1'b1))//search for first non null character + begin //i keeps position of first non null character + j = 7; + while ((j >= 0) && (found != 1'b1)) + begin + if (tmp_timing[i*8+j] != 1'd0) + found = 1'b1; + else + j = j-1; + end + i = i - 1; + end + i = i +1; + if (found)//if non null character is found + begin + for (j=0;j<=7;j=j+1) + begin + //EHPLC/HPLC character is 15 + tmp_char1[j] = TimingModel[(i-14)*8+j]; + end + end + if (tmp_char1 == "0" || tmp_char1 == "2" || tmp_char1 == "3" || + tmp_char1 == "R" || tmp_char1 == "A" || tmp_char1 == "B" || + tmp_char1 == "C" || tmp_char1 == "D" || tmp_char1 == "Y" || + tmp_char1 == "Z" || tmp_char1 == "S" || tmp_char1 == "T" || + tmp_char1 == "K" || tmp_char1 == "L") + begin + EHP = 1; + if(tmp_char1 == "Z" || tmp_char1 == "S" || tmp_char1 == "T" || + tmp_char1 == "K" || tmp_char1 == "L" || tmp_char1 == "Y") + begin + RdPswdProtEnable = 1; + end + end + else if (tmp_char1 == "4" || tmp_char1 == "6" || tmp_char1 == "7" || + tmp_char1 == "8" || tmp_char1 == "9" || tmp_char1 == "Q") + begin + EHP = 0; + end + + if (tmp_char1 == "0" || tmp_char1 == "2" || tmp_char1 == "3" || + tmp_char1 == "R" || tmp_char1 == "A" || tmp_char1 == "B" || + tmp_char1 == "C" || tmp_char1 == "D" || tmp_char1 == "4" || + tmp_char1 == "6" || tmp_char1 == "7" || tmp_char1 == "8" || + tmp_char1 == "9" || tmp_char1 == "Q") + begin + ASP_reg = 16'hFE7F; + ASP_reg_in = 16'hFE7F; + end + else if (tmp_char1 == "Y" || tmp_char1 == "Z" || tmp_char1 == "S" || + tmp_char1 == "T" || tmp_char1 == "K" || tmp_char1 == "L") + begin + ASP_reg = 16'hFE4F; + ASP_reg_in = 16'hFE4F; + end + + end + + //CFI + initial + begin: InitCFI + integer i; + integer j; + /////////////////////////////////////////////////////////////////////// + // ID-CFI array data + /////////////////////////////////////////////////////////////////////// + // Manufacturer and Device ID + CFI_array[8'h00] = Jedec_ID; + CFI_array[8'h01] = DeviceID1; + CFI_array[8'h02] = DeviceID2; + CFI_array[8'h03] = 8'h00; + // Uniform 256kB sectors + CFI_array[8'h04] = ExtendedID; + CFI_array[8'h05] = 8'h80; + CFI_array[8'h06] = 8'h00; + CFI_array[8'h07] = 8'h00; + CFI_array[8'h08] = 8'h00; + CFI_array[8'h09] = 8'h00; + CFI_array[8'h0A] = 8'h00; + CFI_array[8'h0B] = 8'h00; + CFI_array[8'h0C] = 8'h00; + CFI_array[8'h0D] = 8'h00; + CFI_array[8'h0E] = 8'h00; + CFI_array[8'h0F] = 8'h00; + // CFI Query Identification String + CFI_array[8'h10] = 8'h51; + CFI_array[8'h11] = 8'h52; + CFI_array[8'h12] = 8'h59; + CFI_array[8'h13] = 8'h02; + CFI_array[8'h14] = 8'h00; + CFI_array[8'h15] = 8'h40; + CFI_array[8'h16] = 8'h00; + CFI_array[8'h17] = 8'h53; + CFI_array[8'h18] = 8'h46; + CFI_array[8'h19] = 8'h51; + CFI_array[8'h1A] = 8'h00; + //CFI system interface string + CFI_array[8'h1B] = 8'h27; + CFI_array[8'h1C] = 8'h36; + CFI_array[8'h1D] = 8'h00; + CFI_array[8'h1E] = 8'h00; + CFI_array[8'h1F] = 8'h06; + //512B page + CFI_array[8'h20] = 8'h09; + // 256kB sector + CFI_array[8'h21] = 8'h09; + CFI_array[8'h22] = 8'h11; + CFI_array[8'h23] = 8'h02; + CFI_array[8'h24] = 8'h02; + CFI_array[8'h25] = 8'h03; + CFI_array[8'h26] = 8'h03; + // Device Geometry Definition(Uniform Sector Devices) + CFI_array[8'h27] = 8'h1A; + CFI_array[8'h28] = 8'h02; + CFI_array[8'h29] = 8'h01; + CFI_array[8'h2A] = 8'h09; + CFI_array[8'h2B] = 8'h00; + CFI_array[8'h2C] = 8'h01; + CFI_array[8'h2D] = 8'hFF; + CFI_array[8'h2E] = 8'h00; + CFI_array[8'h2F] = 8'h00; + CFI_array[8'h30] = 8'h04; + CFI_array[8'h31] = 8'hFF; + CFI_array[8'h32] = 8'hFF; + CFI_array[8'h33] = 8'hFF; + CFI_array[8'h34] = 8'hFF; + CFI_array[8'h35] = 8'hFF; + CFI_array[8'h36] = 8'hFF; + CFI_array[8'h37] = 8'hFF; + CFI_array[8'h38] = 8'hFF; + CFI_array[8'h39] = 8'hFF; + CFI_array[8'h3A] = 8'hFF; + CFI_array[8'h3B] = 8'hFF; + CFI_array[8'h3C] = 8'hFF; + CFI_array[8'h3D] = 8'hFF; + CFI_array[8'h3E] = 8'hFF; + CFI_array[8'h3F] = 8'hFF; + // CFI Primary Vendor-Specific Extended Query + CFI_array[8'h40] = 8'h50; + CFI_array[8'h41] = 8'h52; + CFI_array[8'h42] = 8'h49; + CFI_array[8'h43] = 8'h31; + CFI_array[8'h44] = 8'h33; + CFI_array[8'h45] = 8'h21; + CFI_array[8'h46] = 8'h02; + CFI_array[8'h47] = 8'h01; + CFI_array[8'h48] = 8'h00; + CFI_array[8'h49] = 8'h08; + CFI_array[8'h4A] = 8'h00; + CFI_array[8'h4B] = 8'h01; + CFI_array[8'h4C] = 8'h04; + CFI_array[8'h4D] = 8'h00; + CFI_array[8'h4E] = 8'h00; + CFI_array[8'h4F] = 8'h07; + CFI_array[8'h50] = 8'h01; + + begin + for(i=80;i>=0;i=i-1) + begin + CFI_tmp = CFI_array[8'h00-i+80]; + for(j=7;j>=0;j=j-1) + begin + CFI_array_tmp[8*i+j] = CFI_tmp[j]; + end + end + end + end + + always @(next_state_event or PoweredUp or RST or RST_out) + begin: StateTransition + if (PoweredUp) + begin + if ((RSTNeg_in) && RST_out == 1'b1) + current_state = #(1000) next_state; + else if ((~RSTNeg_in || rising_edge_RSTNeg) && falling_edge_RST) + begin + // no state transition while RESET# low + current_state = RESET_STATE; + RST_in = 1'b1; + #1000 RST_in = 1'b0; + end + end + end + + always @(posedge RST_in) + begin:Threset + RST_out = 1'b0; + #(35000000-200000) RST_out = 1'b1; + end + + always @(negedge CSNeg_ipd) + begin:CheckCEOnPowerUP + if (~PoweredUp) + $display ("Device is selected during Power Up"); + end + + /////////////////////////////////////////////////////////////////////////// + //// Internal Delays + /////////////////////////////////////////////////////////////////////////// + + always @(posedge PRGSUSP_in) + begin:PRGSuspend + PRGSUSP_out = 1'b0; + #tdevice_PRGSUSP PRGSUSP_out = 1'b1; + end + + always @(posedge PPBERASE_in) + begin:PPBErs + PPBERASE_out = 1'b0; + #tdevice_PPBERASE PPBERASE_out = 1'b1; + end + + always @(posedge ERSSUSP_in) + begin:ERSSuspend + ERSSUSP_out = 1'b0; + #tdevice_ERSSUSP ERSSUSP_out = 1'b1; + end + + always @(posedge PASSULCK_in) + begin:PASSULock + PASSULCK_out = 1'b0; + #tdevice_PASSULCK PASSULCK_out = 1'b1; + end + + always @(posedge PASSACC_in) + begin:PASSAcc + PASSACC_out = 1'b0; + #tdevice_PASSACC PASSACC_out = 1'b1; + end + +/////////////////////////////////////////////////////////////////////////////// +// write cycle decode +/////////////////////////////////////////////////////////////////////////////// + integer opcode_cnt = 0; + integer addr_cnt = 0; + integer mode_cnt = 0; + integer dummy_cnt = 0; + integer data_cnt = 0; + integer bit_cnt = 0; + + reg [4095:0] Data_in = 4096'b0; + reg [7:0] opcode; + reg [7:0] opcode_in; + reg [7:0] opcode_tmp; + reg [31:0] addr_bytes; + reg [31:0] hiaddr_bytes; + reg [31:0] Address_in; + reg [7:0] mode_bytes; + reg [7:0] mode_in; + integer Latency_code; + integer quad_data_in [0:1023]; + reg [3:0] quad_nybble = 4'b0; + reg [3:0] Quad_slv; + reg [7:0] Byte_slv; + + always @(rising_edge_CSNeg_ipd or falling_edge_CSNeg_ipd or + rising_edge_SCK_ipd or falling_edge_SCK_ipd) + begin: Buscycle + integer i; + integer j; + integer k; + time CLK_PER; + time LAST_CLK; + + if (falling_edge_CSNeg_ipd) + begin + if (bus_cycle_state==STAND_BY) + begin + Instruct = NONE; + write = 1'b1; + cfg_write = 0; + opcode_cnt = 0; + addr_cnt = 0; + mode_cnt = 0; + dummy_cnt = 0; + data_cnt = 0; + opcode_tmp = 0; + DOUBLE = 1'b0; + QUADRD = 1'b0; + CLK_PER = 1'b0; + LAST_CLK = 1'b0; + if (current_state == AUTOBOOT) + begin + bus_cycle_state = DATA_BYTES; + end + else + begin + bus_cycle_state = OPCODE_BYTE; + end + end + end + + if (rising_edge_SCK_ipd) // Instructions, addresses or data present + begin // at SI are latched on the rising edge of SCK + + CLK_PER = $time - LAST_CLK; + LAST_CLK = $time; + if (CHECK_FREQ) + begin + if ((CLK_PER < 20000 && Latency_code == 3) || + (CLK_PER < 12500 && Latency_code == 0) || + (CLK_PER < 11100 && Latency_code == 1) || + (CLK_PER < 9600 && Latency_code == 2)) + begin + $display ("More wait states are required for"); + $display ("this clock frequency value"); + end + CHECK_FREQ = 0; + end + + if (~CSNeg_ipd) + begin + case (bus_cycle_state) + OPCODE_BYTE: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + opcode_in[opcode_cnt] = SI_in; + opcode_cnt = opcode_cnt + 1; + Latency_code = Config_reg1[7:6]; + if (opcode_cnt == BYTE) + begin + for(i=7;i>=0;i=i-1) + begin + opcode[i] = opcode_in[7-i]; + end + case (opcode) + 8'b00000110 : // 06h + begin + Instruct = WREN; + bus_cycle_state = DATA_BYTES; + end + 8'b00000100 : // 04h + begin + Instruct = WRDI; + bus_cycle_state = DATA_BYTES; + end + 8'b00000001 : // 01h + begin + Instruct = WRR; + bus_cycle_state = DATA_BYTES; + end + 8'b00000011 : // 03h + begin + Instruct = READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00010011 : // 13h + begin + Instruct = RD4; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01001011 : // 4Bh + begin + Instruct = OTPR; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00000101 : // 05h + begin + Instruct = RDSR; + bus_cycle_state = DATA_BYTES; + end + 8'b00000111 : // 07h + begin + Instruct = RDSR2; + bus_cycle_state = DATA_BYTES; + end + 8'b00110101 : // 35h + begin + Instruct = RDCR; + bus_cycle_state = DATA_BYTES; + end + 8'b10010000 : // 90h + begin + Instruct = REMS; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10011111 : // 9Fh + begin + Instruct = RDID; + bus_cycle_state = DATA_BYTES; + end + 8'b10101011 : // ABh + begin + Instruct = RES; + bus_cycle_state = DUMMY_BYTES; + end + 8'b00001011 : // 0Bh + begin + Instruct = FSTRD; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00001100 : // 0Ch + begin + Instruct = FSTRD4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00001101 : // 0Dh + begin + Instruct = DDRFR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00001110 : // 0Eh + begin + Instruct = DDRFR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00111011 : // 3Bh + begin + Instruct = DOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00111100 : // 3Ch + begin + Instruct = DOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b10111011 : // BBh + begin + Instruct = DIOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b10111100 : // BCh + begin + Instruct = DIOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b10111101 : // BDh + begin + Instruct = DDRDIOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b10111110 : // BEh + begin + Instruct = DDRDIOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b01101011 : // 6Bh + begin + Instruct = QOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b01101100 : // 6Ch + begin + Instruct = QOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b11101011 : // EBh + begin + Instruct = QIOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b11101100 : // ECh + begin + Instruct = QIOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b11101101 : // EDh + begin + Instruct = DDRQIOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b11101110 : // EEh + begin + Instruct = DDRQIOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00000010 : // 02h + begin + Instruct = PP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00010010 : // 12h + begin + Instruct = PP4; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00110010: // 32h + begin + Instruct = QPP; + bus_cycle_state = ADDRESS_BYTES; + quad_pg = 1'b1; + end + 8'b00111000: // 38h + begin + Instruct = QPP; + bus_cycle_state = ADDRESS_BYTES; + quad_pg = 1'b1; + end + 8'b00110100 : // 34h + begin + Instruct = QPP4; + bus_cycle_state = ADDRESS_BYTES; + quad_pg = 1'b1; + end + 8'b01000010 : // 42h + begin + Instruct = OTPP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10000101 : // 85h + begin + Instruct = PGSP; + bus_cycle_state = DATA_BYTES; + end + 8'b10001010 : // 8Ah + begin + Instruct = PGRS; + bus_cycle_state = DATA_BYTES; + end + 8'b11000111 : // C7h + begin + Instruct = BE; + bus_cycle_state = DATA_BYTES; + end + 8'b01100000 : // 60h + begin + Instruct = BE; + bus_cycle_state = DATA_BYTES; + end + 8'b11011000 : // D8h + begin + Instruct = SE; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11011100 : // DCh + begin + Instruct = SE4; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01110101 : // 75h + begin + Instruct = ERSP; + bus_cycle_state = DATA_BYTES; + end + 8'b01111010 : // 7Ah + begin + Instruct = ERRS; + bus_cycle_state = DATA_BYTES; + end + 8'b00010100 : // 14h + begin + Instruct = ABRD; + bus_cycle_state = DATA_BYTES; + end + 8'b00010101 : // 15h + begin + Instruct = ABWR; + bus_cycle_state = DATA_BYTES; + end + 8'b00010110 : // 16h + begin + Instruct = BRRD; + bus_cycle_state = DATA_BYTES; + end + 8'b00010111 : // 17h + begin + Instruct = BRWR; + bus_cycle_state = DATA_BYTES; + end + 8'b00101011 : // 2Bh + begin + Instruct = ASPRD; + bus_cycle_state = DATA_BYTES; + end + 8'b00101111 : // 2Fh + begin + Instruct = ASPP; + bus_cycle_state = DATA_BYTES; + end + 8'b11100000 : // E0h + begin + Instruct = DYBRD; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11100001 : // E1h + begin + Instruct = DYBWR; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11100010 : // E2h + begin + Instruct = PPBRD; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11100011 : // E3h + begin + Instruct = PPBP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11100100 : // E4h + begin + Instruct = PPBERS; + bus_cycle_state = DATA_BYTES; + end + 8'b10100110 : // A6h + begin + Instruct = PLBWR; + bus_cycle_state = DATA_BYTES; + end + 8'b10100111 : // A7h + begin + Instruct = PLBRD; + bus_cycle_state = DATA_BYTES; + end + 8'b11100111 : // E7h + begin + Instruct = PASSRD; + bus_cycle_state = DATA_BYTES; + end + 8'b11101000 : // E8h + begin + Instruct = PASSP; + bus_cycle_state = DATA_BYTES; + end + 8'b11101001 : // E9h + begin + Instruct = PASSU; + bus_cycle_state = DATA_BYTES; + end + 8'b11110000 : // F0h + begin + Instruct = RESET; + bus_cycle_state = DATA_BYTES; + end + 8'b00110000 : // 30h + begin + Instruct = CLSR; + bus_cycle_state = DATA_BYTES; + end + 8'b01000001 : // 41h + begin + Instruct = DLPRD; + bus_cycle_state = DATA_BYTES; + end + 8'b01000011 : // 43h + begin + Instruct = PNVDLR; + bus_cycle_state = DATA_BYTES; + end + 8'b01001010 : // 4Ah + begin + Instruct = WVDLR; + bus_cycle_state = DATA_BYTES; + end + 8'b10111001 : // B9h + begin + Instruct = BRAC; + bus_cycle_state = DATA_BYTES; + end + 8'b11111111 : // FFh + begin + Instruct = MBR; + bus_cycle_state = MODE_BYTE; + end + 8'b00100000 : // 20h + begin + Instruct = P4E; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00100001 : // 21h + begin + Instruct = P4E4; + bus_cycle_state = ADDRESS_BYTES; + end + endcase + end + end + end //end of OPCODE BYTE + + ADDRESS_BYTES : + begin + if ((Instruct == DDRFR) || (Instruct == DDRFR4) || + (Instruct == DDRDIOR) || (Instruct == DDRDIOR4) || + (Instruct == DDRQIOR) || (Instruct == DDRQIOR4)) + DOUBLE = 1'b1; + else + DOUBLE = 1'b0; + if ((Instruct == QOR) || (Instruct == QOR4) || + (Instruct == QIOR) || (Instruct == QIOR4) || + (Instruct == DDRQIOR) || (Instruct == DDRQIOR4)) + QUADRD = 1'b1; + else + QUADRD = 1'b0; + if (DOUBLE == 1'b0) + begin + if (((((Instruct == FSTRD) && (~EXTADD)) || + ((Instruct == DOR) && (~EXTADD)) || + (Instruct == OTPR)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + ((Instruct == QOR) && QUAD && (~EXTADD))) + begin + //Instruction + 3 Bytes Address + Dummy Byte + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE) + begin + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:26] = 6'b000000; + addr_bytes[24] = Bank_Addr_reg[0]; + addr_bytes[25] = Bank_Addr_reg[1]; + Address = addr_bytes ; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (Instruct==FSTRD || Instruct==DOR || + Instruct == QOR) + begin + if (Latency_code == 3) + bus_cycle_state = DATA_BYTES; + else + bus_cycle_state = DUMMY_BYTES; + end + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((((Instruct==FSTRD4) || + (Instruct==DOR4) || + ((Instruct==FSTRD) && EXTADD) || + ((Instruct==DOR) && EXTADD)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + ((Instruct==QOR4) && QUAD) || + ((Instruct==QOR) && QUAD && EXTADD)) + begin + //Instruction + 4 Bytes Address + Dummy Byte + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 4*BYTE) + begin + for(i=31;i>=0;i=i-1) + begin + hiaddr_bytes[31-i] = Address_in[i]; + end + Address = hiaddr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (Latency_code == 3) + bus_cycle_state = DATA_BYTES; + else + begin + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + + end + end + end + end + else if ((Instruct==DIOR) && (~EXTADD) && + ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + //DUAL I/O High Performance Read(3 Bytes Addr) + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt + 1] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE/2) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i]=Address_in[i]; + end + addr_bytes[31:26] = 6'b000000; + addr_bytes[24] = Bank_Addr_reg[0]; + addr_bytes[25] = Bank_Addr_reg[1]; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if (((Instruct==DIOR4) || + ((Instruct==DIOR) && EXTADD)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) + begin //DUAL I/O High Performance Read(4Bytes Addr) + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt + 1] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 4*BYTE/2) + begin + addr_cnt = 0; + for(i=31;i>=0;i=i-1) + begin + addr_bytes[31-i] = Address_in[i]; + end + Address = addr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((Instruct == QIOR) && (~EXTADD)) + begin + //QUAD I/O High Performance Read (3Bytes Address) + if (QUAD) + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE/4) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:26] = 6'b000000; + addr_bytes[24] = Bank_Addr_reg[0]; + addr_bytes[25] = Bank_Addr_reg[1]; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + else + bus_cycle_state = STAND_BY; + end + else if ((Instruct==QIOR4) || ((Instruct==QIOR) + && EXTADD)) + begin + //QUAD I/O High Performance Read (4Bytes Addr) + if (QUAD) + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt +1; + if (addr_cnt == 4*BYTE/4) + begin + addr_cnt =0; + for(i=31;i>=0;i=i-1) + begin + hiaddr_bytes[31-i] = Address_in[i]; + end + Address = hiaddr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + else + bus_cycle_state = STAND_BY; + end + else if ((((Instruct==RD4) || (Instruct==PP4) || + (Instruct==SE4) ||(Instruct==PPBRD) || + (Instruct==DYBRD) ||(Instruct==DYBWR) || + (Instruct==PPBP) || (Instruct==P4E4) || + ((Instruct==READ) && EXTADD) || + ((Instruct==PP) && EXTADD) || + ((Instruct==P4E) && EXTADD) || + ((Instruct==SE) && EXTADD)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + (QUAD && (Instruct==QPP4 || + ((Instruct==QPP) && EXTADD)))) + begin + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 4*BYTE) + begin + for(i=31;i>=0;i=i-1) + begin + hiaddr_bytes[31-i] = Address_in[i]; + end + Address = hiaddr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = DATA_BYTES; + end + end + else if (((HOLDNeg_in && ~QUAD) || QUAD) && + (~EXTADD)) + begin + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE) + begin + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:26] = 6'b000000; + addr_bytes[24] = Bank_Addr_reg[0]; + addr_bytes[25] = Bank_Addr_reg[1]; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = DATA_BYTES; + end + end + end + else + begin + if ((Instruct==DDRFR) && (~EXTADD)) + //Fast DDR Read Mode + begin + Address_in[addr_cnt] = SI_in; + if ((addr_cnt/2) <= 16) + begin + opcode_tmp[addr_cnt/2] = SI_in; + end + addr_cnt = addr_cnt + 1; + read_cnt = 0; + end + else if ((Instruct==DDRFR4) || + ((Instruct==DDRFR) && EXTADD)) + begin + Address_in[addr_cnt] = SI_in; + if ((addr_cnt/2) <= 16) + begin + opcode_tmp[addr_cnt/2] = SI_in; + end + addr_cnt = addr_cnt + 1; + read_cnt = 0; + end + else if ((Instruct == DDRDIOR) && (~EXTADD)) + begin //Dual I/O DDR Read Mode + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt+1]= SI_in; + if ((addr_cnt/2) <= 16) + begin + opcode_tmp[addr_cnt/2] = SI_in; + end + addr_cnt = addr_cnt + 1; + read_cnt = 0; + end + else if ((Instruct==DDRDIOR4) || + ((Instruct==DDRDIOR) && EXTADD)) + begin //Dual I/O DDR Read Mode + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt+1] = SI_in; + if ((addr_cnt/2) <= 16) + begin + opcode_tmp[addr_cnt/2] = SI_in; + end + addr_cnt = addr_cnt + 1; + read_cnt = 0; + end + else if ((Instruct==DDRQIOR) && (~EXTADD) && QUAD) + begin //Quad I/O DDR Read Mode + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + opcode_tmp[addr_cnt/2] = SI_in; + addr_cnt = addr_cnt +1; + read_cnt = 0; + end + else if (QUAD && ((Instruct==DDRQIOR4) || + ((Instruct==DDRQIOR) && EXTADD))) + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + opcode_tmp[addr_cnt/2] = SI_in; + addr_cnt = addr_cnt +1; + read_cnt = 0; + end + end + end + + MODE_BYTE : + begin + if (((Instruct==DIOR) || (Instruct == DIOR4)) + && ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + mode_in[2*mode_cnt] = SO_in; + mode_in[2*mode_cnt+1] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/2) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + if (Latency_code == 0 || Latency_code == 3) + bus_cycle_state = DATA_BYTES; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if (((Instruct==QIOR) || (Instruct == QIOR4)) + && QUAD) + begin + mode_in[4*mode_cnt] = HOLDNeg_in; + mode_in[4*mode_cnt+1] = WPNeg_in; + mode_in[4*mode_cnt+2] = SO_in; + mode_in[4*mode_cnt+3] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/4) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((Instruct == DDRFR) || (Instruct == DDRFR4)) + mode_in[2*mode_cnt] = SI_in; + else if ((Instruct==DDRDIOR) || (Instruct==DDRDIOR4)) + begin + mode_in[4*mode_cnt] = SO_in; + mode_in[4*mode_cnt+1] = SI_in; + end + else if (((Instruct==DDRQIOR) || (Instruct == DDRQIOR4)) + && QUAD) + begin + mode_in[0] = HOLDNeg_in; + mode_in[1] = WPNeg_in; + mode_in[2] = SO_in; + mode_in[3] = SI_in; + end + dummy_cnt = 0; + end + + DUMMY_BYTES : + begin + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + if ((((Instruct==FSTRD) || (Instruct==FSTRD4) || + (Instruct==DOR) || (Instruct==DOR4) || + (Instruct==OTPR)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + (((Instruct==QOR)||(Instruct==QOR4)) && QUAD)) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == BYTE) + begin + bus_cycle_state = DATA_BYTES; + end + end + + else if ((Instruct==DDRFR) || (Instruct==DDRFR4)) + begin + dummy_cnt = dummy_cnt + 1; + if (EHP) + begin + if (((Latency_code == 3) && (dummy_cnt==1)) || + ((Latency_code == 0) && (dummy_cnt==2)) || + ((Latency_code == 1) && (dummy_cnt==4)) || + ((Latency_code == 2) && (dummy_cnt==5))) + begin + bus_cycle_state = DATA_BYTES; + end + end + else + begin + if (((Latency_code == 3) && (dummy_cnt==4)) || + ((Latency_code == 0) && (dummy_cnt==5)) || + ((Latency_code == 1) && (dummy_cnt==6)) || + ((Latency_code == 2) && (dummy_cnt==7))) + begin + bus_cycle_state = DATA_BYTES; + end + end + end + else if (Instruct==RES) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == 3*BYTE) + bus_cycle_state = DATA_BYTES; + end + else if ((Instruct == DIOR) || (Instruct == DIOR4) + && ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + dummy_cnt = dummy_cnt + 1; + if (EHP) + begin + if (((Latency_code == 1) && (dummy_cnt==1)) || + ((Latency_code == 2) && (dummy_cnt==2))) + bus_cycle_state = DATA_BYTES; + end + else + begin + if (((Latency_code == 3) && (dummy_cnt==4)) || + ((Latency_code == 0) && (dummy_cnt==4)) || + ((Latency_code == 1) && (dummy_cnt==5)) || + ((Latency_code == 2) && (dummy_cnt==6))) + bus_cycle_state = DATA_BYTES; + end + end + else if ((Instruct==DDRDIOR) || (Instruct==DDRDIOR4)) + begin + dummy_cnt = dummy_cnt + 1; + if (EHP) + begin + if (((Latency_code == 3) && (dummy_cnt==2)) || + ((Latency_code == 0) && (dummy_cnt==4)) || + ((Latency_code == 1) && (dummy_cnt==5)) || + ((Latency_code == 2) && (dummy_cnt==6))) + begin + bus_cycle_state = DATA_BYTES; + end + end + else + begin + if (((Latency_code == 3) && (dummy_cnt==4)) || + ((Latency_code == 0) && (dummy_cnt==6)) || + ((Latency_code == 1) && (dummy_cnt==7)) || + ((Latency_code == 2) && (dummy_cnt==8))) + begin + bus_cycle_state = DATA_BYTES; + end + end + end + else if (((Instruct == QIOR) || (Instruct == QIOR4)) + && QUAD) + begin + dummy_cnt = dummy_cnt + 1; + if (((Latency_code == 3) && (dummy_cnt==1)) || + ((Latency_code == 0) && (dummy_cnt==4)) || + ((Latency_code == 1) && (dummy_cnt==4)) || + ((Latency_code == 2) && (dummy_cnt==5))) + begin + bus_cycle_state = DATA_BYTES; + end + end + else if (((Instruct==DDRQIOR) || (Instruct==DDRQIOR4)) + && QUAD) + begin + dummy_cnt = dummy_cnt + 1; + + if (((Latency_code == 3) && (dummy_cnt==3)) || + ((Latency_code == 0) && (dummy_cnt==6)) || + ((Latency_code == 1) && (dummy_cnt==7)) || + ((Latency_code == 2) && (dummy_cnt==8))) + begin + bus_cycle_state = DATA_BYTES; + end + end + end + + DATA_BYTES : + begin + + if (DOUBLE == 1'b1 && (hold_mode==0)) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + + if ((QUAD) && ((Instruct==QPP) || (Instruct == QPP4))) + begin + quad_nybble = {HOLDNeg_in, WPNeg_in, SO_in, SI_in}; + if (data_cnt > ((PageSize+1)*2-1)) + begin + //In case of quad mode and QPP, + //if more than 512 bytes are sent to the device + for(i=0;i<=(PageSize*2-1);i=i+1) + begin + quad_data_in[i] = quad_data_in[i+1]; + end + quad_data_in[(PageSize+1)*2-1] = quad_nybble; + data_cnt = data_cnt +1; + end + else + begin + if (quad_nybble !== 4'bZZZZ) + begin + quad_data_in[data_cnt] = quad_nybble; + end + data_cnt = data_cnt +1; + end + end + else if ((~QUADRD) && ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + if (data_cnt > ((PageSize+1)*8-1)) + begin + //In case of serial mode and PP, + //if more than PageSize are sent to the device + //previously latched data are discarded and last + //256/512 data bytes are guaranteed to be programmed + //correctly within the same page. + if (bit_cnt == 0) + begin + for(i=0;i<=(PageSize*BYTE-1);i=i+1) + begin + Data_in[i] = Data_in[i+8]; + end + end + Data_in[PageSize*BYTE + bit_cnt] = SI_in; + bit_cnt = bit_cnt + 1; + if (bit_cnt == 8) + begin + bit_cnt = 0; + end + data_cnt = data_cnt + 1; + end + else + begin + Data_in[data_cnt] = SI_in; + data_cnt = data_cnt + 1; + bit_cnt = 0; + end + end + end + endcase + end + end + + if (falling_edge_SCK_ipd) + begin + if (~CSNeg_ipd) + begin + case (bus_cycle_state) + ADDRESS_BYTES : + begin + if (DOUBLE == 1'b1) + begin + if ((Instruct==DDRFR) && (~EXTADD)) + //Fast DDR Read Mode + begin + Address_in[addr_cnt] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 3*BYTE) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:26] = 6'b000000; + addr_bytes[24] = Bank_Addr_reg[0]; + addr_bytes[25] = Bank_Addr_reg[1]; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((Instruct==DDRFR4) || + ((Instruct==DDRFR) && EXTADD)) + begin + Address_in[addr_cnt] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 4*BYTE) + begin + addr_cnt = 0; + for(i=31;i>=0;i=i-1) + begin + addr_bytes[31-i] = Address_in[i]; + end + Address = addr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + begin + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + end + else if ((Instruct == DDRDIOR) && (~EXTADD)) + begin //Dual I/O DDR Read Mode + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt+1]= SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 3*BYTE/2) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:26] = 6'b000000; + addr_bytes[24] = Bank_Addr_reg[0]; + addr_bytes[25] = Bank_Addr_reg[1]; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((Instruct==DDRDIOR4) || + ((Instruct==DDRDIOR) && EXTADD)) + begin //Dual I/O DDR Read Mode + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt+1] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 4*BYTE/2) + begin + addr_cnt = 0; + for(i=31;i>=0;i=i-1) + begin + addr_bytes[31-i] = Address_in[i]; + end + Address = addr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + begin + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + end + else if ((Instruct==DDRQIOR) && (~EXTADD) && QUAD) + begin //Quad I/O DDR Read Mode + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 3*BYTE/4) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:26] = 6'b000000; + addr_bytes[24] = Bank_Addr_reg[0]; + addr_bytes[25] = Bank_Addr_reg[1]; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + else if (QUAD && ((Instruct==DDRQIOR4) || + ((Instruct==DDRQIOR) && EXTADD))) + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 4*BYTE/4) + begin + addr_cnt = 0; + for(i=31;i>=0;i=i-1) + begin + addr_bytes[31-i] = Address_in[i]; + end + Address = addr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + end + end + + MODE_BYTE : + begin + if ((Instruct == DDRFR) || (Instruct == DDRFR4)) + begin + mode_in[2*mode_cnt+1] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/2) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + else if ((Instruct==DDRDIOR) || (Instruct==DDRDIOR4)) + begin + mode_in[4*mode_cnt+2] = SO_in; + mode_in[4*mode_cnt+3] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/4) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + else if ((Instruct==DDRQIOR) || (Instruct==DDRQIOR4)) + begin + mode_in[4] = HOLDNeg_in; + mode_in[5] = WPNeg_in; + mode_in[6] = SO_in; + mode_in[7] = SI_in; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + + DATA_BYTES: + begin + if (hold_mode==0) + begin + if (DOUBLE == 1'b1 ) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + + end + else + begin + if ((Instruct==READ) || (Instruct==RD4) || + (Instruct==FSTRD)|| (Instruct==FSTRD4)|| + (Instruct==RDSR) || (Instruct==RDSR2) || + (Instruct==RDCR) || (Instruct==OTPR) || + (Instruct==DOR) || (Instruct==DOR4) || + (Instruct==DIOR)|| (Instruct==DIOR4)|| + (Instruct==ABRD) || (Instruct==BRRD) || + (Instruct==ASPRD)|| (Instruct==DYBRD) || + (Instruct==PPBRD)|| + (Instruct==PASSRD)|| (Instruct==RDID)|| + (Instruct==RES) || (Instruct==REMS) || + (Instruct==PLBRD)|| (Instruct==DLPRD) || + (current_state == AUTOBOOT && + start_delay == 0) || + (((Instruct==QOR) || (Instruct==QIOR) || + (Instruct==QOR4) || + (Instruct==QIOR4)) && QUAD)) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + end + + DUMMY_BYTES: + begin + if (hold_mode==0) + begin + if (DOUBLE == 1'b1 && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + + endcase + end + end + + if (rising_edge_CSNeg_ipd) + begin + if ((bus_cycle_state != DATA_BYTES) && + (bus_cycle_state != DUMMY_BYTES)) + begin + if (bus_cycle_state == ADDRESS_BYTES && opcode_tmp == 8'hFF) + begin + Instruct = MBR; + end + bus_cycle_state = STAND_BY; + end + else + begin + if (bus_cycle_state == DATA_BYTES) + begin + if (((mode_bytes[7:4] == 4'b1010) && + (Instruct==DIOR || Instruct==DIOR4 || + Instruct==QIOR || Instruct==QIOR4)) || + ((mode_bytes[7:4] == ~mode_bytes[3:0]) && + (Instruct == DDRFR || Instruct == DDRFR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4))) + bus_cycle_state = ADDRESS_BYTES; + else + bus_cycle_state = STAND_BY; + + case (Instruct) + WREN, + WRDI, + BE, + SE, + SE4, + CLSR, + P4E, + P4E4, + BRAC, + RESET, + PPBERS, + PPBP, + PLBWR, + PGSP, + PGRS, + ERSP, + ERRS: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 0) + write = 1'b0; + end + end + + WRR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + //If CS# is driven high after eight + //cycle,only the Status Register is + //written to. + begin + write = 1'b0; + if (BAR_ACC == 0) + begin + for(i=0;i<=7;i=i+1) + begin + Status_reg1_in[i]= + Data_in[7-i]; + end + end + else + begin + if (P_ERR == 0 && E_ERR == 0) + begin + for(i=0;i<=7;i=i+1) + begin + Bank_Addr_reg_in[i]= + Data_in[7-i]; + end + end + end + end + else if (data_cnt == 16) + //After the 16th cycle both the + //Status and Configuration Registers + //are written to. + begin + write = 1'b0; + if (BAR_ACC == 0) + begin + cfg_write = 1'b1; + for(i=0;i<=7;i=i+1) + begin + Status_reg1_in[i]= + Data_in[7-i]; + Config_reg1_in[i]= + Data_in[15-i]; + end + end + else + begin + if (P_ERR == 0 && E_ERR == 0) + begin + for(i=0;i<=7;i=i+1) + begin + Bank_Addr_reg_in[i]= + Data_in[7-i]; + end + end + end + end + end + end + + PP, + PP4, + OTPP: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt > 0) + begin + if ((data_cnt % 8) == 0) + begin + write = 1'b0; + for(i=0;i<=PageSize;i=i+1) + begin + for(j=7;j>=0;j=j-1) + begin + if ((Data_in[(i*8)+(7-j)]) + !== 1'bX) + begin + Byte_slv[j] = + Data_in[(i*8)+(7-j)]; + end + end + WByte[i] = Byte_slv; + end + + if (data_cnt > (PageSize+1)*BYTE) + Byte_number = PageSize; + else + Byte_number = + ((data_cnt/8) - 1); + end + end + end + end + + QPP, + QPP4: + begin + if (data_cnt >0) + begin + if ((data_cnt % 2) == 0) + begin + write = 1'b0; + quad_pg = 1'b0; + for(i=0;i<=PageSize;i=i+1) + begin + for(j=1;j>=0;j=j-1) + begin + Quad_slv = + quad_data_in[(i*2)+(1-j)]; + if (j==1) + Byte_slv[7:4] = Quad_slv; + else if (j==0) + Byte_slv[3:0] = Quad_slv; + end + WByte[i] = Byte_slv; + end + if (data_cnt > (PageSize+1)*2) + Byte_number = PageSize; + else + Byte_number = ((data_cnt/2)-1); + end + end + end + + ABWR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 32) + begin + write = 1'b0; + for(j=0;j<=31;j=j+1) + begin + AutoBoot_reg_in[j] = Data_in[31-j]; + end + end + end + end + + BRWR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + begin + write = 1'b0; + for(j=0;j<=7;j=j+1) + begin + Bank_Addr_reg_in[j] = Data_in[7-j]; + end + end + end + end + + ASPP: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 16) + begin + write = 1'b0; + for(j=0;j<=15;j=j+1) + begin + ASP_reg_in[j] = Data_in[15-j]; + end + end + end + end + + DYBWR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + begin + write = 1'b0; + for(j=0;j<=7;j=j+1) + begin + DYBAR_in[j] = Data_in[7-j]; + end + end + end + end + + PNVDLR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + begin + write = 1'b0; + for(j=0;j<=7;j=j+1) + begin + NVDLR_reg_in[j] = Data_in[7-j]; + end + end + end + end + + WVDLR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + begin + write = 1'b0; + for(j=0;j<=7;j=j+1) + begin + VDLR_reg_in[j] = Data_in[7-j]; + end + end + end + end + + PASSP: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 64) + begin + write = 1'b0; + for(j=1;j<=8;j=j+1) + begin + for(k=1;k<=8;k=k+1) + begin + Password_reg_in[j*8-k] = + Data_in[8*(j-1)+k-1]; + end + end + end + end + end + + PASSU: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 64) + begin + write = 1'b0; + for(j=1;j<=8;j=j+1) + begin + for(k=1;k<=8;k=k+1) + begin + PASS_TEMP[j*8-k] = + Data_in[8*(j-1)+k-1]; + end + end + end + end + end + endcase + end + end + end + end + +/////////////////////////////////////////////////////////////////////////////// +// Timing control for the Page Program +/////////////////////////////////////////////////////////////////////////////// + time pob; + time elapsed_pgm; + time start_pgm; + time duration_pgm; + event pdone_event; + + always @(rising_edge_PSTART) + begin + if ((Instruct == PP) || (Instruct == PP4) || (Instruct == OTPP) || + (Instruct == QPP) || (Instruct == QPP4)) + if (PageSize == 255) + begin + pob = tdevice_PP_256; + end + else + begin + pob = tdevice_PP_512; + end + else + pob = tdevice_BP; + if ((rising_edge_PSTART) && PDONE) + begin + elapsed_pgm = 0; + duration_pgm = pob; + PDONE = 1'b0; + ->pdone_event; + start_pgm = $time; + end + end + + always @(posedge PGSUSP) + begin + if (PGSUSP && (~PDONE)) + begin + disable pdone_process; + elapsed_pgm = $time - start_pgm; + duration_pgm = pob - elapsed_pgm; + PDONE = 1'b0; + end + end + + always @(posedge PGRES) + begin + start_pgm = $time; + ->pdone_event; + end + + always @(pdone_event) + begin:pdone_process + PDONE = 1'b0; + #duration_pgm PDONE = 1'b1; + end + +/////////////////////////////////////////////////////////////////////////////// +// Timing control for the Write Status Register +/////////////////////////////////////////////////////////////////////////////// + time wob; + always @(posedge WSTART) + begin:wdone_process + wob = tdevice_WRR; + if (WSTART && WDONE) + begin + WDONE = 1'b0; + #wob WDONE = 1'b1; + end + end + +/////////////////////////////////////////////////////////////////////////////// +// Reset Timing +/////////////////////////////////////////////////////////////////////////////// + + time startlo; + time starthi; + time durationlo; + time durationhi; + + always @(negedge RSTNeg_in or Instruct) + begin + if (~RSTNeg_in) + begin + RST = 1'b1; + #200000 RST = 1'b0; // 200 ns + end + else if (Instruct == RESET) + begin + Reseted = 1'b0; + #10000 Reseted = 1'b1; // 10 ns + end + end + + always @(RST_in or rising_edge_Reseted) // Reset done,program terminated + begin + if ((RST_in && ~RST) || (rising_edge_Reseted)) + disable pdone_process; + disable edone_process; + disable wdone_process; + PDONE = 1'b1; + EDONE = 1'b1; + WDONE = 1'b1; + end + +/////////////////////////////////////////////////////////////////////////////// +// Timing control for the Bulk Erase +/////////////////////////////////////////////////////////////////////////////// + time seo; + time beo; + event edone_event; + time elapsed_ers; + time start_ers; + time duration_ers; + + always @(rising_edge_ESTART) + begin + seo = tdevice_SE; + beo = tdevice_BE; + if ((rising_edge_ESTART) && EDONE) + begin + if (Instruct == BE) + begin + duration_ers = beo; + end + else + begin + duration_ers = seo; + end + elapsed_ers = 0; + EDONE = 1'b0; + ->edone_event; + start_ers = $time; + end + end + + always @(posedge ESUSP) + begin + if (ESUSP && (~EDONE)) + begin + disable edone_process; + elapsed_ers = $time - start_ers; + duration_ers = seo - elapsed_ers; + EDONE = 1'b0; + end + end + + always @(posedge ERES) + begin + if (ERES && (~EDONE)) + begin + start_ers = $time; + ->edone_event; + end + end + + always @(edone_event) + begin : edone_process + EDONE = 1'b0; + #duration_ers EDONE = 1'b1; + end + + /////////////////////////////////////////////////////////////////// + // Process for clock frequency determination + /////////////////////////////////////////////////////////////////// + always @(posedge SCK_ipd) + begin : clock_period + if (SCK_ipd) + begin + SCK_cycle = $time - prev_SCK; + prev_SCK = $time; + end + end + +// ///////////////////////////////////////////////////////////////////////// +// // Main Behavior Process +// // combinational process for next state generation +// ///////////////////////////////////////////////////////////////////////// + + reg rising_edge_PDONE = 1'b0; + reg rising_edge_EDONE = 1'b0; + reg rising_edge_WDONE = 1'b0; + reg falling_edge_write = 1'b0; + reg falling_edge_PPBERASE_in = 1'b0; + reg falling_edge_PASSULCK_in = 1'b0; + + integer i; + integer j; + + always @(rising_edge_PoweredUp or falling_edge_write or + falling_edge_RSTNeg or rising_edge_PDONE or rising_edge_WDONE or + rising_edge_EDONE or ERSSUSP_out_event or rising_edge_RSTNeg or + PRGSUSP_out_event or rising_edge_CSNeg_ipd or rising_edge_RST_out + or falling_edge_PPBERASE_in or falling_edge_PASSULCK_in) + begin: StateGen1 + + integer sect; + + if (rising_edge_PoweredUp) + begin + if (ABE == 1 && RPME !== 0 ) + begin + next_state = AUTOBOOT; + read_cnt = 0; + byte_cnt = 1; + read_addr = {AutoBoot_reg[31:9], 9'b0}; + start_delay = AutoBoot_reg[8:1]; + start_autoboot = 0; + ABSD = AutoBoot_reg[8:1]; + end + else + next_state = IDLE; + end + else + begin + if (RST_out == 1'b0) + next_state = current_state; + else if (falling_edge_write && Instruct == RESET) + begin + if (ABE == 1 && RPME !== 0) + begin + read_cnt = 0; + byte_cnt = 1; + read_addr = {AutoBoot_reg[31:9], 9'b0}; + start_delay = AutoBoot_reg[8:1]; + ABSD = AutoBoot_reg[8:1]; + start_autoboot = 0; + next_state = AUTOBOOT; + end + else + next_state = IDLE; + end + else + begin + case (current_state) + RESET_STATE : + begin + if (rising_edge_RST_out) + begin + if (ABE == 1 && RPME!== 0) + begin + next_state = AUTOBOOT; + read_cnt = 0; + byte_cnt = 1; + read_addr = {AutoBoot_reg[31:9],9'b0}; + start_delay = AutoBoot_reg[8:1]; + start_autoboot = 0; + ABSD = AutoBoot_reg[8:1]; + end + else + next_state = IDLE; + end + end + + IDLE : + begin + if (falling_edge_write && RdPswdProtMode == 0) + begin + if (Instruct == WRR && WEL == 1 && BAR_ACC == 0 + && (((~(SRWD == 1 && ~WPNeg_in))&& ~QUAD) || QUAD)) + // can not execute if HPM is entered or + // if WEL bit is zero + if (((TBPROT==1 && Config_reg1_in[5]==1'b0) || + (BPNV ==1 && Config_reg1_in[3]==1'b0)) && + cfg_write) + begin + $display ("WARNING: Changing value of "); + $display ("Configuration Register OTP "); + $display ("bit from 1 to 0 is not"); + $display ("allowed!!!"); + end + else + begin + next_state = WRITE_SR; + end + else if ((Instruct == PP || Instruct == QPP || + Instruct == PP4 || Instruct == QPP4) && + WEL == 1) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + if (Sec_Prot[sect]== 0 && PPB_bits[sect]== 1 && + DYB_bits[sect]== 1) + begin + next_state = PAGE_PG; + if ((Instruct==QPP || Instruct==QPP4) && + QPP_page[pgm_page] == 1) + begin + $display ("WARNING:The same page"); + $display (" must not be"); + $display (" programmed more"); + $display (" than once!!!"); + end + end + end + else if (Instruct==OTPP && WEL==1 && FREEZE==0) + begin + if (((((Address>=16'h0010 && Address<=16'h0013) + ||(Address>=16'h0020 && Address<=16'h00FF)) + && LOCK_BYTE1[Address/32] == 1) || + ((Address>=16'h0100 && Address<=16'h01FF) + && LOCK_BYTE2[(Address-16'h0100)/32]==1) || + ((Address>=16'h0200 && Address<=16'h02FF) + && LOCK_BYTE3[(Address-16'h0200)/32]==1) || + ((Address>=16'h0300 && Address<=16'h03FF) + && LOCK_BYTE4[(Address-16'h0300)/32] == 1)) + && (Address + Byte_number <= OTPHiAddr)) + next_state = OTP_PG; + end + else if ((Instruct == SE || Instruct == SE4) + && WEL == 1) + begin + ReturnSectorID(sect,Address); + if (Sec_Prot[sect]== 0 && PPB_bits[sect]== 1 + && DYB_bits[sect]== 1) + next_state = SECTOR_ERS; + end + else if (Instruct == BE && WEL == 1 && + (Status_reg1[4]== 0 && Status_reg1[3]== 0 && + Status_reg1[2]== 0)) + next_state = BULK_ERS; + else if (Instruct == ABWR && WEL == 1) + //Autoboot Register Write Command + next_state = AUTOBOOT_PG; + else if (Instruct == ASPP && WEL == 1) + begin + //ASP Register Program Command + if (~(ASPOTPFLAG)) + next_state = ASP_PG; + end + else if (Instruct == PLBWR && WEL == 1 && + RdPswdProtEnable == 0) + next_state = PLB_PG; + else if (Instruct == PASSP && WEL == 1) + begin + if (~(PWDMLB== 0 && PSTMLB== 1)) + next_state = PASS_PG; + end + else if (Instruct == PASSU && WEL && ~WIP) + next_state = PASS_UNLOCK; + else if (Instruct == PPBP && WEL == 1) + next_state <= PPB_PG; + else if (Instruct == PPBERS && WEL && PPBOTP) + next_state <= PPB_ERS; + else if (Instruct == DYBWR && WEL == 1) + next_state = DYB_PG; + else if (Instruct == PNVDLR && WEL == 1) + next_state = NVDLR_PG; + else if (Instruct == P4E || Instruct == P4E4 + && WEL == 1) + begin + $display("Warning!"); + $display("Instructions:"); + $display("Parameter 4KB-sector Erase"); + $display("are not allowed"); + $display("for 512Mbit memory size"); + end + else + next_state = IDLE; + end + if (falling_edge_write && RdPswdProtMode == 1 && ~WIP) + begin + if (Instruct == PASSU) + next_state = PASS_UNLOCK; + end + end + + AUTOBOOT : + begin + if (rising_edge_CSNeg_ipd) + next_state = IDLE; + end + + WRITE_SR : + begin + if (rising_edge_WDONE) + next_state = IDLE; + end + + PAGE_PG : + begin + if (PRGSUSP_out_event && PRGSUSP_out == 1) + next_state = PG_SUSP; + else if (rising_edge_PDONE) + next_state = IDLE; + end + + PG_SUSP : + begin + if (falling_edge_write) + begin + if (Instruct == PGRS) + begin + next_state = PAGE_PG; + end + else + begin + next_state = PG_SUSP; + end + end + end + + OTP_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + BULK_ERS : + begin + if (rising_edge_EDONE) + next_state = IDLE; + end + + SECTOR_ERS : + begin + if (ERSSUSP_out_event && ERSSUSP_out == 1) + next_state = ERS_SUSP; + else if (rising_edge_EDONE) + next_state = IDLE; + end + + ERS_SUSP : + begin + if (falling_edge_write) + begin + if ((Instruct == PP || Instruct == QPP || + Instruct == PP4 || Instruct == QPP4) && + WEL == 1) + begin + if (SectorSuspend != Address/(SecSize+1)) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + if (PPB_bits[sect]== 1 && + DYB_bits[sect]== 1) + begin + next_state = ERS_SUSP_PG; + if ((Instruct==QPP || Instruct==QPP4) && + QPP_page[pgm_page] == 1) + begin + $display ("WARNING:The same page"); + $display (" must not be"); + $display (" programmed more"); + $display (" than once!!!"); + end + end + end + end + else if (Instruct == DYBWR && WEL == 1) + next_state = DYB_PG; + else if (Instruct == ERRS) + next_state = SECTOR_ERS; + else + next_state = ERS_SUSP; + end + end + + ERS_SUSP_PG : + begin + if (rising_edge_PDONE) + next_state = ERS_SUSP; + else if (PRGSUSP_out_event && PRGSUSP_out == 1) + next_state = ERS_SUSP_PG_SUSP; + end + + ERS_SUSP_PG_SUSP : + begin + if (rising_edge_PDONE) + next_state = ERS_SUSP; + if (falling_edge_write) + begin + if (Instruct == PGRS) + begin + next_state = ERS_SUSP_PG; + end + else + begin + next_state = ERS_SUSP_PG_SUSP; + end + end + end + + PASS_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + PASS_UNLOCK : + begin + if (falling_edge_PASSULCK_in) + next_state = IDLE; + end + + PPB_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + PPB_ERS : + begin + if (falling_edge_PPBERASE_in) + next_state = IDLE; + end + + AUTOBOOT_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + PLB_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + DYB_PG : + begin + if (rising_edge_PDONE) + if (ES) + next_state = ERS_SUSP; + else + next_state = IDLE; + end + + ASP_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + NVDLR_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + endcase + end + end + end + + /////////////////////////////////////////////////////////////////////////// + //FSM Output generation and general functionality + /////////////////////////////////////////////////////////////////////////// + reg rising_edge_read_out = 1'b0; + reg Instruct_event = 1'b0; + reg change_addr_event = 1'b0; + reg current_state_event = 1'b0; + reg rising_edge_DP_out = 1'b0; + + integer WData [0:511]; + integer WOTPData; + integer Addr; + integer Addr_tmp; + + always @(Instruct_event) + begin + read_cnt = 0; + byte_cnt = 1; + rd_fast = 1'b1; + dual = 1'b0; + rd_slow = 1'b0; + any_read = 1'b0; + end + + always @(rising_edge_read_out) + begin + if (rising_edge_read_out == 1'b1) + begin + if (PoweredUp == 1'b1) + begin + oe_z = 1'b1; + #1000 oe_z = 1'b0; + oe = 1'b1; + #1000 oe = 1'b0; + end + end + end + + always @(change_addr_event) + begin + if (change_addr_event) + begin + read_addr = Address; + end + end + + always @(posedge PASSACC_out) + begin + Status_reg1[0] = 1'b0; //WIP + PASSACC_in = 1'b0; + end + + always @(Instruct or posedge start_autoboot or oe or current_state_event or + falling_edge_write or posedge PDONE or posedge WDONE or oe_z or + posedge EDONE or ERSSUSP_out or rising_edge_Reseted or + rising_edge_PoweredUp or rising_edge_CSNeg_ipd or PRGSUSP_out or + Address) + begin: Functionality + integer i,j; + integer sect; + + if (rising_edge_PoweredUp) + begin + //the default condition after power-up + //The Bank Address Register is loaded to all zeroes + Bank_Addr_reg = 8'h0; + //The Configuration Register FREEZE bit is cleared. + Config_reg1[0] = 0; + //The WEL bit is cleared. + Status_reg1[1] = 0; + //When BPNV is set to '1'. the BP2-0 bits in Status Register are + //volatile and will be reset binary 111 after power-on reset + if (BPNV == 1 && LOCK == 0 && FREEZE == 0 ) + begin + Status_reg1[4] = 1'b0;// BP2 + Status_reg1[3] = 1'b0;// BP1 + Status_reg1[2] = 1'b0;// BP0 + BP_bits = {Status_reg1[4],Status_reg1[3],Status_reg1[2]}; + change_BP = 1'b1; + #1000 change_BP = 1'b0; + end + + //As shipped from the factory, all devices default ASP to the + //Persistent Protection mode, with all sectors unprotected, + //when power is applied. The device programmer or host system must + //then choose which sector protection method to use. + //For Persistent Protection mode, PPBLOCK defaults to "1" + PPBL[0] = 1'b1; + + //All the DYB power-up in the unprotected state + DYB_bits = {512{1'b1}}; + + end + + if (Instruct == RESET) + begin + //EXTADD is cleared to “0” + Bank_Addr_reg[7] = 1'b0; + //P_ERR bit is cleared + Status_reg1[6] = 1'b0; + //E_ERR bit is cleared + Status_reg1[5] = 1'b0; + //The WEL bit is cleared. + Status_reg1[1] = 1'b0; + //The WIP bit is cleared. + Status_reg1[0] = 1'b0; + //The ES bit is cleared. + Status_reg2[1] = 1'b0; + //The PS bit is cleared. + Status_reg2[0] = 1'b0; + //When BPNV is set to '1'. the BP2-0 bits in Status + //Register are volatile and will be reseted after + //reset command + if (BPNV == 1 && LOCK== 0 && FREEZE == 0) + begin + Status_reg1[4] = 1'b1; + Status_reg1[3] = 1'b1; + Status_reg1[2] = 1'b1; + + BP_bits = {Status_reg1[4],Status_reg1[3], + Status_reg1[2]}; + change_BP = 1'b1; + #1000 change_BP = 1'b0; + end + end + + case (current_state) + IDLE : + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + + if (falling_edge_write && RdPswdProtMode == 1) + begin + if(Instruct == PASSU) + begin + if (~WIP) + begin + PASSULCK_in = 1; + Status_reg1[0] = 1'b1; //WIP + end + else + begin + $display ("The PASSU command cannot be accepted"); + $display (" any faster than once every 100us"); + end + end + else if (Instruct == CLSR) + begin + //The Clear Status Register Command resets bit SR1[5] + //(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + Status_reg1[5] = 0; + Status_reg1[6] = 0; + end + end + + if (falling_edge_write && RdPswdProtMode == 0) + begin + read_cnt = 0; + byte_cnt = 1; + if (Instruct == WREN) + Status_reg1[1] = 1'b1; + else if (Instruct == WRDI) + Status_reg1[1] = 0; + else if ((Instruct == WRR) && WEL == 1 && WDONE == 1 && + BAR_ACC == 0) + begin + if (((~(SRWD == 1 && ~WPNeg_in))&& ~QUAD) || QUAD) + begin + if (((TBPROT==1 && Config_reg1_in[5]==1'b0) || + (BPNV ==1 && Config_reg1_in[3]==1'b0)) && + cfg_write) + begin + // P_ERR bit is set to 1 + Status_reg1[6] = 1'b1; + end + else + begin + // can not execute if Hardware Protection Mode + // is entered or if WEL bit is zero + WSTART = 1'b1; + WSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + end + else + Status_reg1[1] = 0; + end + else if ((Instruct == PP || Instruct == PP4) && WEL ==1 && + PDONE == 1 ) + begin + ReturnSectorID(sect,Address); + if (Sec_Prot[sect] == 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 0; + PGRES = 0; + INITIAL_CONFIG = 1; + Status_reg1[0] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + //P_ERR bit will be set when the user attempts to + //to program within a protected main memory sector + Status_reg1[6] = 1'b1; //P_ERR + Status_reg1[1] = 1'b0; //WEL + end + end + else if ((Instruct == QPP || Instruct == QPP4) && WEL ==1 && + PDONE == 1 ) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + if (Sec_Prot[sect] == 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 0; + PGRES = 0; + INITIAL_CONFIG = 1; + QPP_page[pgm_page] = 1'b1; + Status_reg1[0] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + //P_ERR bit will be set when the user attempts to + //to program within a protected main memory sector + Status_reg1[6] = 1'b1; //P_ERR + Status_reg1[1] = 1'b0; //WEL + end + end + else if (Instruct == OTPP && WEL == 1) + begin + // As long as the FREEZE bit remains cleared to a logic + // '0' the OTP address space is programmable. + if (FREEZE == 0) + begin + if (((((Address>= 16'h0010 && Address<= 16'h0013) || + (Address >= 16'h0020 && Address <= 16'h00FF)) + && LOCK_BYTE1[Address/32] == 1) || + ((Address >= 16'h0100 && Address <= 16'h01FF) + && LOCK_BYTE2[(Address-16'h0100)/32] == 1) || + ((Address >= 16'h0200 && Address <= 16'h02FF) + && LOCK_BYTE3[(Address-16'h0200)/32] == 1) || + ((Address >= 16'h0300 && Address <= 16'h03FF) + && LOCK_BYTE4[(Address-16'h0300)/32] == 1)) && + (Address + Byte_number <= OTPHiAddr)) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else if ((Address < 8'h10 || (Address > 8'h13 && + Address < 8'h20) || Address > 12'h3FF )) + begin + Status_reg1[6] = 1'b1;//P_ERR + Status_reg1[1] = 1'b0;//WEL + if (Address < 8'h20) + begin + $display ("Given address is "); + $display ("in reserved address range"); + end + else if (Address > 12'h3FF) + begin + $display ("Given address is "); + $display ("out of OTP address range"); + end + end + else + begin + //P_ERR bit will be set when the user attempts to + // to program within locked OTP region + Status_reg1[6] = 1'b1;//P_ERR + Status_reg1[1] = 1'b0;//WEL + end + end + else + begin + //P_ERR bit will be set when the user attempts to + //to program within locked OTP region + Status_reg1[6] = 1'b1;//P_ERR + Status_reg1[1] = 1'b0;//WEL + end + end + else if ((Instruct == SE || Instruct == SE4) && WEL == 1) + begin + ReturnSectorID(sect,Address); + SectorSuspend = sect; + if (Sec_Prot[sect] == 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + ESTART = 1'b1; + ESTART <= #5 1'b0; + SecAddrERS = sect; + ESUSP = 0; + ERES = 0; + INITIAL_CONFIG = 1; + Status_reg1[0] = 1'b1; + Addr = Address; + end + else + begin + //E_ERR bit will be set when the user attempts to + //erase an individual protected main memory sector + Status_reg1[5] = 1'b1;//E_ERR + Status_reg1[1] = 1'b0;//WEL + end + end + else if ((Instruct == P4E || Instruct == P4E4) && WEL == 1) + begin + Status_reg1[1] = 1'b0;//WEL + end + else if (Instruct == BE && WEL == 1) + begin + if (Status_reg1[4]== 0 && Status_reg1[3]== 0 && + Status_reg1[2]== 0) + begin + ESTART = 1'b1; + ESTART <= #5 1'b0; + ESUSP = 0; + ERES = 0; + INITIAL_CONFIG = 1; + Status_reg1[0] = 1'b1; + end + else + begin + //The Bulk Erase command will not set E_ERR if a + //protected sector is found during the command + //execution. + Status_reg1[1] = 1'b0;//WEL + end + end + else if (Instruct == PASSP && WEL == 1) + begin + if (~(PWDMLB== 0 && PSTMLB== 1)) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else + begin + $display ("Password programming is not allowed"); + $display (" in Password Protection Mode."); + end + end + else if (Instruct == PASSU && WEL) + begin + if (~WIP) + begin + PASSULCK_in = 1; + Status_reg1[0] = 1'b1; //WIP + end + else + begin + $display ("The PASSU command cannot be accepted"); + $display (" any faster than once every 100us"); + end + end + else if (Instruct == BRWR) + begin + Bank_Addr_reg[7] = Bank_Addr_reg_in[7]; + Bank_Addr_reg[1] = Bank_Addr_reg_in[1]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + end + else if (Instruct == WRR && BAR_ACC == 1) + begin + // Write to the lower address bits of the BAR + if (P_ERR == 0 && E_ERR == 0) + begin + Bank_Addr_reg[1] = Bank_Addr_reg_in[1]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + end + end + else if (Instruct == ASPP && WEL == 1) + begin + if (~(ASPOTPFLAG)) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + $display ("Once the Protection Mode is selected,"); + $display ("no further changes to the ASP "); + $display ("register is allowed."); + end + end + else if (Instruct == ABWR && WEL == 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == PPBP && WEL == 1) + begin + ReturnSectorID(sect,Address); + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == PPBERS && WEL == 1) + begin + if (PPBOTP) + begin + PPBERASE_in = 1'b1; + Status_reg1[0] = 1'b1; + end + else + begin + Status_reg1[5] = 1'b1; + end + end + else if (Instruct == PLBWR && WEL == 1 && + RdPswdProtEnable == 0) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == DYBWR && WEL == 1) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == PNVDLR && WEL == 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == WVDLR && WEL == 1) + begin + VDLR_reg = VDLR_reg_in; + Status_reg1[1] = 1'b0; + end + else if (Instruct == CLSR) + begin + //The Clear Status Register Command resets bit SR1[5] + //(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + Status_reg1[5] = 0; + Status_reg1[6] = 0; + end + + if (Instruct == BRAC && P_ERR == 0 && E_ERR == 0) + begin + BAR_ACC = 1; + end + else + begin + BAR_ACC = 0; + end + end + else if (oe_z) + begin + if (Instruct == READ || Instruct == RD4 || + Instruct == RES || + (Instruct == DLPRD && RdPswdProtMode == 0)) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else if (Instruct == DDRDIOR || Instruct == DDRDIOR4 || + ((Instruct == DDRQIOR || Instruct == DDRQIOR4) + && QUAD)) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + ((Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4) + && QUAD)) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + else if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == READ || Instruct == RD4 || + Instruct == FSTRD || Instruct == FSTRD4 || + Instruct == DDRFR || Instruct == DDRFR4 ) + begin + //Read Memory array + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + if (bus_cycle_state == DUMMY_BYTES + && VDLR_reg != 8'b00000000) + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) is enabled + // Optional DLP + if (VDLR_reg != 8'b00000000 && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + read_addr_tmp = read_addr; + ReturnSectorID(sect,read_addr); + SecAddr = sect; + SecAddr_tmp = SecAddr; + Sec_addr = read_addr - SecAddr*(SecSize+1); + SecAddr = ReturnSectorIDRdPswdMd(TBPROT); + read_addr = Sec_addr + SecAddr*(SecSize+1); + if (RdPswdProtMode == 0) + begin + read_addr = read_addr_tmp; + SecAddr = SecAddr_tmp; + end + + READMEM(read_addr,SecAddr); + if (OutputD !== -1) + begin + data_out[7:0] = OutputD; + SOut_zd = data_out[7-read_cnt]; + end + else + begin + SOut_zd = 8'bx; + end + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 ) + begin + //Read Memory array + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + if (VDLR_reg != 8'b00000000 && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + read_addr_tmp = read_addr; + ReturnSectorID(sect,read_addr); + SecAddr = sect; + SecAddr_tmp = SecAddr; + Sec_addr = read_addr - SecAddr*(SecSize+1); + SecAddr = ReturnSectorIDRdPswdMd(TBPROT); + read_addr = Sec_addr + SecAddr*(SecSize+1); + if (RdPswdProtMode == 0) + begin + read_addr = read_addr_tmp; + SecAddr = SecAddr_tmp; + end + + READMEM(read_addr,SecAddr); + data_out[7:0] = OutputD; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if ((Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4 ) + && QUAD) + begin + //Read Memory array + if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (bus_cycle_state == DUMMY_BYTES) + begin + if ((Instruct == DDRQIOR || Instruct == DDRQIOR4) + && QUAD) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) is enabled + // Optional DLP + if (VDLR_reg != 8'b00000000 && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + HOLDNegOut_zd = data_out[7-read_cnt]; + WPNegOut_zd = data_out[7-read_cnt]; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + read_addr_tmp = read_addr; + ReturnSectorID(sect,read_addr); + SecAddr = sect; + SecAddr_tmp = SecAddr; + Sec_addr = read_addr - SecAddr*(SecSize+1); + SecAddr = ReturnSectorIDRdPswdMd(TBPROT); + read_addr = Sec_addr + SecAddr*(SecSize+1); + if (RdPswdProtMode == 0) + begin + read_addr = read_addr_tmp; + SecAddr = SecAddr_tmp; + end + + READMEM(read_addr,SecAddr); + data_out[7:0] = OutputD; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == OTPR) + begin + if(read_addr>=OTPLoAddr && read_addr<=OTPHiAddr + && RdPswdProtMode == 0) + begin + //Read OTP Memory array + rd_fast = 1'b1; + rd_slow = 1'b0; + data_out[7:0] = OTPMem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + else if ((read_addr > OTPHiAddr)||(RdPswdProtMode==1)) + begin + //OTP Read operation will not wrap to the + //starting address after the OTP address is at + //its maximum or Read Password Protection Mode + //is selected instead, the data beyond the + //maximum OTP address will be undefined. + SOut_zd = 1'bX; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (Instruct == REMS) + begin + //Read Manufacturer and Device ID + if (read_addr % 2 == 0) + begin + data_out[7:0] = Manuf_ID; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + else + begin + data_out[7:0] = DeviceID; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = 0; + end + end + end + else if (Instruct == RDID) + begin + ident_out = CFI_array_tmp; + if(read_cnt < 648) + begin + SOut_zd = ident_out[647-read_cnt]; + read_cnt = read_cnt + 1; + end + else + begin + //Continued shifting of output beyond the end of + //the defined ID-CFI address space will + //provide undefined data. + SOut_zd = 1'bX; + end + end + else if (Instruct == RES) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + data_out = ESignature; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == DLPRD && RdPswdProtMode == 0) + begin + //Read DLP + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = VDLR_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == ABRD && RdPswdProtMode == 0) + begin + //Read AutoBoot register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = AutoBoot_reg[31-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 32) + read_cnt = 0; + end + else if (Instruct == BRRD && RdPswdProtMode == 0) + begin + //Read Bank Address Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = Bank_Addr_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == ASPRD && RdPswdProtMode == 0) + begin + //Read ASP Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = ASP_reg[15-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 16) + read_cnt = 0; + end + else if (Instruct == PASSRD && RdPswdProtMode == 0) + begin + //Read Password Register + if (~(PWDMLB == 0 && PSTMLB == 1)) + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = + Password_reg[(8*byte_cnt-1)-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + byte_cnt = byte_cnt + 1; + if (byte_cnt == 9) + byte_cnt = 1; + end + end + end + else if (Instruct == PLBRD) + begin + //Read PPB Lock Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = PPBL[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == DYBRD) + begin + //Read DYB Access Register + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + DYBAR[7:0] = 8'bXXXXXXXX; + + if (RdPswdProtMode == 0) + begin + if (DYB_bits[sect] == 1) + DYBAR[7:0] = 8'hFF; + else + begin + DYBAR[7:0] = 8'h0; + end + end + + SOut_zd = DYBAR[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == PPBRD) + begin + //Read PPB Access Register + ReturnSectorID(sect,Address); + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + PPBAR[7:0] = 8'bXXXXXXXX; + if (RdPswdProtMode == 0) + begin + if (PPB_bits[sect] == 1) + PPBAR[7:0] = 8'hFF; + else + begin + PPBAR[7:0] = 8'h0; + end + end + SOut_zd = PPBAR[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + end + + AUTOBOOT: + begin + if (start_autoboot == 1) + begin + if (oe) + begin + any_read = 1'b1; + if (QUAD == 1) + begin + if (ABSD > 0) //If ABSD > 0, + begin //max SCK frequency is 104MHz + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else // If ABSD = 0, max SCK frequency is 50 MHz + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + ReturnSectorID(sect,read_addr); + SecAddr = sect; + READMEM(read_addr,SecAddr); + data_out[7:0] = OutputD; + + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + else + begin + if (ABSD > 0) //If ABSD > 0, + begin //max SCK frequency is 133MHz + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + else // If ABSD = 0, max SCK frequency is 50 MHz + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + ReturnSectorID(sect,read_addr); + SecAddr = sect; + READMEM(read_addr,SecAddr); + data_out[7:0] = OutputD; + + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + end + else if (oe_z) + begin + if (QUAD == 1) + begin + if (ABSD > 0) //If ABSD > 0, + begin //max SCK frequency is 104MHz + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else // If ABSD = 0, max SCK frequency is 50 MHz + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + end + else + begin + if (ABSD > 0) //If ABSD > 0, + begin //max SCK frequency is 133MHz + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + else // If ABSD = 0, max SCK frequency is 50 MHz + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + end + end + + WRITE_SR: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (WDONE == 1) + begin + Status_reg1[0] = 1'b0; //WIP + Status_reg1[1] = 1'b0; //WEL + //SRWD bit + Status_reg1[7] = Status_reg1_in[7]; //MSB first + + if (LOCK == 0) + begin + if (FREEZE == 0) + //The Freeze Bit, when set to 1, locks the current + //state of the BP2-0 bits in Status Register, + //the TBPROT bit in the Config Register + //As long as the FREEZE bit remains cleared to logic + //'0', the other bits of the Configuration register + //including FREEZE are writeable. + begin + Status_reg1[4] = Status_reg1_in[4];//BP2 + Status_reg1[3] = Status_reg1_in[3];//BP1 + Status_reg1[2] = Status_reg1_in[2];//BP0 + + BP_bits = {Status_reg1[4],Status_reg1[3], + Status_reg1[2]}; + if (TBPROT == 1'b0 && INITIAL_CONFIG == 1'b0) + begin + Config_reg1[5] = Config_reg1_in[5];//TBPROT + end + change_BP = 1'b1; + #1000 change_BP = 1'b0; + end + end + + Config_reg1[7] = Config_reg1_in[7];//LC1 + Config_reg1[6] = Config_reg1_in[6];//LC0 + Config_reg1[1] = Config_reg1_in[1];//QUAD + + if (FREEZE == 1'b0) + begin + Config_reg1[0] = Config_reg1_in[0];//FREEZE + end + + if (WRLOCKENABLE== 1'b1 && LOCK == 1'b0) + begin + Config_reg1[4] = Config_reg1_in[4];//LOCK + WRLOCKENABLE = 1'b0; + end + if (BPNV == 1'b0) + begin + Config_reg1[3] = Config_reg1_in[3];//BPNV + end + end + end + + PAGE_PG : + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == PAGE_PG) + begin + if (~PDONE) + begin + ADDRHILO_PG(AddrLo, AddrHi, Addr); + cnt = 0; + + for (i=0;i<=wr_cnt;i=i+1) + begin + new_int = WData[i]; + ReturnSectorID(sect,read_addr); + SecAddr = sect; + memory_features_i0.read_mem_w( + mem_data, + Addr + i - cnt + ); + if (corrupt_Sec[SecAddr]) + begin + if (mem_data== MaxData+1) + mem_data = MaxData; + else if (mem_data == MaxData) + mem_data = -1; + end + old_int = mem_data; + if (new_int > -1) + begin + new_bit = new_int; + if (old_int > -1) + begin + old_bit = old_int; + for(j=0;j<=7;j=j+1) + begin + if (~old_bit[j]) + new_bit[j]=1'b0; + end + new_int=new_bit; + end + WData[i]= new_int; + end + else + begin + WData[i] = -1; + end + + memory_features_i0.write_mem_w( + Addr + i -cnt, + -1 + ); + + if ((Addr + i) == AddrHi) + begin + Addr = AddrLo; + cnt = i + 1; + end + end + end + cnt = 0; + end + + if (PDONE) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + for (i=0;i<=wr_cnt;i=i+1) + begin + memory_features_i0.write_mem_w( + Addr_tmp + i -cnt, + WData[i] + ); + if ((Addr_tmp + i) == AddrHi) + begin + Addr_tmp = AddrLo; + cnt = i + 1; + end + + end + end + + if (Instruct) + begin + if (Instruct == PGSP && ~PRGSUSP_in) + begin + if (~RES_TO_SUSP_MIN_TIME) + begin + PGSUSP = 1'b1; + PGSUSP <= #5 1'b0; + PRGSUSP_in = 1'b1; + if (RES_TO_SUSP_TYP_TIME) + begin + $display("Typical periods are needed for ", + "Program to progress to completion"); + end + end + else + begin + $display("Minimum for tPRS is not satisfied! ", + "PGSP command is ignored"); + end + end + end + end + + PG_SUSP: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + + if (PRGSUSP_out && PRGSUSP_in) + begin + PRGSUSP_in = 1'b0; + //The RDY/BSY bit in the Status Register will indicate that + //the device is ready for another operation. + Status_reg1[0] = 1'b0; + //The Program Suspend (PS) bit in the Status Register will + //be set to the logical “1” state to indicate that the + //program operation has been suspended. + Status_reg2[0] = 1'b1; + PDONE = 1'b1; + end + + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == BRRD) + begin + //Read Bank Address Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = Bank_Addr_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + //Read Array Operations + else if (Instruct == READ || Instruct == RD4 || + Instruct == FSTRD || Instruct == FSTRD4 || + Instruct == DDRFR || Instruct == DDRFR4 ) + begin + //Read Memory array + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + if (pgm_page != read_addr / (PageSize+1)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + ReturnSectorID(sect,read_addr); + SecAddr = sect; + READMEM(read_addr,SecAddr); + data_out[7:0] = OutputD; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + + end + end + else + begin + SOut_zd = 8'bxxxxxxxx; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 ) + begin + //Read Memory array + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (pgm_page != read_addr / (PageSize+1)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + ReturnSectorID(sect,read_addr); + SecAddr = sect; + READMEM(read_addr,SecAddr); + data_out[7:0] = OutputD; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4 ) + begin + //Read Memory array + if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (pgm_page != read_addr / (PageSize+1)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if ((Instruct == DDRQIOR + || Instruct == DDRQIOR4) && QUAD) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + HOLDNegOut_zd=data_out[7-read_cnt]; + WPNegOut_zd = data_out[7-read_cnt]; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + ReturnSectorID(sect,read_addr); + SecAddr = sect; + READMEM(read_addr,SecAddr); + data_out[7:0] = OutputD; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + HOLDNegOut_zd = 1'bx; + WPNegOut_zd = 1'bx; + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + end + else if (oe_z) + begin + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (falling_edge_write) + begin + if (Instruct == BRWR) + begin + Bank_Addr_reg[7] = Bank_Addr_reg_in[7]; + Bank_Addr_reg[1] = Bank_Addr_reg_in[1]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + end + else if (Instruct == WRR && BAR_ACC == 1) + begin + // Write to the lower address bits of the BAR + if (P_ERR == 0 && E_ERR == 0) + begin + Bank_Addr_reg[1] = Bank_Addr_reg_in[1]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + end + end + else if (Instruct == PGRS) + begin + Status_reg2[0] = 1'b0; + Status_reg1[0] = 1'b1; + PGRES = 1'b1; + PGRES <= #5 1'b0; + RES_TO_SUSP_MIN_TIME = 1'b1; + RES_TO_SUSP_MIN_TIME <= #60000 1'b0;//60 ns + RES_TO_SUSP_TYP_TIME = 1'b1; + RES_TO_SUSP_TYP_TIME <= #100000000 1'b0;//100us + end + + if (Instruct == BRAC && P_ERR == 0 && E_ERR == 0 && + RdPswdProtMode == 0) + begin + BAR_ACC = 1; + end + else + begin + BAR_ACC = 0; + end + end + end + + ERS_SUSP_PG_SUSP: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + + if (PRGSUSP_out && PRGSUSP_in) + begin + PRGSUSP_in = 1'b0; + //The RDY/BSY bit in the Status Register will indicate that + //the device is ready for another operation. + Status_reg1[0] = 1'b0; + //The Program Suspend (PS) bit in the Status Register will + //be set to the logical “1” state to indicate that the + //program operation has been suspended. + Status_reg2[0] = 1'b1; + end + + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == BRRD) + begin + //Read Bank Address Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = Bank_Addr_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + //Read Array Operations + else if (Instruct == READ || Instruct == RD4 || + Instruct == FSTRD || Instruct == FSTRD4 || + Instruct == DDRFR || Instruct == DDRFR4 ) + begin + //Read Memory array + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + if ((SectorSuspend != read_addr/(SecSize+1)) && + (pgm_page != read_addr / (PageSize+1))) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + ReturnSectorID(sect,read_addr); + SecAddr = sect; + READMEM(read_addr,SecAddr); + data_out[7:0] = OutputD; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + + end + end + else + begin + SOut_zd = 8'bxxxxxxxx; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 ) + begin + //Read Memory array + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if ((SectorSuspend != read_addr/(SecSize+1)) && + (pgm_page != read_addr / (PageSize+1))) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + ReturnSectorID(sect,read_addr); + SecAddr = sect; + READMEM(read_addr,SecAddr); + data_out[7:0] = OutputD; + + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4 ) + begin + //Read Memory array + if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if ((SectorSuspend != read_addr/(SecSize+1)) && + (pgm_page != read_addr / (PageSize+1))) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if ((Instruct == DDRQIOR + || Instruct == DDRQIOR4) && QUAD) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + HOLDNegOut_zd =data_out[7-read_cnt]; + WPNegOut_zd = data_out[7-read_cnt]; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + ReturnSectorID(sect,read_addr); + SecAddr = sect; + READMEM(read_addr,SecAddr); + data_out[7:0] = OutputD; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + HOLDNegOut_zd = 1'bx; + WPNegOut_zd = 1'bx; + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + end + else if (oe_z) + begin + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (falling_edge_write) + begin + if (Instruct == BRWR) + begin + Bank_Addr_reg[7] = Bank_Addr_reg_in[7]; + Bank_Addr_reg[1] = Bank_Addr_reg_in[1]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + end + else if (Instruct == WRR && BAR_ACC == 1) + begin + // Write to the lower address bits of the BAR + if (P_ERR == 0 && E_ERR == 0) + begin + Bank_Addr_reg[1] = Bank_Addr_reg_in[1]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + end + end + else if (Instruct == PGRS) + begin + Status_reg2[0] = 1'b0; + Status_reg1[0] = 1'b1; + PGRES = 1'b1; + PGRES <= #5 1'b0; + RES_TO_SUSP_MIN_TIME = 1'b1; + RES_TO_SUSP_MIN_TIME <= #60000 1'b0;//60 ns + RES_TO_SUSP_TYP_TIME = 1'b1; + RES_TO_SUSP_TYP_TIME <= #100000000 1'b0;//100us + end + + if (Instruct == BRAC && P_ERR == 0 && E_ERR == 0 && + RdPswdProtMode == 0) + begin + BAR_ACC = 1; + end + else + begin + BAR_ACC = 0; + end + end + end + + OTP_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == OTP_PG) + begin + if (~PDONE) + begin + if (Address + wr_cnt <= OTPHiAddr) + begin + for (i=0;i<=wr_cnt;i=i+1) + begin + new_int = WData[i]; + old_int = OTPMem[Addr + i]; + if (new_int > -1) + begin + new_bit = new_int; + if (old_int > -1) + begin + old_bit = old_int; + for(j=0;j<=7;j=j+1) + begin + if (~old_bit[j]) + new_bit[j] = 1'b0; + end + new_int = new_bit; + end + WData[i] = new_int; + end + else + begin + WData[i] = -1; + end + OTPMem[Addr + i] = -1; + end + end + else + begin + $display ("Programming will reach over "); + $display ("address limit of OTP array"); + end + end + end + + if (PDONE) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + for (i=0;i<=wr_cnt;i=i+1) + begin + OTPMem[Addr + i] = WData[i]; + end + LOCK_BYTE1 = OTPMem[16]; + LOCK_BYTE2 = OTPMem[17]; + LOCK_BYTE3 = OTPMem[18]; + LOCK_BYTE4 = OTPMem[19]; + end + end + + SECTOR_ERS: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == SECTOR_ERS) + begin + if (~EDONE) + begin + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + memory_features_i0.erase_mem_w( + AddrLo, + AddrHi + ); + corrupt_Sec[SecAddrERS] = 1; + end + end + + if (EDONE == 1) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + corrupt_Sec[SecAddrERS] = 0; + end + else if (Instruct == ERSP && ~ERSSUSP_in) + begin + ESUSP = 1'b1; + ESUSP <= #5 1'b0; + ERSSUSP_in = 1'b1; + if (RES_TO_SUSP_TYP_TIME) + begin + $display("Typical periods are needed for ", + "Program to progress to completion"); + end + end + end + + BULK_ERS: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == BULK_ERS) + begin + if (~EDONE) + begin + for (i=SecNum; i>=0; i=i-1) + begin + if (PPB_bits[i] == 1 && DYB_bits[i] == 1) + begin + memory_features_i0.erase_mem_w( + i*(SecSize+1), + i*(SecSize+1)+SecSize + ); + corrupt_Sec[i] = 1; + end + end + end + end + + if (EDONE == 1) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + for (j=0; j<=SecNum; j=j+1) + if (PPB_bits[j] == 1 && DYB_bits[j] == 1) + begin + corrupt_Sec[j] = 0; + end + end + end + + ERS_SUSP: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (ERSSUSP_out == 1) + begin + ERSSUSP_in = 0; + //The Erase Suspend (ES) bit in the Status Register will + //be set to the logical “1” state to indicate that the + //erase operation has been suspended. + Status_reg2[1] = 1'b1; + //The WIP bit in the Status Register will indicate that + //the device is ready for another operation. + Status_reg1[0] = 1'b0; + end + + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == DYBRD) + begin + //Read DYB Access Register + ReturnSectorID(sect,Address); + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (DYB_bits[sect] == 1) + DYBAR[7:0] = 8'hFF; + else + begin + DYBAR[7:0] = 8'h0; + end + SOut_zd = DYBAR[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == BRRD) + begin + //Read Bank Address Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = Bank_Addr_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == PPBRD) + begin + //Read PPB Access Register + ReturnSectorID(sect,Address); + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + PPBAR[7:0] = 8'bXXXXXXXX; + if (RdPswdProtMode == 0) + begin + if (PPB_bits[sect] == 1) + PPBAR[7:0] = 8'hFF; + else + begin + PPBAR[7:0] = 8'h0; + end + end + SOut_zd = PPBAR[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == READ || Instruct == RD4 || + Instruct == FSTRD || Instruct == FSTRD4 || + Instruct == DDRFR || Instruct == DDRFR4 ) + begin + //Read Memory array + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + if (SectorSuspend != read_addr/(SecSize+1)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + ReturnSectorID(sect,read_addr); + SecAddr = sect; + READMEM(read_addr,SecAddr); + data_out[7:0] = OutputD; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + SOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 ) + begin + //Read Memory array + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (SectorSuspend != read_addr/(SecSize+1)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + ReturnSectorID(sect,read_addr); + SecAddr = sect; + READMEM(read_addr,SecAddr); + data_out[7:0] = OutputD; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4 ) + begin + //Read Memory array + if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (SectorSuspend != read_addr/(SecSize+1)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if ((Instruct == DDRQIOR + || Instruct == DDRQIOR4) && QUAD) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + HOLDNegOut_zd=data_out[7-read_cnt]; + WPNegOut_zd = data_out[7-read_cnt]; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + ReturnSectorID(sect,read_addr); + SecAddr = sect; + READMEM(read_addr,SecAddr); + data_out[7:0] = OutputD; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + HOLDNegOut_zd = 1'bx; + WPNegOut_zd = 1'bx; + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + end + else if (oe_z) + begin + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (falling_edge_write) + begin + if ((Instruct == PP || Instruct == PP4) && WEL == 1) + begin + if (SectorSuspend != Address/(SecSize+1)) + begin + ReturnSectorID(sect,Address); + if (Sec_Prot[sect] == 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 0; + PGRES = 0; + Status_reg1[0] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + end + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + end + end + else if ((Instruct == QPP || Instruct == QPP4) && WEL == 1) + begin + if (SectorSuspend != Address/(SecSize+1)) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + + if (Sec_Prot[sect] == 0 + && PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 0; + PGRES = 0; + Status_reg1[0] = 1'b1; + QPP_page[pgm_page] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + end + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + end + end + else if (Instruct == WREN) + Status_reg1[1] = 1'b1; + else if (Instruct == CLSR) + begin + //The Clear Status Register Command resets bit SR1[5] + //(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + Status_reg1[5] = 0; + Status_reg1[6] = 0; + end + else if (Instruct == BRWR) + begin + Bank_Addr_reg[7] = Bank_Addr_reg_in[7]; + Bank_Addr_reg[1] = Bank_Addr_reg_in[1]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + end + else if (Instruct == WRR && BAR_ACC == 1) + begin + // Write to the lower address bits of the BAR + if (P_ERR == 0 && E_ERR == 0) + begin + Bank_Addr_reg[1] = Bank_Addr_reg_in[1]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + end + end + else if (Instruct == DYBWR && WEL == 1) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == ERRS) + begin + Status_reg2[1] = 1'b0; + Status_reg1[0] = 1'b1; + Addr = SectorSuspend*(SecSize+1); + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + ERES = 1'b1; + ERES <= #5 1'b0; + RES_TO_SUSP_TYP_TIME = 1'b1; + RES_TO_SUSP_TYP_TIME <= #100000000 1'b0;//100us + end + + if (Instruct == BRAC && P_ERR == 0 && E_ERR == 0 && + RdPswdProtMode == 0) + begin + BAR_ACC = 1; + end + else + begin + BAR_ACC = 0; + end + end + end + + ERS_SUSP_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == ERS_SUSP_PG) + begin + if (~PDONE) + begin + ADDRHILO_PG(AddrLo, AddrHi, Addr); + cnt = 0; + for (i=0;i<=wr_cnt;i=i+1) + begin + new_int = WData[i]; + ReturnSectorID(sect,read_addr); + SecAddr = sect; + memory_features_i0.read_mem_w( + mem_data, + Addr + i - cnt + ); + if (corrupt_Sec[SecAddr]) + begin + if (mem_data== MaxData+1) + mem_data = MaxData; + else if (mem_data == MaxData) + mem_data = -1; + end + old_int = mem_data; + if (new_int > -1) + begin + new_bit = new_int; + if (old_int > -1) + begin + old_bit = old_int; + for(j=0;j<=7;j=j+1) + begin + if (~old_bit[j]) + new_bit[j] = 1'b0; + end + new_int = new_bit; + end + WData[i] = new_int; + end + else + begin + WData[i] = -1; + end + + if ((Addr + i) == AddrHi) + begin + Addr = AddrLo; + cnt = i + 1; + end + end + end + cnt =0; + end + + if(PDONE == 1) + begin + Status_reg1[0] = 1'b0;//WIP + Status_reg1[1] = 1'b0;//WEL + for (i=0;i<=wr_cnt;i=i+1) + begin + memory_features_i0.write_mem_w( + Addr_tmp + i -cnt, + WData[i] + ); + if ((Addr_tmp + i) == AddrHi ) + begin + Addr_tmp = AddrLo; + cnt = i + 1; + end + end + end + + if (Instruct) + begin + if (Instruct == PGSP && ~PRGSUSP_in) + begin + if (~RES_TO_SUSP_MIN_TIME) + begin + PGSUSP = 1'b1; + PGSUSP <= #5 1'b0; + PRGSUSP_in = 1'b1; + if (RES_TO_SUSP_TYP_TIME) + begin + $display("Typical periods are needed for ", + "Program to progress to completion"); + end + end + else + begin + $display("Minimum for tPRS is not satisfied! ", + "PGSP command is ignored"); + end + end + end + end + + PASS_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + new_pass = Password_reg_in; + old_pass = Password_reg; + for (i=0;i<=63;i=i+1) + begin + if (old_pass[j] == 0) + new_pass[j] = 0; + end + + if (PDONE == 1) + begin + Password_reg = new_pass; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + PASS_UNLOCK: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PASS_TEMP == Password_reg) + begin + PASS_UNLOCKED = 1'b1; + end + else + begin + PASS_UNLOCKED = 1'b0; + end + if (PASSULCK_out == 1'b1) + begin + if ((PASS_UNLOCKED == 1'b1) && (~PWDMLB)) + begin + PPBL[0] = 1'b1; + Status_reg1[0] = 1'b0; //WIP + end + else + begin + Status_reg1[6] = 1'b1; + $display ("Incorrect Password"); + PASSACC_in = 1'b1; + end + Status_reg1[1] = 1'b0; + PASSULCK_in = 1'b0; + end + end + + PPB_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + if (PPB_LOCK !== 0) + begin + PPB_bits[sect]= 1'b0; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + else + begin + Status_reg1[5] = 1'b0; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + end + + PPB_ERS: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PPBERASE_out == 1'b1) + begin + if ((PPB_LOCK !== 0) && PPBOTP) + begin + PPB_bits = {512{1'b1}}; + end + else + begin + Status_reg1[5] = 1'b1; + end + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + PPBERASE_in = 1'b0; + end + end + + AUTOBOOT_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + AutoBoot_reg = AutoBoot_reg_in; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + PLB_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + PPBL[0] = 1'b0; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + DYB_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + DYBAR = DYBAR_in; + if (DYBAR == 8'hFF) + begin + DYB_bits[sect]= 1'b1; + end + else if (DYBAR == 8'h00) + begin + DYB_bits[sect]= 1'b0; + end + else + begin + Status_reg1[6] = 1'b1; + end + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + ASP_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + + if (RPME == 1'b0 && ASP_reg_in[5] == 1'b1) + begin + Status_reg1[6] = 1'b1; //P_ERR + $display("RPME bit is allready programmed"); + end + else + begin + ASP_reg[5] = ASP_reg_in[5];//RPME + end + + if (PPBOTP == 1'b0 && ASP_reg_in[3] == 1'b1) + begin + Status_reg1[6] = 1'b1; //P_ERR + $display("PPBOTP bit is allready programmed"); + end + else + begin + ASP_reg[3] = ASP_reg_in[3];//PPBOTP + end + + if (PWDMLB == 1'b1 && PSTMLB == 1'b1) + begin + if (ASP_reg_in[2] == 1'b0 && ASP_reg_in[1] == 1'b0) + begin + $display("ASPR[2:1] = 00 Illegal condition"); + Status_reg1[6] = 1'b1; //P_ERR + end + else + begin + if (ASP_reg_in[2]!==1'b1 || ASP_reg_in[1]!==1'b1) + begin + ASPOTPFLAG = 1'b1; + end + ASP_reg[2] = ASP_reg_in[2];//PWDMLB + ASP_reg[1] = ASP_reg_in[1];//PSTMLB + end + end + + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + NVDLR_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + if (NVDLR_reg == 0) + begin + NVDLR_reg = NVDLR_reg_in; + VDLR_reg = NVDLR_reg_in; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + else + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; //P_ERR + $display("NVDLR bits allready programmed"); + end + end + end + + RESET_STATE: + begin + //the default condition hardware reset + //The Bank Address Register is loaded to all zeroes + Bank_Addr_reg = 8'h0; + if (BPNV && ~LOCK && ~FREEZE) + begin + Status_reg1[2] = 1'b1;// BP0 + Status_reg1[3] = 1'b1;// BP1 + Status_reg1[4] = 1'b1;// BP2 + BP_bits = 3'b111; + change_BP = 1'b1; + #1000 change_BP = 1'b0; + end + //Resets the volatile bits in the Status register 1 + Status_reg1[6] = 1'b0; + Status_reg1[5] = 1'b0; + Status_reg1[1] = 1'b0; + Status_reg1[0] = 1'b0; + //Resets the volatile bits in the Status register 2 + Status_reg2[1] = 1'b0; + Status_reg2[0] = 1'b0; + //Resets the volatile bits in the Configuration register 1 + Config_reg1[0] = 1'b0; + //On reset cycles the data pattern reverts back + //to what is in the NVDLR + VDLR_reg = NVDLR_reg; + dlp_act = 1'b0; + //Loads the Program Buffer with all ones + for(i=0;i<=511;i=i+1) + begin + WData[i] = MaxData; + end + if (~PWDMLB) + PPBL[0] = 1'b0; + else + PPBL[0] = 1'b1; + end + + endcase + + //Output Disable Control + if (CSNeg_ipd ) + begin + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + end + end + + assign fast_rd = rd_fast; + assign rd = rd_slow; + assign ddrd = ddr; + assign fast_ddr = ddr_fast; + + always @(posedge change_BP) + begin + case (Status_reg1[4:2]) + + 3'b000: + begin + Sec_Prot = 256'b0; + end + + 3'b001: + begin + if (~TBPROT) + begin + Sec_Prot[SecNum:(SecNum+1)*63/64] = 4'b1111; + Sec_Prot[(SecNum+1)*63/64-1 : 0] = 252'h0; + end + else + begin + Sec_Prot[(SecNum+1)/64-1 : 0] = 4'b1111; + Sec_Prot[SecNum : (SecNum+1)/64] = 252'h0; + end + end + + 3'b010: + begin + if (~TBPROT) + begin + Sec_Prot[SecNum : (SecNum+1)*31/32] = 8'b11111111; + Sec_Prot[(SecNum+1)*31/32-1 : 0] = 248'h0; + end + else + begin + Sec_Prot[(SecNum+1)/32-1 : 0] = 8'b11111111; + Sec_Prot[SecNum : (SecNum+1)/32] = 248'h0; + end + end + + 3'b011: + begin + if (~TBPROT) + begin + Sec_Prot[SecNum : (SecNum+1)*15/16] = 16'hFFFF; + Sec_Prot[(SecNum+1)*15/16-1 : 0] = 240'h0; + end + else + begin + Sec_Prot[(SecNum+1)/16-1 : 0] = 16'hFFFF; + Sec_Prot[SecNum : (SecNum+1)/16] = 240'h0; + end + end + + 3'b100: + begin + if (~TBPROT) + begin + Sec_Prot[SecNum : (SecNum+1)*7/8] = 32'hFFFFFFFF; + Sec_Prot[(SecNum+1)*7/8-1 : 0] = 224'h0; + end + else + begin + Sec_Prot[(SecNum+1)/8-1 : 0] = 32'hFFFFFFFF; + Sec_Prot[SecNum : (SecNum+1)/8] = 224'h0; + end + end + + 3'b101: + begin + if (~TBPROT) + begin + Sec_Prot[SecNum : (SecNum+1)*3/4] + = 64'hFFFFFFFFFFFFFFFF; + Sec_Prot[(SecNum+1)*3/4-1 : 0] = 192'h0; + end + else + begin + Sec_Prot[(SecNum+1)/4-1 : 0] = 64'hFFFFFFFFFFFFFFFF; + Sec_Prot[SecNum : (SecNum+1)/4] = 192'h0; + end + end + + 3'b110: + begin + if (~TBPROT) + begin + Sec_Prot[SecNum : (SecNum+1)/2] + = 128'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + Sec_Prot[(SecNum+1)/2-1 : 0] = 128'h0; + end + else + begin + Sec_Prot[(SecNum+1)/2-1 : 0] + = 128'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + Sec_Prot[SecNum : (SecNum+1)/2] = 128'h0; + end + end + + 3'b111: + begin + Sec_Prot[127:0] = 128'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + Sec_Prot[255:128] = 128'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + end + endcase + end + + always @(SOut_zd or HOLDNeg_in or SIOut_zd) + begin + if (HOLDNeg_in == 0 && ~QUAD) + begin + hold_mode = 1'b1; + SIOut_z = 1'bZ; + SOut_z = 1'bZ; + end + else + begin + if (hold_mode == 1) + begin + SIOut_z <= #(tpd_HOLDNeg_SO) SIOut_zd; + SOut_z <= #(tpd_HOLDNeg_SO) SOut_zd; + hold_mode = #(tpd_HOLDNeg_SO) 1'b0; + end + else + begin + SIOut_z = SIOut_zd; + SOut_z = SOut_zd; + hold_mode = 1'b0; + end + end + end + + //////////////////////////////////////////////////////////////////////// + // autoboot control logic + //////////////////////////////////////////////////////////////////////// + always @(rising_edge_SCK_ipd or current_state_event) + begin + if(current_state == AUTOBOOT) + begin + if (rising_edge_SCK_ipd) + begin + if (start_delay > 0) + start_delay = start_delay - 1; + end + + if (start_delay == 0) + begin + start_autoboot = 1; + end + end + end + //////////////////////////////////////////////////////////////////////// + // functions & tasks + //////////////////////////////////////////////////////////////////////// + // Procedure FDDR_DPL + task Return_DLP; + input integer Instruct; + input integer EHP; + input integer Latency_code; + input integer dummy_cnt; + inout dlp_act; + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + if (EHP) + begin + if (Latency_code == 1) + dlp_act = 1'b1; + else if (Latency_code == 2 && dummy_cnt >= 1) + dlp_act = 1'b1; + else if(Latency_code == 3 || Latency_code == 0) + begin + dlp_act = 1'b0; + $display("Warning at", $time); + $display("Inappropriate latency is set during DPL mode"); + end + end + else + begin + if (Latency_code == 3) + dlp_act = 1'b1; + else if (Latency_code == 0 && dummy_cnt >= 1) + dlp_act = 1'b1; + else if(Latency_code == 1 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if(Latency_code == 2 && dummy_cnt >= 3) + dlp_act = 1'b1; + end + end + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + if (EHP) + begin + if (Latency_code == 1 && dummy_cnt >= 1) + dlp_act = 1'b1; + else if (Latency_code == 2 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if( Latency_code == 3 || Latency_code == 0) + begin + dlp_act = 1'b0; + $display("Warning at", $time); + $display("Inappropriate latency is set during DPL mode"); + end + end + else + begin + if (Latency_code == 3) + dlp_act = 1'b0; + else if (Latency_code == 0 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if (Latency_code == 1 && dummy_cnt >= 3) + dlp_act = 1'b1; + else if(Latency_code == 2 && dummy_cnt >= 4) + dlp_act = 1'b1; + end + end + if ((Instruct == DDRQIOR || Instruct == DDRQIOR4) && QUAD) + begin + if (EHP) + begin + if (Latency_code == 0 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if (Latency_code == 1 && dummy_cnt >= 3) + dlp_act = 1'b1; + else if (Latency_code == 2 && dummy_cnt >= 4) + dlp_act = 1'b1; + else if( Latency_code == 3) + begin + dlp_act = 1'b0; + $display("Warning at", $time); + $display("Inappropriate latency is"); + $display("set during DPL mode"); + end + end + else + begin + if (Latency_code == 0 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if (Latency_code == 1 && dummy_cnt >= 3) + dlp_act = 1'b1; + else if (Latency_code == 2 && dummy_cnt >= 4) + dlp_act = 1'b1; + else if( Latency_code == 3) + begin + dlp_act = 1'b0; + $display("Warning at", $time); + $display("Inappropriate latency is"); + $display("set during DPL mode"); + end + end + end + end + endtask + + task READMEM; + input integer Address; + input integer SecAddr; + reg [15:0] ReadData; + begin + memory_features_i0.read_mem_w( + mem_data, + Address); + if (mem_data != -1) + begin + if (corrupt_Sec[SecAddr] == 1) + begin + if (mem_data == MaxData) + ReadData = 8'hx; + else if (mem_data == MaxData+1) + begin + mem_data = MaxData; + ReadData = mem_data; + end + else + ReadData = mem_data; + end + else + ReadData = mem_data; + end + else + ReadData = 8'bx; + + OutputD = ReadData; + end + endtask + + function integer ReturnSectorIDRdPswdMd; + input reg TBPROT; + begin + if(TBPROT == 0) + begin + ReturnSectorIDRdPswdMd = 0; + end + else + begin + ReturnSectorIDRdPswdMd = SecNum; + end + end + endfunction + + // Procedure ADDRHILO_SEC + task ADDRHILO_SEC; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer sector; + begin + sector = Addr/(SecSize+1); + AddrLOW = sector*(SecSize+1); + AddrHIGH = sector*(SecSize+1) + SecSize; + end + endtask + + // Procedure ADDRHILO_PG + task ADDRHILO_PG; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer page; + begin + page = Addr / (PageSize + 1); + AddrLOW = page * (PageSize + 1); + AddrHIGH = page * (PageSize + 1) + PageSize; + end + endtask + + // Procedure ReturnSectorID + task ReturnSectorID; + inout sect; + input Address; + integer sect; + integer Address; + integer conv; + begin + sect = Address/(SecSize+1); + end + endtask + + always @(PPBL[0], ASP_reg) + begin + if (PPBL[0] == 0 && PWDMLB == 0 && RPME == 0 && RdPswdProtEnable) + begin + RdPswdProtMode = 1; + AutoBoot_reg[0] = 0;//AUTOBOOT is disabled when Read Password + end //Protection is enabled + else + begin + RdPswdProtMode = 0; + end + end + + /////////////////////////////////////////////////////////////////////////// + // edge controll processes + /////////////////////////////////////////////////////////////////////////// + + always @(posedge PoweredUp) + begin + rising_edge_PoweredUp = 1; + #1000 rising_edge_PoweredUp = 0; + end + + always @(posedge SCK_ipd) + begin + rising_edge_SCK_ipd = 1'b1; + #1000 rising_edge_SCK_ipd = 1'b0; + end + + always @(negedge SCK_ipd) + begin + falling_edge_SCK_ipd = 1'b1; + #1000 falling_edge_SCK_ipd = 1'b0; + end + + always @(posedge read_out) + begin + rising_edge_read_out = 1'b1; + #1000 rising_edge_read_out = 1'b0; + end + + always @(negedge write) + begin + falling_edge_write = 1; + #1000 falling_edge_write = 0; + end + + always @(posedge PRGSUSP_out) + begin + PRGSUSP_out_event = 1; + #1000 PRGSUSP_out_event = 0; + end + + always @(posedge ERSSUSP_out) + begin + ERSSUSP_out_event = 1; + #1000 ERSSUSP_out_event = 0; + end + + always @(posedge CSNeg_ipd) + begin + rising_edge_CSNeg_ipd = 1'b1; + #1000 rising_edge_CSNeg_ipd = 1'b0; + end + + always @(negedge CSNeg_ipd) + begin + falling_edge_CSNeg_ipd = 1'b1; + #1000 falling_edge_CSNeg_ipd = 1'b0; + end + + always @(negedge RSTNeg_in) + begin + falling_edge_RSTNeg = 1'b1; + #50000 falling_edge_RSTNeg = 1'b0; + end + + always @(posedge RSTNeg_in) + begin + rising_edge_RSTNeg = 1'b1; + #10000 rising_edge_RSTNeg = 1'b0; + end + + always @(negedge RST) + begin + falling_edge_RST = 1'b1; + #10000 falling_edge_RST = 1'b0; + end + + always @(posedge RST) + begin + rising_edge_RST = 1'b1; + #1000 rising_edge_RST = 1'b0; + end + + always @(posedge PDONE) + begin + rising_edge_PDONE = 1'b1; + #1000 rising_edge_PDONE = 1'b0; + end + + always @(posedge WDONE) + begin + rising_edge_WDONE = 1'b1; + #1000 rising_edge_WDONE = 1'b0; + end + + always @(posedge WSTART) + begin + rising_edge_WSTART = 1'b1; + #1000 rising_edge_WSTART = 1'b0; + end + + always @(posedge EDONE) + begin + rising_edge_EDONE = 1'b1; + #1000 rising_edge_EDONE = 1'b0; + end + + always @(posedge ESTART) + begin + rising_edge_ESTART = 1'b1; + #1000 rising_edge_ESTART = 1'b0; + end + + always @(posedge PSTART) + begin + rising_edge_PSTART = 1'b1; + #1000 rising_edge_PSTART = 1'b0; + end + + always @(posedge Reseted) + begin + rising_edge_Reseted = 1'b1; + #1000 rising_edge_Reseted = 1'b0; + end + + always @(negedge PASSULCK_in) + begin + falling_edge_PASSULCK_in = 1'b1; + #1000 falling_edge_PASSULCK_in = 1'b0; + end + + always @(negedge PPBERASE_in) + begin + falling_edge_PPBERASE_in = 1'b1; + #1000 falling_edge_PPBERASE_in = 1'b0; + end + + always @(Instruct) + begin + Instruct_event = 1'b1; + #1000 Instruct_event = 1'b0; + end + + always @(change_addr) + begin + change_addr_event = 1'b1; + #1000 change_addr_event = 1'b0; + end + + always @(next_state) + begin + next_state_event = 1'b1; + #1000 next_state_event = 1'b0; + end + + always @(current_state) + begin + current_state_event = 1'b1; + #1000 current_state_event = 1'b0; + end + + always @(posedge RST_out) + begin + rising_edge_RST_out = 1'b1; + #1000 rising_edge_RST_out = 1'b0; + end + +endmodule +module memory_features(); +// ------------------------------------------------------------------------ +// ---------------- start of memory management section -------------- +// ------------------------------------------------------------------------ + + // memory partitioning parameters + parameter list_num = 256; + parameter list_size = 20'h40000; + // memory initial data value + parameter MaxData = 8'hFF; + + // memory management routines + // handle dynamic memory allocation + + // abstract memory region model + class linked_list_c; + // memory element model + reg[31:0] key_address; + integer val_data; + // organize memory storage elements into a linked list + linked_list_c successor; + + function new( + integer address_a, + integer data_a); + begin + key_address = address_a; + val_data = data_a; + successor = null; + end + endfunction + endclass + + // partition memory region for faster access + linked_list_c linked_list [list_num]; + // class methods internal communication pool + linked_list_c found; + linked_list_c prev; + linked_list_c sub_linked_list; + linked_list_c sub_linked_list_last; + + // low-level routines + class low_level_interface_c; + + // assure proper initialization + function new; + integer new_iter; + begin + // initialize linked list handles + for(new_iter=0; new_iter < list_num; new_iter = new_iter + 1) + linked_list[new_iter] = null; + found = null; + prev = null; + sub_linked_list = null; + sub_linked_list_last = null; + end + endfunction + + // Iterate through linked listed comapring key values + // Stop when key value greater or equal + task position_list( + input integer address_a, + input linked_list_c root); + begin + found = root; + prev = null; + while ((found != null) && (found.key_address < address_a)) + begin + prev = found; + found = found.successor; + end + end + endtask + + // Add new element to a linked list + task insert_list( + input integer address_a, + input integer data_a, + input integer list_id); + + linked_list_c new_element; + begin + this.position_list( + address_a, + linked_list[list_id]); + + // Insert at list tail + if (found == null) + begin + prev.successor = new(address_a, data_a); + end + else + begin + // Element exists, update memory data value + if (found.key_address == address_a) + begin + found.val_data = data_a; + end + else + begin + // No element found, allocate and link + new_element = new(address_a, data_a); + new_element.successor = found; + // Possible root position + if (prev != null) + begin + prev.successor = new_element; + end + else + begin + linked_list[list_id] = new_element; + end + end + end + end + endtask + + // Remove element from a linked list + task remove_list( + input integer address_a, + input integer list_id); + + begin + this.position_list( + address_a, + linked_list[list_id]); + + if (found != null) + // Key value match + if (found.key_address == address_a) + begin + // Handle root position removal + if (prev != null) + prev.successor = found.successor; + else + linked_list[list_id] = found.successor; + // garbage collector + found = null; + end + end + endtask + + // Remove range of elements from a linked list + // Higher performance than one-by-one removal + task remove_list_range( + input integer address_low, + input integer address_high, + input integer list_id); + linked_list_c iter; + linked_list_c prev_remove; + linked_list_c link_element; + integer flag_test; + begin + iter = linked_list[list_id]; + prev_remove = null; + flag_test = 1; + // Find first linked list element belonging to + // a specified address range [address_low, address_high] + if (iter != null) + while (flag_test == 1) + if (iter == null) + flag_test = 0; + else if (!((iter.key_address >= address_low) && + (iter.key_address <= address_high))) + begin + prev_remove = iter; + iter = iter.successor; + end + else + flag_test = 0; + // Continue until address_high reached + // Deallocate linked list elements pointed by iterator + if (iter != null) + begin + while ((iter != null) && + (iter.key_address >= address_low) && + (iter.key_address <= address_high)) + begin + link_element = iter.successor; + //garbage collector + iter.successor = null; + iter = link_element; + end + // Handle possible root value change + if ( prev_remove != null ) + prev_remove.successor = link_element; + else + linked_list[list_id] = link_element; + end + end + endtask + + endclass + + // higher-level routines + // provided memory RW operation class interface + class rw_interface_c; + + low_level_interface_c low_level_interface; + + // assure proper initialization + function new; + integer new_iter; + begin + // allocate low level interface object + low_level_interface = new; + end + endfunction + + task read_mem( + inout integer data_a, + input integer address_a); + + integer mem_data; + integer list_id; + begin + // Higher performance, segment paritioning + list_id = address_a / list_size; + if (linked_list[list_id] == null) + // Not allocated, not written, initial value + mem_data = MaxData; + else + begin + low_level_interface.position_list( + address_a, + linked_list[list_id]); + if (found != null) + begin + if (found.key_address == address_a) + // Allocated, val_data stored + mem_data = found.val_data; + else + // Not allocated, not written, initial value + mem_data = MaxData; + end + else + begin + // Not allocated, not written, initial value + mem_data = MaxData; + end + end + data_a = mem_data; + end + endtask + + // Memory WRITE operation performed above dynamically allocated space + task write_mem( + input integer address_a, + input integer data_a); + + integer list_id; + begin + // Higher performance, segment paritioning + list_id = address_a / list_size; + if (data_a !== MaxData) + begin + // Handle possible root value update + if (linked_list[list_id] !== null) + begin + low_level_interface.insert_list( + address_a, + data_a, + list_id); + end + else + begin + linked_list[list_id] = + new(address_a, data_a); + end + end + else + begin + // Deallocate if initial value written + // No linked list, NOP, initial value implicit + if (linked_list[list_id] !== null) + begin + low_level_interface.remove_list( + address_a, + list_id); + end + end + end + endtask + + // Address range to be erased + task erase_mem( + input integer address_low, + input integer address_high); + + integer list_id; + begin + list_id = address_low / list_size; + + low_level_interface.remove_list_range( + address_low, + address_high, + list_id + ); + end + endtask + + endclass + + // object declaration holding memory management model + rw_interface_c rw_interface; + + //interface towards higher hierarchy instances routine calls + //wrapped from within the memory_features module + //low-level routine access forbidden + task initialize_w; + begin + rw_interface = new; + end + endtask + + task read_mem_w( + inout integer data_a, + input integer address_a); + begin + rw_interface.read_mem(data_a, address_a); + end + endtask + + task write_mem_w( + input integer address_a, + input integer data_a); + begin + rw_interface.write_mem(address_a, data_a); + end + endtask + + task erase_mem_w( + input integer address_low, + input integer address_high); + begin + rw_interface.erase_mem(address_low, address_high); + end + endtask +endmodule \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl512s/model/s25fl512s.v b/lib/models/memory/flash/serial/S25fl512s/model/s25fl512s.v new file mode 100644 index 0000000..d4a8250 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl512s/model/s25fl512s.v @@ -0,0 +1,7523 @@ +/////////////////////////////////////////////////////////////////////////////// +// File name : s25fl512s.v +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2011 Spansion, LLC. +// +// MODIFICATION HISTORY : +// +// version: | author: | mod date: | changes made: +// V1.0 V.Mancev 19 Nov 09 Initial +// R.Prokopovic +// V1.1 V.Mancev 04 Mar 10 addr_cnt for second read in +// high performance read continuous +// mode can change its value only +// when CSNeg = '0' +// V1.2 V.Mancev 23 Mar 10 During read operations read_out +// signal changes its value in +// shorter interval +// V1.3 V.Mancev 12 Apr 10 HOLD mode corrected +// Condition for PP operation +// corrected +// V1.4 V.Mancev 20 May 10 SRWD bit assignment is corrected +// Condition for WRR command in +// write_cycle _decode section is +// corrected +// Blocking assignments for signals +// WSTART and PSTART are replaced +// with nonblocking assignments +// Conditions in Page Program +// section are fixed +// V1.5 V.Mancev 25 May 10 Conditions in programming +// sections are fixed +// Timing control sections for +// Program and Erase operation are +// changed +// V1.6 V.Mancev 03 June 10 bus_cycle_state section for +// PGSP command is fixed +// V1.7 V.Mancev 28 July 10 During the QUAD mode HOLD# input +// is not monitored for its normal +// function +// write cycle decode section is +// changed +// V1.8 B.Colakovic 24 Aug 10 All redundant signals are +// removed from BusCycle process +// V1.9 V.Mancev 05 Nov 10 Latest datasheet aligned +// B.Colakovic +// V2.0 H.Dimitrijevic 15 Nov 10 QUAD Program operation during +// Erase Suspend is added. +// Warning for Resume to Suspend +// time is added. +// During Erase Suspend, after +// Program operation is completed, +// WEL bit is cleared. +// Implemetation of Software Reset +// is Changed. +// V2.1 S.Petrovic 18 Apr 11 Corrected timing in always block +// that generates +// rising_edge_CSNeg_ipd +// V2.2 V.Mancev 11 July 11 Latest datasheet aligned +// B.Colakovic +// V2.3 B.Colakovic 15 July 11 Optimization issue is fixed +// V2.4 V.Mancev 22 July 11 Timing check issue is fixed +// B.Colakovic +// V2.5 V. Mancev 18 Nov 11 Time tHO is changed to 1 ns +// (customer's request) +// BRWR instruction is corrected +// V2.6 S.Petrovic 02 Jun 12 QPP Instruction is allowed on +// previously programmed page +/////////////////////////////////////////////////////////////////////////////// +// PART DESCRIPTION: +// +// Library: FLASH +// Technology: FLASH MEMORY +// Part: S25FL512S +// +// Description: 512 Megabit Serial Flash Memory +// +////////////////////////////////////////////////////////////////////////////// +// Comments : +// For correct simulation, simulator resolution should be set to 1 ps +// A device ordering (trim) option determines whether a feature is enabled +// or not, or provide relevant parameters: +// -15th character in TimingModel determines if enhanced high +// performance option is available +// (0,2,3,R,A,B,C,D) EHPLC +// (Y,Z,S,T,K,L) Security EHPLC +// (4,6,7,8,9,Q) HPLC +// -15th character in TimingModel determines if RESET# input +// is available +// (R,A,B,C,D,Q.6,7,K,L,S,T,M,N,U,V) RESET# is available +// (0,2,3,4,8,9,Y.Z.W,X) RESET# is tied to the inactive +// state,inside the package. +////////////////////////////////////////////////////////////////////////////// +// Known Bugs: +// +////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// MODULE DECLARATION // +////////////////////////////////////////////////////////////////////////////// +`timescale 1 ps/1 ps + +module s25fl512s + ( + // Data Inputs/Outputs + SI , + SO , + // Controls + SCK , + CSNeg , + RSTNeg , + WPNeg , + HOLDNeg + +); + +/////////////////////////////////////////////////////////////////////////////// +// Port / Part Pin Declarations +/////////////////////////////////////////////////////////////////////////////// + + inout SI ; + inout SO ; + + input SCK ; + input CSNeg ; + input RSTNeg ; + inout HOLDNeg ; + inout WPNeg ; + + // interconnect path delay signals + wire SCK_ipd ; + wire SI_ipd ; + wire SO_ipd ; + + wire SI_in ; + assign SI_in = SI_ipd ; + + wire SI_out ; + assign SI_out = SI ; + + wire SO_in ; + assign SO_in = SO_ipd ; + + wire SO_out ; + assign SO_out = SO ; + + wire CSNeg_ipd ; + wire HOLDNeg_ipd ; + wire WPNeg_ipd ; + wire RSTNeg_ipd ; + + wire HOLDNeg_in ; + //Internal pull-up + assign HOLDNeg_in = (HOLDNeg_ipd === 1'bx) ? 1'b1 : HOLDNeg_ipd; + + wire HOLDNeg_out ; + assign HOLDNeg_out = HOLDNeg ; + + wire WPNeg_in ; + //Internal pull-up + assign WPNeg_in = (WPNeg_ipd === 1'bx) ? 1'b1 : WPNeg_ipd; + + wire WPNeg_out ; + assign WPNeg_out = WPNeg ; + + wire RSTNeg_in ; + //Internal pull-up + assign RSTNeg_in = (RSTNeg_ipd === 1'bx) ? 1'b1 : RSTNeg_ipd; + + // internal delays + reg PP_in ; + reg PP_out ; + reg BP_in ; + reg BP_out ; + reg SE_in ; + reg SE_out ; + reg BE_in ; + reg BE_out ; + reg WRR_in ; + reg WRR_out ; + reg ERSSUSP_in ; + reg ERSSUSP_out ; + reg PRGSUSP_in ; + reg PRGSUSP_out ; + reg PU_in ; + reg PU_out ; + reg RST_in ; + reg RST_out ; + reg PPBERASE_in ; + reg PPBERASE_out; + reg PASSULCK_in ; + reg PASSULCK_out; + reg PASSACC_in ; + reg PASSACC_out; + + // event control registers + reg PRGSUSP_out_event; + reg ERSSUSP_out_event; + reg Reseted_event; + reg SCK_ipd_event; + reg next_state_event; + + reg rising_edge_PoweredUp; + reg rising_edge_Reseted; + reg rising_edge_PASSULCK_in; + reg rising_edge_RES_out; + reg rising_edge_PSTART; + reg rising_edge_WSTART; + reg rising_edge_ESTART; + reg rising_edge_RSTNeg; + reg rising_edge_RST; + reg falling_edge_RSTNeg; + reg falling_edge_RST; + reg rising_edge_RST_out; + reg rising_edge_CSNeg_ipd = 1'b0; + reg falling_edge_CSNeg_ipd = 1'b0; + reg rising_edge_SCK_ipd = 1'b0; + reg falling_edge_SCK_ipd = 1'b0; + + reg RST ; + + reg SOut_zd = 1'bZ ; + reg SOut_z = 1'bZ ; + + wire SI_z ; + wire SO_z ; + + reg SIOut_zd = 1'bZ ; + reg SIOut_z = 1'bZ ; + + reg WPNegOut_zd = 1'bZ ; + reg HOLDNegOut_zd = 1'bZ ; + + assign SI_z = SIOut_z; + assign SO_z = SOut_z; + + parameter UserPreload = 1; + parameter mem_file_name = "none";//"s25fl512s.mem"; + parameter otp_file_name = "s25fl512sOTP.mem";//"none"; + + parameter TimingModel = "DefaultTimingModel"; + + parameter PartID = "s25fl512s"; + parameter MaxData = 255; + parameter MemSize = 28'h3FFFFFF; + parameter SecSize = 20'h3FFFF; + parameter SecNum = 255; + parameter PageNum = 17'h1FFFF; + parameter AddrRANGE = 28'h3FFFFFF; + parameter HiAddrBit = 31; + parameter OTPSize = 1023; + parameter OTPLoAddr = 12'h000; + parameter OTPHiAddr = 12'h3FF; + parameter BYTE = 8; + + // Manufacturer Identification + parameter Manuf_ID = 8'h01; + parameter DeviceID = 8'h19; + // Electronic Signature + parameter ESignature = 8'h19; + // Device ID + //Manufacturer Identification && Memory Type && Memory Capacity + parameter Jedec_ID = 8'h01; + parameter DeviceID1 = 8'h02; + parameter DeviceID2 = 8'h20; + parameter ExtendedBytes = 8'h4D; + parameter ExtendedID = 8'h00; + parameter DieRev = 8'h00; + parameter MaskRev = 8'h00; + + integer PageSize = 511; + + integer EHP; //Enhanced High Performance Mode active + + integer BAR_ACC = 0; //Bank Register Access active + + //varaibles to resolve architecture used + reg [24*8-1:0] tmp_timing;//stores copy of TimingModel + reg [7:0] tmp_char1;//Define EHPLC or HPLC Mode + integer found = 1'b0; + + // If speedsimulation is needed uncomment following line + +// `define SPEEDSIM; + + // powerup + reg PoweredUp; + + // FSM control signals + reg PDONE ; + reg PSTART ; + reg PGSUSP ; + reg PGRES ; + + reg RES_TO_SUSP_MIN_TIME; + reg RES_TO_SUSP_TYP_TIME; + + reg WDONE ; + reg WSTART ; + + reg EDONE ; + reg ESTART ; + reg ESUSP ; + reg ERES ; + + reg Reseted ; + + // Lock Bit is enabled for customer programming + reg WRLOCKENABLE = 1'b1; + // Flag that mark if ASP Register is allready programmed + reg ASPOTPFLAG = 1'b0; + + //Flag for Password unlock command + reg PASS_UNLOCKED = 1'b0; + reg [63:0] PASS_TEMP = 64'hFFFFFFFFFFFFFFFF; + + reg QUADRD = 1'b0; + reg INITIAL_CONFIG = 1'b0; + reg CHECK_FREQ = 1'b0; + + // Programming buffer + integer WByte[0:511]; + // CFI array + integer CFI_array[8'h00:8'h50]; + // OTP Memory Array + integer OTPMem[OTPLoAddr:OTPHiAddr]; + // Flash Memory Array + integer Mem[0:AddrRANGE]; + + // Registers + // VDLR Register + reg[7:0] VDLR_reg = 8'h00; + reg[7:0] VDLR_reg_in = 8'h00; + // NVDLR Register + reg[7:0] NVDLR_reg = 8'h00; + reg[7:0] NVDLR_reg_in = 8'h00; + reg dlp_act = 1'b0; + + // Status Register 1 + reg[7:0] Status_reg1 = 8'h00; + reg[7:0] Status_reg1_in = 8'h00; + + wire SRWD ; + wire P_ERR; + wire E_ERR; + wire [2:0]BP; + wire WEL; + wire WIP; + assign SRWD = Status_reg1[7]; + assign P_ERR = Status_reg1[6]; + assign E_ERR = Status_reg1[5]; + assign BP = Status_reg1[4:2]; + assign WEL = Status_reg1[1]; + assign WIP = Status_reg1[0]; + + // Status Register 2 + reg[7:0] Status_reg2 = 8'h00; + reg[7:0] Status_reg2_in = 8'h00; + + wire ES ; + wire PS ; + assign ES = Status_reg2[1]; + assign PS = Status_reg2[0]; + + // Configuration Register 1 + reg[7:0] Config_reg1 = 8'h00; + reg[7:0] Config_reg1_in = 8'h00; + + wire LC1 ; + wire LC0 ; + wire TBPROT ; + wire LOCK ; + wire BPNV ; + wire QUAD ; + wire FREEZE ; + assign LC1 = Config_reg1[7]; + assign LC0 = Config_reg1[6]; + assign TBPROT = Config_reg1[5]; + assign LOCK = Config_reg1[4]; + assign BPNV = Config_reg1[3]; + assign QUAD = Config_reg1[1]; + assign FREEZE = Config_reg1[0]; + + // Autoboot Register + reg[31:0] AutoBoot_reg = 32'h00000000; + reg[31:0] AutoBoot_reg_in = 32'h00000000; + + wire ABE; + assign ABE = AutoBoot_reg[0]; + + // Bank Address Register + reg [7:0] Bank_Addr_reg = 8'h00; + reg [7:0] Bank_Addr_reg_in = 8'h00; + + wire EXTADD; + wire BA25; + wire BA24; + + assign EXTADD = Bank_Addr_reg[7]; + assign BA25 = Bank_Addr_reg[1]; + assign BA24 = Bank_Addr_reg[0]; + + // ASP Register + reg[15:0] ASP_reg; + reg[15:0] ASP_reg_in; + + wire RPME ; + wire PPBOTP ; + wire PWDMLB ; + wire PSTMLB ; + assign RPME = ASP_reg[5]; + assign PPBOTP = ASP_reg[3]; + assign PWDMLB = ASP_reg[2]; + assign PSTMLB = ASP_reg[1]; + + // Password register + reg[63:0] Password_reg = 64'hFFFFFFFFFFFFFFFF; + reg[63:0] Password_reg_in = 64'hFFFFFFFFFFFFFFFF; + + // PPB Lock Register + reg[7:0] PPBL = 8'h00; + reg[7:0] PPBL_in = 8'h00; + + wire PPB_LOCK ; + assign PPB_LOCK = PPBL[0]; + + // PPB Access Register + reg[7:0] PPBAR = 8'hFF; + reg[7:0] PPBAR_in = 8'hFF; + + reg[SecNum:0] PPB_bits = {512{1'b1}}; + + // DYB Access Register + reg[7:0] DYBAR = 8'hFF; + reg[7:0] DYBAR_in = 8'hFF; + + reg[SecNum:0] DYB_bits = {512{1'b1}}; + + //The Lock Protection Registers for OTP Memory space + reg[7:0] LOCK_BYTE1; + reg[7:0] LOCK_BYTE2; + reg[7:0] LOCK_BYTE3; + reg[7:0] LOCK_BYTE4; + + // Command Register + reg write; + reg cfg_write; + reg read_out; + reg dual = 1'b0; + reg rd_fast = 1'b1; + reg rd_slow = 1'b0; + reg ddr = 1'b0; + reg ddr_fast = 1'b0; + reg hold_mode = 1'b0; + reg any_read = 1'b0; + reg quad_pg = 1'b0; + + wire rd ; + wire fast_rd ; + wire ddrd ; + wire fast_ddr ; + + wire quadpg ; + assign quadpg = quad_pg; + + wire RD_EQU_1; + assign RD_EQU_1 = any_read; + + wire RD_EQU_0; + assign RD_EQU_0 = ~any_read; + + reg change_BP = 0; + reg [2:0] BP_bits = 3'b0; + + reg DOUBLE = 1'b0; //Double Data Rate (DDR) flag + + reg RdPswdProtMode = 1'b0;//Read Password Protection Mode Active flag + reg RdPswdProtEnable = 1'b0;//Read Password Protection Mode Support flag + + integer Byte_number = 0; + + reg oe = 1'b0; + reg oe_z = 1'b0; + + reg [647:0] CFI_array_tmp ; + reg [7:0] CFI_tmp; + + integer start_delay; + reg start_autoboot; + integer ABSD; + + reg change_addr ; + integer Address = 0; + integer SectorSuspend = 0; + + //Sector and subsector addresses + integer SA = 0; + + // Sector is protect if Sec_Prot(SecNum) = '1' + reg [SecNum:0] Sec_Prot = 512'b0; + + // Page Number for QPP operations + reg[PageNum:0] QPP_page = 0; + + // timing check violation + reg Viol = 1'b0; + + integer WOTPByte; + integer AddrLo; + integer AddrHi; + + reg[7:0] old_bit, new_bit; + integer old_int, new_int; + reg[63:0] old_pass; + reg[63:0] new_pass; + integer wr_cnt; + integer cnt; + + integer read_cnt = 0; + integer byte_cnt = 1; + integer read_addr = 0; + integer read_addr_tmp = 0; + integer Sec_addr = 0; + integer SecAddr = 0; + integer Page_addr = 0; + integer pgm_page = 0; + + reg[7:0] data_out; + reg[647:0] ident_out; + + time SCK_cycle = 0; + time prev_SCK; + time start_ddr; + time out_time; + time SCK_SO_DDR; +/////////////////////////////////////////////////////////////////////////////// +//Interconnect Path Delay Section +/////////////////////////////////////////////////////////////////////////////// + buf (SCK_ipd, SCK); + buf (SI_ipd, SI); + + buf (SO_ipd, SO); + buf (CSNeg_ipd, CSNeg); + buf (HOLDNeg_ipd, HOLDNeg); + buf (WPNeg_ipd, WPNeg); + buf (RSTNeg_ipd, RSTNeg); + +/////////////////////////////////////////////////////////////////////////////// +// Propagation delay Section +/////////////////////////////////////////////////////////////////////////////// + nmos (SI, SI_z , 1); + + nmos (SO, SO_z , 1); + nmos (HOLDNeg, HOLDNegOut_zd , 1); + nmos (WPNeg, WPNegOut_zd , 1); + + wire deg_pin; + wire deg_sin; + wire deg_holdin; + //VHDL VITAL CheckEnable equivalents + wire quad_rd; + assign quad_rd = deg_holdin && ~QUAD && (SIOut_z != 1'bz); + wire wr_prot; + assign wr_prot = SRWD && WEL && ~QUAD; + wire dual_rd; + assign dual_rd = dual ; + wire ddro; + assign ddro = ddr && ~dual ; + wire ddr_rd; + assign ddr_rd = PoweredUp && ddr; + wire sdr_rd; + assign sdr_rd = PoweredUp && ~ddr; + +specify + // tipd delays: interconnect path delays , mapped to input port delays. + // In Verilog is not necessary to declare any tipd_ delay variables, + // they can be taken from SDF file + // With all the other delays real delays would be taken from SDF file + + // tpd delays + specparam tpd_SCK_SO_normal =1; + specparam tpd_CSNeg_SO =1; + specparam tpd_HOLDNeg_SO =1; + specparam tpd_RSTNeg_SO =1; + //DDR operation values + specparam tpd_SCK_SO_DDR =1; + + //tsetup values: setup times + specparam tsetup_CSNeg_SCK =1; + specparam tsetup_SI_SCK_normal =1; + specparam tsetup_WPNeg_CSNeg =1; + specparam tsetup_HOLDNeg_SCK =1; + specparam tsetup_RSTNeg_CSNeg =1; + // DDR operation values + specparam tsetup_SI_SCK_DDR =1; + specparam tsetup_SI_SCK_DDR_fast =1; + specparam tsetup_CSNeg_SCK_DDR =1; + + //thold values: hold times + specparam thold_CSNeg_SCK =1; + specparam thold_SI_SCK_normal =1; + specparam thold_WPNeg_CSNeg =1; + specparam thold_HOLDNeg_SCK =1; + specparam thold_CSNeg_RSTNeg =1; + // DDR operation values + specparam thold_SI_SCK_DDR =1; + specparam thold_SI_SCK_DDR_fast =1; + specparam thold_CSNeg_SCK_DDR =1; + + // tpw values: pulse width + specparam tpw_SCK_serial_posedge =1; + specparam tpw_SCK_dual_posedge =1; + specparam tpw_SCK_fast_posedge =1; + specparam tpw_SCK_quadpg_posedge =1; + specparam tpw_SCK_serial_negedge =1; + specparam tpw_SCK_dual_negedge =1; + specparam tpw_SCK_fast_negedge =1; + specparam tpw_SCK_quadpg_negedge =1; + specparam tpw_CSNeg_read_posedge =1; + specparam tpw_CSNeg_pgers_posedge =1; + specparam tpw_RSTNeg_negedge =1; + specparam tpw_RSTNeg_posedge =1; + // DDR operation values + specparam tpw_SCK_DDR_posedge =1; + specparam tpw_SCK_DDR_negedge =1; + + // tperiod min (calculated as 1/max freq) + specparam tperiod_SCK_serial_rd =1;// 50 MHz + specparam tperiod_SCK_fast_rd =1;//133 MHz + specparam tperiod_SCK_dual_rd =1;//104 MHz + specparam tperiod_SCK_quadpg =1;// 80 MHz + // DDR operation values + specparam tperiod_SCK_DDR_rd =1;// 66 MHz + + `ifdef SPEEDSIM + // Page Program Operation + specparam tdevice_PP_256 = 55e7;//tPP + // Page Program Operation + specparam tdevice_PP_512 = 75e7;//tPP + // Typical Byte Programming Time + specparam tdevice_BP = 4e8;//tBP + // Sector Erase Operation + specparam tdevice_SE = 1875e7;//tSE + // Bulk Erase Operation + specparam tdevice_BE = 460e9;//tBE + // WRR Cycle Time + specparam tdevice_WRR = 2e9;//tW + // Erase Suspend/Erase Resume Time + specparam tdevice_ERSSUSP = 40e6;//tESL + // Program Suspend/Program Resume Time + specparam tdevice_PRGSUSP = 40e6;// + // VCC (min) to CS# Low + specparam tdevice_PU = 3e8;//tPU + // PPB Erase Time + specparam tdevice_PPBERASE = 15e9;// + // Password Unlock Time + specparam tdevice_PASSULCK = 1e6;// + // Password Unlock to Password Unlock Time + specparam tdevice_PASSACC = 100e6; + `else + // Page Program Operation + specparam tdevice_PP_256 = 55e7;//tPP + // Page Program Operation + specparam tdevice_PP_512 = 75e7;//tPP + // Typical Byte Programming Time + specparam tdevice_BP = 4e8;//tBP + // Sector Erase Operation + specparam tdevice_SE = 1875e9;//tSE + // Bulk Erase Operation + specparam tdevice_BE = 460e12;//tBE + // WRR Cycle Time + specparam tdevice_WRR = 2e11;//tW + // Erase Suspend/Erase Resume Time + specparam tdevice_ERSSUSP = 40e6;//tESL + // Program Suspend/Program Resume Time + specparam tdevice_PRGSUSP = 40e6;// + // VCC (min) to CS# Low + specparam tdevice_PU = 3e8;//tPU + // PPB Erase Time + specparam tdevice_PPBERASE = 15e9;// + // Password Unlock Time + specparam tdevice_PASSULCK = 1e6;// + // Password Unlock to Password Unlock Time + specparam tdevice_PASSACC = 100e6; + `endif // SPEEDSIM + +/////////////////////////////////////////////////////////////////////////////// +// Input Port Delays don't require Verilog description +/////////////////////////////////////////////////////////////////////////////// +// Path delays // +/////////////////////////////////////////////////////////////////////////////// + if (~ddr) (SCK => SO) = tpd_SCK_SO_normal; + if (ddr || rd_fast) (SCK => SO) = tpd_SCK_SO_DDR; + + if (~ddr && dual) (SCK => SI) = tpd_SCK_SO_normal; + if ( ddr && dual) (SCK => SI) = tpd_SCK_SO_DDR; + + if (~ddr && QUAD)(SCK => HOLDNeg) = tpd_SCK_SO_normal; + if ( ddr && QUAD)(SCK => HOLDNeg) = tpd_SCK_SO_DDR; + if (~ddr && QUAD)(SCK => WPNeg) = tpd_SCK_SO_normal; + if ( ddr && QUAD)(SCK => WPNeg) = tpd_SCK_SO_DDR; + + if (CSNeg) (CSNeg => SO) = tpd_CSNeg_SO; + if (CSNeg && dual) (CSNeg => SI) = tpd_CSNeg_SO; + + if (CSNeg && QUAD) (CSNeg => HOLDNeg) = tpd_CSNeg_SO; + if (CSNeg && QUAD) (CSNeg => WPNeg) = tpd_CSNeg_SO; + + if (~QUAD) (HOLDNeg => SO) = tpd_HOLDNeg_SO; + if (~QUAD && dual) (HOLDNeg => SI) = tpd_HOLDNeg_SO; + + (RSTNeg => SO) = tpd_RSTNeg_SO; +/////////////////////////////////////////////////////////////////////////////// +// Timing Violation // +/////////////////////////////////////////////////////////////////////////////// + $setup ( CSNeg , posedge SCK &&& sdr_rd, + tsetup_CSNeg_SCK, Viol); + $setup ( CSNeg , posedge SCK &&& ddr_rd, + tsetup_CSNeg_SCK_DDR, Viol); + $setup ( SI , posedge SCK &&& deg_sin, + tsetup_SI_SCK_normal, Viol); + $setup ( WPNeg , negedge CSNeg &&& wr_prot, + tsetup_WPNeg_CSNeg, Viol); + $setup ( HOLDNeg , posedge SCK &&& quad_rd, + tsetup_HOLDNeg_SCK, Viol); + $setup ( SI , posedge SCK &&& ddro, + tsetup_SI_SCK_DDR, Viol); + $setup ( SI , negedge SCK &&& ddro, + tsetup_SI_SCK_DDR, Viol); + + $setup ( RSTNeg , negedge CSNeg, + tsetup_RSTNeg_CSNeg, Viol); + + $hold ( posedge SCK &&& sdr_rd , CSNeg, + thold_CSNeg_SCK, Viol); + $hold ( posedge SCK &&& ddr_rd , CSNeg, + thold_CSNeg_SCK_DDR, Viol); + $hold ( posedge SCK &&& deg_sin , SI , + thold_SI_SCK_normal, Viol); + $hold ( posedge CSNeg &&& wr_prot , WPNeg , + thold_WPNeg_CSNeg, Viol); + $hold ( posedge SCK &&& quad_rd , HOLDNeg , + thold_HOLDNeg_SCK, Viol); + $hold ( posedge SCK &&& ddro , SI, + thold_SI_SCK_DDR, Viol); + $hold ( negedge SCK &&& ddro , SI, + thold_SI_SCK_DDR, Viol); + + $hold ( negedge RSTNeg , CSNeg, + thold_CSNeg_RSTNeg, Viol); + + $width ( posedge SCK &&& rd , tpw_SCK_serial_posedge); + $width ( negedge SCK &&& rd , tpw_SCK_serial_negedge); + $width ( posedge SCK &&& dual_rd , tpw_SCK_dual_posedge); + $width ( negedge SCK &&& dual_rd , tpw_SCK_dual_negedge); + $width ( posedge SCK &&& fast_rd , tpw_SCK_fast_posedge); + $width ( negedge SCK &&& fast_rd , tpw_SCK_fast_negedge); + $width ( posedge SCK &&& ddrd , tpw_SCK_DDR_posedge); + $width ( negedge SCK &&& ddrd , tpw_SCK_DDR_negedge); + $width ( posedge SCK &&& quadpg , tpw_SCK_quadpg_posedge); + $width ( negedge SCK &&& quadpg , tpw_SCK_quadpg_negedge); + + $width ( posedge CSNeg &&& RD_EQU_1, tpw_CSNeg_read_posedge); + $width ( posedge CSNeg &&& RD_EQU_0, tpw_CSNeg_pgers_posedge); + $width ( negedge RSTNeg , tpw_RSTNeg_negedge); + $width ( posedge RSTNeg , tpw_RSTNeg_posedge); + + $period ( posedge SCK &&& rd , tperiod_SCK_serial_rd); + $period ( posedge SCK &&& fast_rd , tperiod_SCK_fast_rd); + $period ( posedge SCK &&& dual_rd , tperiod_SCK_dual_rd); + $period ( posedge SCK &&& quadpg , tperiod_SCK_quadpg); + $period ( posedge SCK &&& ddrd , tperiod_SCK_DDR_rd); + +endspecify + +/////////////////////////////////////////////////////////////////////////////// +// Main Behavior Block // +/////////////////////////////////////////////////////////////////////////////// +// FSM states + parameter IDLE = 5'd0; + parameter RESET_STATE = 5'd1; + parameter AUTOBOOT = 5'd2; + parameter WRITE_SR = 5'd3; + parameter PAGE_PG = 5'd4; + parameter OTP_PG = 5'd5; + parameter PG_SUSP = 5'd6; + parameter SECTOR_ERS = 5'd7; + parameter BULK_ERS = 5'd8; + parameter ERS_SUSP = 5'd9; + parameter ERS_SUSP_PG = 5'd10; + parameter ERS_SUSP_PG_SUSP= 5'd11; + parameter PASS_PG = 5'd12; + parameter PASS_UNLOCK = 5'd13; + parameter PPB_PG = 5'd14; + parameter PPB_ERS = 5'd15; + parameter AUTOBOOT_PG = 5'd16; + parameter ASP_PG = 5'd17; + parameter PLB_PG = 5'd18; + parameter DYB_PG = 5'd19; + parameter NVDLR_PG = 5'd20; + + reg [4:0] current_state; + reg [4:0] next_state; + +// Instruction type + parameter NONE = 7'd0; + parameter WRR = 7'd1; + parameter PP = 7'd2; + parameter READ = 7'd3; + parameter WRDI = 7'd4; + parameter RDSR = 7'd5; + parameter WREN = 7'd6; + parameter RDSR2 = 7'd7; + parameter FSTRD = 7'd8; + parameter FSTRD4 = 7'd9; + parameter DDRFR = 7'd10; + parameter DDRFR4 = 7'd11; + parameter PP4 = 7'd12; + parameter RD4 = 7'd13; + parameter ABRD = 7'd14; + parameter ABWR = 7'd15; + parameter BRRD = 7'd16; + parameter BRWR = 7'd17; + parameter P4E = 7'd18; + parameter P4E4 = 7'd19; + parameter ASPRD = 7'd20; + parameter ASPP = 7'd21; + parameter CLSR = 7'd22; + parameter QPP = 7'd23; + parameter QPP4 = 7'd24; + parameter RDCR = 7'd25; + parameter DOR = 7'd26; + parameter DOR4 = 7'd27; + parameter DLPRD = 7'd28; + parameter OTPP = 7'd29; + parameter PNVDLR = 7'd30; + parameter OTPR = 7'd31; + parameter WVDLR = 7'd32; + parameter BE = 7'd33; + parameter QOR = 7'd34; + parameter QOR4 = 7'd35; + parameter ERSP = 7'd36; + parameter ERRS = 7'd37; + parameter PGSP = 7'd38; + parameter PGRS = 7'd39; + parameter REMS = 7'd40; + parameter RDID = 7'd41; + parameter MPM = 7'd42; + parameter PLBWR = 7'd43; + parameter PLBRD = 7'd44; + parameter RES = 7'd45; + parameter DIOR = 7'd46; + parameter DIOR4 = 7'd47; + parameter DDRDIOR = 7'd48; + parameter DDRDIOR4 = 7'd49; + parameter SE = 7'd50; + parameter SE4 = 7'd51; + parameter DYBRD = 7'd52; + parameter DYBWR = 7'd53; + parameter PPBRD = 7'd54; + parameter PPBP = 7'd55; + parameter PPBERS = 7'd56; + parameter PASSRD = 7'd57; + parameter PASSP = 7'd58; + parameter PASSU = 7'd69; + parameter QIOR = 7'd70; + parameter QIOR4 = 7'd71; + parameter DDRQIOR = 7'd72; + parameter DDRQIOR4 = 7'd73; + parameter RESET = 7'd74; + parameter MBR = 7'd75; + parameter BRAC = 7'd76; + + reg [6:0] Instruct; + +//Bus cycle state + parameter STAND_BY = 3'd0; + parameter OPCODE_BYTE = 3'd1; + parameter ADDRESS_BYTES = 3'd2; + parameter DUMMY_BYTES = 3'd3; + parameter MODE_BYTE = 3'd4; + parameter DATA_BYTES = 3'd5; + + reg [2:0] bus_cycle_state; + + reg deq_pin; + always @(SO_in, SO_z) + begin + if (SO_in==SO_z) + deq_pin=1'b0; + else + deq_pin=1'b1; + end + // check when data is generated from model to avoid setuphold check in + // this occasion + assign deg_pin=deq_pin; + + reg deq_sin; + always @(SI_in, SIOut_z) + begin + if (SI_in==SIOut_z) + deq_sin=1'b0; + else + deq_sin=1'b1; + end + // check when data is generated from model to avoid setuphold check in + // this occasion + assign deg_sin=deq_sin + && (ddr == 1'b0) && (Instruct !== DDRFR) + && (Instruct !== DDRFR4) && (Instruct !== DDRDIOR) + && (Instruct !== DDRDIOR4) && (Instruct !== DDRQIOR) + && (Instruct !== DDRQIOR4) && (SIOut_z != 1'bz); + + reg deq_holdin; + always @(HOLDNeg_ipd, HOLDNegOut_zd) + begin + if (HOLDNeg_ipd==HOLDNegOut_zd) + deq_holdin=1'b0; + else + deq_holdin=1'b1; + end + // check when data is generated from model to avoid setuphold check in + // this occasion + assign deg_holdin=deq_holdin; + + //Power Up time; + initial + begin + PoweredUp = 1'b0; + #tdevice_PU PoweredUp = 1'b1; + end + + initial + begin : Init + write = 1'b0; + cfg_write = 1'b0; + read_out = 1'b0; + Address = 0; + change_addr = 1'b0; + cnt = 0; + RST = 1'b0; + RST_in = 1'b0; + RST_out = 1'b1; + PDONE = 1'b1; + PSTART = 1'b0; + PGSUSP = 1'b0; + PGRES = 1'b0; + PRGSUSP_in = 1'b0; + ERSSUSP_in = 1'b0; + RES_TO_SUSP_MIN_TIME = 1'b0; + RES_TO_SUSP_TYP_TIME = 1'b0; + + EDONE = 1'b1; + ESTART = 1'b0; + ESUSP = 1'b0; + ERES = 1'b0; + + WDONE = 1'b1; + WSTART = 1'b0; + + Reseted = 1'b0; + + Instruct = NONE; + bus_cycle_state = STAND_BY; + current_state = IDLE; + next_state = IDLE; + end + + // initialize memory and load preload files if any + initial + begin: InitMemory + integer i; + + for (i=0;i<=AddrRANGE;i=i+1) + begin + Mem[i] = MaxData; + end + + if ((UserPreload) && !(mem_file_name == "none")) + begin + // Memory Preload + //s25fl512s.mem, memory preload file + // @aaaaaa - stands for address + // dd -
is byte to be written at Mem(aaaaaa++) + // (aaaaaa is incremented at every load) + $readmemh(mem_file_name,Mem); + end + + for (i=OTPLoAddr;i<=OTPHiAddr;i=i+1) + begin + OTPMem[i] = MaxData; + end + + if (UserPreload && !(otp_file_name == "none")) + begin + //s25fl512s_otp memory file + // / - comment + // @aaaaaa - stands for address within last defined + // sector + // dd -
is byte to be written at OTPMem(aaa++) + // (aa is incremented at every load) + // only first 1-4 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + $readmemh(otp_file_name,OTPMem); + end + + LOCK_BYTE1[7:0] = OTPMem[16]; + LOCK_BYTE2[7:0] = OTPMem[17]; + LOCK_BYTE3[7:0] = OTPMem[18]; + LOCK_BYTE4[7:0] = OTPMem[19]; + end + + // initialize memory and load preload files if any + initial + begin: InitTimingModel + integer i; + integer j; + //UNIFORM OR HYBRID arch model is used + //assumptions: + //1. TimingModel has format as S25FL128SXXXXXXXX_X_XXpF + //it is important that 16-th character from first one is "0" or "1" + //2. TimingModel does not have more then 24 characters + tmp_timing = TimingModel;//copy of TimingModel + + i = 23; + while ((i >= 0) && (found != 1'b1))//search for first non null character + begin //i keeps position of first non null character + j = 7; + while ((j >= 0) && (found != 1'b1)) + begin + if (tmp_timing[i*8+j] != 1'd0) + found = 1'b1; + else + j = j-1; + end + i = i - 1; + end + i = i +1; + if (found)//if non null character is found + begin + for (j=0;j<=7;j=j+1) + begin + //EHPLC/HPLC character is 15 + tmp_char1[j] = TimingModel[(i-14)*8+j]; + end + end + if (tmp_char1 == "0" || tmp_char1 == "2" || tmp_char1 == "3" || + tmp_char1 == "R" || tmp_char1 == "A" || tmp_char1 == "B" || + tmp_char1 == "C" || tmp_char1 == "D" || tmp_char1 == "Y" || + tmp_char1 == "Z" || tmp_char1 == "S" || tmp_char1 == "T" || + tmp_char1 == "K" || tmp_char1 == "L") + begin + EHP = 1; + if(tmp_char1 == "Z" || tmp_char1 == "S" || tmp_char1 == "T" || + tmp_char1 == "K" || tmp_char1 == "L" || tmp_char1 == "Y") + begin + RdPswdProtEnable = 1; + end + end + else if (tmp_char1 == "4" || tmp_char1 == "6" || tmp_char1 == "7" || + tmp_char1 == "8" || tmp_char1 == "9" || tmp_char1 == "Q") + begin + EHP = 0; + end + + if (tmp_char1 == "0" || tmp_char1 == "2" || tmp_char1 == "3" || + tmp_char1 == "R" || tmp_char1 == "A" || tmp_char1 == "B" || + tmp_char1 == "C" || tmp_char1 == "D" || tmp_char1 == "4" || + tmp_char1 == "6" || tmp_char1 == "7" || tmp_char1 == "8" || + tmp_char1 == "9" || tmp_char1 == "Q") + begin + ASP_reg = 16'hFE7F; + ASP_reg_in = 16'hFE7F; + end + else if (tmp_char1 == "Y" || tmp_char1 == "Z" || tmp_char1 == "S" || + tmp_char1 == "T" || tmp_char1 == "K" || tmp_char1 == "L") + begin + ASP_reg = 16'hFE4F; + ASP_reg_in = 16'hFE4F; + end + + end + + //CFI + initial + begin: InitCFI + integer i; + integer j; + /////////////////////////////////////////////////////////////////////// + // ID-CFI array data + /////////////////////////////////////////////////////////////////////// + // Manufacturer and Device ID + CFI_array[8'h00] = Jedec_ID; + CFI_array[8'h01] = DeviceID1; + CFI_array[8'h02] = DeviceID2; + CFI_array[8'h03] = 8'h00; + // Uniform 256kB sectors + CFI_array[8'h04] = ExtendedID; + CFI_array[8'h05] = 8'h80; + CFI_array[8'h06] = 8'h00; + CFI_array[8'h07] = 8'h00; + CFI_array[8'h08] = 8'h00; + CFI_array[8'h09] = 8'h00; + CFI_array[8'h0A] = 8'h00; + CFI_array[8'h0B] = 8'h00; + CFI_array[8'h0C] = 8'h00; + CFI_array[8'h0D] = 8'h00; + CFI_array[8'h0E] = 8'h00; + CFI_array[8'h0F] = 8'h00; + // CFI Query Identification String + CFI_array[8'h10] = 8'h51; + CFI_array[8'h11] = 8'h52; + CFI_array[8'h12] = 8'h59; + CFI_array[8'h13] = 8'h02; + CFI_array[8'h14] = 8'h00; + CFI_array[8'h15] = 8'h40; + CFI_array[8'h16] = 8'h00; + CFI_array[8'h17] = 8'h53; + CFI_array[8'h18] = 8'h46; + CFI_array[8'h19] = 8'h51; + CFI_array[8'h1A] = 8'h00; + //CFI system interface string + CFI_array[8'h1B] = 8'h27; + CFI_array[8'h1C] = 8'h36; + CFI_array[8'h1D] = 8'h00; + CFI_array[8'h1E] = 8'h00; + CFI_array[8'h1F] = 8'h06; + //512B page + CFI_array[8'h20] = 8'h09; + // 256kB sector + CFI_array[8'h21] = 8'h09; + CFI_array[8'h22] = 8'h11; + CFI_array[8'h23] = 8'h02; + CFI_array[8'h24] = 8'h02; + CFI_array[8'h25] = 8'h03; + CFI_array[8'h26] = 8'h03; + // Device Geometry Definition(Uniform Sector Devices) + CFI_array[8'h27] = 8'h1A; + CFI_array[8'h28] = 8'h02; + CFI_array[8'h29] = 8'h01; + CFI_array[8'h2A] = 8'h09; + CFI_array[8'h2B] = 8'h00; + CFI_array[8'h2C] = 8'h01; + CFI_array[8'h2D] = 8'hFF; + CFI_array[8'h2E] = 8'h00; + CFI_array[8'h2F] = 8'h00; + CFI_array[8'h30] = 8'h04; + CFI_array[8'h31] = 8'hFF; + CFI_array[8'h32] = 8'hFF; + CFI_array[8'h33] = 8'hFF; + CFI_array[8'h34] = 8'hFF; + CFI_array[8'h35] = 8'hFF; + CFI_array[8'h36] = 8'hFF; + CFI_array[8'h37] = 8'hFF; + CFI_array[8'h38] = 8'hFF; + CFI_array[8'h39] = 8'hFF; + CFI_array[8'h3A] = 8'hFF; + CFI_array[8'h3B] = 8'hFF; + CFI_array[8'h3C] = 8'hFF; + CFI_array[8'h3D] = 8'hFF; + CFI_array[8'h3E] = 8'hFF; + CFI_array[8'h3F] = 8'hFF; + // CFI Primary Vendor-Specific Extended Query + CFI_array[8'h40] = 8'h50; + CFI_array[8'h41] = 8'h52; + CFI_array[8'h42] = 8'h49; + CFI_array[8'h43] = 8'h31; + CFI_array[8'h44] = 8'h33; + CFI_array[8'h45] = 8'h21; + CFI_array[8'h46] = 8'h02; + CFI_array[8'h47] = 8'h01; + CFI_array[8'h48] = 8'h00; + CFI_array[8'h49] = 8'h08; + CFI_array[8'h4A] = 8'h00; + CFI_array[8'h4B] = 8'h01; + CFI_array[8'h4C] = 8'h04; + CFI_array[8'h4D] = 8'h00; + CFI_array[8'h4E] = 8'h00; + CFI_array[8'h4F] = 8'h07; + CFI_array[8'h50] = 8'h01; + + begin + for(i=80;i>=0;i=i-1) + begin + CFI_tmp = CFI_array[8'h00-i+80]; + for(j=7;j>=0;j=j-1) + begin + CFI_array_tmp[8*i+j] = CFI_tmp[j]; + end + end + end + end + + always @(next_state_event or PoweredUp or RST or RST_out) + begin: StateTransition + if (PoweredUp) + begin + if ((RSTNeg_in) && RST_out == 1'b1) + current_state = #(1000) next_state; + else if ((~RSTNeg_in || rising_edge_RSTNeg) && falling_edge_RST) + begin + // no state transition while RESET# low + current_state = RESET_STATE; + RST_in = 1'b1; + #1000 RST_in = 1'b0; + end + end + end + + always @(posedge RST_in) + begin:Threset + RST_out = 1'b0; + #(35000000-200000) RST_out = 1'b1; + end + + always @(negedge CSNeg_ipd) + begin:CheckCEOnPowerUP + if (~PoweredUp) + $display ("Device is selected during Power Up"); + end + + /////////////////////////////////////////////////////////////////////////// + //// Internal Delays + /////////////////////////////////////////////////////////////////////////// + + always @(posedge PRGSUSP_in) + begin:PRGSuspend + PRGSUSP_out = 1'b0; + #tdevice_PRGSUSP PRGSUSP_out = 1'b1; + end + + always @(posedge PPBERASE_in) + begin:PPBErs + PPBERASE_out = 1'b0; + #tdevice_PPBERASE PPBERASE_out = 1'b1; + end + + always @(posedge ERSSUSP_in) + begin:ERSSuspend + ERSSUSP_out = 1'b0; + #tdevice_ERSSUSP ERSSUSP_out = 1'b1; + end + + always @(posedge PASSULCK_in) + begin:PASSULock + PASSULCK_out = 1'b0; + #tdevice_PASSULCK PASSULCK_out = 1'b1; + end + + always @(posedge PASSACC_in) + begin:PASSAcc + PASSACC_out = 1'b0; + #tdevice_PASSACC PASSACC_out = 1'b1; + end + +/////////////////////////////////////////////////////////////////////////////// +// write cycle decode +/////////////////////////////////////////////////////////////////////////////// + integer opcode_cnt = 0; + integer addr_cnt = 0; + integer mode_cnt = 0; + integer dummy_cnt = 0; + integer data_cnt = 0; + integer bit_cnt = 0; + + reg [4095:0] Data_in = 4096'b0; + reg [7:0] opcode; + reg [7:0] opcode_in; + reg [7:0] opcode_tmp; + reg [31:0] addr_bytes; + reg [31:0] hiaddr_bytes; + reg [31:0] Address_in; + reg [7:0] mode_bytes; + reg [7:0] mode_in; + integer Latency_code; + integer quad_data_in [0:1023]; + reg [3:0] quad_nybble = 4'b0; + reg [3:0] Quad_slv; + reg [7:0] Byte_slv; + + always @(rising_edge_CSNeg_ipd or falling_edge_CSNeg_ipd or + rising_edge_SCK_ipd or falling_edge_SCK_ipd) + begin: Buscycle + integer i; + integer j; + integer k; + time CLK_PER; + time LAST_CLK; + + if (falling_edge_CSNeg_ipd) + begin + if (bus_cycle_state==STAND_BY) + begin + Instruct = NONE; + write = 1'b1; + cfg_write = 0; + opcode_cnt = 0; + addr_cnt = 0; + mode_cnt = 0; + dummy_cnt = 0; + data_cnt = 0; + opcode_tmp = 0; + DOUBLE = 1'b0; + QUADRD = 1'b0; + CLK_PER = 1'b0; + LAST_CLK = 1'b0; + if (current_state == AUTOBOOT) + begin + bus_cycle_state = DATA_BYTES; + end + else + begin + bus_cycle_state = OPCODE_BYTE; + end + end + end + + if (rising_edge_SCK_ipd) // Instructions, addresses or data present + begin // at SI are latched on the rising edge of SCK + + CLK_PER = $time - LAST_CLK; + LAST_CLK = $time; + if (CHECK_FREQ) + begin + if ((CLK_PER < 20000 && Latency_code == 3) || + (CLK_PER < 12500 && Latency_code == 0) || + (CLK_PER < 11100 && Latency_code == 1) || + (CLK_PER < 9600 && Latency_code == 2)) + begin + $display ("More wait states are required for"); + $display ("this clock frequency value"); + end + CHECK_FREQ = 0; + end + + if (~CSNeg_ipd) + begin + case (bus_cycle_state) + OPCODE_BYTE: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + opcode_in[opcode_cnt] = SI_in; + opcode_cnt = opcode_cnt + 1; + Latency_code = Config_reg1[7:6]; + if (opcode_cnt == BYTE) + begin + for(i=7;i>=0;i=i-1) + begin + opcode[i] = opcode_in[7-i]; + end + case (opcode) + 8'b00000110 : // 06h + begin + Instruct = WREN; + bus_cycle_state = DATA_BYTES; + end + 8'b00000100 : // 04h + begin + Instruct = WRDI; + bus_cycle_state = DATA_BYTES; + end + 8'b00000001 : // 01h + begin + Instruct = WRR; + bus_cycle_state = DATA_BYTES; + end + 8'b00000011 : // 03h + begin + Instruct = READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00010011 : // 13h + begin + Instruct = RD4; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01001011 : // 4Bh + begin + Instruct = OTPR; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00000101 : // 05h + begin + Instruct = RDSR; + bus_cycle_state = DATA_BYTES; + end + 8'b00000111 : // 07h + begin + Instruct = RDSR2; + bus_cycle_state = DATA_BYTES; + end + 8'b00110101 : // 35h + begin + Instruct = RDCR; + bus_cycle_state = DATA_BYTES; + end + 8'b10010000 : // 90h + begin + Instruct = REMS; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10011111 : // 9Fh + begin + Instruct = RDID; + bus_cycle_state = DATA_BYTES; + end + 8'b10101011 : // ABh + begin + Instruct = RES; + bus_cycle_state = DUMMY_BYTES; + end + 8'b00001011 : // 0Bh + begin + Instruct = FSTRD; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00001100 : // 0Ch + begin + Instruct = FSTRD4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00001101 : // 0Dh + begin + Instruct = DDRFR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00001110 : // 0Eh + begin + Instruct = DDRFR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00111011 : // 3Bh + begin + Instruct = DOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00111100 : // 3Ch + begin + Instruct = DOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b10111011 : // BBh + begin + Instruct = DIOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b10111100 : // BCh + begin + Instruct = DIOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b10111101 : // BDh + begin + Instruct = DDRDIOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b10111110 : // BEh + begin + Instruct = DDRDIOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b01101011 : // 6Bh + begin + Instruct = QOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b01101100 : // 6Ch + begin + Instruct = QOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b11101011 : // EBh + begin + Instruct = QIOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b11101100 : // ECh + begin + Instruct = QIOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b11101101 : // EDh + begin + Instruct = DDRQIOR; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b11101110 : // EEh + begin + Instruct = DDRQIOR4; + bus_cycle_state = ADDRESS_BYTES; + CHECK_FREQ = 1'b1; + end + 8'b00000010 : // 02h + begin + Instruct = PP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00010010 : // 12h + begin + Instruct = PP4; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00110010: // 32h + begin + Instruct = QPP; + bus_cycle_state = ADDRESS_BYTES; + quad_pg = 1'b1; + end + 8'b00111000: // 38h + begin + Instruct = QPP; + bus_cycle_state = ADDRESS_BYTES; + quad_pg = 1'b1; + end + 8'b00110100 : // 34h + begin + Instruct = QPP4; + bus_cycle_state = ADDRESS_BYTES; + quad_pg = 1'b1; + end + 8'b01000010 : // 42h + begin + Instruct = OTPP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10000101 : // 85h + begin + Instruct = PGSP; + bus_cycle_state = DATA_BYTES; + end + 8'b10001010 : // 8Ah + begin + Instruct = PGRS; + bus_cycle_state = DATA_BYTES; + end + 8'b11000111 : // C7h + begin + Instruct = BE; + bus_cycle_state = DATA_BYTES; + end + 8'b01100000 : // 60h + begin + Instruct = BE; + bus_cycle_state = DATA_BYTES; + end + 8'b11011000 : // D8h + begin + Instruct = SE; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11011100 : // DCh + begin + Instruct = SE4; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01110101 : // 75h + begin + Instruct = ERSP; + bus_cycle_state = DATA_BYTES; + end + 8'b01111010 : // 7Ah + begin + Instruct = ERRS; + bus_cycle_state = DATA_BYTES; + end + 8'b00010100 : // 14h + begin + Instruct = ABRD; + bus_cycle_state = DATA_BYTES; + end + 8'b00010101 : // 15h + begin + Instruct = ABWR; + bus_cycle_state = DATA_BYTES; + end + 8'b00010110 : // 16h + begin + Instruct = BRRD; + bus_cycle_state = DATA_BYTES; + end + 8'b00010111 : // 17h + begin + Instruct = BRWR; + bus_cycle_state = DATA_BYTES; + end + 8'b00101011 : // 2Bh + begin + Instruct = ASPRD; + bus_cycle_state = DATA_BYTES; + end + 8'b00101111 : // 2Fh + begin + Instruct = ASPP; + bus_cycle_state = DATA_BYTES; + end + 8'b11100000 : // E0h + begin + Instruct = DYBRD; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11100001 : // E1h + begin + Instruct = DYBWR; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11100010 : // E2h + begin + Instruct = PPBRD; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11100011 : // E3h + begin + Instruct = PPBP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11100100 : // E4h + begin + Instruct = PPBERS; + bus_cycle_state = DATA_BYTES; + end + 8'b10100110 : // A6h + begin + Instruct = PLBWR; + bus_cycle_state = DATA_BYTES; + end + 8'b10100111 : // A7h + begin + Instruct = PLBRD; + bus_cycle_state = DATA_BYTES; + end + 8'b11100111 : // E7h + begin + Instruct = PASSRD; + bus_cycle_state = DATA_BYTES; + end + 8'b11101000 : // E8h + begin + Instruct = PASSP; + bus_cycle_state = DATA_BYTES; + end + 8'b11101001 : // E9h + begin + Instruct = PASSU; + bus_cycle_state = DATA_BYTES; + end + 8'b11110000 : // F0h + begin + Instruct = RESET; + bus_cycle_state = DATA_BYTES; + end + 8'b00110000 : // 30h + begin + Instruct = CLSR; + bus_cycle_state = DATA_BYTES; + end + 8'b01000001 : // 41h + begin + Instruct = DLPRD; + bus_cycle_state = DATA_BYTES; + end + 8'b01000011 : // 43h + begin + Instruct = PNVDLR; + bus_cycle_state = DATA_BYTES; + end + 8'b01001010 : // 4Ah + begin + Instruct = WVDLR; + bus_cycle_state = DATA_BYTES; + end + 8'b10111001 : // B9h + begin + Instruct = BRAC; + bus_cycle_state = DATA_BYTES; + end + 8'b11111111 : // FFh + begin + Instruct = MBR; + bus_cycle_state = MODE_BYTE; + end + 8'b00100000 : // 20h + begin + Instruct = P4E; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00100001 : // 21h + begin + Instruct = P4E4; + bus_cycle_state = ADDRESS_BYTES; + end + endcase + end + end + end //end of OPCODE BYTE + + ADDRESS_BYTES : + begin + if ((Instruct == DDRFR) || (Instruct == DDRFR4) || + (Instruct == DDRDIOR) || (Instruct == DDRDIOR4) || + (Instruct == DDRQIOR) || (Instruct == DDRQIOR4)) + DOUBLE = 1'b1; + else + DOUBLE = 1'b0; + if ((Instruct == QOR) || (Instruct == QOR4) || + (Instruct == QIOR) || (Instruct == QIOR4) || + (Instruct == DDRQIOR) || (Instruct == DDRQIOR4)) + QUADRD = 1'b1; + else + QUADRD = 1'b0; + if (DOUBLE == 1'b0) + begin + if (((((Instruct == FSTRD) && (~EXTADD)) || + ((Instruct == DOR) && (~EXTADD)) || + (Instruct == OTPR)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + ((Instruct == QOR) && QUAD && (~EXTADD))) + begin + //Instruction + 3 Bytes Address + Dummy Byte + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE) + begin + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:26] = 6'b000000; + addr_bytes[24] = Bank_Addr_reg[0]; + addr_bytes[25] = Bank_Addr_reg[1]; + Address = addr_bytes ; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (Instruct==FSTRD || Instruct==DOR || + Instruct == QOR) + begin + if (Latency_code == 3) + bus_cycle_state = DATA_BYTES; + else + bus_cycle_state = DUMMY_BYTES; + end + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((((Instruct==FSTRD4) || + (Instruct==DOR4) || + ((Instruct==FSTRD) && EXTADD) || + ((Instruct==DOR) && EXTADD)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + ((Instruct==QOR4) && QUAD) || + ((Instruct==QOR) && QUAD && EXTADD)) + begin + //Instruction + 4 Bytes Address + Dummy Byte + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 4*BYTE) + begin + for(i=31;i>=0;i=i-1) + begin + hiaddr_bytes[31-i] = Address_in[i]; + end + Address = hiaddr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (Latency_code == 3) + bus_cycle_state = DATA_BYTES; + else + begin + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + + end + end + end + end + else if ((Instruct==DIOR) && (~EXTADD) && + ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + //DUAL I/O High Performance Read(3 Bytes Addr) + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt + 1] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE/2) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i]=Address_in[i]; + end + addr_bytes[31:26] = 6'b000000; + addr_bytes[24] = Bank_Addr_reg[0]; + addr_bytes[25] = Bank_Addr_reg[1]; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if (((Instruct==DIOR4) || + ((Instruct==DIOR) && EXTADD)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) + begin //DUAL I/O High Performance Read(4Bytes Addr) + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt + 1] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 4*BYTE/2) + begin + addr_cnt = 0; + for(i=31;i>=0;i=i-1) + begin + addr_bytes[31-i] = Address_in[i]; + end + Address = addr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((Instruct == QIOR) && (~EXTADD)) + begin + //QUAD I/O High Performance Read (3Bytes Address) + if (QUAD) + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE/4) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:26] = 6'b000000; + addr_bytes[24] = Bank_Addr_reg[0]; + addr_bytes[25] = Bank_Addr_reg[1]; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + else + bus_cycle_state = STAND_BY; + end + else if ((Instruct==QIOR4) || ((Instruct==QIOR) + && EXTADD)) + begin + //QUAD I/O High Performance Read (4Bytes Addr) + if (QUAD) + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt +1; + if (addr_cnt == 4*BYTE/4) + begin + addr_cnt =0; + for(i=31;i>=0;i=i-1) + begin + hiaddr_bytes[31-i] = Address_in[i]; + end + Address = hiaddr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + else + bus_cycle_state = STAND_BY; + end + else if ((((Instruct==RD4) || (Instruct==PP4) || + (Instruct==SE4) ||(Instruct==PPBRD) || + (Instruct==DYBRD) ||(Instruct==DYBWR) || + (Instruct==PPBP) || (Instruct==P4E4) || + ((Instruct==READ) && EXTADD) || + ((Instruct==PP) && EXTADD) || + ((Instruct==P4E) && EXTADD) || + ((Instruct==SE) && EXTADD)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + (QUAD && (Instruct==QPP4 || + ((Instruct==QPP) && EXTADD)))) + begin + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 4*BYTE) + begin + for(i=31;i>=0;i=i-1) + begin + hiaddr_bytes[31-i] = Address_in[i]; + end + Address = hiaddr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = DATA_BYTES; + end + end + else if (((HOLDNeg_in && ~QUAD) || QUAD) && + (~EXTADD)) + begin + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE) + begin + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:26] = 6'b000000; + addr_bytes[24] = Bank_Addr_reg[0]; + addr_bytes[25] = Bank_Addr_reg[1]; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = DATA_BYTES; + end + end + end + else + begin + if ((Instruct==DDRFR) && (~EXTADD)) + //Fast DDR Read Mode + begin + Address_in[addr_cnt] = SI_in; + if ((addr_cnt/2) <= 16) + begin + opcode_tmp[addr_cnt/2] = SI_in; + end + addr_cnt = addr_cnt + 1; + read_cnt = 0; + end + else if ((Instruct==DDRFR4) || + ((Instruct==DDRFR) && EXTADD)) + begin + Address_in[addr_cnt] = SI_in; + if ((addr_cnt/2) <= 16) + begin + opcode_tmp[addr_cnt/2] = SI_in; + end + addr_cnt = addr_cnt + 1; + read_cnt = 0; + end + else if ((Instruct == DDRDIOR) && (~EXTADD)) + begin //Dual I/O DDR Read Mode + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt+1]= SI_in; + if ((addr_cnt/2) <= 16) + begin + opcode_tmp[addr_cnt/2] = SI_in; + end + addr_cnt = addr_cnt + 1; + read_cnt = 0; + end + else if ((Instruct==DDRDIOR4) || + ((Instruct==DDRDIOR) && EXTADD)) + begin //Dual I/O DDR Read Mode + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt+1] = SI_in; + if ((addr_cnt/2) <= 16) + begin + opcode_tmp[addr_cnt/2] = SI_in; + end + addr_cnt = addr_cnt + 1; + read_cnt = 0; + end + else if ((Instruct==DDRQIOR) && (~EXTADD) && QUAD) + begin //Quad I/O DDR Read Mode + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + opcode_tmp[addr_cnt/2] = SI_in; + addr_cnt = addr_cnt +1; + read_cnt = 0; + end + else if (QUAD && ((Instruct==DDRQIOR4) || + ((Instruct==DDRQIOR) && EXTADD))) + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + opcode_tmp[addr_cnt/2] = SI_in; + addr_cnt = addr_cnt +1; + read_cnt = 0; + end + end + end + + MODE_BYTE : + begin + if (((Instruct==DIOR) || (Instruct == DIOR4)) + && ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + mode_in[2*mode_cnt] = SO_in; + mode_in[2*mode_cnt+1] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/2) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + if (Latency_code == 0 || Latency_code == 3) + bus_cycle_state = DATA_BYTES; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if (((Instruct==QIOR) || (Instruct == QIOR4)) + && QUAD) + begin + mode_in[4*mode_cnt] = HOLDNeg_in; + mode_in[4*mode_cnt+1] = WPNeg_in; + mode_in[4*mode_cnt+2] = SO_in; + mode_in[4*mode_cnt+3] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/4) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((Instruct == DDRFR) || (Instruct == DDRFR4)) + mode_in[2*mode_cnt] = SI_in; + else if ((Instruct==DDRDIOR) || (Instruct==DDRDIOR4)) + begin + mode_in[4*mode_cnt] = SO_in; + mode_in[4*mode_cnt+1] = SI_in; + end + else if (((Instruct==DDRQIOR) || (Instruct == DDRQIOR4)) + && QUAD) + begin + mode_in[0] = HOLDNeg_in; + mode_in[1] = WPNeg_in; + mode_in[2] = SO_in; + mode_in[3] = SI_in; + end + dummy_cnt = 0; + end + + DUMMY_BYTES : + begin + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + if ((((Instruct==FSTRD) || (Instruct==FSTRD4) || + (Instruct==DOR) || (Instruct==DOR4) || + (Instruct==OTPR)) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + (((Instruct==QOR)||(Instruct==QOR4)) && QUAD)) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == BYTE) + begin + bus_cycle_state = DATA_BYTES; + end + end + + else if ((Instruct==DDRFR) || (Instruct==DDRFR4)) + begin + dummy_cnt = dummy_cnt + 1; + if (EHP) + begin + if (((Latency_code == 3) && (dummy_cnt==1)) || + ((Latency_code == 0) && (dummy_cnt==2)) || + ((Latency_code == 1) && (dummy_cnt==4)) || + ((Latency_code == 2) && (dummy_cnt==5))) + begin + bus_cycle_state = DATA_BYTES; + end + end + else + begin + if (((Latency_code == 3) && (dummy_cnt==4)) || + ((Latency_code == 0) && (dummy_cnt==5)) || + ((Latency_code == 1) && (dummy_cnt==6)) || + ((Latency_code == 2) && (dummy_cnt==7))) + begin + bus_cycle_state = DATA_BYTES; + end + end + end + else if (Instruct==RES) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == 3*BYTE) + bus_cycle_state = DATA_BYTES; + end + else if ((Instruct == DIOR) || (Instruct == DIOR4) + && ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + dummy_cnt = dummy_cnt + 1; + if (EHP) + begin + if (((Latency_code == 1) && (dummy_cnt==1)) || + ((Latency_code == 2) && (dummy_cnt==2))) + bus_cycle_state = DATA_BYTES; + end + else + begin + if (((Latency_code == 3) && (dummy_cnt==4)) || + ((Latency_code == 0) && (dummy_cnt==4)) || + ((Latency_code == 1) && (dummy_cnt==5)) || + ((Latency_code == 2) && (dummy_cnt==6))) + bus_cycle_state = DATA_BYTES; + end + end + else if ((Instruct==DDRDIOR) || (Instruct==DDRDIOR4)) + begin + dummy_cnt = dummy_cnt + 1; + if (EHP) + begin + if (((Latency_code == 3) && (dummy_cnt==2)) || + ((Latency_code == 0) && (dummy_cnt==4)) || + ((Latency_code == 1) && (dummy_cnt==5)) || + ((Latency_code == 2) && (dummy_cnt==6))) + begin + bus_cycle_state = DATA_BYTES; + end + end + else + begin + if (((Latency_code == 3) && (dummy_cnt==4)) || + ((Latency_code == 0) && (dummy_cnt==6)) || + ((Latency_code == 1) && (dummy_cnt==7)) || + ((Latency_code == 2) && (dummy_cnt==8))) + begin + bus_cycle_state = DATA_BYTES; + end + end + end + else if (((Instruct == QIOR) || (Instruct == QIOR4)) + && QUAD) + begin + dummy_cnt = dummy_cnt + 1; + if (((Latency_code == 3) && (dummy_cnt==1)) || + ((Latency_code == 0) && (dummy_cnt==4)) || + ((Latency_code == 1) && (dummy_cnt==4)) || + ((Latency_code == 2) && (dummy_cnt==5))) + begin + bus_cycle_state = DATA_BYTES; + end + end + else if (((Instruct==DDRQIOR) || (Instruct==DDRQIOR4)) + && QUAD) + begin + dummy_cnt = dummy_cnt + 1; + + if (((Latency_code == 3) && (dummy_cnt==3)) || + ((Latency_code == 0) && (dummy_cnt==6)) || + ((Latency_code == 1) && (dummy_cnt==7)) || + ((Latency_code == 2) && (dummy_cnt==8))) + begin + bus_cycle_state = DATA_BYTES; + end + end + end + + DATA_BYTES : + begin + + if (DOUBLE == 1'b1 && (hold_mode==0)) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + + if ((QUAD) && ((Instruct==QPP) || (Instruct == QPP4))) + begin + quad_nybble = {HOLDNeg_in, WPNeg_in, SO_in, SI_in}; + if (data_cnt > ((PageSize+1)*2-1)) + begin + //In case of quad mode and QPP, + //if more than 512 bytes are sent to the device + for(i=0;i<=(PageSize*2-1);i=i+1) + begin + quad_data_in[i] = quad_data_in[i+1]; + end + quad_data_in[(PageSize+1)*2-1] = quad_nybble; + data_cnt = data_cnt +1; + end + else + begin + if (quad_nybble !== 4'bZZZZ) + begin + quad_data_in[data_cnt] = quad_nybble; + end + data_cnt = data_cnt +1; + end + end + else if ((~QUADRD) && ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + if (data_cnt > ((PageSize+1)*8-1)) + begin + //In case of serial mode and PP, + //if more than PageSize are sent to the device + //previously latched data are discarded and last + //256/512 data bytes are guaranteed to be programmed + //correctly within the same page. + if (bit_cnt == 0) + begin + for(i=0;i<=(PageSize*BYTE-1);i=i+1) + begin + Data_in[i] = Data_in[i+8]; + end + end + Data_in[PageSize*BYTE + bit_cnt] = SI_in; + bit_cnt = bit_cnt + 1; + if (bit_cnt == 8) + begin + bit_cnt = 0; + end + data_cnt = data_cnt + 1; + end + else + begin + Data_in[data_cnt] = SI_in; + data_cnt = data_cnt + 1; + bit_cnt = 0; + end + end + end + endcase + end + end + + if (falling_edge_SCK_ipd) + begin + if (~CSNeg_ipd) + begin + case (bus_cycle_state) + ADDRESS_BYTES : + begin + if (DOUBLE == 1'b1) + begin + if ((Instruct==DDRFR) && (~EXTADD)) + //Fast DDR Read Mode + begin + Address_in[addr_cnt] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 3*BYTE) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:26] = 6'b000000; + addr_bytes[24] = Bank_Addr_reg[0]; + addr_bytes[25] = Bank_Addr_reg[1]; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((Instruct==DDRFR4) || + ((Instruct==DDRFR) && EXTADD)) + begin + Address_in[addr_cnt] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 4*BYTE) + begin + addr_cnt = 0; + for(i=31;i>=0;i=i-1) + begin + addr_bytes[31-i] = Address_in[i]; + end + Address = addr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + begin + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + end + else if ((Instruct == DDRDIOR) && (~EXTADD)) + begin //Dual I/O DDR Read Mode + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt+1]= SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 3*BYTE/2) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:26] = 6'b000000; + addr_bytes[24] = Bank_Addr_reg[0]; + addr_bytes[25] = Bank_Addr_reg[1]; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + bus_cycle_state = DUMMY_BYTES; + end + end + else if ((Instruct==DDRDIOR4) || + ((Instruct==DDRDIOR) && EXTADD)) + begin //Dual I/O DDR Read Mode + Address_in[2*addr_cnt] = SO_in; + Address_in[2*addr_cnt+1] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 4*BYTE/2) + begin + addr_cnt = 0; + for(i=31;i>=0;i=i-1) + begin + addr_bytes[31-i] = Address_in[i]; + end + Address = addr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + if (EHP) + bus_cycle_state = MODE_BYTE; + else + begin + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + end + else if ((Instruct==DDRQIOR) && (~EXTADD) && QUAD) + begin //Quad I/O DDR Read Mode + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 3*BYTE/4) + begin + addr_cnt = 0; + for(i=23;i>=0;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + addr_bytes[31:26] = 6'b000000; + addr_bytes[24] = Bank_Addr_reg[0]; + addr_bytes[25] = Bank_Addr_reg[1]; + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + else if (QUAD && ((Instruct==DDRQIOR4) || + ((Instruct==DDRQIOR) && EXTADD))) + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SO_in; + Address_in[4*addr_cnt+3] = SI_in; + if (addr_cnt != 0) + begin + addr_cnt = addr_cnt + 1; + end + read_cnt = 0; + if (addr_cnt == 4*BYTE/4) + begin + addr_cnt = 0; + for(i=31;i>=0;i=i-1) + begin + addr_bytes[31-i] = Address_in[i]; + end + Address = addr_bytes[31:0]; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + end + end + + MODE_BYTE : + begin + if ((Instruct == DDRFR) || (Instruct == DDRFR4)) + begin + mode_in[2*mode_cnt+1] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/2) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + else if ((Instruct==DDRDIOR) || (Instruct==DDRDIOR4)) + begin + mode_in[4*mode_cnt+2] = SO_in; + mode_in[4*mode_cnt+3] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/4) + begin + mode_cnt = 0; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + else if ((Instruct==DDRQIOR) || (Instruct==DDRQIOR4)) + begin + mode_in[4] = HOLDNeg_in; + mode_in[5] = WPNeg_in; + mode_in[6] = SO_in; + mode_in[7] = SI_in; + for(i=7;i>=0;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DUMMY_BYTES; + if (DOUBLE == 1'b1 && (hold_mode==0) + && VDLR_reg != 8'b00000000) + begin + + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + + DATA_BYTES: + begin + if (hold_mode==0) + begin + if (DOUBLE == 1'b1 ) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + + end + else + begin + if ((Instruct==READ) || (Instruct==RD4) || + (Instruct==FSTRD)|| (Instruct==FSTRD4)|| + (Instruct==RDSR) || (Instruct==RDSR2) || + (Instruct==RDCR) || (Instruct==OTPR) || + (Instruct==DOR) || (Instruct==DOR4) || + (Instruct==DIOR)|| (Instruct==DIOR4)|| + (Instruct==ABRD) || (Instruct==BRRD) || + (Instruct==ASPRD)|| (Instruct==DYBRD) || + (Instruct==PPBRD)|| + (Instruct==PASSRD)|| (Instruct==RDID)|| + (Instruct==RES) || (Instruct==REMS) || + (Instruct==PLBRD)|| (Instruct==DLPRD) || + (current_state == AUTOBOOT && + start_delay == 0) || + (((Instruct==QOR) || (Instruct==QIOR) || + (Instruct==QOR4) || + (Instruct==QIOR4)) && QUAD)) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + end + + DUMMY_BYTES: + begin + if (hold_mode==0) + begin + if (DOUBLE == 1'b1 && VDLR_reg != 8'b00000000) + begin + read_out = 1'b1; + #10 read_out = 1'b0; + end + end + end + + endcase + end + end + + if (rising_edge_CSNeg_ipd) + begin + if ((bus_cycle_state != DATA_BYTES) && + (bus_cycle_state != DUMMY_BYTES)) + begin + if (bus_cycle_state == ADDRESS_BYTES && opcode_tmp == 8'hFF) + begin + Instruct = MBR; + end + bus_cycle_state = STAND_BY; + end + else + begin + if (bus_cycle_state == DATA_BYTES) + begin + if (((mode_bytes[7:4] == 4'b1010) && + (Instruct==DIOR || Instruct==DIOR4 || + Instruct==QIOR || Instruct==QIOR4)) || + ((mode_bytes[7:4] == ~mode_bytes[3:0]) && + (Instruct == DDRFR || Instruct == DDRFR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4))) + bus_cycle_state = ADDRESS_BYTES; + else + bus_cycle_state = STAND_BY; + + case (Instruct) + WREN, + WRDI, + BE, + SE, + SE4, + CLSR, + P4E, + P4E4, + BRAC, + RESET, + PPBERS, + PPBP, + PLBWR, + PGSP, + PGRS, + ERSP, + ERRS: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 0) + write = 1'b0; + end + end + + WRR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + //If CS# is driven high after eight + //cycle,only the Status Register is + //written to. + begin + write = 1'b0; + if (BAR_ACC == 0) + begin + for(i=0;i<=7;i=i+1) + begin + Status_reg1_in[i]= + Data_in[7-i]; + end + end + else + begin + if (P_ERR == 0 && E_ERR == 0) + begin + for(i=0;i<=7;i=i+1) + begin + Bank_Addr_reg_in[i]= + Data_in[7-i]; + end + end + end + end + else if (data_cnt == 16) + //After the 16th cycle both the + //Status and Configuration Registers + //are written to. + begin + write = 1'b0; + if (BAR_ACC == 0) + begin + cfg_write = 1'b1; + for(i=0;i<=7;i=i+1) + begin + Status_reg1_in[i]= + Data_in[7-i]; + Config_reg1_in[i]= + Data_in[15-i]; + end + end + else + begin + if (P_ERR == 0 && E_ERR == 0) + begin + for(i=0;i<=7;i=i+1) + begin + Bank_Addr_reg_in[i]= + Data_in[7-i]; + end + end + end + end + end + end + + PP, + PP4, + OTPP: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt > 0) + begin + if ((data_cnt % 8) == 0) + begin + write = 1'b0; + for(i=0;i<=PageSize;i=i+1) + begin + for(j=7;j>=0;j=j-1) + begin + if ((Data_in[(i*8)+(7-j)]) + !== 1'bX) + begin + Byte_slv[j] = + Data_in[(i*8)+(7-j)]; + end + end + WByte[i] = Byte_slv; + end + + if (data_cnt > (PageSize+1)*BYTE) + Byte_number = PageSize; + else + Byte_number = + ((data_cnt/8) - 1); + end + end + end + end + + QPP, + QPP4: + begin + if (data_cnt >0) + begin + if ((data_cnt % 2) == 0) + begin + write = 1'b0; + quad_pg = 1'b0; + for(i=0;i<=PageSize;i=i+1) + begin + for(j=1;j>=0;j=j-1) + begin + Quad_slv = + quad_data_in[(i*2)+(1-j)]; + if (j==1) + Byte_slv[7:4] = Quad_slv; + else if (j==0) + Byte_slv[3:0] = Quad_slv; + end + WByte[i] = Byte_slv; + end + if (data_cnt > (PageSize+1)*2) + Byte_number = PageSize; + else + Byte_number = ((data_cnt/2)-1); + end + end + end + + ABWR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 32) + begin + write = 1'b0; + for(j=0;j<=31;j=j+1) + begin + AutoBoot_reg_in[j] = Data_in[31-j]; + end + end + end + end + + BRWR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + begin + write = 1'b0; + for(j=0;j<=7;j=j+1) + begin + Bank_Addr_reg_in[j] = Data_in[7-j]; + end + end + end + end + + ASPP: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 16) + begin + write = 1'b0; + for(j=0;j<=15;j=j+1) + begin + ASP_reg_in[j] = Data_in[15-j]; + end + end + end + end + + DYBWR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + begin + write = 1'b0; + for(j=0;j<=7;j=j+1) + begin + DYBAR_in[j] = Data_in[7-j]; + end + end + end + end + + PNVDLR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + begin + write = 1'b0; + for(j=0;j<=7;j=j+1) + begin + NVDLR_reg_in[j] = Data_in[7-j]; + end + end + end + end + + WVDLR: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + begin + write = 1'b0; + for(j=0;j<=7;j=j+1) + begin + VDLR_reg_in[j] = Data_in[7-j]; + end + end + end + end + + PASSP: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 64) + begin + write = 1'b0; + for(j=1;j<=8;j=j+1) + begin + for(k=1;k<=8;k=k+1) + begin + Password_reg_in[j*8-k] = + Data_in[8*(j-1)+k-1]; + end + end + end + end + end + + PASSU: + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 64) + begin + write = 1'b0; + for(j=1;j<=8;j=j+1) + begin + for(k=1;k<=8;k=k+1) + begin + PASS_TEMP[j*8-k] = + Data_in[8*(j-1)+k-1]; + end + end + end + end + end + endcase + end + end + end + end + +/////////////////////////////////////////////////////////////////////////////// +// Timing control for the Page Program +/////////////////////////////////////////////////////////////////////////////// + time pob; + time elapsed_pgm; + time start_pgm; + time duration_pgm; + event pdone_event; + + always @(rising_edge_PSTART) + begin + if ((Instruct == PP) || (Instruct == PP4) || (Instruct == OTPP) || + (Instruct == QPP) || (Instruct == QPP4)) + if (PageSize == 255) + begin + pob = tdevice_PP_256; + end + else + begin + pob = tdevice_PP_512; + end + else + pob = tdevice_BP; + if ((rising_edge_PSTART) && PDONE) + begin + elapsed_pgm = 0; + duration_pgm = pob; + PDONE = 1'b0; + ->pdone_event; + start_pgm = $time; + end + end + + always @(posedge PGSUSP) + begin + if (PGSUSP && (~PDONE)) + begin + disable pdone_process; + elapsed_pgm = $time - start_pgm; + duration_pgm = pob - elapsed_pgm; + PDONE = 1'b0; + end + end + + always @(posedge PGRES) + begin + start_pgm = $time; + ->pdone_event; + end + + always @(pdone_event) + begin:pdone_process + PDONE = 1'b0; + #duration_pgm PDONE = 1'b1; + end + +/////////////////////////////////////////////////////////////////////////////// +// Timing control for the Write Status Register +/////////////////////////////////////////////////////////////////////////////// + time wob; + always @(posedge WSTART) + begin:wdone_process + wob = tdevice_WRR; + if (WSTART && WDONE) + begin + WDONE = 1'b0; + #wob WDONE = 1'b1; + end + end + +/////////////////////////////////////////////////////////////////////////////// +// Reset Timing +/////////////////////////////////////////////////////////////////////////////// + + time startlo; + time starthi; + time durationlo; + time durationhi; + + always @(negedge RSTNeg_in or Instruct) + begin + if (~RSTNeg_in) + begin + RST = 1'b1; + #200000 RST = 1'b0; // 200 ns + end + else if (Instruct == RESET) + begin + Reseted = 1'b0; + #10000 Reseted = 1'b1; // 10 ns + end + end + + always @(RST_in or rising_edge_Reseted) // Reset done,program terminated + begin + if ((RST_in && ~RST) || (rising_edge_Reseted)) + disable pdone_process; + disable edone_process; + disable wdone_process; + PDONE = 1'b1; + EDONE = 1'b1; + WDONE = 1'b1; + end + +/////////////////////////////////////////////////////////////////////////////// +// Timing control for the Bulk Erase +/////////////////////////////////////////////////////////////////////////////// + time seo; + time beo; + event edone_event; + time elapsed_ers; + time start_ers; + time duration_ers; + + always @(rising_edge_ESTART) + begin + seo = tdevice_SE; + beo = tdevice_BE; + if ((rising_edge_ESTART) && EDONE) + begin + if (Instruct == BE) + begin + duration_ers = beo; + end + else + begin + duration_ers = seo; + end + elapsed_ers = 0; + EDONE = 1'b0; + ->edone_event; + start_ers = $time; + end + end + + always @(posedge ESUSP) + begin + if (ESUSP && (~EDONE)) + begin + disable edone_process; + elapsed_ers = $time - start_ers; + duration_ers = seo - elapsed_ers; + EDONE = 1'b0; + end + end + + always @(posedge ERES) + begin + if (ERES && (~EDONE)) + begin + start_ers = $time; + ->edone_event; + end + end + + always @(edone_event) + begin : edone_process + EDONE = 1'b0; + #duration_ers EDONE = 1'b1; + end + + /////////////////////////////////////////////////////////////////// + // Process for clock frequency determination + /////////////////////////////////////////////////////////////////// + always @(posedge SCK_ipd) + begin : clock_period + if (SCK_ipd) + begin + SCK_cycle = $time - prev_SCK; + prev_SCK = $time; + end + end + +// ///////////////////////////////////////////////////////////////////////// +// // Main Behavior Process +// // combinational process for next state generation +// ///////////////////////////////////////////////////////////////////////// + + reg rising_edge_PDONE = 1'b0; + reg rising_edge_EDONE = 1'b0; + reg rising_edge_WDONE = 1'b0; + reg falling_edge_write = 1'b0; + reg falling_edge_PPBERASE_in = 1'b0; + reg falling_edge_PASSULCK_in = 1'b0; + + integer i; + integer j; + + always @(rising_edge_PoweredUp or falling_edge_write or + falling_edge_RSTNeg or rising_edge_PDONE or rising_edge_WDONE or + rising_edge_EDONE or ERSSUSP_out_event or rising_edge_RSTNeg or + PRGSUSP_out_event or rising_edge_CSNeg_ipd or rising_edge_RST_out + or falling_edge_PPBERASE_in or falling_edge_PASSULCK_in) + begin: StateGen1 + + integer sect; + + if (rising_edge_PoweredUp) + begin + if (ABE == 1 && RPME !== 0 ) + begin + next_state = AUTOBOOT; + read_cnt = 0; + byte_cnt = 1; + read_addr = {AutoBoot_reg[31:9], 9'b0}; + start_delay = AutoBoot_reg[8:1]; + start_autoboot = 0; + ABSD = AutoBoot_reg[8:1]; + end + else + next_state = IDLE; + end + else + begin + if (RST_out == 1'b0) + next_state = current_state; + else if (falling_edge_write && Instruct == RESET) + begin + if (ABE == 1 && RPME !== 0) + begin + read_cnt = 0; + byte_cnt = 1; + read_addr = {AutoBoot_reg[31:9], 9'b0}; + start_delay = AutoBoot_reg[8:1]; + ABSD = AutoBoot_reg[8:1]; + start_autoboot = 0; + next_state = AUTOBOOT; + end + else + next_state = IDLE; + end + else + begin + case (current_state) + RESET_STATE : + begin + if (rising_edge_RST_out) + begin + if (ABE == 1 && RPME!== 0) + begin + next_state = AUTOBOOT; + read_cnt = 0; + byte_cnt = 1; + read_addr = {AutoBoot_reg[31:9],9'b0}; + start_delay = AutoBoot_reg[8:1]; + start_autoboot = 0; + ABSD = AutoBoot_reg[8:1]; + end + else + next_state = IDLE; + end + end + + IDLE : + begin + if (falling_edge_write && RdPswdProtMode == 0) + begin + if (Instruct == WRR && WEL == 1 && BAR_ACC == 0 + && (((~(SRWD == 1 && ~WPNeg_in))&& ~QUAD) || QUAD)) + // can not execute if HPM is entered or + // if WEL bit is zero + if (((TBPROT==1 && Config_reg1_in[5]==1'b0) || + (BPNV ==1 && Config_reg1_in[3]==1'b0)) && + cfg_write) + begin + $display ("WARNING: Changing value of "); + $display ("Configuration Register OTP "); + $display ("bit from 1 to 0 is not"); + $display ("allowed!!!"); + end + else + begin + next_state = WRITE_SR; + end + else if ((Instruct == PP || Instruct == QPP || + Instruct == PP4 || Instruct == QPP4) && + WEL == 1) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + if (Sec_Prot[sect]== 0 && PPB_bits[sect]== 1 && + DYB_bits[sect]== 1) + begin + next_state = PAGE_PG; + if ((Instruct==QPP || Instruct==QPP4) && + QPP_page[pgm_page] == 1) + begin + $display ("WARNING:The same page"); + $display (" must not be"); + $display (" programmed more"); + $display (" than once!!!"); + end + end + end + else if (Instruct==OTPP && WEL==1 && FREEZE==0) + begin + if (((((Address>=16'h0010 && Address<=16'h0013) + ||(Address>=16'h0020 && Address<=16'h00FF)) + && LOCK_BYTE1[Address/32] == 1) || + ((Address>=16'h0100 && Address<=16'h01FF) + && LOCK_BYTE2[(Address-16'h0100)/32]==1) || + ((Address>=16'h0200 && Address<=16'h02FF) + && LOCK_BYTE3[(Address-16'h0200)/32]==1) || + ((Address>=16'h0300 && Address<=16'h03FF) + && LOCK_BYTE4[(Address-16'h0300)/32] == 1)) + && (Address + Byte_number <= OTPHiAddr)) + next_state = OTP_PG; + end + else if ((Instruct == SE || Instruct == SE4) + && WEL == 1) + begin + ReturnSectorID(sect,Address); + if (Sec_Prot[sect]== 0 && PPB_bits[sect]== 1 + && DYB_bits[sect]== 1) + next_state = SECTOR_ERS; + end + else if (Instruct == BE && WEL == 1 && + (Status_reg1[4]== 0 && Status_reg1[3]== 0 && + Status_reg1[2]== 0)) + next_state = BULK_ERS; + else if (Instruct == ABWR && WEL == 1) + //Autoboot Register Write Command + next_state = AUTOBOOT_PG; + else if (Instruct == ASPP && WEL == 1) + begin + //ASP Register Program Command + if (~(ASPOTPFLAG)) + next_state = ASP_PG; + end + else if (Instruct == PLBWR && WEL == 1 && + RdPswdProtEnable == 0) + next_state = PLB_PG; + else if (Instruct == PASSP && WEL == 1) + begin + if (~(PWDMLB== 0 && PSTMLB== 1)) + next_state = PASS_PG; + end + else if (Instruct == PASSU && WEL && ~WIP) + next_state = PASS_UNLOCK; + else if (Instruct == PPBP && WEL == 1) + next_state <= PPB_PG; + else if (Instruct == PPBERS && WEL && PPBOTP) + next_state <= PPB_ERS; + else if (Instruct == DYBWR && WEL == 1) + next_state = DYB_PG; + else if (Instruct == PNVDLR && WEL == 1) + next_state = NVDLR_PG; + else if (Instruct == P4E || Instruct == P4E4 + && WEL == 1) + begin + $display("Warning!"); + $display("Instructions:"); + $display("Parameter 4KB-sector Erase"); + $display("are not allowed"); + $display("for 512Mbit memory size"); + end + else + next_state = IDLE; + end + if (falling_edge_write && RdPswdProtMode == 1 && ~WIP) + begin + if (Instruct == PASSU) + next_state = PASS_UNLOCK; + end + end + + AUTOBOOT : + begin + if (rising_edge_CSNeg_ipd) + next_state = IDLE; + end + + WRITE_SR : + begin + if (rising_edge_WDONE) + next_state = IDLE; + end + + PAGE_PG : + begin + if (PRGSUSP_out_event && PRGSUSP_out == 1) + next_state = PG_SUSP; + else if (rising_edge_PDONE) + next_state = IDLE; + end + + PG_SUSP : + begin + if (falling_edge_write) + begin + if (Instruct == PGRS) + begin + next_state = PAGE_PG; + end + else + begin + next_state = PG_SUSP; + end + end + end + + OTP_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + BULK_ERS : + begin + if (rising_edge_EDONE) + next_state = IDLE; + end + + SECTOR_ERS : + begin + if (ERSSUSP_out_event && ERSSUSP_out == 1) + next_state = ERS_SUSP; + else if (rising_edge_EDONE) + next_state = IDLE; + end + + ERS_SUSP : + begin + if (falling_edge_write) + begin + if ((Instruct == PP || Instruct == QPP || + Instruct == PP4 || Instruct == QPP4) && + WEL == 1) + begin + if (SectorSuspend != Address/(SecSize+1)) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + if (PPB_bits[sect]== 1 && + DYB_bits[sect]== 1) + begin + next_state = ERS_SUSP_PG; + if ((Instruct==QPP || Instruct==QPP4) && + QPP_page[pgm_page] == 1) + begin + $display ("WARNING:The same page"); + $display (" must not be"); + $display (" programmed more"); + $display (" than once!!!"); + end + end + end + end + else if (Instruct == DYBWR && WEL == 1) + next_state = DYB_PG; + else if (Instruct == ERRS) + next_state = SECTOR_ERS; + else + next_state = ERS_SUSP; + end + end + + ERS_SUSP_PG : + begin + if (rising_edge_PDONE) + next_state = ERS_SUSP; + else if (PRGSUSP_out_event && PRGSUSP_out == 1) + next_state = ERS_SUSP_PG_SUSP; + end + + ERS_SUSP_PG_SUSP : + begin + if (rising_edge_PDONE) + next_state = ERS_SUSP; + if (falling_edge_write) + begin + if (Instruct == PGRS) + begin + next_state = ERS_SUSP_PG; + end + else + begin + next_state = ERS_SUSP_PG_SUSP; + end + end + end + + PASS_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + PASS_UNLOCK : + begin + if (falling_edge_PASSULCK_in) + next_state = IDLE; + end + + PPB_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + PPB_ERS : + begin + if (falling_edge_PPBERASE_in) + next_state = IDLE; + end + + AUTOBOOT_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + PLB_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + DYB_PG : + begin + if (rising_edge_PDONE) + if (ES) + next_state = ERS_SUSP; + else + next_state = IDLE; + end + + ASP_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + NVDLR_PG : + begin + if (rising_edge_PDONE) + next_state = IDLE; + end + + endcase + end + end + end + + /////////////////////////////////////////////////////////////////////////// + //FSM Output generation and general functionality + /////////////////////////////////////////////////////////////////////////// + reg rising_edge_read_out = 1'b0; + reg Instruct_event = 1'b0; + reg change_addr_event = 1'b0; + reg current_state_event = 1'b0; + reg rising_edge_DP_out = 1'b0; + + integer WData [0:511]; + integer WOTPData; + integer Addr; + integer Addr_tmp; + + always @(Instruct_event) + begin + read_cnt = 0; + byte_cnt = 1; + rd_fast = 1'b1; + dual = 1'b0; + rd_slow = 1'b0; + any_read = 1'b0; + end + + always @(rising_edge_read_out) + begin + if (rising_edge_read_out == 1'b1) + begin + if (PoweredUp == 1'b1) + begin + oe_z = 1'b1; + #1000 oe_z = 1'b0; + oe = 1'b1; + #1000 oe = 1'b0; + end + end + end + + always @(change_addr_event) + begin + if (change_addr_event) + begin + read_addr = Address; + end + end + + always @(posedge PASSACC_out) + begin + Status_reg1[0] = 1'b0; //WIP + PASSACC_in = 1'b0; + end + + always @(Instruct or posedge start_autoboot or oe or current_state_event or + falling_edge_write or posedge PDONE or posedge WDONE or oe_z or + posedge EDONE or ERSSUSP_out or rising_edge_Reseted or + rising_edge_PoweredUp or rising_edge_CSNeg_ipd or PRGSUSP_out or + Address) + begin: Functionality + integer i,j; + integer sect; + + if (rising_edge_PoweredUp) + begin + //the default condition after power-up + //The Bank Address Register is loaded to all zeroes + Bank_Addr_reg = 8'h0; + //The Configuration Register FREEZE bit is cleared. + Config_reg1[0] = 0; + //The WEL bit is cleared. + Status_reg1[1] = 0; + //When BPNV is set to '1'. the BP2-0 bits in Status Register are + //volatile and will be reset binary 111 after power-on reset + if (BPNV == 1 && LOCK == 0 && FREEZE == 0 ) + begin + Status_reg1[4] = 1'b0;// BP2 + Status_reg1[3] = 1'b0;// BP1 + Status_reg1[2] = 1'b0;// BP0 + BP_bits = {Status_reg1[4],Status_reg1[3],Status_reg1[2]}; + change_BP = 1'b1; + #1000 change_BP = 1'b0; + end + + //As shipped from the factory, all devices default ASP to the + //Persistent Protection mode, with all sectors unprotected, + //when power is applied. The device programmer or host system must + //then choose which sector protection method to use. + //For Persistent Protection mode, PPBLOCK defaults to "1" + PPBL[0] = 1'b1; + + //All the DYB power-up in the unprotected state + DYB_bits = {512{1'b1}}; + + end + + if (Instruct == RESET) + begin + //EXTADD is cleared to “0” + Bank_Addr_reg[7] = 1'b0; + //P_ERR bit is cleared + Status_reg1[6] = 1'b0; + //E_ERR bit is cleared + Status_reg1[5] = 1'b0; + //The WEL bit is cleared. + Status_reg1[1] = 1'b0; + //The WIP bit is cleared. + Status_reg1[0] = 1'b0; + //The ES bit is cleared. + Status_reg2[1] = 1'b0; + //The PS bit is cleared. + Status_reg2[0] = 1'b0; + //When BPNV is set to '1'. the BP2-0 bits in Status + //Register are volatile and will be reseted after + //reset command + if (BPNV == 1 && LOCK== 0 && FREEZE == 0) + begin + Status_reg1[4] = 1'b1; + Status_reg1[3] = 1'b1; + Status_reg1[2] = 1'b1; + + BP_bits = {Status_reg1[4],Status_reg1[3], + Status_reg1[2]}; + change_BP = 1'b1; + #1000 change_BP = 1'b0; + end + end + + case (current_state) + IDLE : + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + + if (falling_edge_write && RdPswdProtMode == 1) + begin + if(Instruct == PASSU) + begin + if (~WIP) + begin + PASSULCK_in = 1; + Status_reg1[0] = 1'b1; //WIP + end + else + begin + $display ("The PASSU command cannot be accepted"); + $display (" any faster than once every 100us"); + end + end + else if (Instruct == CLSR) + begin + //The Clear Status Register Command resets bit SR1[5] + //(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + Status_reg1[5] = 0; + Status_reg1[6] = 0; + end + end + + if (falling_edge_write && RdPswdProtMode == 0) + begin + read_cnt = 0; + byte_cnt = 1; + if (Instruct == WREN) + Status_reg1[1] = 1'b1; + else if (Instruct == WRDI) + Status_reg1[1] = 0; + else if ((Instruct == WRR) && WEL == 1 && WDONE == 1 && + BAR_ACC == 0) + begin + if (((~(SRWD == 1 && ~WPNeg_in))&& ~QUAD) || QUAD) + begin + if (((TBPROT==1 && Config_reg1_in[5]==1'b0) || + (BPNV ==1 && Config_reg1_in[3]==1'b0)) && + cfg_write) + begin + // P_ERR bit is set to 1 + Status_reg1[6] = 1'b1; + end + else + begin + // can not execute if Hardware Protection Mode + // is entered or if WEL bit is zero + WSTART = 1'b1; + WSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + end + else + Status_reg1[1] = 0; + end + else if ((Instruct == PP || Instruct == PP4) && WEL ==1 && + PDONE == 1 ) + begin + ReturnSectorID(sect,Address); + if (Sec_Prot[sect] == 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 0; + PGRES = 0; + INITIAL_CONFIG = 1; + Status_reg1[0] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + //P_ERR bit will be set when the user attempts to + //to program within a protected main memory sector + Status_reg1[6] = 1'b1; //P_ERR + Status_reg1[1] = 1'b0; //WEL + end + end + else if ((Instruct == QPP || Instruct == QPP4) && WEL ==1 && + PDONE == 1 ) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + if (Sec_Prot[sect] == 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 0; + PGRES = 0; + INITIAL_CONFIG = 1; + QPP_page[pgm_page] = 1'b1; + Status_reg1[0] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + //P_ERR bit will be set when the user attempts to + //to program within a protected main memory sector + Status_reg1[6] = 1'b1; //P_ERR + Status_reg1[1] = 1'b0; //WEL + end + end + else if (Instruct == OTPP && WEL == 1) + begin + // As long as the FREEZE bit remains cleared to a logic + // '0' the OTP address space is programmable. + if (FREEZE == 0) + begin + if (((((Address>= 16'h0010 && Address<= 16'h0013) || + (Address >= 16'h0020 && Address <= 16'h00FF)) + && LOCK_BYTE1[Address/32] == 1) || + ((Address >= 16'h0100 && Address <= 16'h01FF) + && LOCK_BYTE2[(Address-16'h0100)/32] == 1) || + ((Address >= 16'h0200 && Address <= 16'h02FF) + && LOCK_BYTE3[(Address-16'h0200)/32] == 1) || + ((Address >= 16'h0300 && Address <= 16'h03FF) + && LOCK_BYTE4[(Address-16'h0300)/32] == 1)) && + (Address + Byte_number <= OTPHiAddr)) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else if ((Address < 8'h10 || (Address > 8'h13 && + Address < 8'h20) || Address > 12'h3FF )) + begin + Status_reg1[6] = 1'b1;//P_ERR + Status_reg1[1] = 1'b0;//WEL + if (Address < 8'h20) + begin + $display ("Given address is "); + $display ("in reserved address range"); + end + else if (Address > 12'h3FF) + begin + $display ("Given address is "); + $display ("out of OTP address range"); + end + end + else + begin + //P_ERR bit will be set when the user attempts to + // to program within locked OTP region + Status_reg1[6] = 1'b1;//P_ERR + Status_reg1[1] = 1'b0;//WEL + end + end + else + begin + //P_ERR bit will be set when the user attempts to + //to program within locked OTP region + Status_reg1[6] = 1'b1;//P_ERR + Status_reg1[1] = 1'b0;//WEL + end + end + else if ((Instruct == SE || Instruct == SE4) && WEL == 1) + begin + ReturnSectorID(sect,Address); + SectorSuspend = sect; + if (Sec_Prot[sect] == 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + ESTART = 1'b1; + ESTART <= #5 1'b0; + ESUSP = 0; + ERES = 0; + INITIAL_CONFIG = 1; + Status_reg1[0] = 1'b1; + Addr = Address; + end + else + begin + //E_ERR bit will be set when the user attempts to + //erase an individual protected main memory sector + Status_reg1[5] = 1'b1;//E_ERR + Status_reg1[1] = 1'b0;//WEL + end + end + else if ((Instruct == P4E || Instruct == P4E4) && WEL == 1) + begin + Status_reg1[1] = 1'b0;//WEL + end + else if (Instruct == BE && WEL == 1) + begin + if (Status_reg1[4]== 0 && Status_reg1[3]== 0 && + Status_reg1[2]== 0) + begin + ESTART = 1'b1; + ESTART <= #5 1'b0; + ESUSP = 0; + ERES = 0; + INITIAL_CONFIG = 1; + Status_reg1[0] = 1'b1; + end + else + begin + //The Bulk Erase command will not set E_ERR if a + //protected sector is found during the command + //execution. + Status_reg1[1] = 1'b0;//WEL + end + end + else if (Instruct == PASSP && WEL == 1) + begin + if (~(PWDMLB== 0 && PSTMLB== 1)) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else + begin + $display ("Password programming is not allowed"); + $display (" in Password Protection Mode."); + end + end + else if (Instruct == PASSU && WEL) + begin + if (~WIP) + begin + PASSULCK_in = 1; + Status_reg1[0] = 1'b1; //WIP + end + else + begin + $display ("The PASSU command cannot be accepted"); + $display (" any faster than once every 100us"); + end + end + else if (Instruct == BRWR) + begin + Bank_Addr_reg[7] = Bank_Addr_reg_in[7]; + Bank_Addr_reg[1] = Bank_Addr_reg_in[1]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + end + else if (Instruct == WRR && BAR_ACC == 1) + begin + // Write to the lower address bits of the BAR + if (P_ERR == 0 && E_ERR == 0) + begin + Bank_Addr_reg[1] = Bank_Addr_reg_in[1]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + end + end + else if (Instruct == ASPP && WEL == 1) + begin + if (~(ASPOTPFLAG)) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + $display ("Once the Protection Mode is selected,"); + $display ("no further changes to the ASP "); + $display ("register is allowed."); + end + end + else if (Instruct == ABWR && WEL == 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == PPBP && WEL == 1) + begin + ReturnSectorID(sect,Address); + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == PPBERS && WEL == 1) + begin + if (PPBOTP) + begin + PPBERASE_in = 1'b1; + Status_reg1[0] = 1'b1; + end + else + begin + Status_reg1[5] = 1'b1; + end + end + else if (Instruct == PLBWR && WEL == 1 && + RdPswdProtEnable == 0) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == DYBWR && WEL == 1) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == PNVDLR && WEL == 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == WVDLR && WEL == 1) + begin + VDLR_reg = VDLR_reg_in; + Status_reg1[1] = 1'b0; + end + else if (Instruct == CLSR) + begin + //The Clear Status Register Command resets bit SR1[5] + //(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + Status_reg1[5] = 0; + Status_reg1[6] = 0; + end + + if (Instruct == BRAC && P_ERR == 0 && E_ERR == 0) + begin + BAR_ACC = 1; + end + else + begin + BAR_ACC = 0; + end + end + else if (oe_z) + begin + if (Instruct == READ || Instruct == RD4 || + Instruct == RES || + (Instruct == DLPRD && RdPswdProtMode == 0)) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else if (Instruct == DDRDIOR || Instruct == DDRDIOR4 || + ((Instruct == DDRQIOR || Instruct == DDRQIOR4) + && QUAD)) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + ((Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4) + && QUAD)) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + else if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == READ || Instruct == RD4 || + Instruct == FSTRD || Instruct == FSTRD4 || + Instruct == DDRFR || Instruct == DDRFR4 ) + begin + //Read Memory array + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + if (bus_cycle_state == DUMMY_BYTES + && VDLR_reg != 8'b00000000) + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) is enabled + // Optional DLP + if (VDLR_reg != 8'b00000000 && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + read_addr_tmp = read_addr; + SecAddr = read_addr/(SecSize+1) ; + Sec_addr = read_addr - SecAddr*(SecSize+1); + SecAddr = ReturnSectorIDRdPswdMd(TBPROT); + read_addr = Sec_addr + SecAddr*(SecSize+1); + if (RdPswdProtMode == 0) + begin + read_addr = read_addr_tmp; + end + if (Mem[read_addr] !== -1) + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + end + else + begin + SOut_zd = 8'bx; + end + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 ) + begin + //Read Memory array + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + if (VDLR_reg != 8'b00000000 && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + read_addr_tmp = read_addr; + SecAddr = read_addr/(SecSize+1) ; + Sec_addr = read_addr - SecAddr*(SecSize+1); + SecAddr = ReturnSectorIDRdPswdMd(TBPROT); + read_addr = Sec_addr + SecAddr*(SecSize+1); + if (RdPswdProtMode == 0) + read_addr = read_addr_tmp; + + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if ((Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4 ) + && QUAD) + begin + //Read Memory array + if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (bus_cycle_state == DUMMY_BYTES) + begin + if ((Instruct == DDRQIOR || Instruct == DDRQIOR4) + && QUAD) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) is enabled + // Optional DLP + if (VDLR_reg != 8'b00000000 && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + HOLDNegOut_zd = data_out[7-read_cnt]; + WPNegOut_zd = data_out[7-read_cnt]; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + read_addr_tmp = read_addr; + SecAddr = read_addr/(SecSize+1) ; + Sec_addr = read_addr - SecAddr*(SecSize+1); + SecAddr = ReturnSectorIDRdPswdMd(TBPROT); + read_addr = Sec_addr + SecAddr*(SecSize+1); + if (RdPswdProtMode == 0) + read_addr = read_addr_tmp; + + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == OTPR) + begin + if(read_addr>=OTPLoAddr && read_addr<=OTPHiAddr + && RdPswdProtMode == 0) + begin + //Read OTP Memory array + rd_fast = 1'b1; + rd_slow = 1'b0; + data_out[7:0] = OTPMem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + else if ((read_addr > OTPHiAddr)||(RdPswdProtMode==1)) + begin + //OTP Read operation will not wrap to the + //starting address after the OTP address is at + //its maximum or Read Password Protection Mode + //is selected instead, the data beyond the + //maximum OTP address will be undefined. + SOut_zd = 1'bX; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (Instruct == REMS) + begin + //Read Manufacturer and Device ID + if (read_addr % 2 == 0) + begin + data_out[7:0] = Manuf_ID; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + else + begin + data_out[7:0] = DeviceID; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = 0; + end + end + end + else if (Instruct == RDID) + begin + ident_out = CFI_array_tmp; + if(read_cnt < 648) + begin + SOut_zd = ident_out[647-read_cnt]; + read_cnt = read_cnt + 1; + end + else + begin + //Continued shifting of output beyond the end of + //the defined ID-CFI address space will + //provide undefined data. + SOut_zd = 1'bX; + end + end + else if (Instruct == RES) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + data_out = ESignature; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == DLPRD && RdPswdProtMode == 0) + begin + //Read DLP + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = VDLR_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == ABRD && RdPswdProtMode == 0) + begin + //Read AutoBoot register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = AutoBoot_reg[31-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 32) + read_cnt = 0; + end + else if (Instruct == BRRD && RdPswdProtMode == 0) + begin + //Read Bank Address Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = Bank_Addr_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == ASPRD && RdPswdProtMode == 0) + begin + //Read ASP Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = ASP_reg[15-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 16) + read_cnt = 0; + end + else if (Instruct == PASSRD && RdPswdProtMode == 0) + begin + //Read Password Register + if (~(PWDMLB == 0 && PSTMLB == 1)) + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = + Password_reg[(8*byte_cnt-1)-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + byte_cnt = byte_cnt + 1; + if (byte_cnt == 9) + byte_cnt = 1; + end + end + end + else if (Instruct == PLBRD) + begin + //Read PPB Lock Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = PPBL[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == DYBRD) + begin + //Read DYB Access Register + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + DYBAR[7:0] = 8'bXXXXXXXX; + + if (RdPswdProtMode == 0) + begin + if (DYB_bits[sect] == 1) + DYBAR[7:0] = 8'hFF; + else + begin + DYBAR[7:0] = 8'h0; + end + end + SOut_zd = DYBAR[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == PPBRD) + begin + //Read PPB Access Register + ReturnSectorID(sect,Address); + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + PPBAR[7:0] = 8'bXXXXXXXX; + if (RdPswdProtMode == 0) + begin + if (PPB_bits[sect] == 1) + PPBAR[7:0] = 8'hFF; + else + begin + PPBAR[7:0] = 8'h0; + end + end + SOut_zd = PPBAR[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + end + + AUTOBOOT: + begin + if (start_autoboot == 1) + begin + if (oe) + begin + any_read = 1'b1; + if (QUAD == 1) + begin + if (ABSD > 0) //If ABSD > 0, + begin //max SCK frequency is 104MHz + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else // If ABSD = 0, max SCK frequency is 50 MHz + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + else + begin + if (ABSD > 0) //If ABSD > 0, + begin //max SCK frequency is 133MHz + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + else // If ABSD = 0, max SCK frequency is 50 MHz + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + end + else if (oe_z) + begin + if (QUAD == 1) + begin + if (ABSD > 0) //If ABSD > 0, + begin //max SCK frequency is 104MHz + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else // If ABSD = 0, max SCK frequency is 50 MHz + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + end + else + begin + if (ABSD > 0) //If ABSD > 0, + begin //max SCK frequency is 133MHz + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + else // If ABSD = 0, max SCK frequency is 50 MHz + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + end + end + + WRITE_SR: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (WDONE == 1) + begin + Status_reg1[0] = 1'b0; //WIP + Status_reg1[1] = 1'b0; //WEL + //SRWD bit + Status_reg1[7] = Status_reg1_in[7]; //MSB first + + if (LOCK == 0) + begin + if (FREEZE == 0) + //The Freeze Bit, when set to 1, locks the current + //state of the BP2-0 bits in Status Register, + //the TBPROT bit in the Config Register + //As long as the FREEZE bit remains cleared to logic + //'0', the other bits of the Configuration register + //including FREEZE are writeable. + begin + Status_reg1[4] = Status_reg1_in[4];//BP2 + Status_reg1[3] = Status_reg1_in[3];//BP1 + Status_reg1[2] = Status_reg1_in[2];//BP0 + + BP_bits = {Status_reg1[4],Status_reg1[3], + Status_reg1[2]}; + if (TBPROT == 1'b0 && INITIAL_CONFIG == 1'b0) + begin + Config_reg1[5] = Config_reg1_in[5];//TBPROT + end + change_BP = 1'b1; + #1000 change_BP = 1'b0; + end + end + + Config_reg1[7] = Config_reg1_in[7];//LC1 + Config_reg1[6] = Config_reg1_in[6];//LC0 + Config_reg1[1] = Config_reg1_in[1];//QUAD + + if (FREEZE == 1'b0) + begin + Config_reg1[0] = Config_reg1_in[0];//FREEZE + end + + if (WRLOCKENABLE== 1'b1 && LOCK == 1'b0) + begin + Config_reg1[4] = Config_reg1_in[4];//LOCK + WRLOCKENABLE = 1'b0; + end + if (BPNV == 1'b0) + begin + Config_reg1[3] = Config_reg1_in[3];//BPNV + end + end + end + + PAGE_PG : + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == PAGE_PG) + begin + if (~PDONE) + begin + ADDRHILO_PG(AddrLo, AddrHi, Addr); + cnt = 0; + + for (i=0;i<=wr_cnt;i=i+1) + begin + new_int = WData[i]; + old_int = Mem[Addr + i - cnt]; + if (new_int > -1) + begin + new_bit = new_int; + if (old_int > -1) + begin + old_bit = old_int; + for(j=0;j<=7;j=j+1) + begin + if (~old_bit[j]) + new_bit[j]=1'b0; + end + new_int=new_bit; + end + WData[i]= new_int; + end + else + begin + WData[i] = -1; + end + + Mem[Addr + i - cnt] = - 1; + if ((Addr + i) == AddrHi) + begin + Addr = AddrLo; + cnt = i + 1; + end + end + end + cnt = 0; + end + + if (PDONE) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + quad_pg = 0; + for (i=0;i<=wr_cnt;i=i+1) + begin + Mem[Addr_tmp + i - cnt] = WData[i]; + if ((Addr_tmp + i) == AddrHi) + begin + Addr_tmp = AddrLo; + cnt = i + 1; + end + end + end + + if (Instruct) + begin + if (Instruct == PGSP && ~PRGSUSP_in) + begin + if (~RES_TO_SUSP_MIN_TIME) + begin + PGSUSP = 1'b1; + PGSUSP <= #5 1'b0; + PRGSUSP_in = 1'b1; + if (RES_TO_SUSP_TYP_TIME) + begin + $display("Typical periods are needed for ", + "Program to progress to completion"); + end + end + else + begin + $display("Minimum for tPRS is not satisfied! ", + "PGSP command is ignored"); + end + end + end + end + + PG_SUSP: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + + if (PRGSUSP_out && PRGSUSP_in) + begin + PRGSUSP_in = 1'b0; + //The RDY/BSY bit in the Status Register will indicate that + //the device is ready for another operation. + Status_reg1[0] = 1'b0; + //The Program Suspend (PS) bit in the Status Register will + //be set to the logical “1” state to indicate that the + //program operation has been suspended. + Status_reg2[0] = 1'b1; + PDONE = 1'b1; + end + + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == BRRD) + begin + //Read Bank Address Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = Bank_Addr_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + //Read Array Operations + else if (Instruct == READ || Instruct == RD4 || + Instruct == FSTRD || Instruct == FSTRD4 || + Instruct == DDRFR || Instruct == DDRFR4 ) + begin + //Read Memory array + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + if (pgm_page != read_addr / (PageSize+1)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + + end + end + else + begin + SOut_zd = 8'bxxxxxxxx; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 ) + begin + //Read Memory array + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (pgm_page != read_addr / (PageSize+1)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4 ) + begin + //Read Memory array + if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (pgm_page != read_addr / (PageSize+1)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if ((Instruct == DDRQIOR + || Instruct == DDRQIOR4) && QUAD) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + HOLDNegOut_zd= data_out[7-read_cnt]; + WPNegOut_zd = data_out[7-read_cnt]; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + HOLDNegOut_zd = 1'bx; + WPNegOut_zd = 1'bx; + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + end + else if (oe_z) + begin + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (falling_edge_write) + begin + if (Instruct == BRWR) + begin + Bank_Addr_reg[7] = Bank_Addr_reg_in[7]; + Bank_Addr_reg[1] = Bank_Addr_reg_in[1]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + end + else if (Instruct == WRR && BAR_ACC == 1) + begin + // Write to the lower address bits of the BAR + if (P_ERR == 0 && E_ERR == 0) + begin + Bank_Addr_reg[1] = Bank_Addr_reg_in[1]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + end + end + else if (Instruct == PGRS) + begin + Status_reg2[0] = 1'b0; + Status_reg1[0] = 1'b1; + PGRES = 1'b1; + PGRES <= #5 1'b0; + RES_TO_SUSP_MIN_TIME = 1'b1; + RES_TO_SUSP_MIN_TIME <= #60000 1'b0;//60 ns + RES_TO_SUSP_TYP_TIME = 1'b1; + RES_TO_SUSP_TYP_TIME <= #100000000 1'b0;//100us + end + + if (Instruct == BRAC && P_ERR == 0 && E_ERR == 0 && + RdPswdProtMode == 0) + begin + BAR_ACC = 1; + end + else + begin + BAR_ACC = 0; + end + end + end + + ERS_SUSP_PG_SUSP: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + + if (PRGSUSP_out && PRGSUSP_in) + begin + PRGSUSP_in = 1'b0; + //The RDY/BSY bit in the Status Register will indicate that + //the device is ready for another operation. + Status_reg1[0] = 1'b0; + //The Program Suspend (PS) bit in the Status Register will + //be set to the logical “1” state to indicate that the + //program operation has been suspended. + Status_reg2[0] = 1'b1; + end + + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == BRRD) + begin + //Read Bank Address Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = Bank_Addr_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + //Read Array Operations + else if (Instruct == READ || Instruct == RD4 || + Instruct == FSTRD || Instruct == FSTRD4 || + Instruct == DDRFR || Instruct == DDRFR4 ) + begin + //Read Memory array + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + if ((SectorSuspend != read_addr/(SecSize+1)) && + (pgm_page != read_addr / (PageSize+1))) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + + end + end + else + begin + SOut_zd = 8'bxxxxxxxx; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 ) + begin + //Read Memory array + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if ((SectorSuspend != read_addr/(SecSize+1)) && + (pgm_page != read_addr / (PageSize+1))) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4 ) + begin + //Read Memory array + if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if ((SectorSuspend != read_addr/(SecSize+1)) && + (pgm_page != read_addr / (PageSize+1))) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if ((Instruct == DDRQIOR + || Instruct == DDRQIOR4) && QUAD) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + HOLDNegOut_zd =data_out[7-read_cnt]; + WPNegOut_zd = data_out[7-read_cnt]; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + HOLDNegOut_zd = 1'bx; + WPNegOut_zd = 1'bx; + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + end + else if (oe_z) + begin + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (falling_edge_write) + begin + if (Instruct == BRWR) + begin + Bank_Addr_reg[7] = Bank_Addr_reg_in[7]; + Bank_Addr_reg[1] = Bank_Addr_reg_in[1]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + end + else if (Instruct == WRR && BAR_ACC == 1) + begin + // Write to the lower address bits of the BAR + if (P_ERR == 0 && E_ERR == 0) + begin + Bank_Addr_reg[1] = Bank_Addr_reg_in[1]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + end + end + else if (Instruct == PGRS) + begin + Status_reg2[0] = 1'b0; + Status_reg1[0] = 1'b1; + PGRES = 1'b1; + PGRES <= #5 1'b0; + RES_TO_SUSP_MIN_TIME = 1'b1; + RES_TO_SUSP_MIN_TIME <= #60000 1'b0;//60 ns + RES_TO_SUSP_TYP_TIME = 1'b1; + RES_TO_SUSP_TYP_TIME <= #100000000 1'b0;//100us + end + + if (Instruct == BRAC && P_ERR == 0 && E_ERR == 0 && + RdPswdProtMode == 0) + begin + BAR_ACC = 1; + end + else + begin + BAR_ACC = 0; + end + end + end + + OTP_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == OTP_PG) + begin + if (~PDONE) + begin + if (Address + wr_cnt <= OTPHiAddr) + begin + for (i=0;i<=wr_cnt;i=i+1) + begin + new_int = WData[i]; + old_int = OTPMem[Addr + i]; + if (new_int > -1) + begin + new_bit = new_int; + if (old_int > -1) + begin + old_bit = old_int; + for(j=0;j<=7;j=j+1) + begin + if (~old_bit[j]) + new_bit[j] = 1'b0; + end + new_int = new_bit; + end + WData[i] = new_int; + end + else + begin + WData[i] = -1; + end + OTPMem[Addr + i] = -1; + end + end + else + begin + $display ("Programming will reach over "); + $display ("address limit of OTP array"); + end + end + end + + if (PDONE) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + for (i=0;i<=wr_cnt;i=i+1) + begin + OTPMem[Addr + i] = WData[i]; + end + LOCK_BYTE1 = OTPMem[16]; + LOCK_BYTE2 = OTPMem[17]; + LOCK_BYTE3 = OTPMem[18]; + LOCK_BYTE4 = OTPMem[19]; + end + end + + SECTOR_ERS: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == SECTOR_ERS) + begin + if (~EDONE) + begin + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = -1; + end + end + end + + if (EDONE == 1) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = MaxData; + end + end + else if (Instruct == ERSP && ~ERSSUSP_in) + begin + ESUSP = 1'b1; + ESUSP <= #5 1'b0; + ERSSUSP_in = 1'b1; + if (RES_TO_SUSP_TYP_TIME) + begin + $display("Typical periods are needed for ", + "Program to progress to completion"); + end + end + end + + BULK_ERS: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == BULK_ERS) + begin + if (~EDONE) + begin + for (i=0;i<=AddrRANGE;i=i+1) + begin + ReturnSectorID(sect,i); + if (PPB_bits[sect] == 1 && DYB_bits[sect] == 1) + begin + Mem[i] = -1; + end + end + end + end + + if (EDONE == 1) + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + for (i=0;i<=AddrRANGE;i=i+1) + begin + ReturnSectorID(sect,i); + if (PPB_bits[sect] == 1 && DYB_bits[sect] == 1) + begin + Mem[i] = MaxData; + end + end + end + end + + ERS_SUSP: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (ERSSUSP_out == 1) + begin + ERSSUSP_in = 0; + //The Erase Suspend (ES) bit in the Status Register will + //be set to the logical “1” state to indicate that the + //erase operation has been suspended. + Status_reg2[1] = 1'b1; + //The WIP bit in the Status Register will indicate that + //the device is ready for another operation. + Status_reg1[0] = 1'b0; + end + + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == DYBRD) + begin + //Read DYB Access Register + ReturnSectorID(sect,Address); + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (DYB_bits[sect] == 1) + DYBAR[7:0] = 8'hFF; + else + begin + DYBAR[7:0] = 8'h0; + end + SOut_zd = DYBAR[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == BRRD) + begin + //Read Bank Address Register + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + SOut_zd = Bank_Addr_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == PPBRD) + begin + //Read PPB Access Register + ReturnSectorID(sect,Address); + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + PPBAR[7:0] = 8'bXXXXXXXX; + if (RdPswdProtMode == 0) + begin + if (PPB_bits[sect] == 1) + PPBAR[7:0] = 8'hFF; + else + begin + PPBAR[7:0] = 8'h0; + end + end + SOut_zd = PPBAR[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == READ || Instruct == RD4 || + Instruct == FSTRD || Instruct == FSTRD4 || + Instruct == DDRFR || Instruct == DDRFR4 ) + begin + //Read Memory array + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + if (SectorSuspend != read_addr/(SecSize+1)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + SOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == DDRDIOR || Instruct == DDRDIOR4 ) + begin + //Read Memory array + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (SectorSuspend != read_addr/(SecSize+1)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else if (Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4 || + Instruct == DDRQIOR || Instruct == DDRQIOR4 ) + begin + //Read Memory array + if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + if (SectorSuspend != read_addr/(SecSize+1)) + begin + if (bus_cycle_state == DUMMY_BYTES) + begin + if ((Instruct == DDRQIOR + || Instruct == DDRQIOR4) && QUAD) + begin + Return_DLP(Instruct, EHP, Latency_code, + dummy_cnt, dlp_act); + // Data Learning Pattern (DLP) + // is enabled Optional DLP + if (VDLR_reg != 8'b00000000 + && dlp_act == 1'b1) + begin + data_out[7:0] = VDLR_reg; + HOLDNegOut_zd= data_out[7-read_cnt]; + WPNegOut_zd = data_out[7-read_cnt]; + SOut_zd = data_out[7-read_cnt]; + SIOut_zd = data_out[7-read_cnt]; + dlp_act = 1'b0; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + end + end + end + end + else + begin + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + else + begin + HOLDNegOut_zd = 1'bx; + WPNegOut_zd = 1'bx; + SOut_zd = 1'bx; + SIOut_zd = 1'bx; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + end + end + else if (oe_z) + begin + if (Instruct == READ || Instruct == RD4) + begin + rd_fast = 1'b0; + rd_slow = 1'b1; + dual = 1'b0; + ddr = 1'b0; + end + else if (Instruct == DDRFR || Instruct == DDRFR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b1; + end + else if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else if (Instruct == DOR || Instruct == DOR4 || + Instruct == DIOR || Instruct == DIOR4 || + Instruct == QOR || Instruct == QOR4 || + Instruct == QIOR || Instruct == QIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b0; + end + else if (Instruct == DDRQIOR || Instruct == DDRQIOR4) + begin + rd_fast = 1'b0; + rd_slow = 1'b0; + dual = 1'b1; + ddr = 1'b1; + end + else + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + end + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (falling_edge_write) + begin + if ((Instruct == PP || Instruct == PP4) && WEL == 1) + begin + if (SectorSuspend != Address/(SecSize+1)) + begin + ReturnSectorID(sect,Address); + if (Sec_Prot[sect] == 0 && + PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 0; + PGRES = 0; + Status_reg1[0] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + end + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + end + end + else if ((Instruct == QPP || Instruct == QPP4) && WEL == 1) + begin + if (SectorSuspend != Address/(SecSize+1)) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + + if (Sec_Prot[sect] == 0 + && PPB_bits[sect]== 1 && DYB_bits[sect]== 1) + begin + PSTART = 1'b1; + PSTART <= #5 1'b0; + PGSUSP = 0; + PGRES = 0; + Status_reg1[0] = 1'b1; + QPP_page[pgm_page] = 1'b1; + SA = sect; + Addr = Address; + Addr_tmp= Address; + wr_cnt = Byte_number; + for (i=wr_cnt;i>=0;i=i-1) + begin + if (Viol != 0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + end + end + else + begin + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; + end + end + else if (Instruct == WREN) + Status_reg1[1] = 1'b1; + else if (Instruct == CLSR) + begin + //The Clear Status Register Command resets bit SR1[5] + //(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + Status_reg1[5] = 0; + Status_reg1[6] = 0; + end + else if (Instruct == BRWR) + begin + Bank_Addr_reg[7] = Bank_Addr_reg_in[7]; + Bank_Addr_reg[1] = Bank_Addr_reg_in[1]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + end + else if (Instruct == WRR && BAR_ACC == 1) + begin + // Write to the lower address bits of the BAR + if (P_ERR == 0 && E_ERR == 0) + begin + Bank_Addr_reg[1] = Bank_Addr_reg_in[1]; + Bank_Addr_reg[0] = Bank_Addr_reg_in[0]; + end + end + else if (Instruct == DYBWR && WEL == 1) + begin + ReturnSectorID(sect,Address); + pgm_page = Address / (PageSize+1); + PSTART = 1'b1; + PSTART <= #5 1'b0; + Status_reg1[0] = 1'b1; + end + else if (Instruct == ERRS) + begin + Status_reg2[1] = 1'b0; + Status_reg1[0] = 1'b1; + Addr = SectorSuspend*(SecSize+1); + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + ERES = 1'b1; + ERES <= #5 1'b0; + RES_TO_SUSP_TYP_TIME = 1'b1; + RES_TO_SUSP_TYP_TIME <= #100000000 1'b0;//100us + end + + if (Instruct == BRAC && P_ERR == 0 && E_ERR == 0 && + RdPswdProtMode == 0) + begin + BAR_ACC = 1; + end + else + begin + BAR_ACC = 0; + end + end + end + + ERS_SUSP_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if(current_state_event && current_state == ERS_SUSP_PG) + begin + if (~PDONE) + begin + ADDRHILO_PG(AddrLo, AddrHi, Addr); + cnt = 0; + for (i=0;i<=wr_cnt;i=i+1) + begin + new_int = WData[i]; + old_int = Mem[Addr + i - cnt]; + if (new_int > -1) + begin + new_bit = new_int; + if (old_int > -1) + begin + old_bit = old_int; + for(j=0;j<=7;j=j+1) + begin + if (~old_bit[j]) + new_bit[j] = 1'b0; + end + new_int = new_bit; + end + WData[i] = new_int; + end + else + begin + WData[i] = -1; + end + + if ((Addr + i) == AddrHi) + begin + Addr = AddrLo; + cnt = i + 1; + end + end + end + cnt =0; + end + + if(PDONE == 1) + begin + Status_reg1[0] = 1'b0;//WIP + Status_reg1[1] = 1'b0;//WEL + for (i=0;i<=wr_cnt;i=i+1) + begin + Mem[Addr_tmp + i - cnt] = WData[i]; + if ((Addr_tmp + i) == AddrHi ) + begin + Addr_tmp = AddrLo; + cnt = i + 1; + end + end + end + + if (Instruct) + begin + if (Instruct == PGSP && ~PRGSUSP_in) + begin + if (~RES_TO_SUSP_MIN_TIME) + begin + PGSUSP = 1'b1; + PGSUSP <= #5 1'b0; + PRGSUSP_in = 1'b1; + if (RES_TO_SUSP_TYP_TIME) + begin + $display("Typical periods are needed for ", + "Program to progress to completion"); + end + end + else + begin + $display("Minimum for tPRS is not satisfied! ", + "PGSP command is ignored"); + end + end + end + end + + PASS_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + new_pass = Password_reg_in; + old_pass = Password_reg; + for (i=0;i<=63;i=i+1) + begin + if (old_pass[j] == 0) + new_pass[j] = 0; + end + + if (PDONE == 1) + begin + Password_reg = new_pass; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + PASS_UNLOCK: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PASS_TEMP == Password_reg) + begin + PASS_UNLOCKED = 1'b1; + end + else + begin + PASS_UNLOCKED = 1'b0; + end + if (PASSULCK_out == 1'b1) + begin + if ((PASS_UNLOCKED == 1'b1) && (~PWDMLB)) + begin + PPBL[0] = 1'b1; + Status_reg1[0] = 1'b0; //WIP + end + else + begin + Status_reg1[6] = 1'b1; + $display ("Incorrect Password"); + PASSACC_in = 1'b1; + end + Status_reg1[1] = 1'b0; + PASSULCK_in = 1'b0; + end + end + + PPB_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + if (PPB_LOCK !== 0) + begin + PPB_bits[sect]= 1'b0; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + else + begin + Status_reg1[5] = 1'b0; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + end + + PPB_ERS: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PPBERASE_out == 1'b1) + begin + if ((PPB_LOCK !== 0) && PPBOTP) + begin + PPB_bits = {512{1'b1}}; + end + else + begin + Status_reg1[5] = 1'b1; + end + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + PPBERASE_in = 1'b0; + end + end + + AUTOBOOT_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register 2 + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + AutoBoot_reg = AutoBoot_reg_in; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + PLB_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + PPBL[0] = 1'b0; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + DYB_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + DYBAR = DYBAR_in; + if (DYBAR == 8'hFF) + begin + DYB_bits[sect]= 1'b1; + end + else if (DYBAR == 8'h00) + begin + DYB_bits[sect]= 1'b0; + end + else + begin + Status_reg1[6] = 1'b1; + end + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + ASP_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + + if (RPME == 1'b0 && ASP_reg_in[5] == 1'b1) + begin + Status_reg1[6] = 1'b1; //P_ERR + $display("RPME bit is allready programmed"); + end + else + begin + ASP_reg[5] = ASP_reg_in[5];//RPME + end + + if (PPBOTP == 1'b0 && ASP_reg_in[3] == 1'b1) + begin + Status_reg1[6] = 1'b1; //P_ERR + $display("PPBOTP bit is allready programmed"); + end + else + begin + ASP_reg[3] = ASP_reg_in[3];//PPBOTP + end + + if (PWDMLB == 1'b1 && PSTMLB == 1'b1) + begin + if (ASP_reg_in[2] == 1'b0 && ASP_reg_in[1] == 1'b0) + begin + $display("ASPR[2:1] = 00 Illegal condition"); + Status_reg1[6] = 1'b1; //P_ERR + end + else + begin + if (ASP_reg_in[2]!==1'b1 || ASP_reg_in[1]!==1'b1) + begin + ASPOTPFLAG = 1'b1; + end + ASP_reg[2] = ASP_reg_in[2];//PWDMLB + ASP_reg[1] = ASP_reg_in[1];//PSTMLB + end + end + + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + end + + NVDLR_PG: + begin + rd_fast = 1'b1; + rd_slow = 1'b0; + dual = 1'b0; + ddr = 1'b0; + if (oe) + begin + any_read = 1'b1; + if (Instruct == RDSR) + begin + //Read Status Register 1 + SOut_zd = Status_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDSR2) + begin + //Read Status Register + SOut_zd = Status_reg2[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == RDCR) + begin + //Read Configuration Register 1 + SOut_zd = Config_reg1[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (oe_z) + begin + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + end + + if (PDONE) + begin + if (NVDLR_reg == 0) + begin + NVDLR_reg = NVDLR_reg_in; + VDLR_reg = NVDLR_reg_in; + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + end + else + begin + Status_reg1[0] = 1'b0; + Status_reg1[1] = 1'b0; + Status_reg1[6] = 1'b1; //P_ERR + $display("NVDLR bits allready programmed"); + end + end + end + + RESET_STATE: + begin + //the default condition hardware reset + //The Bank Address Register is loaded to all zeroes + Bank_Addr_reg = 8'h0; + if (BPNV && ~LOCK && ~FREEZE) + begin + Status_reg1[2] = 1'b1;// BP0 + Status_reg1[3] = 1'b1;// BP1 + Status_reg1[4] = 1'b1;// BP2 + BP_bits = 3'b111; + change_BP = 1'b1; + #1000 change_BP = 1'b0; + end + //Resets the volatile bits in the Status register 1 + Status_reg1[6] = 1'b0; + Status_reg1[5] = 1'b0; + Status_reg1[1] = 1'b0; + Status_reg1[0] = 1'b0; + //Resets the volatile bits in the Status register 2 + Status_reg2[1] = 1'b0; + Status_reg2[0] = 1'b0; + //Resets the volatile bits in the Configuration register 1 + Config_reg1[0] = 1'b0; + //On reset cycles the data pattern reverts back + //to what is in the NVDLR + VDLR_reg = NVDLR_reg; + dlp_act = 1'b0; + //Loads the Program Buffer with all ones + for(i=0;i<=511;i=i+1) + begin + WData[i] = MaxData; + end + if (~PWDMLB) + PPBL[0] = 1'b0; + else + PPBL[0] = 1'b1; + end + + endcase + + //Output Disable Control + if (CSNeg_ipd ) + begin + SOut_zd = 1'bZ; + SIOut_zd = 1'bZ; + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + end + end + + assign fast_rd = rd_fast; + assign rd = rd_slow; + assign ddrd = ddr; + assign fast_ddr = ddr_fast; + + always @(posedge change_BP) + begin + case (Status_reg1[4:2]) + + 3'b000: + begin + Sec_Prot = 256'b0; + end + + 3'b001: + begin + if (~TBPROT) + begin + Sec_Prot[SecNum:(SecNum+1)*63/64] = 4'b1111; + Sec_Prot[(SecNum+1)*63/64-1 : 0] = 252'h0; + end + else + begin + Sec_Prot[(SecNum+1)/64-1 : 0] = 4'b1111; + Sec_Prot[SecNum : (SecNum+1)/64] = 252'h0; + end + end + + 3'b010: + begin + if (~TBPROT) + begin + Sec_Prot[SecNum : (SecNum+1)*31/32] = 8'b11111111; + Sec_Prot[(SecNum+1)*31/32-1 : 0] = 248'h0; + end + else + begin + Sec_Prot[(SecNum+1)/32-1 : 0] = 8'b11111111; + Sec_Prot[SecNum : (SecNum+1)/32] = 248'h0; + end + end + + 3'b011: + begin + if (~TBPROT) + begin + Sec_Prot[SecNum : (SecNum+1)*15/16] = 16'hFFFF; + Sec_Prot[(SecNum+1)*15/16-1 : 0] = 240'h0; + end + else + begin + Sec_Prot[(SecNum+1)/16-1 : 0] = 16'hFFFF; + Sec_Prot[SecNum : (SecNum+1)/16] = 240'h0; + end + end + + 3'b100: + begin + if (~TBPROT) + begin + Sec_Prot[SecNum : (SecNum+1)*7/8] = 32'hFFFFFFFF; + Sec_Prot[(SecNum+1)*7/8-1 : 0] = 224'h0; + end + else + begin + Sec_Prot[(SecNum+1)/8-1 : 0] = 32'hFFFFFFFF; + Sec_Prot[SecNum : (SecNum+1)/8] = 224'h0; + end + end + + 3'b101: + begin + if (~TBPROT) + begin + Sec_Prot[SecNum : (SecNum+1)*3/4] + = 64'hFFFFFFFFFFFFFFFF; + Sec_Prot[(SecNum+1)*3/4-1 : 0] = 192'h0; + end + else + begin + Sec_Prot[(SecNum+1)/4-1 : 0] = 64'hFFFFFFFFFFFFFFFF; + Sec_Prot[SecNum : (SecNum+1)/4] = 192'h0; + end + end + + 3'b110: + begin + if (~TBPROT) + begin + Sec_Prot[SecNum : (SecNum+1)/2] + = 128'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + Sec_Prot[(SecNum+1)/2-1 : 0] = 128'h0; + end + else + begin + Sec_Prot[(SecNum+1)/2-1 : 0] + = 128'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + Sec_Prot[SecNum : (SecNum+1)/2] = 128'h0; + end + end + + 3'b111: + begin + Sec_Prot[127:0] = 128'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + Sec_Prot[255:128] = 128'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + end + endcase + end + + always @(SOut_zd or HOLDNeg_in or SIOut_zd) + begin + if (HOLDNeg_in == 0 && ~QUAD) + begin + hold_mode = 1'b1; + SIOut_z = 1'bZ; + SOut_z = 1'bZ; + end + else + begin + if (hold_mode == 1) + begin + SIOut_z <= #(tpd_HOLDNeg_SO) SIOut_zd; + SOut_z <= #(tpd_HOLDNeg_SO) SOut_zd; + hold_mode = #(tpd_HOLDNeg_SO) 1'b0; + end + else + begin + SIOut_z = SIOut_zd; + SOut_z = SOut_zd; + hold_mode = 1'b0; + end + end + end + + //////////////////////////////////////////////////////////////////////// + // autoboot control logic + //////////////////////////////////////////////////////////////////////// + always @(rising_edge_SCK_ipd or current_state_event) + begin + if(current_state == AUTOBOOT) + begin + if (rising_edge_SCK_ipd) + begin + if (start_delay > 0) + start_delay = start_delay - 1; + end + + if (start_delay == 0) + begin + start_autoboot = 1; + end + end + end + + //////////////////////////////////////////////////////////////////////// + // functions & tasks + //////////////////////////////////////////////////////////////////////// + // Procedure FDDR_DPL + task Return_DLP; + input integer Instruct; + input integer EHP; + input integer Latency_code; + input integer dummy_cnt; + inout dlp_act; + begin + if (Instruct == DDRFR || Instruct == DDRFR4) + begin + if (EHP) + begin + if (Latency_code == 1) + dlp_act = 1'b1; + else if (Latency_code == 2 && dummy_cnt >= 1) + dlp_act = 1'b1; + else if(Latency_code == 3 || Latency_code == 0) + begin + dlp_act = 1'b0; + $display("Warning at", $time); + $display("Inappropriate latency is set during DPL mode"); + end + end + else + begin + if (Latency_code == 3) + dlp_act = 1'b1; + else if (Latency_code == 0 && dummy_cnt >= 1) + dlp_act = 1'b1; + else if(Latency_code == 1 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if(Latency_code == 2 && dummy_cnt >= 3) + dlp_act = 1'b1; + end + end + if (Instruct == DDRDIOR || Instruct == DDRDIOR4) + begin + if (EHP) + begin + if (Latency_code == 1 && dummy_cnt >= 1) + dlp_act = 1'b1; + else if (Latency_code == 2 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if( Latency_code == 3 || Latency_code == 0) + begin + dlp_act = 1'b0; + $display("Warning at", $time); + $display("Inappropriate latency is set during DPL mode"); + end + end + else + begin + if (Latency_code == 3) + dlp_act = 1'b0; + else if (Latency_code == 0 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if (Latency_code == 1 && dummy_cnt >= 3) + dlp_act = 1'b1; + else if(Latency_code == 2 && dummy_cnt >= 4) + dlp_act = 1'b1; + end + end + if ((Instruct == DDRQIOR || Instruct == DDRQIOR4) && QUAD) + begin + if (EHP) + begin + if (Latency_code == 0 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if (Latency_code == 1 && dummy_cnt >= 3) + dlp_act = 1'b1; + else if (Latency_code == 2 && dummy_cnt >= 4) + dlp_act = 1'b1; + else if( Latency_code == 3) + begin + dlp_act = 1'b0; + $display("Warning at", $time); + $display("Inappropriate latency is"); + $display("set during DPL mode"); + end + end + else + begin + if (Latency_code == 0 && dummy_cnt >= 2) + dlp_act = 1'b1; + else if (Latency_code == 1 && dummy_cnt >= 3) + dlp_act = 1'b1; + else if (Latency_code == 2 && dummy_cnt >= 4) + dlp_act = 1'b1; + else if( Latency_code == 3) + begin + dlp_act = 1'b0; + $display("Warning at", $time); + $display("Inappropriate latency is"); + $display("set during DPL mode"); + end + end + end + end + endtask + + function integer ReturnSectorIDRdPswdMd; + input reg TBPROT; + begin + if(TBPROT == 0) + begin + ReturnSectorIDRdPswdMd = 0; + end + else + begin + ReturnSectorIDRdPswdMd = SecNum; + end + end + endfunction + + // Procedure ADDRHILO_SEC + task ADDRHILO_SEC; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer sector; + begin + sector = Addr/(SecSize+1); + AddrLOW = sector*(SecSize+1); + AddrHIGH = sector*(SecSize+1) + SecSize; + end + endtask + + // Procedure ADDRHILO_PG + task ADDRHILO_PG; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer page; + begin + page = Addr / (PageSize + 1); + AddrLOW = page * (PageSize + 1); + AddrHIGH = page * (PageSize + 1) + PageSize; + end + endtask + + // Procedure ReturnSectorID + task ReturnSectorID; + inout sect; + input Address; + integer sect; + integer Address; + integer conv; + begin + sect = Address/(SecSize+1); + end + endtask + + always @(PPBL[0], ASP_reg) + begin + if (PPBL[0] == 0 && PWDMLB == 0 && RPME == 0 && RdPswdProtEnable) + begin + RdPswdProtMode = 1; + AutoBoot_reg[0] = 0;//AUTOBOOT is disabled when Read Password + end //Protection is enabled + else + begin + RdPswdProtMode = 0; + end + end + + /////////////////////////////////////////////////////////////////////////// + // edge controll processes + /////////////////////////////////////////////////////////////////////////// + + always @(posedge PoweredUp) + begin + rising_edge_PoweredUp = 1; + #1000 rising_edge_PoweredUp = 0; + end + + always @(posedge SCK_ipd) + begin + rising_edge_SCK_ipd = 1'b1; + #1000 rising_edge_SCK_ipd = 1'b0; + end + + always @(negedge SCK_ipd) + begin + falling_edge_SCK_ipd = 1'b1; + #1000 falling_edge_SCK_ipd = 1'b0; + end + + always @(posedge read_out) + begin + rising_edge_read_out = 1'b1; + #1000 rising_edge_read_out = 1'b0; + end + + always @(negedge write) + begin + falling_edge_write = 1; + #1000 falling_edge_write = 0; + end + + always @(posedge PRGSUSP_out) + begin + PRGSUSP_out_event = 1; + #1000 PRGSUSP_out_event = 0; + end + + always @(posedge ERSSUSP_out) + begin + ERSSUSP_out_event = 1; + #1000 ERSSUSP_out_event = 0; + end + + always @(posedge CSNeg_ipd) + begin + rising_edge_CSNeg_ipd = 1'b1; + #1000 rising_edge_CSNeg_ipd = 1'b0; + end + + always @(negedge CSNeg_ipd) + begin + falling_edge_CSNeg_ipd = 1'b1; + #1000 falling_edge_CSNeg_ipd = 1'b0; + end + + always @(negedge RSTNeg_in) + begin + falling_edge_RSTNeg = 1'b1; + #50000 falling_edge_RSTNeg = 1'b0; + end + + always @(posedge RSTNeg_in) + begin + rising_edge_RSTNeg = 1'b1; + #10000 rising_edge_RSTNeg = 1'b0; + end + + always @(negedge RST) + begin + falling_edge_RST = 1'b1; + #10000 falling_edge_RST = 1'b0; + end + + always @(posedge RST) + begin + rising_edge_RST = 1'b1; + #1000 rising_edge_RST = 1'b0; + end + + always @(posedge PDONE) + begin + rising_edge_PDONE = 1'b1; + #1000 rising_edge_PDONE = 1'b0; + end + + always @(posedge WDONE) + begin + rising_edge_WDONE = 1'b1; + #1000 rising_edge_WDONE = 1'b0; + end + + always @(posedge WSTART) + begin + rising_edge_WSTART = 1'b1; + #1000 rising_edge_WSTART = 1'b0; + end + + always @(posedge EDONE) + begin + rising_edge_EDONE = 1'b1; + #1000 rising_edge_EDONE = 1'b0; + end + + always @(posedge ESTART) + begin + rising_edge_ESTART = 1'b1; + #1000 rising_edge_ESTART = 1'b0; + end + + always @(posedge PSTART) + begin + rising_edge_PSTART = 1'b1; + #1000 rising_edge_PSTART = 1'b0; + end + + always @(posedge Reseted) + begin + rising_edge_Reseted = 1'b1; + #1000 rising_edge_Reseted = 1'b0; + end + + always @(negedge PASSULCK_in) + begin + falling_edge_PASSULCK_in = 1'b1; + #1000 falling_edge_PASSULCK_in = 1'b0; + end + + always @(negedge PPBERASE_in) + begin + falling_edge_PPBERASE_in = 1'b1; + #1000 falling_edge_PPBERASE_in = 1'b0; + end + + always @(Instruct) + begin + Instruct_event = 1'b1; + #1000 Instruct_event = 1'b0; + end + + always @(change_addr) + begin + change_addr_event = 1'b1; + #1000 change_addr_event = 1'b0; + end + + always @(next_state) + begin + next_state_event = 1'b1; + #1000 next_state_event = 1'b0; + end + + always @(current_state) + begin + current_state_event = 1'b1; + #1000 current_state_event = 1'b0; + end + + always @(posedge RST_out) + begin + rising_edge_RST_out = 1'b1; + #1000 rising_edge_RST_out = 1'b0; + end + +endmodule \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl512s/model/s25fl512s.vhd b/lib/models/memory/flash/serial/S25fl512s/model/s25fl512s.vhd new file mode 100644 index 0000000..2867468 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl512s/model/s25fl512s.vhd @@ -0,0 +1,13905 @@ +------------------------------------------------------------------------------- +-- File Name: s25fl512s.vhd +------------------------------------------------------------------------------- +-- Copyright (C) 2011 Spansion, LLC. +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 V.Mancev 09 Nov 26 Inital Release +-- V1.1 V.Mancev 10 Mar 04 addr_cnt for second read in +-- high performance read continuous +-- mode can change its value only +-- when CSNeg = '0' +-- V1.2 V.Mancev 10 July 28 During the QUAD mode HOLD# input +-- is not monitored for its normal +-- function +-- V1.3 V.Mancev 10 Oct 28 Latest datasheet aligned +-- V1.4 V.Mancev 10 Nov 15 QUAD Program operation during Erase +-- Suspend is added +-- Warning for Resume to Suspend time +-- is added +-- During Erase Suspend, after Program +-- operation is completed, WEL bit is +-- cleared +-- Implemetation of Software Reset is +-- Changed +-- V1.2 V.Mancev 11 July 11 Latest datasheet aligned +-- V1.3 V.Mancev 22 July 11 Corrections for P4E and P4E4 +-- V1.4 V. Mancev 18 Nov 11 Time tHO is changed to 1 ns +-- (customer's request) +-- BRWR instruction is corrected +-- V1.5 S.Petrovic 02 Jun 12 QPP Instruction is allowed on +-- previously programmed page +------------------------------------------------------------------------------- +-- PART DESCRIPTION: +-- +-- Library: FLASH +-- Technology: FLASH MEMORY +-- Part: S25FL512S +-- +-- Description: 512 Megabit Serial Flash Memory +-- +------------------------------------------------------------------------------- +-- Comments : +-- For correct simulation, simulator resolution should be set to 1 ps +-- A device ordering (trim) option determines whether a feature is enabled +-- or not, or provide relevant parameters: +-- -15th character in TimingModel determines if enhanced high +-- performance option is available +-- (0,2,3,R,A,B,C,D) EHPLC +-- (Y,Z,S,T,K,L) Security EHPLC +-- (4,6,7,8,9,Q) HPLC +-- -15th character in TimingModel determines if RESET# input +-- is available +-- (R,A,B,C,D,Q.6,7,K,L,S,T,M,N,U,V) RESET# is available +-- (0,2,3,4,8,9,Y.Z.W,X) RESET# is tied to the inactive +-- state,inside the package. +-- +-------------------------------------------------------------------------------- +-- Known Bugs: +-- +-------------------------------------------------------------------------------- +LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; + USE STD.textio.ALL; + USE IEEE.VITAL_timing.ALL; + USE IEEE.VITAL_primitives.ALL; + +LIBRARY FMF; USE FMF.gen_utils.ALL; + USE FMF.conversions.ALL; +------------------------------------------------------------------------------- +-- ENTITY DECLARATION +------------------------------------------------------------------------------- +ENTITY s25fl512s IS + GENERIC ( + --------------------------------------------------------------------------- + -- TIMING GENERICS: + --------------------------------------------------------------------------- + -- tipd delays: interconnect path delays (delay between components) + -- There should be one for each IN or INOUT pin in the port list + -- They are given default values of zero delay. + tipd_SCK : VitalDelayType01 := VitalZeroDelay01; + tipd_SI : VitalDelayType01 := VitalZeroDelay01; + tipd_SO : VitalDelayType01 := VitalZeroDelay01; + + tipd_CSNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_HOLDNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_RSTNeg : VitalDelayType01 := VitalZeroDelay01; + + -- tpd delays: propagation delays (pin-to-pin delay within a component) + tpd_SCK_SO_normal : VitalDelayType01Z := UnitDelay01Z; -- tV, tHO + tpd_CSNeg_SO : VitalDelayType01Z := UnitDelay01Z; -- tDIS + tpd_HOLDNeg_SO : VitalDelayType01Z := UnitDelay01Z;-- + tpd_RSTNeg_SO : VitalDelayType01Z := UnitDelay01Z;-- + -- DDR operation values + tpd_SCK_SO_DDR : VitalDelayType01Z := UnitDelay01Z;--tV(66MHz) + + -- tsetup values: setup times + -- setup time is minimum time before the referent signal edge the + -- input should be stable + tsetup_CSNeg_SCK_normal_noedge_posedge + : VitalDelayType := UnitDelay; -- tCSS / + tsetup_CSNeg_SCK_DDR_noedge_posedge + : VitalDelayType := UnitDelay; -- tCSS / + tsetup_SI_SCK_normal_noedge_posedge: VitalDelayType + := UnitDelay; -- tSU:DAT / + tsetup_WPNeg_CSNeg : VitalDelayType := UnitDelay; -- tWPS \ + tsetup_HOLDNeg_SCK : VitalDelayType := UnitDelay; + tsetup_RSTNeg_CSNeg : VitalDelayType := UnitDelay; -- tRP + -- DDR operation values + tsetup_SI_SCK_DDR_noedge_posedge: VitalDelayType + := UnitDelay; -- tSU / + tsetup_SI_SCK_DDR_noedge_negedge: VitalDelayType + := UnitDelay; -- tSU \ + + -- thold values: hold times + -- hold time is minimum time the input should be present stable + -- after the referent signal edge + thold_CSNeg_SCK_normal_noedge_posedge + : VitalDelayType := UnitDelay; -- tCSH / + thold_CSNeg_SCK_DDR_noedge_posedge + : VitalDelayType := UnitDelay; -- tCSH / + thold_SI_SCK_normal_noedge_posedge: VitalDelayType + := UnitDelay; -- tHD:DAT / + thold_WPNeg_CSNeg : VitalDelayType := UnitDelay; -- tWPH / + thold_HOLDNeg_SCK : VitalDelayType := UnitDelay; -- + thold_CSNeg_RSTNeg : VitalDelayType := UnitDelay; -- tRPH + -- DDR operation values + thold_SI_SCK_DDR_noedge_posedge: VitalDelayType + := UnitDelay; -- tHD / + thold_SI_SCK_DDR_noedge_negedge: VitalDelayType + := UnitDelay; -- tHD \ + + --tpw values: pulse width + tpw_SCK_serial_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_dual_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_fast_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_quadpg_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_serial_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_SCK_dual_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_SCK_fast_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_SCK_quadpg_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_CSNeg_read_posedge : VitalDelayType := UnitDelay; -- tCS + tpw_CSNeg_pgers_posedge : VitalDelayType := UnitDelay; -- tCS + tpw_RSTNeg_negedge : VitalDelayType := UnitDelay; -- tRP + tpw_RSTNeg_posedge : VitalDelayType := UnitDelay; -- tRS + -- DDR operation values + tpw_SCK_DDR_posedge : VitalDelayType := UnitDelay; -- tWH(66MHz) + tpw_SCK_DDR_negedge : VitalDelayType := UnitDelay; -- tWL(66Hz) + + -- tperiod min (calculated as 1/max freq) + tperiod_SCK_serial_rd : VitalDelayType := UnitDelay; --fSCK=50MHz + tperiod_SCK_fast_rd : VitalDelayType := UnitDelay; --fSCK=133MHz + tperiod_SCK_dual_rd : VitalDelayType := UnitDelay; --fSCK=104MHz + tperiod_SCK_quadpg : VitalDelayType := UnitDelay; --fSCK=80MHz + -- DDR operation values + tperiod_SCK_DDR_rd : VitalDelayType := UnitDelay; --fSCK=66MHz + + -- tdevice values: values for internal delays + --timing values that are internal to the model and not associated + --with any port. + tdevice_PP : VitalDelayType := 750 us; --tPP + -- Typical Byte Programming Time + tdevice_BP : VitalDelayType := 400 us; --tBP + -- Sector Erase Operation + tdevice_SE : VitalDelayType := 1875 ms; --tSE + -- Bulk Erase Operation + tdevice_BE : VitalDelayType := 460 sec; --tBE + -- WRR Cycle Time + tdevice_WRR : VitalDelayType := 200 ms; --tW + -- Erase Suspend/Erase Resume Time + tdevice_ERSSUSP : VitalDelayType := 40 us; --tESL + -- Program Suspend/Program Resume Time + tdevice_PRGSUSP : VitalDelayType := 40 us; --tPSL + -- VCC (min) to CS# Low + tdevice_PU : VitalDelayType := 300 us; --tPU + -- PPB Erase Time + tdevice_PPBERASE :VitalDelayType := 15 ms; + -- Password Unlock Time + tdevice_PASSULCK :VitalDelayType := 1 us; + -- Password Unlock Time + tdevice_PASSACC :VitalDelayType := 100 us; + + --------------------------------------------------------------------------- + -- CONTROL GENERICS: + --------------------------------------------------------------------------- + -- generic control parameters + InstancePath : STRING := DefaultInstancePath; + TimingChecksOn : BOOLEAN := DefaultTimingChecks; + MsgOn : BOOLEAN := DefaultMsgOn; + XOn : BOOLEAN := DefaultXon; + -- memory file to be loaded + mem_file_name : STRING := "s25fl512s.mem"; + otp_file_name : STRING := "s25fl512sOTP.mem"; + + UserPreload : BOOLEAN := FALSE; --TRUE; + LongTimming : BOOLEAN := TRUE; + + -- For FMF SDF technology file usage + TimingModel : STRING + ); + PORT ( + -- Data Inputs/Outputs + SI : INOUT std_ulogic := 'U'; -- serial data input/IO0 + SO : INOUT std_ulogic := 'U'; -- serial data output/IO1 + -- Controls + SCK : IN std_ulogic := 'U'; -- serial clock input + CSNeg : IN std_ulogic := 'U'; -- chip select input + RSTNeg : IN std_ulogic := 'U'; -- hardware reset pin + WPNeg : INOUT std_ulogic := 'U'; -- write protect input/IO2 + HOLDNeg : INOUT std_ulogic := 'U' -- hold input/IO3 + ); + + ATTRIBUTE VITAL_LEVEL0 of s25fl512s : ENTITY IS TRUE; +END s25fl512s; + +------------------------------------------------------------------------------- +-- ARCHITECTURE DECLARATION +------------------------------------------------------------------------------- +ARCHITECTURE vhdl_behavioral_dynamic_memory_allocation of s25fl512s IS + ATTRIBUTE VITAL_LEVEL0 OF + vhdl_behavioral_dynamic_memory_allocation : ARCHITECTURE IS TRUE; + + --------------------------------------------------------------------------- + -- CONSTANT AND SIGNAL DECLARATION + --------------------------------------------------------------------------- + --Declaration of constants - memory characteristics + -- The constant declared here are used to enable the creation of models + -- of memories within a family with a minimum amount of editing + + CONSTANT PartID : STRING := "s25fl512s"; + CONSTANT MaxData : NATURAL := 16#FF#; --255; + CONSTANT MemSize : NATURAL := 16#3FFFFFF#; + CONSTANT SecNum : NATURAL := 255; + CONSTANT SecSize : NATURAL := 16#3FFFF#; --256KB + CONSTANT PageNum : NATURAL := 16#1FFFF#; + CONSTANT PageSize : NATURAL := 512; + CONSTANT AddrRANGE : NATURAL := 16#3FFFFFF#; + CONSTANT HiAddrBit : NATURAL := 31; + CONSTANT OTPSize : NATURAL := 1023; + CONSTANT OTPLoAddr : NATURAL := 16#000#; + CONSTANT OTPHiAddr : NATURAL := 16#3FF#; + CONSTANT BYTE : NATURAL := 8; + + --Manufacturer Identification + CONSTANT Manuf_ID : NATURAL := 16#01#; + CONSTANT DeviceID : NATURAL := 16#19#; + --Electronic Signature + CONSTANT ESignature : NATURAL := 16#19#; + --Device ID + --Manufacturer Identification && Memory Type && Memory Capacity + CONSTANT Jedec_ID : NATURAL := 16#01#; -- first byte of Device ID + CONSTANT DeviceID1 : NATURAL := 16#02#; + CONSTANT DeviceID2 : NATURAL := 16#20#; + CONSTANT ExtendedBytes : NATURAL := 16#4D#; + CONSTANT ExtendedID : NATURAL := 16#00#; + CONSTANT DieRev : NATURAL := 16#00#; + CONSTANT MaskRev : NATURAL := 16#00#; + + -- Declaration of signals that will hold the delayed values of ports + SIGNAL SI_ipd : std_ulogic := 'U'; + SIGNAL SO_ipd : std_ulogic := 'U'; + SIGNAL SCK_ipd : std_ulogic := 'U'; + SIGNAL CSNeg_ipd : std_ulogic := 'U'; + SIGNAL RSTNeg_ipd : std_ulogic := 'U'; + SIGNAL WPNeg_ipd : std_ulogic := 'U'; + SIGNAL HOLDNeg_ipd : std_ulogic := 'U'; + SIGNAL HOLDNeg_pullup : std_ulogic := 'U'; + SIGNAL WPNeg_pullup : std_ulogic := 'U'; + SIGNAL RSTNeg_pullup : std_ulogic := 'U'; + + -- internal delays + SIGNAL PP_in : std_ulogic := '0'; + SIGNAL PP_out : std_ulogic := '0'; + SIGNAL BP_in : std_ulogic := '0'; + SIGNAL BP_out : std_ulogic := '0'; + SIGNAL SE_in : std_ulogic := '0'; + SIGNAL SE_out : std_ulogic := '0'; + SIGNAL BE_in : std_ulogic := '0'; + SIGNAL BE_out : std_ulogic := '0'; + SIGNAL WRR_in : std_ulogic := '0'; + SIGNAL WRR_out : std_ulogic := '0'; + SIGNAL ERSSUSP_in : std_ulogic := '0'; + SIGNAL ERSSUSP_out : std_ulogic := '0'; + SIGNAL PRGSUSP_in : std_ulogic := '0'; + SIGNAL PRGSUSP_out : std_ulogic := '0'; + SIGNAL PU_in : std_ulogic := '0'; + SIGNAL PU_out : std_ulogic := '0'; + SIGNAL RST_in : std_ulogic := '0';-- Hardware Reset Timeout + SIGNAL RST_out : std_ulogic := '1';-- + SIGNAL PPBERASE_in : std_ulogic := '0'; + SIGNAL PPBERASE_out : std_ulogic := '0'; + SIGNAL PASSULCK_in : std_ulogic := '0'; + SIGNAL PASSULCK_out : std_ulogic := '0'; + SIGNAL PASSACC_in : std_ulogic := '0'; + SIGNAL PASSACC_out : std_ulogic := '0'; + + --------------------------------------------------------------------------- + -- Memory data initial value. + -- Default value may be overridden by conigure_memory procedure + --------------------------------------------------------------------------- + SHARED VARIABLE max_data : NATURAL := 16#FF#; + + --------------------------------------------------------------------------- + -- Handle dynamic memory allocation + --------------------------------------------------------------------------- + -- Partition dynamically allocated space for performance + + SHARED VARIABLE corrupt_Sec : std_logic_vector(SecNum downto 0) + :=(OTHERS=>'0'); + + -- ------------------------------------------------------------------------ + -- Data types required to implement link list structure + -- ------------------------------------------------------------------------ + TYPE mem_data_t; + TYPE mem_data_pointer_t IS ACCESS mem_data_t; + TYPE mem_data_t IS RECORD + key_address : INTEGER; + val_data : INTEGER; + successor : mem_data_pointer_t; + END RECORD; + + -- --------------------------------------------------------------------- + -- Array of linked lists. + -- Support memory region partitioning for faster access. + -- --------------------------------------------------------------------- + TYPE mem_data_pointer_array_t IS + ARRAY(NATURAL RANGE <>) OF mem_data_pointer_t; + + SHARED VARIABLE linked_list : + mem_data_pointer_array_t(0 TO SecNum); + + -- --------------------------------------------------------------------- + -- Override mechanism provided for default parameter values + -- --------------------------------------------------------------------- + PROCEDURE configure_memory( + max_data_c : IN INTEGER) IS + BEGIN + max_data := max_data_c; + END PROCEDURE configure_memory; + + -- Asure proper initialization + PROCEDURE initialize IS + VARIABLE I : INTEGER; + BEGIN + FOR I IN 0 TO SecNum LOOP + linked_list(I) := NULL; + END LOOP; + END PROCEDURE initialize; + + -- --------------------------------------------------------------------- + -- Create linked listed + -- --------------------------------------------------------------------- + PROCEDURE create_list( + key_address : IN INTEGER; + val_data : IN INTEGER; + root : INOUT mem_data_pointer_t) IS + BEGIN + root := NEW mem_data_t; + root.successor := NULL; + root.key_address := key_address; + root.val_data := val_data; + END PROCEDURE create_list; + + -- -------------------------------------------------------------------- + -- Iterate through linked listed comapring key values + -- Stop when key value greater or equal + -- -------------------------------------------------------------------- + PROCEDURE position_list( + key_address : IN INTEGER; + root : INOUT mem_data_pointer_t; + found : INOUT mem_data_pointer_t; + prev : INOUT mem_data_pointer_t) IS + BEGIN + found := root; + prev := NULL; + WHILE ((found /= NULL) AND (found.key_address < key_address)) LOOP + prev := found; + found := found.successor; + END LOOP; + END PROCEDURE position_list; + + -- ------------------------------------------------------------------- + -- Add new element to a linked list + -- ------------------------------------------------------------------- + PROCEDURE insert_list( + key_address : IN INTEGER; + val_data : IN INTEGER; + root : INOUT mem_data_pointer_t) IS + + VARIABLE new_element : mem_data_pointer_t; + VARIABLE found : mem_data_pointer_t; + VARIABLE prev : mem_data_pointer_t; + BEGIN + position_list(key_address, root, found, prev); + + -- Insert at list tail + IF (found = NULL) THEN + prev.successor := NEW mem_data_t; + prev.successor.key_address := key_address; + prev.successor.val_data := val_data; + prev.successor.successor := NULL; + ELSE + -- Element exists, update memory data value + IF (found.key_address = key_address) THEN + found.val_data := val_data; + ELSE + -- No element found, allocate and link + new_element := NEW mem_data_t; + new_element.key_address := key_address; + new_element.val_data := val_data; + new_element.successor := found; + -- Possible root position + IF (prev /= NULL) THEN + prev.successor := new_element; + ELSE + root := new_element; + END IF; + END IF; + END IF; + END PROCEDURE insert_list; + + -- -------------------------------------------------------------------- + -- Remove element from a linked list + -- -------------------------------------------------------------------- + PROCEDURE remove_list( + key_address : IN INTEGER; + root : INOUT mem_data_pointer_t) IS + + VARIABLE found : mem_data_pointer_t; + VARIABLE prev : mem_data_pointer_t; + BEGIN + position_list(key_address, root, found, prev); + IF (found /= NULL) THEN + -- Key value match + IF (found.key_address = key_address) THEN + -- Handle root position removal + IF (prev /= NULL) THEN + prev.successor := found.successor; + ELSE + root := found.successor; + END IF; + DEALLOCATE(found); + END IF; + END IF; + END PROCEDURE remove_list; + + -- ------------------------------------------------------------------- + -- Remove range of elements from a linked list + -- Higher performance than one-by-one removal + -- ------------------------------------------------------------------- + PROCEDURE remove_list_range( + address_low : IN INTEGER; + address_high : IN INTEGER; + root : INOUT mem_data_pointer_t) IS + + VARIABLE iter : mem_data_pointer_t; + VARIABLE prev : mem_data_pointer_t; + VARIABLE link_element : mem_data_pointer_t; + BEGIN + iter := root; + prev := NULL; + -- Find first linked list element belonging to + -- a specified address range [address_low, address_high] + WHILE ((iter /= NULL) AND NOT ( + (iter.key_address >= address_low) AND + (iter.key_address <= address_high))) LOOP + prev := iter; + iter := iter.successor; + END LOOP; + -- Continue until address_high reached + -- Deallocate linked list elements pointed by iterator + IF (iter /= NULL) THEN + WHILE ((iter /= NULL) AND + (iter.key_address >= address_low) AND + (iter.key_address <= address_high)) LOOP + link_element := iter.successor; + DEALLOCATE(iter); + iter := link_element; + END LOOP; + -- Handle possible root value change + IF prev /= NULL THEN + prev.successor := link_element; + ELSE + root := link_element; + END IF; + END IF; + END PROCEDURE remove_list_range; + + -- --------------------------------------------------------------------- + -- Address range to be erased + -- --------------------------------------------------------------------- + PROCEDURE erase_mem( + address_low : IN INTEGER; + address_high : IN INTEGER; + linked_list : INOUT mem_data_pointer_t) IS + + BEGIN + remove_list_range( + address_low, + address_high, + linked_list + ); + END PROCEDURE erase_mem; + + -- -------------------------------------------------------------------- + -- Memory READ operation performed above dynamically allocated space + -- -------------------------------------------------------------------- + PROCEDURE read_mem( + linked_list : INOUT mem_data_pointer_t; + data : INOUT INTEGER; + address : IN INTEGER) IS + + VARIABLE found : mem_data_pointer_t; + VARIABLE prev : mem_data_pointer_t; + VARIABLE mem_data : INTEGER; + BEGIN + IF (linked_list = NULL) THEN + -- Not allocated, not written, initial value + mem_data := max_data ; + ELSE + position_list(address, linked_list, found, prev); + IF (found /= NULL) THEN + IF found.key_address = address THEN + -- Allocated, val_data stored + mem_data := found.val_data; + ELSE + -- Not allocated, not written, initial value + mem_data := max_data ; + END IF; + ELSE + -- Not allocated, not written, initial value + mem_data := max_data ; + END IF; + END IF; + data := mem_data; + END PROCEDURE read_mem; + + -- ------------------------------------------------------------------ + -- Memory WRITE operation performed above dynamically allocated space + -- ------------------------------------------------------------------ + PROCEDURE write_mem( + linked_list : INOUT mem_data_pointer_t; + address : IN INTEGER; + data : IN INTEGER) IS + + BEGIN + IF (data /= max_data ) THEN + -- Handle possible root value update + IF (linked_list /= NULL) THEN + insert_list(address, data, linked_list); + ELSE + create_list(address, data, linked_list); + END IF; + ELSE + -- Deallocate if initial value written + -- No linked list, NOP, initial value implicit + IF (linked_list /= NULL) THEN + remove_list(address, linked_list); + END IF; + END IF; + END PROCEDURE write_mem; + + PROCEDURE READ_DATA( + sectoraddr : IN NATURAL RANGE 0 TO Secnum; + addressinsec : IN NATURAL RANGE 0 TO SecSize; + ReadData : INOUT INTEGER) IS + BEGIN + read_mem(linked_list(sectoraddr), + ReadData, + addressinsec + ); + IF (ReadData = MaxData AND Corrupt_Sec(sectoraddr) = '1') THEN + ReadData := -1; + ELSIF (ReadData = MaxData+1) AND Corrupt_Sec(sectoraddr) = '1' THEN + ReadData := MaxData; + END IF; + END READ_DATA; + + PROCEDURE WRITE_DATA( + sectoraddr : IN NATURAL RANGE 0 TO Secnum; + addressinsec : IN NATURAL RANGE 0 TO SecSize; + WriteData : IN INTEGER) IS + BEGIN + IF (WriteData = MaxData AND Corrupt_Sec(sectoraddr) = '1') THEN + write_mem(linked_list(sectoraddr), + addressinsec, + WriteData+1 + ); + ELSE + write_mem(linked_list(sectoraddr), + addressinsec, + WriteData + ); + END IF; + END WRITE_DATA; + + FUNCTION ReturnSectorID(ADDR : NATURAL) RETURN NATURAL IS + VARIABLE result : NATURAL; + BEGIN + IF ADDR <= AddrRange THEN + result := ADDR / (SecSize+1); + ELSE + result := SecNum+1; + END IF; + RETURN result; + END ReturnSectorID; + + FUNCTION ReturnSectorIDRdPswdMd(TBPROT : std_logic) RETURN NATURAL IS + VARIABLE result : NATURAL; + BEGIN + result := SecNum; + IF TBPROT = '0' THEN + result := 0; + END IF; + RETURN result; + END ReturnSectorIDRdPswdMd; + +BEGIN + --------------------------------------------------------------------------- + -- Internal Delays + --------------------------------------------------------------------------- + -- Artificial VITAL primitives to incorporate internal delays + -- Because a tdevice generics is used, there must be a VITAL_primitives + -- assotiated with them + PP :VitalBuf(PP_out, PP_in, (tdevice_PP ,UnitDelay)); + BP :VitalBuf(BP_out, BP_in, (tdevice_BP ,UnitDelay)); + SE :VitalBuf(SE_out, SE_in, (tdevice_SE ,UnitDelay)); + BE :VitalBuf(BE_out, BE_in, (tdevice_BE ,UnitDelay)); + WRR :VitalBuf(WRR_out, WRR_in, (tdevice_WRR ,UnitDelay)); + ERSSUSP :VitalBuf(ERSSUSP_out, ERSSUSP_in, (tdevice_ERSSUSP ,UnitDelay)); + PRGSUSP :VitalBuf(PRGSUSP_out, PRGSUSP_in, (tdevice_PRGSUSP ,UnitDelay)); + PU :VitalBuf(PU_out, PU_in, (tdevice_PU ,UnitDelay)); + PPBERASE :VitalBuf(PPBERASE_out,PPBERASE_in,(tdevice_PPBERASE,UnitDelay)); + PASSULCK :VitalBuf(PASSULCK_out,PASSULCK_in,(tdevice_PASSULCK,UnitDelay)); + PASSACC :VitalBuf(PASSACC_out, PASSACC_in, (tdevice_PASSACC ,UnitDelay)); + + --------------------------------------------------------------------------- + -- Wire Delays + --------------------------------------------------------------------------- + WireDelay : BLOCK + BEGIN + + w_1 : VitalWireDelay (SI_ipd, SI, tipd_SI); + w_2 : VitalWireDelay (SO_ipd, SO, tipd_SO); + w_3 : VitalWireDelay (SCK_ipd, SCK, tipd_SCK); + w_4 : VitalWireDelay (CSNeg_ipd, CSNeg, tipd_CSNeg); + w_5 : VitalWireDelay (RSTNeg_ipd, RSTNeg, tipd_RSTNeg); + w_6 : VitalWireDelay (WPNeg_ipd, WPNeg, tipd_WPNeg); + w_7 : VitalWireDelay (HOLDNeg_ipd, HOLDNeg, tipd_HOLDNeg); + + END BLOCK; + + --------------------------------------------------------------------------- + -- Main Behavior Block + --------------------------------------------------------------------------- + Behavior: BLOCK + + PORT ( + SIIn : IN std_ulogic := 'U'; + SIOut : OUT std_ulogic := 'U'; + SOIn : IN std_logic := 'U'; + SOut : OUT std_logic := 'U'; + SCK : IN std_ulogic := 'U'; + CSNeg : IN std_ulogic := 'U'; + RSTNeg : IN std_ulogic := 'U'; + HOLDNegIn : IN std_ulogic := 'U'; + HOLDNegOut : OUT std_ulogic := 'U'; + WPNegIn : IN std_ulogic := 'U'; + WPNegOut : OUT std_ulogic := 'U' + ); + + PORT MAP ( + SIIn => SI_ipd, + SIOut => SI, + SOIn => SO_ipd, + SOut => SO, + SCK => SCK_ipd, + CSNeg => CSNeg_ipd, + RSTNeg => RSTNeg_ipd, + HOLDNegIn => HOLDNeg_ipd, + HOLDNegOut => HOLDNeg, + WPNegIn => WPNeg_ipd, + WPNegOut => WPNeg + ); + + -- State Machine : State_Type + TYPE state_type IS (IDLE, + RESET_STATE, + AUTOBOOT, + WRITE_SR, + PAGE_PG, + OTP_PG, + PG_SUSP, + SECTOR_ERS, + BULK_ERS, + ERS_SUSP, + ERS_SUSP_PG, + ERS_SUSP_PG_SUSP, + PASS_PG, + PASS_UNLOCK, + PPB_PG, + PPB_ERS, + AUTOBOOT_PG, + ASP_PG, + PLB_PG, + DYB_PG, + NVDLR_PG + ); + + -- Instruction Type + TYPE instruction_type IS ( NONE, + WREN, -- Write Enable + WRDI, -- Write Disable + WRR, -- Write Register + READ, -- Read Normal (3Byte Address) + RD4, -- Read Normal (4Byte +) + OTPR, -- OTP Read + RDSR, -- Read Status Register 1 + RDSR2, -- Read Status Register 2 + RDCR, -- Read Configuration Register 1 + REMS, -- Read ID (SST) + RDID, -- Read ID JEDEC + RES, -- Read ID + FSTRD, -- Fast Read (3Byte Address) + FSTRD4, -- Fast Read (4Byte +) + DDRFR, -- Fast Read DDR (3Byte Address) + DDRFR4, -- Fast Read DDR (4Byte +) + DOR, -- Read Dual Out (3Byte Address) + DOR4, -- Read Dual Out (4Byte +) + DIOR, -- Read Dual I/O (3Byte Address) + DIOR4, -- Read Dual I/O (4Byte +) + DDRDIOR, -- Read DDR Dual I/O (3Byte) + DDRDIOR4, -- Read DDR Dual I/O (4Byte +) + QOR, -- Read Quad Out (3Byte Address) + QOR4, -- Read Quad Out (4Byte +) + QIOR, -- Read Quad I/O (3Byte Address) + QIOR4, -- Read Quad I/O (4Byte +) + DDRQIOR, -- Read DDR Quad I/O (3Byte) + DDRQIOR4, -- Read DDR Quad I/O (4Byte +) + PP, -- Program Page (3Byte Address) + PP4, -- Program Page (4Byte +) + QPP, -- Quad Page Program (3Byte) + QPP4, -- Quad Page Program (4Byte +) + OTPP, -- OTP Program + PGSP, -- Program Suspend + PGRS, -- Program Resume + BE, -- Bulk Erase + SE, -- Erase 128/256KB (3Byte) + SE4, -- Erase 128/256KB (4Byte +) + P4E, -- 4KB-sector Erase (3Byte Addr) + P4E4, -- 4KB-sector Erase (4Byte Addr) + ERSP, -- Erase Suspend + ERRS, -- Erase Resume + ABRD, -- AutoBoot Register Read + ABWR, -- AutoBoot Register Write + BRRD, -- Bank Register Read + BRWR, -- Bank Register Write + BRAC, -- Bank Register Access + DLPRD, -- Read Data Learning Pattern + PNVDLR, -- Program NVDLP Reg + WVDLR, -- Write Volatile DLP Reg + ASPRD, -- ASP Read + ASPP, -- ASP Program + DYBRD, -- DYB Read + DYBWR, -- DYB Write + PPBRD, -- PPB Read + PPBP, -- PPB Program + PPBERS, -- PPB Erase + PLBWR, -- PPB Lock Bit Write + PLBRD, -- PPB Lock Bit Read + PASSRD, -- Password Read + PASSP, -- Password Program + PASSU, -- Password Unlock + RESET, -- Reset + MBR, -- Mode Bit Reset + MPM, -- Multi-I/O-High Perf Mode + CLSR -- Clear Status Register + ); + + TYPE WByteType IS ARRAY (0 TO 511) OF INTEGER RANGE -1 TO MaxData; + -- OTP Memory Array + TYPE OTPArray IS ARRAY (OTPLoAddr TO OTPHiAddr) OF INTEGER + RANGE -1 TO MaxData; + --CFI Array (Common Flash Interface Query codes) + TYPE CFItype IS ARRAY (16#00# TO 16#55#) OF + INTEGER RANGE -1 TO 16#FF#; + ----------------------------------------------------------------------- + -- memory declaration + ----------------------------------------------------------------------- + -- OTP Sector + SHARED VARIABLE OTPMem : OTPArray := (OTHERS => MaxData); + --CFI Array + SHARED VARIABLE CFI_array : CFItype := (OTHERS => 0); + -- Programming Buffer + SIGNAL WByte : WByteType := (OTHERS => MaxData); + + -- states + SIGNAL current_state : state_type; + SIGNAL next_state : state_type; + + SIGNAL Instruct : instruction_type; + --zero delay signal + SIGNAL SOut_zd : std_logic := 'Z'; + SIGNAL SIOut_zd : std_logic := 'Z'; + SIGNAL HOLDNegOut_zd : std_logic := 'Z'; + SIGNAL WPNegOut_zd : std_logic := 'Z'; + --HOLD delay on output data + SIGNAL SOut_z : std_logic := 'Z'; + SIGNAL SIOut_z : std_logic := 'Z'; + -- powerup + SIGNAL PoweredUp : std_logic := '0'; + + ----------------------------------------------------------------------- + -- Registers + ----------------------------------------------------------------------- + -- *** Status Register 1 *** + SHARED VARIABLE Status_reg1 : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Status_reg1_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Status Register Write Disable Bit + ALIAS SRWD :std_logic IS Status_reg1(7); + -- Status Register Programming Error Bit + ALIAS P_ERR :std_logic IS Status_reg1(6); + -- Status Register Erase Error Bit + ALIAS E_ERR :std_logic IS Status_reg1(5); + -- Status Register Block Protection Bits + ALIAS BP2 :std_logic IS Status_reg1(4); + ALIAS BP1 :std_logic IS Status_reg1(3); + ALIAS BP0 :std_logic IS Status_reg1(2); + -- Status Register Write Enable Latch Bit + ALIAS WEL :std_logic IS Status_reg1(1); + -- Status Register Write In Progress Bit + ALIAS WIP :std_logic IS Status_reg1(0); + + -- *** Status Register 2 *** + SHARED VARIABLE Status_reg2 : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Status_reg2_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Status Register Write Enable Latch Bit + ALIAS ES :std_logic IS Status_reg2(1); + -- Status Register Write In Progress Bit + ALIAS PS :std_logic IS Status_reg2(0); + + -- *** Configuration Register 1 *** + SHARED VARIABLE Config_reg1 : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Config_reg1_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Latency code + ALIAS LC1 :std_logic IS Config_reg1(7); + ALIAS LC0 :std_logic IS Config_reg1(6); + -- Configuration Register TBPROT bit + ALIAS TBPROT :std_logic IS Config_reg1(5); + -- Configuration Register LOCK bit + ALIAS LOCK :std_logic IS Config_reg1(4); + -- Configuration Register BPNV bit + ALIAS BPNV :std_logic IS Config_reg1(3); + -- Configuration Register QUAD bit + ALIAS QUAD :std_logic IS Config_reg1(1); + -- Configuration Register FREEZE bit + ALIAS FREEZE :std_logic IS Config_reg1(0); + + -- *** VDLR Register *** + SHARED VARIABLE VDLR_reg : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL VDLR_reg_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- *** NVDLR Register *** + SHARED VARIABLE NVDLR_reg : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL NVDLR_reg_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- *** AutoBoot Register *** + SHARED VARIABLE AutoBoot_reg : std_logic_vector(31 downto 0) + := (others => '0'); + SIGNAL AutoBoot_reg_in : std_logic_vector(31 downto 0) + := (others => '0'); + + --AutoBoot Enable Bit + ALIAS ABE :std_logic IS AutoBoot_reg(0); + + -- *** Bank Address Register *** + SHARED VARIABLE Bank_Addr_reg : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Bank_Addr_reg_in : std_logic_vector(7 downto 0) + := (others => '0'); + --Bank Address Register EXTADD bit + ALIAS EXTADD :std_logic IS Bank_Addr_reg(7); + + -- *** ASP Register *** + SHARED VARIABLE ASP_reg : std_logic_vector(15 downto 0); + SIGNAL ASP_reg_in : std_logic_vector(15 downto 0) + := (others => '1'); + --Read Password Mode Enable Bit + ALIAS RPME :std_logic IS ASP_reg(5); + --PPB OTP Bit + ALIAS PPBOTP :std_logic IS ASP_reg(3); + -- Password Protection Mode Lock Bit + ALIAS PWDMLB :std_logic IS ASP_reg(2); + --Persistent Protection Mode Lock Bit + ALIAS PSTMLB :std_logic IS ASP_reg(1); + + -- *** Password Register *** + SHARED VARIABLE Password_reg : std_logic_vector(63 downto 0) + := (others => '1'); + SIGNAL Password_reg_in : std_logic_vector(63 downto 0) + := (others => '1'); + -- *** PPB Lock Register *** + SHARED VARIABLE PPBL : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL PPBL_in : std_logic_vector(7 downto 0) + := (others => '0'); + --Persistent Protection Mode Lock Bit + ALIAS PPB_LOCK : std_logic IS PPBL(0); + SIGNAL PPB_LOCK_temp : std_ulogic := '0'; + -- *** PPB Access Register *** + SHARED VARIABLE PPBAR : std_logic_vector(7 downto 0) + := (others => '1'); + SIGNAL PPBAR_in : std_logic_vector(7 downto 0) + := (others => '1'); + -- PPB_bits(Sec) + SHARED VARIABLE PPB_bits : std_logic_vector(SecNum downto 0) + := (OTHERS => '1'); + -- *** DYB Access Register *** + SHARED VARIABLE DYBAR : std_logic_vector(7 downto 0) + := (others => '1'); + SIGNAL DYBAR_in : std_logic_vector(7 downto 0) + := (others => '1'); + -- DYB(Sec) + SHARED VARIABLE DYB_bits : std_logic_vector(SecNum downto 0); + + -- The Lock Protection Registers for OTP Memory space + SHARED VARIABLE LOCK_BYTE1 :std_logic_vector(7 downto 0); + SHARED VARIABLE LOCK_BYTE2 :std_logic_vector(7 downto 0); + SHARED VARIABLE LOCK_BYTE3 :std_logic_vector(7 downto 0); + SHARED VARIABLE LOCK_BYTE4 :std_logic_vector(7 downto 0); + + --Command Register + SIGNAL write : std_logic := '0'; + SIGNAL cfg_write : std_logic := '0'; + SIGNAL read_out : std_logic := '0'; + + SIGNAL rd : boolean := false; + SIGNAL dual : boolean := false; + SIGNAL fast_rd : boolean := true; + SIGNAL ddr : boolean := false; + SIGNAL any_read : boolean := false; + + SIGNAL quadpg : boolean := false; + + SIGNAL oe : boolean := false; + SIGNAL oe_z : boolean := false; + + SHARED VARIABLE hold_mode : boolean := false; + + --FSM control signals + SIGNAL PDONE : std_logic := '1'; --Page Prog. Done + SIGNAL PSTART : std_logic := '0'; --Start Page Programming + SIGNAL PGSUSP : std_logic := '0'; --Suspend Program + SIGNAL PGRES : std_logic := '0'; --Resume Program + + SIGNAL RES_TO_SUSP_MIN_TIME : std_logic := '0';--Resume to Suspend Flag + SIGNAL RES_TO_SUSP_TYP_TIME : std_logic := '0';--Resume to Suspend Flag + + SIGNAL WDONE : std_logic := '1'; --Write operation Done + SIGNAL WSTART : std_logic := '0'; --Start Write operation + + SIGNAL ESTART : std_logic := '0'; --Start Erase operation + SIGNAL EDONE : std_logic := '1'; --Erase operation Done + SIGNAL ESUSP : std_logic := '0'; --Suspend Erase + SIGNAL ERES : std_logic := '0'; --Resume Erase + + --reset timing + SIGNAL RST : std_logic := '0'; + SIGNAL Reseted : std_logic := '0'; --Reset Timing Control + --Lock Bit is enabled for customer programming + SIGNAL WRLOCKENABLE : BOOLEAN := TRUE; + --Flag that mark if ASP Register is allready programmed + SIGNAL ASPOTPFLAG : BOOLEAN := FALSE; + SIGNAL ASP_INIT : NATURAL RANGE 0 TO 1; + SIGNAL INITIAL_CONFIG : std_logic := '0'; + + SHARED VARIABLE SecAddr : NATURAL RANGE 0 TO SecNum:= 0; + + SHARED VARIABLE Sec_addr : NATURAL := 0; + + SHARED VARIABLE Page_addr : NATURAL; + SHARED VARIABLE pgm_page : NATURAL; + + SHARED VARIABLE QPP_page : std_logic_vector(PageNum downto 0) + := (OTHERS => '0'); + + --Flag for Password unlock command + SIGNAL PASS_UNLOCKED : boolean := FALSE; + SIGNAL PASS_TEMP : std_logic_vector(63 downto 0) + := (others => '1'); + + SHARED VARIABLE DOUBLE : BOOLEAN := FALSE; + SHARED VARIABLE EHP : BOOLEAN := FALSE; + + SHARED VARIABLE read_cnt : NATURAL := 0; + SHARED VARIABLE byte_cnt : NATURAL := 1; + SHARED VARIABLE read_addr : NATURAL RANGE 0 TO AddrRANGE ; + + SHARED VARIABLE start_delay : NATURAL RANGE 0 TO 7; + SHARED VARIABLE ABSD : NATURAL RANGE 0 TO 7; + SIGNAL start_autoboot : std_logic := '0'; + + SIGNAL change_addr : std_logic := '0'; + SIGNAL Address : NATURAL RANGE 0 TO AddrRANGE := 0; + SIGNAL SectorSuspend : NATURAL RANGE 0 TO SecNum := 0; + + -- Sector address + SIGNAL SA : NATURAL RANGE 0 TO SecNum := 0; + + -- Sector is protect if Sec_Prot(SecNum) = '1' + SHARED VARIABLE Sec_Prot : std_logic_vector(SecNum downto 0) := + (OTHERS => '0'); + + SIGNAL change_BP : std_logic := '0'; + SHARED VARIABLE BP_bits : std_logic_vector(2 downto 0) := "000"; + + SHARED VARIABLE CFI_array_tmp : std_logic_vector(647 downto 0); + + SIGNAL Byte_number : NATURAL RANGE 0 TO 511 := 0; + + TYPE bus_cycle_type IS (STAND_BY, + OPCODE_BYTE, + ADDRESS_BYTES, + DUMMY_BYTES, + MODE_BYTE, + DATA_BYTES + ); + SHARED VARIABLE bus_cycle_state : bus_cycle_type; + -- switch between Data bytes and Dummy bytes + SHARED VARIABLE DummyBytes_act : X01 := '0'; + SIGNAL dummy_cnt_act_temp : NATURAL := 0; + SIGNAL dummy_cnt_act : NATURAL := 0; + --Read Password Protection Mode Active flag + SIGNAL RdPswdProtMode : std_ulogic := '0'; + --Read Password Protection Mode Support flag + SIGNAL RdPswdProtEnable : std_ulogic := '0'; + SIGNAL BAR_ACC : std_ulogic := '0'; + + SHARED VARIABLE Latency_code : NATURAL RANGE 0 TO 7; + SHARED VARIABLE opcode_cnt : NATURAL := 0; + SHARED VARIABLE addr_cnt : NATURAL := 0; + SHARED VARIABLE mode_cnt : NATURAL := 0; + SHARED VARIABLE dummy_cnt : NATURAL := 0; + SHARED VARIABLE data_cnt : NATURAL := 0; + + -- timing check violation + SIGNAL Viol : X01 := '0'; + + PROCEDURE ADDRHILO_SEC( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE Addr : NATURAL) IS + VARIABLE sector : NATURAL RANGE 0 TO SecNum; + BEGIN + sector := Addr/16#40000#; + AddrLOW := sector*16#40000#; + AddrHIGH := sector*16#40000# + 16#3FFFF#; + END ADDRHILO_SEC; + + PROCEDURE ADDRHILO_PG( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE Sec_address : INOUT NATURAL RANGE 0 TO SecSize; + VARIABLE Page_address : INOUT NATURAL; + VARIABLE Addr : NATURAL) IS + VARIABLE page : NATURAL RANGE 0 TO PageNum; + VARIABLE Sec : NATURAL RANGE 0 TO SecNum; + VARIABLE Sec_addr_tmp : NATURAL RANGE 0 TO ADDRRange; + BEGIN + Sec := Addr/(SecSize+1); + Sec_addr_tmp := Sec*(SecSize+1); + page := Addr/PageSize; + AddrLOW := Page*PageSize; + AddrLOW := AddrLOW - Sec_addr_tmp; + AddrHIGH := AddrLOW + PageSize-1; + Sec_address := Addr - Sec_addr_tmp; + Page_address := page; + END ADDRHILO_PG; + + BEGIN + --------------------------------------------------------------------------- + --Power Up time + --------------------------------------------------------------------------- + + PoweredUp <= '1' AFTER tdevice_PU; + + TimingModelSel: PROCESS + BEGIN + --Enhanced High Performance Flag + IF (TimingModel(15) = '0' OR TimingModel(15) = '2' OR + TimingModel(15) = '3' OR TimingModel(15) = 'R' OR + TimingModel(15) = 'A' OR TimingModel(15) = 'B' OR + TimingModel(15) = 'C' OR TimingModel(15) = 'D' OR + TimingModel(15) = 'Y' OR TimingModel(15) = 'Z' OR + TimingModel(15) = 'S' OR TimingModel(15) = 'T' OR + TimingModel(15) = 'K' OR TimingModel(15) = 'L') THEN + EHP := TRUE; + IF (TimingModel(15) = 'Y' OR TimingModel(15) = 'Z' OR + TimingModel(15) = 'S' OR TimingModel(15) = 'T' OR + TimingModel(15) = 'K' OR TimingModel(15) = 'L') THEN + RdPswdProtEnable <= '1'; + END IF; + ELSIF (TimingModel(15) = '4' OR TimingModel(15) = '6' OR + TimingModel(15) = '7' OR TimingModel(15) = '8' OR + TimingModel(15) = '9' OR TimingModel(15) = 'Q') THEN + EHP := FALSE; + END IF; + + IF (TimingModel(15) ='0' OR TimingModel(15) ='2' OR + TimingModel(15) ='3' OR TimingModel(15) ='R' OR + TimingModel(15) ='A' OR TimingModel(15) ='B' OR + TimingModel(15) ='C' OR TimingModel(15) ='D' OR + TimingModel(15) ='4' OR TimingModel(15) ='6' OR + TimingModel(15) ='7' OR TimingModel(15) ='8' OR + TimingModel(15) ='9' OR TimingModel(15) ='Q') THEN + ASP_INIT <= 1; + ELSIF (TimingModel(15) ='Y' OR TimingModel(15) ='Z' OR + TimingModel(15) ='S' OR TimingModel(15) ='T' OR + TimingModel(15) ='K' OR TimingModel(15) ='L') THEN + ASP_INIT <= 0; + END IF; + WAIT; + END PROCESS; + + RSTtiming: PROCESS(RSTNeg_pullup,Instruct) + BEGIN + IF falling_edge(RSTNeg_pullup) THEN + RST <= '1', '0' AFTER 200 ns; + ELSIF Instruct = RESET THEN + Reseted <= '0', '1' AFTER 10 ns; + END IF; + END PROCESS; + + DUMMYcnt: PROCESS(dummy_cnt_act_temp) + BEGIN + dummy_cnt_act <= dummy_cnt_act_temp; + END PROCESS; + + ReadPasswordProtectionMode: PROCESS(PPB_LOCK_temp, + ASP_reg_in(2), ASP_reg_in(5)) + BEGIN + IF (PPB_LOCK = '0' AND PWDMLB = '0' AND RPME = '0' AND + RdPswdProtEnable = '1') THEN + RdPswdProtMode <= '1'; + ABE := '0'; + ELSE + RdPswdProtMode <= '0'; + END IF; + END PROCESS; + --------------------------------------------------------------------------- + -- autoboot control logic + --------------------------------------------------------------------------- + AutoBootControl: PROCESS(SCK_ipd, current_state) + BEGIN + IF (current_state = AUTOBOOT) THEN + IF rising_edge(SCK_ipd) THEN + IF (start_delay > 0) THEN + start_delay := start_delay - 1; + END IF; + END IF; + + IF (start_delay = 0) THEN + start_autoboot <= '1'; + ELSE + start_autoboot <= '0'; + END IF; + END IF; + END PROCESS; + + --------------------------------------------------------------------------- + -- VITAL Timing Checks Procedures + --------------------------------------------------------------------------- + VITALTimingCheck: PROCESS(SIIn, SOIn, SCK_ipd, CSNeg_ipd, RSTNeg_ipd, + HOLDNegIn, WPNegIn) + + -- Timing Check Variables + -- Setup/Hold Checks variables + VARIABLE Tviol_CSNeg_SCK_normal : X01 := '0'; + VARIABLE TD_CSNeg_SCK_normal : VitalTimingDataType; + + VARIABLE Tviol_CSNeg_SCK_DDR : X01 := '0'; + VARIABLE TD_CSNeg_SCK_DDR : VitalTimingDataType; + + VARIABLE Tviol_CSNeg_RSTNeg : X01 := '0'; + VARIABLE TD_CSNeg_RSTNeg : VitalTimingDataType; + + VARIABLE Tviol_SI_SCK : X01 := '0'; + VARIABLE TD_SI_SCK : VitalTimingDataType; + + VARIABLE Tviol_WPNeg_CSNeg_setup : X01 := '0'; + VARIABLE TD_WPNeg_CSNeg_setup : VitalTimingDataType; + + VARIABLE Tviol_WPNeg_CSNeg_hold : X01 := '0'; + VARIABLE TD_WPNeg_CSNeg_hold : VitalTimingDataType; + + VARIABLE Tviol_HOLDNeg_SCK : X01 := '0'; + VARIABLE TD_HOLDNeg_SCK : VitalTimingDataType; + + VARIABLE Tviol_SI_SCK_DDR_R : X01 := '0'; + VARIABLE TD_SI_SCK_DDR_R : VitalTimingDataType; + + VARIABLE Tviol_SI_SCK_DDR_F : X01 := '0'; + VARIABLE TD_SI_SCK_DDR_F : VitalTimingDataType; + + VARIABLE Tviol_RSTNeg_CSNeg : X01 := '0'; + VARIABLE TD_RSTNeg_CSNeg : VitalTimingDataType; + + --Pulse Width and Period Check Variables + VARIABLE Pviol_SCK_serial : X01 := '0'; + VARIABLE PD_SCK_serial : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_dual : X01 := '0'; + VARIABLE PD_SCK_dual : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_fast : X01 := '0'; + VARIABLE PD_SCK_fast : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_quadpg : X01 := '0'; + VARIABLE PD_SCK_quadpg : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_DDR : X01 := '0'; + VARIABLE PD_SCK_DDR : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_CSNeg_read : X01 := '0'; + VARIABLE PD_CSNeg_read : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_CSNeg_pgers : X01 := '0'; + VARIABLE PD_CSNeg_pgers : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_RSTNeg : X01 := '0'; + VARIABLE PD_RSTNeg : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_serial_rd : X01 := '0'; + VARIABLE PD_SCK_serial_rd : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_fast_rd : X01 := '0'; + VARIABLE PD_SCK_fast_rd : VitalPeriodDataType:=VitalPeriodDataInit; + + VARIABLE Pviol_SCK_dual_rd : X01 := '0'; + VARIABLE PD_SCK_dual_rd : VitalPeriodDataType:=VitalPeriodDataInit; + + VARIABLE Pviol_SCK_DDR_rd : X01 := '0'; + VARIABLE PD_SCK_DDR_rd : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_quad_pg : X01 := '0'; + VARIABLE PD_SCK_quad_pg : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Violation : X01 := '0'; + + BEGIN + --------------------------------------------------------------------------- + -- Timing Check Section + --------------------------------------------------------------------------- + IF (TimingChecksOn) THEN + + -- Setup/Hold Check between CS# and SCK + VitalSetupHoldCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_CSNeg_SCK_normal_noedge_posedge, + SetupLow => tsetup_CSNeg_SCK_normal_noedge_posedge, + HoldHigh => thold_CSNeg_SCK_normal_noedge_posedge, + HoldLow => thold_CSNeg_SCK_normal_noedge_posedge, + CheckEnabled => ddr = false, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_CSNeg_SCK_normal, + Violation => Tviol_CSNeg_SCK_normal + ); + + -- Setup/Hold Check between CS# and SCK + VitalSetupHoldCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_CSNeg_SCK_DDR_noedge_posedge, + SetupLow => tsetup_CSNeg_SCK_DDR_noedge_posedge, + HoldHigh => thold_CSNeg_SCK_DDR_noedge_posedge, + HoldLow => thold_CSNeg_SCK_DDR_noedge_posedge, + CheckEnabled => ddr, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_CSNeg_SCK_DDR, + Violation => Tviol_CSNeg_SCK_DDR + ); + + -- Hold Check between CSNeg and RSTNeg + VitalSetupHoldCheck ( + TestSignal => CSNeg, + TestSignalName => "CSNeg", + RefSignal => RSTNeg, + RefSignalName => "RSTNeg", + HoldHigh => thold_CSNeg_RSTNeg, + CheckEnabled => TRUE, + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_CSNeg_RSTNeg, + Violation => Tviol_CSNeg_RSTNeg + ); + + -- Setup/Hold Check between SI and SCK, serial mode + VitalSetupHoldCheck ( + TestSignal => SIIn, + TestSignalName => "SI", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_normal_noedge_posedge, + SetupLow => tsetup_SI_SCK_normal_noedge_posedge, + HoldHigh => thold_SI_SCK_normal_noedge_posedge, + HoldLow => thold_SI_SCK_normal_noedge_posedge, + CheckEnabled => NOT(DOUBLE) AND SIOut_z /= SIIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_SI_SCK, + Violation => Tviol_SI_SCK + ); + + -- Setup Check between WP# and CS# \ + VitalSetupHoldCheck ( + TestSignal => WPNegIn, + TestSignalName => "WP#", + RefSignal => CSNeg_ipd, + RefSignalName => "CS#", + SetupHigh => tsetup_WPNeg_CSNeg, + CheckEnabled => true, + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WPNeg_CSNeg_setup, + Violation => Tviol_WPNeg_CSNeg_setup + ); + + -- Hold Check between WP# and CS# / + VitalSetupHoldCheck ( + TestSignal => WPNegIn, + TestSignalName => "WP#", + RefSignal => CSNeg_ipd, + RefSignalName => "CS#", + HoldHigh => thold_WPNeg_CSNeg, + CheckEnabled => SRWD = '1' AND WEL = '1', + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WPNeg_CSNeg_hold, + Violation => Tviol_WPNeg_CSNeg_hold + ); + + -- Setup/Hold Check between HOLD# and SCK / + VitalSetupHoldCheck ( + TestSignal => HOLDNegIn, + TestSignalName => "HOLD#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupLow => tsetup_HOLDNeg_SCK, + SetupHigh => tsetup_HOLDNeg_SCK, + HoldLow => thold_HOLDNeg_SCK, + HoldHigh => thold_HOLDNeg_SCK, + CheckEnabled => QUAD = '0' + AND HOLDNegOut_zd /= HOLDNegIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_HOLDNeg_SCK, + Violation => Tviol_HOLDNeg_SCK + ); + + -- Setup/Hold Check between SI and SCK, DDR mode + VitalSetupHoldCheck ( + TestSignal => SIIn, + TestSignalName => "SI", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_DDR_noedge_posedge, + SetupLow => tsetup_SI_SCK_DDR_noedge_posedge, + HoldHigh => thold_SI_SCK_DDR_noedge_posedge, + HoldLow => thold_SI_SCK_DDR_noedge_posedge, + CheckEnabled => DOUBLE AND dual = false + AND SIOut_z /= SIIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_SI_SCK_DDR_R, + Violation => Tviol_SI_SCK_DDR_R + ); + + -- Setup/Hold Check between SI and SCK, DDR mode + VitalSetupHoldCheck ( + TestSignal => SIIn, + TestSignalName => "SI", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_DDR_noedge_negedge, + SetupLow => tsetup_SI_SCK_DDR_noedge_negedge, + HoldHigh => thold_SI_SCK_DDR_noedge_negedge, + HoldLow => thold_SI_SCK_DDR_noedge_negedge, + CheckEnabled => ddr AND dual = false + AND SIOut_z /= SIIn, + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_SI_SCK_DDR_F, + Violation => Tviol_SI_SCK_DDR_F + ); + + -- Setup Check between RSTNeg and SCK, DDR fast mode + VitalSetupHoldCheck ( + TestSignal => RSTNeg, + TestSignalName => "RSTNeg", + RefSignal => CSNeg, + RefSignalName => "CSNeg", + SetupHigh => tsetup_RSTNeg_CSNeg, + CheckEnabled => TRUE, + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_RSTNeg_CSNeg, + Violation => Tviol_RSTNeg_CSNeg + ); + + --Pulse Width and Period Check Variables + -- Pulse Width Check SCK for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_serial_negedge, + PulseWidthHigh => tpw_SCK_serial_posedge, + PeriodData => PD_SCK_serial, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_serial, + HeaderMsg => InstancePath & PartID, + CheckEnabled => rd); + + -- Pulse Width Check SCK for DUAL_READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_dual_negedge, + PulseWidthHigh => tpw_SCK_dual_posedge, + PeriodData => PD_SCK_dual, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_dual, + HeaderMsg => InstancePath & PartID, + CheckEnabled => dual); + + -- Pulse Width Check SCK for FAST_READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_fast_negedge, + PulseWidthHigh => tpw_SCK_fast_posedge, + PeriodData => PD_SCK_fast, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_fast, + HeaderMsg => InstancePath & PartID, + CheckEnabled => fast_rd ); + + -- Pulse Width Check SCK for QPP + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_quadpg_negedge, + PulseWidthHigh => tpw_SCK_quadpg_posedge, + PeriodData => PD_SCK_quadpg, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_quadpg, + HeaderMsg => InstancePath & PartID, + CheckEnabled => quadpg); + + -- Pulse Width Check CS# for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + PulseWidthHigh => tpw_CSNeg_read_posedge, + PeriodData => PD_CSNeg_read, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_CSNeg_read, + HeaderMsg => InstancePath & PartID, + CheckEnabled => any_read ); + + -- Pulse Width Check CS# for Program/Erase, serial mode + VitalPeriodPulseCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + PulseWidthHigh => tpw_CSNeg_pgers_posedge, + PeriodData => PD_CSNeg_pgers, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_CSNeg_pgers, + HeaderMsg => InstancePath & PartID, + CheckEnabled => NOT(any_read)); + + -- Pulse Width Check RSTNeg + VitalPeriodPulseCheck ( + TestSignal => RSTNeg_ipd, + TestSignalName => "RSTNeg", + PulseWidthLow => tpw_RSTNeg_negedge, + PulseWidthHigh => tpw_RSTNeg_posedge, + CheckEnabled => TRUE, + HeaderMsg => InstancePath & PartID, + PeriodData => PD_RSTNeg, + Violation => Pviol_RSTNeg + ); + + -- Pulse Width Check SCK for DDR READ + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_DDR_negedge, + PulseWidthHigh => tpw_SCK_DDR_posedge, + PeriodData => PD_SCK_DDR, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_DDR, + HeaderMsg => InstancePath & PartID, + CheckEnabled => ddr); + + -- Period Check SCK for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_serial_rd, + PeriodData => PD_SCK_serial_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_serial_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => rd ); + + -- Period Check SCK for FAST READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_fast_rd, + PeriodData => PD_SCK_fast_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_fast_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => fast_rd ); + + -- Period Check SCK for DUAL READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_dual_rd, + PeriodData => PD_SCK_dual_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_dual_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => dual ); + + -- Period Check SCK for QPP + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_quadpg, + PeriodData => PD_SCK_quad_pg, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_quad_pg, + HeaderMsg => InstancePath & PartID, + CheckEnabled => quadpg ); + + -- Period Check SCK for DDR READ + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_DDR_rd, + PeriodData => PD_SCK_DDR_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_DDR_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => ddr ); + + Violation := Tviol_CSNeg_SCK_normal OR + Tviol_CSNeg_SCK_DDR OR + Tviol_CSNeg_RSTNeg OR + Tviol_SI_SCK OR + Tviol_WPNeg_CSNeg_setup OR + Tviol_WPNeg_CSNeg_hold OR + Tviol_HOLDNeg_SCK OR + Tviol_SI_SCK_DDR_R OR + Tviol_SI_SCK_DDR_F OR + Tviol_RSTNeg_CSNeg OR + Pviol_SCK_serial OR + Pviol_SCK_dual OR + Pviol_SCK_fast OR + Pviol_SCK_quadpg OR + Pviol_CSNeg_read OR + Pviol_CSNeg_pgers OR + Pviol_SCK_DDR OR + Pviol_SCK_serial_rd OR + Pviol_SCK_fast_rd OR + Pviol_SCK_dual_rd OR + Pviol_SCK_quad_pg OR + Pviol_SCK_DDR_rd; + + Viol <= Violation; + + ASSERT Violation = '0' + REPORT InstancePath & partID & ": simulation may be" & + " inaccurate due to timing violations" + SEVERITY WARNING; + + END IF; + END PROCESS VITALTimingCheck; + + ---------------------------------------------------------------------------- + -- sequential process for FSM state transition + ---------------------------------------------------------------------------- + StateTransition : PROCESS(next_state, RST, PoweredUp, RST_out) + + BEGIN + IF PoweredUp = '1' THEN + IF RSTNeg_pullup = '1' and RST_out= '1' THEN + IF next_state'EVENT THEN + current_state <= next_state; + END IF; + ELSIF RSTNeg_pullup = '0' AND falling_edge(RST) THEN + --no state transition while RESET# low + current_state <= RESET_STATE; + RST_in <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END PROCESS StateTransition; + + Threset : PROCESS(RST_in) + BEGIN + IF rising_edge(RST_in) THEN + RST_out <= '0', '1' AFTER (thold_CSNeg_RSTNeg-200 ns); + END IF; + END PROCESS Threset; + + --------------------------------------------------------------------------- + -- Write cycle decode + --------------------------------------------------------------------------- + + BusCycleDecode : PROCESS(SCK_ipd, CSNeg_ipd, HOLDNeg_pullup, SIIn, RST_out, + WPNeg_pullup) + + TYPE quad_data_type IS ARRAY (0 TO 1023) OF INTEGER RANGE 0 TO 15; + + VARIABLE bit_cnt : NATURAL := 0; + VARIABLE Data_in : std_logic_vector(4095 downto 0) + := (others => '0'); + + VARIABLE opcode : std_logic_vector(7 downto 0); + VARIABLE opcode_in : std_logic_vector(7 downto 0); + VARIABLE addr_bytes : std_logic_vector(31 downto 0); + VARIABLE hiaddr_bytes : std_logic_vector(31 downto 0); + VARIABLE Address_in : std_logic_vector(31 downto 0); + VARIABLE mode_bytes : std_logic_vector(7 downto 0); + VARIABLE mode_in : std_logic_vector(7 downto 0); + VARIABLE quad_data_in : quad_data_type; + VARIABLE quad_nybble : std_logic_vector(3 downto 0); + VARIABLE Quad_slv : std_logic_vector(3 downto 0); + VARIABLE Byte_slv : std_logic_vector(7 downto 0); + + VARIABLE CLK_PER : time; + VARIABLE LAST_CLK : time; + VARIABLE Check_freq : boolean := FALSE; + + BEGIN + + IF rising_edge(CSNeg_ipd) AND NOT(bus_cycle_state = DATA_BYTES) + AND NOT(bus_cycle_state = DUMMY_BYTES) THEN + bus_cycle_state := STAND_BY; + ELSE + CASE bus_cycle_state IS + WHEN STAND_BY => + IF falling_edge(CSNeg_ipd) THEN + Instruct <= NONE; + write <= '1'; + cfg_write <= '0'; + opcode_cnt:= 0; + addr_cnt := 0; + mode_cnt := 0; + dummy_cnt := 0; + dummy_cnt_act_temp <= dummy_cnt; + data_cnt := 0; + DOUBLE := FALSE; + CLK_PER := 0 ns; + LAST_CLK := 0 ns; + IF current_state = AUTOBOOT THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := OPCODE_BYTE; + END IF; + END IF; + + WHEN OPCODE_BYTE => + IF rising_edge(SCK_ipd) THEN + + Latency_code := to_nat(LC1 & LC0); + CLK_PER := NOW - LAST_CLK; + LAST_CLK := NOW; + IF Check_freq THEN + IF (CLK_PER < 20 ns AND Latency_code = 3) OR + (CLK_PER < 12.5 ns AND Latency_code = 0) OR + (CLK_PER < 11.1 ns AND Latency_code = 1) OR + (CLK_PER < 9.6 ns AND Latency_code = 2) THEN + ASSERT FALSE + REPORT "More wait states are required for " & + "this clock frequency value" + SEVERITY warning; + END IF; + END IF; + Check_freq := FALSE; + + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1') THEN + --One-byte of instruction opcode is shifted into the + --device on the SI serial input pin with the most + --significant bit (MSB) first.Each bit input on the + --SI serial input pin is latched on the rising edge of + --the SCK serial clock signal. + opcode_in(opcode_cnt) := SIIn; + opcode_cnt := opcode_cnt + 1; + IF opcode_cnt = BYTE THEN + --MSB first + FOR I IN 7 DOWNTO 0 LOOP + opcode(i) := opcode_in(7-i); + END LOOP; + + CASE opcode IS + WHEN "00000110" => --06h + Instruct <= WREN; + bus_cycle_state := DATA_BYTES; + WHEN "00000100" => --04h + Instruct <= WRDI; + bus_cycle_state := DATA_BYTES; + WHEN "00000001" => --01h + Instruct <= WRR; + bus_cycle_state := DATA_BYTES; + WHEN "00000011" => --03h + Instruct <= READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00010011" => --13h + Instruct <= RD4; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01001011" => --4Bh + Instruct <= OTPR; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00000101" => --05h + Instruct <= RDSR; + bus_cycle_state := DATA_BYTES; + WHEN "00000111" => --07h + Instruct <= RDSR2; + bus_cycle_state := DATA_BYTES; + WHEN "00110101" => --35h + Instruct <= RDCR; + bus_cycle_state := DATA_BYTES; + WHEN "10010000" => --90h + Instruct <= REMS; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10011111" => --9Fh + Instruct <= RDID; + bus_cycle_state := DATA_BYTES; + WHEN "10101011" => --ABh + Instruct <= RES; + bus_cycle_state := DUMMY_BYTES; + WHEN "00001011" => --0Bh + Instruct <= FSTRD; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00001100" => --0Ch + Instruct <= FSTRD4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00001101" => --0Dh + Instruct <= DDRFR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00001110" => --0Eh + Instruct <= DDRFR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00111011" => --3Bh + Instruct <= DOR; + Check_freq := TRUE; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00111100" => --3Ch + Instruct <= DOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "10111011" => --BBh + Instruct <= DIOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "10111100" => --BCh + Instruct <= DIOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "10111101" => --BDh + Instruct <= DDRDIOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "10111110" => --BEh + Instruct <= DDRDIOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "01101011" => --6Bh + Instruct <= QOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "01101100" => --6Ch + Instruct <= QOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "11101011" => --EBh + Instruct <= QIOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "11101100" => --ECh + Instruct <= QIOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "11101101" => --EDh + Instruct <= DDRQIOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "11101110" => --EEh + Instruct <= DDRQIOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00000010" => --02h + Instruct <= PP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00010010" => --12h + Instruct <= PP4; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00110010" => --32h + Instruct <= QPP; + bus_cycle_state := ADDRESS_BYTES; + quadpg <= TRUE; + WHEN "00111000" => --38h + Instruct <= QPP; + bus_cycle_state := ADDRESS_BYTES; + quadpg <= TRUE; + WHEN "00110100" => --34h + Instruct <= QPP4; + bus_cycle_state := ADDRESS_BYTES; + quadpg <= TRUE; + WHEN "01000010" => --42h + Instruct <= OTPP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10000101" => --85h + Instruct <= PGSP; + bus_cycle_state := DATA_BYTES; + WHEN "10001010" => --8Ah + Instruct <= PGRS; + bus_cycle_state := DATA_BYTES; + WHEN "11000111" => --C7h + Instruct <= BE; + bus_cycle_state := DATA_BYTES; + WHEN "01100000" => --60h + Instruct <= BE; + bus_cycle_state := DATA_BYTES; + WHEN "11011000" => --D8h + Instruct <= SE; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11011100" => --DCh + Instruct <= SE4; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00100000" => --20h + Instruct <= P4E; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00100001" => --21h + Instruct <= P4E4; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01110101" => --75h + Instruct <= ERSP; + bus_cycle_state := DATA_BYTES; + WHEN "01111010" => --7Ah + Instruct <= ERRS; + bus_cycle_state := DATA_BYTES; + WHEN "00010100" => --14h + Instruct <= ABRD; + bus_cycle_state := DATA_BYTES; + WHEN "00010101" => --15h + Instruct <= ABWR; + bus_cycle_state := DATA_BYTES; + WHEN "00010110" => --16h + Instruct <= BRRD; + bus_cycle_state := DATA_BYTES; + WHEN "00010111" => --17h + Instruct <= BRWR; + bus_cycle_state := DATA_BYTES; + WHEN "10111001" => --B9h + Instruct <= BRAC; + bus_cycle_state := DATA_BYTES; + WHEN "00101011" => --2Bh + Instruct <= ASPRD; + bus_cycle_state := DATA_BYTES; + WHEN "00101111" => --2Fh + Instruct <= ASPP; + bus_cycle_state := DATA_BYTES; + WHEN "11100000" => --E0h + Instruct <= DYBRD; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11100001" => --E1h + Instruct <= DYBWR; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11100010" => --E2h + Instruct <= PPBRD; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11100011" => --E3h + Instruct <= PPBP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11100100" => --E4h + Instruct <= PPBERS; + bus_cycle_state := DATA_BYTES; + WHEN "10100110" => --A6h + Instruct <= PLBWR; + bus_cycle_state := DATA_BYTES; + WHEN "10100111" => --A7h + Instruct <= PLBRD; + bus_cycle_state := DATA_BYTES; + WHEN "11100111" => --E7h + Instruct <= PASSRD; + bus_cycle_state := DATA_BYTES; + WHEN "11101000" => --E8h + Instruct <= PASSP; + bus_cycle_state := DATA_BYTES; + WHEN "11101001" => --E9h + Instruct <= PASSU; + bus_cycle_state := DATA_BYTES; + WHEN "11110000" => --F0h + Instruct <= RESET; + bus_cycle_state := DATA_BYTES; + WHEN "11111111" => --FFh + Instruct <= MBR; + bus_cycle_state := MODE_BYTE; + WHEN "01000001" => -- 41h + Instruct <= DLPRD; + bus_cycle_state := DATA_BYTES; + WHEN "01000011" => -- 43h + Instruct <= PNVDLR; + bus_cycle_state := DATA_BYTES; + WHEN "01001010" => -- 4Ah + Instruct <= WVDLR; + bus_cycle_state := DATA_BYTES; + WHEN "00110000" => --30h + Instruct <= CLSR; + bus_cycle_state := DATA_BYTES; + WHEN others => + null; + + END CASE; + END IF; + END IF; + END IF; + + WHEN ADDRESS_BYTES => + IF Instruct= DDRFR OR Instruct= DDRFR4 OR Instruct= DDRDIOR + OR Instruct = DDRDIOR4 OR Instruct = DDRQIOR OR + Instruct = DDRQIOR4 THEN + DOUBLE := TRUE; + ELSE + DOUBLE := FALSE; + END IF; + + IF (rising_edge(SCK_ipd) AND NOT(DOUBLE) AND + (CSNeg_ipd= '0')) THEN + IF (((Instruct=FSTRD AND EXTADD= '0' ) + OR (Instruct=DOR AND EXTADD= '0') + OR Instruct=OTPR) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) + OR (Instruct=QOR AND QUAD= '1' AND EXTADD='0') THEN + --Instruction + 3 Bytes Address + Dummy Byte + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 3*BYTE THEN + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 26) := "000000"; + addr_bytes(25 downto 24) := + Bank_Addr_reg (1 downto 0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF (Instruct=FSTRD OR Instruct=DOR OR + Instruct=QOR) THEN + IF (Latency_code = 3) THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF ((((Instruct=FSTRD4) OR (Instruct=DOR4) OR + ((Instruct=FSTRD) AND EXTADD= '1') OR + ((Instruct=DOR) AND EXTADD= '1')) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) OR + ((Instruct=QOR4) AND QUAD='1') OR + ((Instruct=QOR) AND QUAD='1' AND EXTADD='1')) THEN + --Instruction + 4 Bytes Address + Dummy Byte + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 4*BYTE THEN + FOR I IN 31 DOWNTO 0 LOOP + hiaddr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(hiaddr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF Latency_code = 3 THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := DUMMY_BYTES; + IF (DOUBLE AND NOT(hold_mode) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + ELSIF Instruct = DIOR AND EXTADD= '0' AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1') THEN + -- DUAL I/O High Performance Read (3Bytes Address) + IF SOIn /= 'Z' THEN + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt+1) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = (3*BYTE) / 2 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 26) := "000000"; + addr_bytes(25 downto 24) := + Bank_Addr_reg (1 downto 0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSE + bus_cycle_state := STAND_BY; + END IF; + ELSIF ((Instruct = DIOR4 OR + (Instruct = DIOR AND EXTADD= '1')) AND + ((HOLDNeg_pullup = '1' AND QUAD = '0') OR + QUAD = '1')) THEN + -- DUAL I/O High Performance Read (4Bytes Address) + IF SOIn /= 'Z' THEN + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt+1) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = (4*BYTE) / 2 THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + hiaddr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(hiaddr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSE + bus_cycle_state := STAND_BY; + END IF; + ELSIF (Instruct = QIOR AND EXTADD= '0') THEN + -- QUAD I/O High Performance Read (3Bytes Address) + IF QUAD = '1' THEN + IF SOIn /= 'Z' THEN + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = (3*BYTE) / 4 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 26) := "000000"; + addr_bytes(25 downto 24) := + Bank_Addr_reg (1 downto 0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + END IF; + ELSE + bus_cycle_state := STAND_BY; + END IF; + ELSIF (Instruct = QIOR4 OR + (Instruct = QIOR AND EXTADD= '1')) THEN + -- QUAD I/O High Performance Read (4Bytes Address) + IF QUAD = '1' THEN + IF SOIn /= 'Z' THEN + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = (4*BYTE) / 4 THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + hiaddr_bytes(31-i) + := Address_in(i); + END LOOP; + Address <= to_nat(hiaddr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + END IF; + ELSE + bus_cycle_state := STAND_BY; + END IF; + ELSIF (((Instruct = RD4 OR Instruct = PP4 OR + Instruct = SE4 OR Instruct = PPBRD OR + Instruct = DYBRD OR Instruct = DYBWR OR + Instruct = PPBP OR Instruct = P4E4 OR + (Instruct = READ AND EXTADD= '1' ) OR + (Instruct = PP AND EXTADD= '1' ) OR + (Instruct = P4E AND EXTADD= '1' ) OR + (Instruct = SE AND EXTADD= '1' )) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) + OR (QUAD ='1' AND (Instruct=QPP4 OR + (Instruct = QPP AND EXTADD= '1' ))))THEN + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 4*BYTE THEN + FOR I IN 31 DOWNTO 0 LOOP + hiaddr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(hiaddr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (((HOLDNeg_pullup='1' AND QUAD='0') + OR QUAD='1') AND EXTADD= '0') THEN + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 3*BYTE THEN + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 26) := "000000"; + addr_bytes(25 downto 24) := + Bank_Addr_reg (1 downto 0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF (SCK_ipd'EVENT AND DOUBLE AND addr_cnt /= 0 ) OR + (rising_edge(SCK_ipd) AND DOUBLE AND addr_cnt = 0 ) THEN + IF (Instruct=DDRFR AND EXTADD= '0' ) THEN + --Fast DDR Read Mode + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = 3*BYTE THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 26) := "000000"; + addr_bytes(25 downto 24) := + Bank_Addr_reg (1 downto 0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF (Instruct=DDRFR4 OR + (Instruct=DDRFR AND EXTADD= '1' )) THEN + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = 4*BYTE THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + addr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + ELSIF (Instruct= DDRDIOR AND EXTADD= '0' ) THEN + --Dual I/O DDR Read Mode + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt+1):= SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = (3*BYTE)/2 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 26) := "000000"; + addr_bytes(25 downto 24) := + Bank_Addr_reg (1 downto 0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF (Instruct=DDRDIOR4 OR + (Instruct=DDRDIOR AND EXTADD= '1' )) THEN + --Dual I/O DDR Read Mode + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt+1) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = (4*BYTE)/2 THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + addr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + ELSIF (Instruct=DDRQIOR AND EXTADD= '0' ) AND + QUAD = '1' THEN + --Quad I/O DDR Read Mode + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = (3*BYTE)/4 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 26) := "000000"; + addr_bytes(25 downto 24) := + Bank_Addr_reg (1 downto 0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 5 ns; + bus_cycle_state := MODE_BYTE; + END IF; + ELSIF QUAD = '1' AND (Instruct=DDRQIOR4 OR + (Instruct=DDRQIOR AND EXTADD= '1' )) THEN + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = (4*BYTE)/4 THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + addr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + END IF; + END IF; + + WHEN MODE_BYTE => + IF rising_edge(SCK_ipd) THEN + IF ((Instruct=DIOR OR Instruct = DIOR4) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) THEN + mode_in(2*mode_cnt) := SOIn; + mode_in(2*mode_cnt+1) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/2 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + IF Latency_code = 0 OR Latency_code = 3 THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF (Instruct=QIOR OR Instruct = QIOR4) + AND QUAD = '1' THEN + mode_in(4*mode_cnt) := HOLDNegIn; + mode_in(4*mode_cnt+1) := WPNegIn; + mode_in(4*mode_cnt+2) := SOIn; + mode_in(4*mode_cnt+3) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/4 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DUMMY_BYTES; + END IF; + ELSIF Instruct=DDRFR OR Instruct = DDRFR4 THEN + mode_in(2*mode_cnt) := SIIn; + ELSIF Instruct=DDRDIOR OR Instruct = DDRDIOR4 THEN + mode_in(4*mode_cnt) := SOIn; + mode_in(4*mode_cnt+1) := SIIn; + ELSIF (Instruct=DDRQIOR OR Instruct = DDRQIOR4) + AND QUAD = '1' THEN + mode_in(0) := HOLDNegIn; + mode_in(1) := WPNegIn; + mode_in(2) := SOIn; + mode_in(3) := SIIn; + END IF; + dummy_cnt := 0; + dummy_cnt_act_temp <= dummy_cnt; + ELSIF falling_edge(SCK_ipd) THEN + IF Instruct=DDRFR OR Instruct = DDRFR4 THEN + mode_in(2*mode_cnt+1) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/2 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + ELSIF Instruct=DDRDIOR OR Instruct = DDRDIOR4 THEN + mode_in(4*mode_cnt+2) := SOIn; + mode_in(4*mode_cnt+3) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/4 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + ELSIF (Instruct=DDRQIOR OR Instruct = DDRQIOR4) + AND QUAD = '1' THEN + mode_in(4) := HOLDNegIn; + mode_in(5) := WPNegIn; + mode_in(6) := SOIn; + mode_in(7) := SIIn; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + + WHEN DUMMY_BYTES => + IF rising_edge(SCK_ipd) THEN + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + IF (((Instruct=FSTRD OR Instruct=FSTRD4 OR + Instruct=DOR OR Instruct=DOR4 OR + Instruct=OTPR) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) OR + ((Instruct = QOR OR Instruct = QOR4) AND + QUAD = '1'))THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF dummy_cnt = BYTE THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct=DDRFR OR Instruct=DDRFR4) THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF EHP THEN + IF ((Latency_code = 3 AND dummy_cnt=1) OR + (Latency_code = 0 AND dummy_cnt=2) OR + (Latency_code = 1 AND dummy_cnt=4) OR + (Latency_code = 2 AND dummy_cnt=5)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + ELSE + IF ((Latency_code = 3 AND dummy_cnt = 4) OR + (Latency_code = 0 AND dummy_cnt = 5) OR + (Latency_code = 1 AND dummy_cnt = 6) OR + (Latency_code = 2 AND dummy_cnt = 7)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF Instruct=RES THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF dummy_cnt = 3*BYTE THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct = DIOR OR Instruct = DIOR4) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1') THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF EHP THEN + IF ((Latency_code = 1 AND dummy_cnt = 1) OR + (Latency_code = 2 AND dummy_cnt = 2)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + ELSE + IF ((Latency_code = 3 AND dummy_cnt = 4) OR + (Latency_code = 0 AND dummy_cnt = 4) OR + (Latency_code = 1 AND dummy_cnt = 5) OR + (Latency_code = 2 AND dummy_cnt = 6)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF EHP THEN + IF ((Latency_code = 3 AND dummy_cnt = 2) OR + (Latency_code = 0 AND dummy_cnt = 4) OR + (Latency_code = 1 AND dummy_cnt = 5) OR + (Latency_code = 2 AND dummy_cnt = 6)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + ELSE + IF ((Latency_code = 3 AND dummy_cnt = 4) OR + (Latency_code = 0 AND dummy_cnt = 6) OR + (Latency_code = 1 AND dummy_cnt = 7) OR + (Latency_code = 2 AND dummy_cnt = 8)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF ((Instruct = QIOR OR Instruct = QIOR4) AND + QUAD = '1') THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF ((Latency_code = 3 AND dummy_cnt = 1) OR + (Latency_code = 0 AND dummy_cnt = 4) OR + (Latency_code = 1 AND dummy_cnt = 4) OR + (Latency_code = 2 AND dummy_cnt = 5)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct = DDRQIOR OR Instruct = DDRQIOR4) + AND QUAD = '1' THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF ((Latency_code = 3 AND dummy_cnt = 3) OR + (Latency_code = 0 AND dummy_cnt = 6) OR + (Latency_code = 1 AND dummy_cnt = 7) OR + (Latency_code = 2 AND dummy_cnt = 8)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF falling_edge(SCK_ipd) THEN + IF NOT(hold_mode) THEN + IF (DOUBLE AND VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + + WHEN DATA_BYTES => + IF rising_edge(CSNeg_ipd) THEN + IF ((mode_bytes(7 downto 4) = "1010" AND + (Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QIOR OR Instruct = QIOR4)) OR + ((mode_bytes(7 downto 4) = + NOT(mode_bytes(3 downto 0))) AND + (Instruct = DDRFR OR Instruct = DDRFR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 OR + Instruct = DDRQIOR OR Instruct = DDRQIOR4))) THEN + bus_cycle_state := ADDRESS_BYTES; + ELSE + bus_cycle_state := STAND_BY; + END IF; + END IF; + IF falling_edge(SCK_ipd) AND CSNeg_ipd = '0' AND + NOT(DOUBLE) THEN + IF ((Instruct = READ OR Instruct=RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = RDSR OR Instruct = RDSR2 OR + Instruct = RDCR OR Instruct = OTPR OR + Instruct = DOR OR Instruct = DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = ABRD OR Instruct = BRRD OR + Instruct = ASPRD OR Instruct = DYBRD OR + Instruct = PPBRD OR + Instruct = PASSRD OR Instruct = RDID OR + Instruct = RES OR Instruct = REMS OR + Instruct = PLBRD OR Instruct = DLPRD) + AND ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) + OR (current_state = AUTOBOOT AND start_delay = 0)OR + ((Instruct=QOR OR Instruct=QIOR OR Instruct=QOR4 + OR Instruct= QIOR4) AND QUAD = '1') THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + ELSIF SCK_ipd'EVENT AND CSNeg_ipd = '0' AND DOUBLE THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + + IF rising_edge(SCK_ipd) THEN + IF QUAD = '1' AND (Instruct=QPP OR Instruct = QPP4)THEN + quad_nybble := HOLDNegIn & WPNegIn & SOIn & SIIn; + IF data_cnt > (PageSize*2-1) THEN + --In case of quad mode and QPP, + --if more than 512 bytes are sent to the device + FOR I IN 0 TO (PageSize*2-2) LOOP + quad_data_in(i) := quad_data_in(i+1); + END LOOP; + quad_data_in((PageSize*2-1)) := + to_nat(quad_nybble); + data_cnt := data_cnt +1; + ELSE + IF quad_nybble /= "ZZZZ" THEN + quad_data_in(data_cnt) := + to_nat(quad_nybble); + END IF; + data_cnt := data_cnt +1; + END IF; + ELSIF ((HOLDNeg_pullup='1' AND QUAD='0') + OR QUAD='1') THEN + IF data_cnt > (PageSize*8-1) THEN + --In case of serial mode and PP, + -- if more than 512 bytes are sent to the device + -- previously latched data are discarded and last + -- 512 data bytes are guaranteed to be programmed + -- correctly within the same page. + IF bit_cnt = 0 THEN + FOR I IN 0 TO ((PageSize-1)*BYTE - 1) LOOP + Data_in(i) := Data_in(i+8); + END LOOP; + END IF; + Data_in((PageSize-1)*BYTE + bit_cnt) := SIIn; + bit_cnt := bit_cnt + 1; + IF bit_cnt = 8 THEN + bit_cnt := 0; + END IF; + data_cnt := data_cnt + 1; + ELSE + Data_in(data_cnt) := SIIn; + data_cnt := data_cnt + 1; + bit_cnt := 0; + END IF; + END IF; + END IF; + + IF rising_edge(CSNeg_ipd) THEN + CASE Instruct IS + WHEN WREN | WRDI | BE | SE | SE4 | CLSR | RESET | + PPBP | PPBERS | PGSP | PGRS | ERSP | BRAC | + ERRS | P4E | P4E4 | PLBWR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') + OR QUAD='1') THEN + IF data_cnt = 0 THEN + write <= '0'; + END IF; + END IF; + + WHEN WRR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') + OR QUAD='1') THEN + IF ((data_cnt mod 8) = 0 AND data_cnt > 0) THEN + IF data_cnt = 8 THEN + --If CS# is driven high after eight + --cycle,only the Status Register is + --written to. + write <= '0'; + IF BAR_ACC = '0' THEN + FOR i IN 0 TO 7 LOOP + Status_reg1_in(i) <= + Data_in(7-i); + END LOOP; + ELSIF P_ERR = '0' AND E_ERR = '0' THEN + FOR i IN 0 TO 7 LOOP + Bank_Addr_reg_in(i) <= + Data_in(7-i); + END LOOP; + END IF; + ELSIF data_cnt = 16 THEN + --After the 16th cycle both the + --Status and Configuration Registers + --are written to. + write <= '0'; + IF BAR_ACC = '0' THEN + FOR i IN 0 TO 7 LOOP + cfg_write <= '1'; + FOR i IN 0 TO 7 LOOP + Status_reg1_in(i) <= + Data_in(7-i); + Config_reg1_in(i) <= + Data_in(15-i); + END LOOP; + END LOOP; + ELSIF P_ERR = '0' AND E_ERR = '0' THEN + FOR i IN 0 TO 7 LOOP + Bank_Addr_reg_in(i) <= + Data_in(7-i); + END LOOP; + END IF; + END IF; + END IF; + END IF; + + WHEN PP | PP4 | OTPP => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt > 0 THEN + IF (data_cnt mod 8) = 0 THEN + write <= '0'; + FOR I IN 0 TO (PageSize-1) LOOP + FOR J IN 7 DOWNTO 0 LOOP + IF Data_in((i*8) + (7-j)) + /= 'X' THEN + Byte_slv(j) := + Data_in((i*8) + (7-j)); + END IF; + END LOOP; + WByte(i) <= + to_nat(Byte_slv); + END LOOP; + IF data_cnt > PageSize*BYTE THEN + Byte_number <= PageSize-1; + ELSE + Byte_number <= data_cnt/8-1; + END IF; + END IF; + END IF; + END IF; + + WHEN QPP | QPP4=> + IF data_cnt > 0 THEN + IF data_cnt mod 2 = 0 THEN + quadpg <= FALSE; + write <= '0'; + FOR I IN 0 TO (PageSize-1) LOOP + FOR J IN 1 DOWNTO 0 LOOP + Quad_slv := + to_slv(quad_data_in((i*2) + + (1-j)),4); + + Byte_slv(4*j+3 DOWNTO 4*j) := + Quad_slv; + END LOOP; + WByte(i) <= to_nat(Byte_slv); + END LOOP; + IF data_cnt > PageSize*2 THEN + Byte_number <= PageSize-1; + ELSE + Byte_number <= data_cnt/2-1; + END IF; + END IF; + END IF; + + WHEN ABWR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 32 THEN + write <= '0'; + FOR J IN 0 TO 31 LOOP + AutoBoot_reg_in(J) <= + Data_in(31-J); + END LOOP; + END IF; + END IF; + + WHEN BRWR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 8 THEN + write <= '0'; + FOR J IN 0 TO 7 LOOP + Bank_Addr_reg_in(J) <= + Data_in(7-J); + END LOOP; + END IF; + END IF; + + WHEN ASPP => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 16 THEN + write <= '0'; + FOR J IN 0 TO 15 LOOP + ASP_reg_in(J) <= + Data_in(15-J); + END LOOP; + END IF; + END IF; + + WHEN DYBWR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 8 THEN + write <= '0'; + FOR J IN 0 TO 7 LOOP + DYBAR_in(J) <= + Data_in(7-J); + END LOOP; + END IF; + END IF; + + WHEN PNVDLR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 8 THEN + write <= '0'; + FOR J IN 0 TO 7 LOOP + NVDLR_reg_in(J) <= Data_in(7-J); + END LOOP; + END IF; + END IF; + + WHEN WVDLR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 8 THEN + write <= '0'; + FOR J IN 0 TO 7 LOOP + VDLR_reg_in(J) <= Data_in(7-J); + END LOOP; + END IF; + END IF; + + WHEN PASSP => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 64 THEN + write <= '0'; + FOR J IN 1 TO 8 LOOP + FOR K IN 1 TO 8 LOOP + Password_reg_in(J*8-K) <= + Data_in(8*(J-1)+K-1); + END LOOP; + END LOOP; + END IF; + END IF; + + WHEN PASSU => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 64 THEN + write <= '0'; + FOR J IN 1 TO 8 LOOP + FOR K IN 1 TO 8 LOOP + PASS_TEMP(J*8-K) <= + Data_in(8*(J-1)+K-1); + END LOOP; + END LOOP; + END IF; + END IF; + + WHEN others => + null; + + END CASE; + END IF; + END CASE; + END IF; + + END PROCESS BusCycleDecode; + + --------------------------------------------------------------------------- + -- Timing control for the Page Program + --------------------------------------------------------------------------- + ProgTime : PROCESS(PSTART, PGSUSP, PGRES, RST, Reseted) + VARIABLE pob : time; + VARIABLE elapsed : time; + VARIABLE start : time; + VARIABLE duration : time; + BEGIN + IF rising_edge(PSTART) AND PDONE = '1' THEN + IF Instruct = PP OR Instruct = PP4 OR Instruct = OTPP OR + Instruct = QPP OR Instruct = QPP4 THEN + pob := tdevice_PP; + ELSE + pob := tdevice_BP; + END IF; + elapsed := 0 ns; + start := NOW; + PDONE <= '0', '1' AFTER pob; + ELSIF PGSUSP'EVENT AND PGSUSP = '1' AND PDONE /= '1' THEN + elapsed := NOW - start; + duration := pob - elapsed; + PDONE <= '0'; + ELSIF PGRES'EVENT AND PGRES = '1' AND PDONE /= '1'THEN + start := NOW; + PDONE <= '0', '1' AFTER duration; + END IF; + + IF (RST'EVENT AND RST = '0') THEN + PDONE <= '1'; -- reset done, programing terminated + ELSIF rising_edge(Reseted) THEN + PDONE <= '1'; -- reset done, programing terminated + END IF; + + END PROCESS ProgTime; + + --------------------------------------------------------------------------- + -- Timing control for the Write Status Register + --------------------------------------------------------------------------- + WriteTime : PROCESS(WSTART) + VARIABLE wob : time; + BEGIN + IF LongTimming THEN + wob := tdevice_WRR; + ELSE + wob := tdevice_WRR / 100; + END IF; + IF rising_edge(WSTART) AND WDONE = '1' THEN + WDONE <= '0', '1' AFTER wob; + END IF; + + IF (RST'EVENT AND RST = '0') THEN + WDONE <= '1'; -- reset done, programing terminated + ELSIF rising_edge(Reseted) THEN + WDONE <= '1'; -- reset done, programing terminated + END IF; + + END PROCESS WriteTime; + + --------------------------------------------------------------------------- + -- Timing control for the Bulk Erase + --------------------------------------------------------------------------- + ErsTime : PROCESS(ESTART, ESUSP, ERES, RST, Reseted) + VARIABLE seo : time; + VARIABLE beo : time; + VARIABLE elapsed : time; + VARIABLE start : time; + VARIABLE duration : time; + BEGIN + IF LongTimming THEN + seo := tdevice_SE; + beo := tdevice_BE; + ELSE + seo := tdevice_SE / 1000; + beo := tdevice_BE / 1000; + END IF; + IF rising_edge(ESTART) AND EDONE = '1' THEN + IF Instruct = BE THEN + duration := beo; + ELSE --Instruct = SE OR SE4 + duration := seo; + END IF; + elapsed := 0 ns; + EDONE <= '0', '1' AFTER duration; + start := NOW; + ELSIF ESUSP'EVENT AND ESUSP = '1' AND EDONE /= '1' THEN + elapsed := NOW - start; + duration := duration - elapsed; + EDONE <= '0'; + ELSIF ERES'EVENT AND ERES = '1' AND EDONE /= '1' THEN + start := NOW; + EDONE <= '0', '1' AFTER duration; + END IF; + + IF (RST'EVENT AND RST = '0') THEN + EDONE <= '1'; -- reset done, eras terminated + ELSIF rising_edge(Reseted) THEN + EDONE <= '1'; -- reset done, erase terminated + END IF; + + END PROCESS ErsTime; + + CheckCEOnPowerUP :PROCESS(CSNeg_ipd) + BEGIN + IF (PoweredUp = '0' AND falling_edge(CSNeg_ipd)) THEN + REPORT InstancePath & partID & + ": Device is selected during Power Up" + SEVERITY WARNING; + END IF; + END PROCESS; + + --------------------------------------------------------------------------- + -- Main Behavior Process + -- combinational process for next state generation + --------------------------------------------------------------------------- + StateGen :PROCESS(PoweredUp, write, CSNeg_ipd, RSTNeg_pullup, WDONE, PDONE, + ERSSUSP_out, PRGSUSP_out, EDONE, RST_out, PPBERASE_in, + PASSULCK_in) + + VARIABLE sect : NATURAL RANGE 0 TO SecNum; + + BEGIN + + IF rising_edge(PoweredUp) THEN + IF ABE = '1' AND RPME /= '0' THEN + --Autoboot is enabled and The Read Password feature is not enabled + next_state <= AUTOBOOT; + read_cnt := 0; + byte_cnt := 1; + read_addr := to_nat(AutoBoot_reg(31 DOWNTO 9)&"000000000"); + start_delay := to_nat(AutoBoot_reg(8 DOWNTO 1)); + ABSD := to_nat(AutoBoot_reg(8 DOWNTO 1)); + ELSE + next_state <= IDLE; + END IF; + ELSE + IF RST_out= '0' then + next_state <= current_state; + ELSIF falling_edge(write) AND Instruct = RESET THEN + IF ABE = '1' AND RPME /= '0' THEN + read_cnt := 0; + byte_cnt := 1; + read_addr := to_nat(AutoBoot_reg(31 DOWNTO 9)& + "000000000"); + start_delay:= to_nat(AutoBoot_reg(8 DOWNTO 1)); + ABSD := to_nat(AutoBoot_reg(8 DOWNTO 1)); + next_state <= AUTOBOOT; + ELSE + next_state <= IDLE; + END IF; + ELSE + CASE current_state IS + WHEN RESET_STATE => + IF rising_edge(RST_out) THEN + IF ABE = '1' AND RPME /= '0' + AND RdPswdProtMode = '0' THEN + next_state <= AUTOBOOT; + read_cnt := 0; + byte_cnt := 1; + read_addr := to_nat(AutoBoot_reg(31 DOWNTO 9)& + "000000000"); + start_delay := to_nat(AutoBoot_reg(8 DOWNTO 1)); + ABSD := to_nat(AutoBoot_reg(8 DOWNTO 1)); + ELSE + next_state <= IDLE; + END IF; + END IF; + + WHEN IDLE => + IF falling_edge(write) AND RdPswdProtMode = '0' THEN + IF (Instruct = WRR AND WEL = '1' AND BAR_ACC = '0') THEN + IF ((not(SRWD = '1' AND WPNeg_pullup = '0') AND + QUAD = '0') OR QUAD = '1') THEN + -- can not execute if HPM is entered + -- or if WEL bit is zero + IF ((TBPROT='1' AND Config_reg1_in(5)='0') OR + (BPNV ='1' AND Config_reg1_in(3)='0')) AND + cfg_write = '1' THEN + ASSERT cfg_write = '0' + REPORT "Changing value of Configuration " & + "Register OTP bit from 1 to 0 is " & + "not allowed!!!" + SEVERITY WARNING; + ELSE + next_state <= WRITE_SR; + END IF; + END IF; + ELSIF (Instruct = PP OR Instruct = QPP OR + Instruct = PP4 OR Instruct = QPP4) AND + WEL = '1' THEN + sect := Address/(SecSize+1); + pgm_page := Address/PageSize; + IF (Sec_Prot(sect) = '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + next_state <= PAGE_PG; + IF (Instruct = QPP OR Instruct = QPP4) AND + QPP_page(pgm_page) = '1' THEN + REPORT "WARNING:The same page must not be" & + " programmed more than once!!!" + SEVERITY WARNING; + END IF; + END IF; + ELSIF Instruct=OTPP AND WEL = '1' AND FREEZE = '0' THEN + IF ((((Address >= 16#10# AND Address <= 16#13#) OR + (Address >= 16#20# AND Address <= 16#FF#)) + AND LOCK_BYTE1(Address/32) = '1') OR + ((Address >= 16#100# AND Address <= 16#1FF#) + AND LOCK_BYTE2((Address-16#100#)/32) = '1') OR + ((Address >= 16#200# AND Address <= 16#2FF#) + AND LOCK_BYTE3((Address-16#200#)/32) = '1') OR + ((Address >= 16#300# AND Address <= 16#3FF#) + AND LOCK_BYTE4((Address-16#300#)/32) = '1')) AND + (Address + Byte_number <= OTPHiAddr) THEN + next_state <= OTP_PG; + END IF; + ELSIF (Instruct= SE OR Instruct= SE4) AND WEL = '1' THEN + sect := Address/(SecSize+1); + IF (Sec_Prot(sect) = '0' AND PPB_bits(sect)='1' + AND DYB_bits(sect)='1') THEN + next_state <= SECTOR_ERS; + END IF; + ELSIF (Instruct=P4E OR Instruct=P4E4) AND WEL='1' THEN + --A P4E instruction applied to a sector that + --is larger than 4 KB will not be executed + --and will not set the E_ERR status. + REPORT "Warning! Parameter 4KB-sector Erase "& + "Instruction is not allowed for "& + "512Mbit memory size!!! "& + "Instruction is ignored!!!" + SEVERITY warning; + ELSIF Instruct = BE AND WEL = '1' AND + (BP0='0' AND BP1='0' AND BP2='0') THEN + next_state <= BULK_ERS; + ELSIF Instruct = ABWR AND WEL = '1' THEN + --Autoboot Register Write Command + next_state <= AUTOBOOT_PG; + ELSIF Instruct = ASPP AND WEL = '1' THEN + --ASP Register Program Command + IF not(ASPOTPFLAG) THEN + next_state <= ASP_PG; + END IF; + ELSIF Instruct = PLBWR AND WEL = '1' AND + RdPswdProtEnable = '0' THEN + next_state <= PLB_PG; + ELSIF Instruct = PASSP AND WEL = '1' THEN + IF not(PWDMLB='0' AND PSTMLB='1') THEN + next_state <= PASS_PG; + END IF; + ELSIF Instruct = PASSU AND WEL= '1' AND WIP= '0' THEN + next_state <= PASS_UNLOCK; + ELSIF Instruct = PPBP AND WEL = '1' THEN + next_state <= PPB_PG; + ELSIF (Instruct=PPBERS AND WEL='1' AND PPBOTP='1') THEN + next_state <= PPB_ERS; + ELSIF Instruct = DYBWR AND WEL = '1' THEN + next_state <= DYB_PG; + ELSIF Instruct = PNVDLR AND WEL = '1' THEN + next_state <= NVDLR_PG; + ELSE + next_state <= IDLE; + END IF; + END IF; + IF falling_edge(write) AND RdPswdProtMode = '1' AND + WIP = '0' THEN + IF Instruct = PASSU THEN + next_state <= PASS_UNLOCK; + END IF; + END IF; + + WHEN AUTOBOOT => + IF rising_edge(CSNeg_ipd) THEN + next_state <= IDLE; + END IF; + + WHEN WRITE_SR => + IF rising_edge(WDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PAGE_PG => + IF PRGSUSP_out'EVENT AND PRGSUSP_out = '1' THEN + next_state <= PG_SUSP; + ELSIF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PG_SUSP => + IF falling_edge(write) THEN + IF Instruct = PGRS THEN + next_state <= PAGE_PG; + ELSE + next_state <= PG_SUSP; + END IF; + ELSE + next_state <= PG_SUSP; + END IF; + + WHEN OTP_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN BULK_ERS => + IF rising_edge(EDONE) THEN + next_state <= IDLE; + END IF; + + WHEN SECTOR_ERS => + IF ERSSUSP_out'EVENT AND ERSSUSP_out = '1' THEN + next_state <= ERS_SUSP; + ELSIF rising_edge(EDONE) THEN + next_state <= IDLE; + END IF; + + WHEN ERS_SUSP => + IF falling_edge(write) THEN + IF (Instruct = PP OR Instruct = QPP OR + Instruct = PP4 OR Instruct = QPP4) AND + WEL = '1' THEN + IF SectorSuspend /= (Address/(SecSize+1)) THEN + pgm_page := Address / PageSize; + IF PPB_bits(Address/SecSize)='1' AND + DYB_bits(Address/SecSize)='1' THEN + next_state <= ERS_SUSP_PG; + IF (Instruct = QPP OR Instruct = QPP4) AND + QPP_page(pgm_page) = '1' THEN + REPORT "WARNING:The same page must " & + "not be programmed more than once!!!" + SEVERITY WARNING; + END IF; + END IF; + END IF; + ELSIF (Instruct = DYBWR AND WEL = '1') THEN + next_state <= DYB_PG; + ELSIF Instruct = ERRS THEN + next_state <= SECTOR_ERS; + END IF; + ELSE + next_state <= ERS_SUSP; + END IF; + + WHEN ERS_SUSP_PG => + IF PRGSUSP_out'EVENT AND PRGSUSP_out = '1' THEN + next_state <= ERS_SUSP_PG_SUSP; + ELSIF rising_edge(PDONE) THEN + next_state <= ERS_SUSP; + END IF; + + WHEN ERS_SUSP_PG_SUSP => + IF falling_edge(write) THEN + IF Instruct = PGRS THEN + next_state <= ERS_SUSP_PG; + ELSE + next_state <= ERS_SUSP_PG_SUSP; + END IF; + ELSE + next_state <= ERS_SUSP_PG_SUSP; + END IF; + + WHEN PASS_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PASS_UNLOCK => + IF falling_edge(PASSULCK_in) THEN + next_state <= IDLE; + END IF; + + WHEN PPB_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PPB_ERS => + IF falling_edge(PPBERASE_in) THEN + next_state <= IDLE; + END IF; + + WHEN AUTOBOOT_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PLB_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN DYB_PG => + IF rising_edge(PDONE) THEN + IF ES = '1' THEN + next_state <= ERS_SUSP; + ELSE + next_state <= IDLE; + END IF; + END IF; + + WHEN ASP_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN NVDLR_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + END CASE; + END IF; + END IF; + + END PROCESS StateGen; + + ReadEnable: PROCESS (read_out) + BEGIN + oe_z <= rising_edge(read_out) AND PoweredUp = '1'; + + IF read_out'EVENT AND read_out = '0' AND PoweredUp = '1' THEN + oe <= TRUE, FALSE AFTER 1 ns; + END IF; + END PROCESS ReadEnable; + + --------------------------------------------------------------------------- + --FSM Output generation and general funcionality + --------------------------------------------------------------------------- + Functional : PROCESS(write,current_state,start_autoboot,CSNeg_ipd, + HOLDNeg_pullup, Instruct, Address, WByte,change_addr, + PoweredUp, WPNeg_pullup, WDONE, PDONE, EDONE, + PRGSUSP_out,ERSSUSP_out, PASSACC_out, oe, oe_z) + + VARIABLE WData : WByteType:= (OTHERS => MaxData); + + VARIABLE AddrLo : NATURAL; + VARIABLE AddrHi : NATURAL; + VARIABLE Addr : NATURAL; + VARIABLE Addr_tmp : NATURAL; + + VARIABLE data_out : std_logic_vector(7 downto 0); + VARIABLE ident_out : std_logic_vector(647 downto 0); + + VARIABLE ExtendedID : NATURAL; + + VARIABLE old_bit : std_logic_vector(7 downto 0); + VARIABLE new_bit : std_logic_vector(7 downto 0); + VARIABLE old_int : INTEGER RANGE -1 to MaxData; + VARIABLE new_int : INTEGER RANGE -1 to MaxData; + VARIABLE old_pass : std_logic_vector(63 downto 0); + VARIABLE new_pass : std_logic_vector(63 downto 0); + VARIABLE wr_cnt : NATURAL RANGE 0 TO 511; + --Data Learning Pattern Enable + VARIABLE dlp_act : BOOLEAN := FALSE; + + VARIABLE sect : NATURAL RANGE 0 TO SecNum; + VARIABLE cnt : NATURAL RANGE 0 TO 512 := 0; + VARIABLE mem_data : INTEGER; + + BEGIN + + ----------------------------------------------------------------------- + -- Functionality Section + ----------------------------------------------------------------------- + + IF Instruct'EVENT THEN + read_cnt := 0; + byte_cnt := 1; + fast_rd <= true; + dual <= false; + rd <= false; + any_read <= false; + END IF; + + IF PASSACC_out'EVENT AND PASSACC_out = '1' THEN + WIP := '0'; + PASSACC_in <= '0'; + END IF; + + IF rising_edge(PoweredUp) THEN + --the default condition after power-up + --The Bank Address Register is loaded to all zeroes + Bank_Addr_reg := (others => '0'); + --The Configuration Register FREEZE bit is cleared. + FREEZE := '0'; + --The WEL bit is cleared. + WEL := '0'; + --When BPNV is set to '1'. the BP2-0 bits in Status Register are + --volatile and will be reset binary 111 after power-on reset + IF BPNV = '1' AND LOCK='0' AND FREEZE = '0' THEN + BP0 := '1'; + BP1 := '1'; + BP2 := '1'; + BP_bits := BP2 & BP1 & BP0; + change_BP <= '1', '0' AFTER 1 ns; + END IF; + --As shipped from the factory, all devices default ASP to the + --Persistent Protection mode, with all sectors unprotected, + --when power is applied. The device programmer or host system must + --then choose which sector protection method to use. + --For Persistent Protection mode, PPBLOCK defaults to "1" + PPB_LOCK := '1'; + PPB_LOCK_temp <= '1'; + DYB_bits := (OTHERS => '1'); + END IF; + + IF falling_edge(write) AND Instruct = RESET THEN + --The Configuration Register is set for Address mode + Bank_Addr_reg := (others => '0'); + --P_ERR bit is cleared + P_ERR := '0'; + --E_ERR bit is cleared + E_ERR := '0'; + --The WEL bit is cleared. + WEL := '0'; + --The WIP bit is cleared. + WIP := '0'; + --The ES bit is cleared. + ES := '0'; + --The PS bit is cleared. + PS := '0'; + + DummyBytes_act := '0'; + --When BPNV is set to '1'. the BP2-0 bits in Status + --Register are volatile and will be reseted after + --reset command + IF BPNV = '1' AND LOCK='0' AND FREEZE = '0' THEN + BP0 := '1'; + BP1 := '1'; + BP2 := '1'; + BP_bits := BP2 & BP1 & BP0; + change_BP <= '1', '0' AFTER 1 ns; + END IF; + END IF; + + IF change_addr'EVENT THEN + read_addr := Address; + END IF; + + CASE current_state IS + WHEN IDLE => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF falling_edge(write) AND RdPswdProtMode = '1' THEN + IF Instruct = PASSU THEN + IF WIP = '0' THEN + PASSULCK_in <= '1'; + ELSE + REPORT "The PASSU command cannot be accepted"& + " any faster than once every 100us" + SEVERITY WARNING; + END IF; + ELSIF Instruct = CLSR THEN + --The Clear Status Register Command resets bit SR1[5] + --(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + E_ERR := '0'; + P_ERR := '0'; + END IF; + END IF; + IF falling_edge(write) AND RdPswdProtMode = '0' THEN + read_cnt := 0; + byte_cnt := 1; + IF Instruct = WREN THEN + WEL := '1'; + ELSIF Instruct = WRDI THEN + WEL := '0'; + ELSIF Instruct = WRR AND WEL = '1' AND BAR_ACC = '0' THEN + IF (not(SRWD = '1' AND WPNeg_pullup = '0') AND + QUAD ='0') OR QUAD ='1' THEN + -- can not execute if Hardware Protection Mode + -- is entered or if WEL bit is zero + + IF ((TBPROT='1' AND Config_reg1_in(5)='0') OR + (BPNV ='1' AND Config_reg1_in(3)='0')) AND + cfg_write = '1' THEN + P_ERR := '1'; + ELSE + WSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + END IF; + ELSE + WEL := '0'; + END IF; + ELSIF (Instruct = PP OR Instruct = PP4) AND WEL = '1' THEN + sect := Address/(SecSize+1); + pgm_page := Address/PageSize; + IF (Sec_Prot(sect) = '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + SA <= sect; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + P_ERR := '1'; + WEL := '0'; + END IF; + ELSIF (Instruct = QPP OR Instruct = QPP4) AND WEL = '1' THEN + sect := Address/(SecSize+1); + pgm_page := Address/PageSize; + IF (Sec_Prot(sect)= '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + SA <= sect; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + P_ERR := '1'; + WEL := '0'; + END IF; + ELSIF Instruct = OTPP AND WEL = '1' THEN + -- As long as the FREEZE bit remains cleared to a logic '0' + --the OTP address space is programmable. + IF FREEZE = '0' THEN + IF ((((Address >= 16#0010# AND Address <= 16#13#)OR + (Address >= 16#0020# AND Address <= 16#FF#)) + AND LOCK_BYTE1(Address/32) = '1') OR + ((Address >= 16#100# AND Address <= 16#1FF#) + AND LOCK_BYTE2((Address-16#100#)/32) = '1') OR + ((Address >= 16#200# AND Address <= 16#2FF#) + AND LOCK_BYTE3((Address-16#200#)/32) = '1') OR + ((Address >= 16#300# AND Address <= 16#3FF#) + AND LOCK_BYTE4((Address-16#300#)/32) = '1')) AND + (Address + Byte_number <= OTPHiAddr) THEN + PSTART <= '1', '0' AFTER 1 ns; + WIP := '1'; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSIF (Address < 16#0010# OR (Address > 16#0013# AND + Address < 16#0020#) OR Address > 16#3FF# ) THEN + P_ERR := '1'; + WEL := '0'; + IF Address < 16#0020# THEN + ASSERT false + REPORT "Given address is in" & + "reserved address range" + SEVERITY warning; + ELSIF Address > 16#3FF# THEN + ASSERT false + REPORT "Given address is out of" & + "OTP address range" + SEVERITY warning; + END IF; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSIF (Instruct = SE OR Instruct = SE4) AND WEL = '1' THEN + sect := Address/(SecSize+1); + SectorSuspend <= sect; + IF (Sec_Prot(sect) = '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + Addr := Address; + ELSE + E_ERR := '1'; + WEL := '0'; + END IF; + ELSIF (Instruct = P4E OR Instruct = P4E4) AND WEL = '1' THEN + WEL := '0'; + ELSIF Instruct = BE AND WEL = '1' THEN + IF (BP0='0' AND BP1='0' AND BP2='0') THEN + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + ELSE + --The Bulk Erase command will not set E_ERR if a + --protected sector is found during the command + --execution. + WEL := '0'; + END IF; + ELSIF Instruct = PASSP AND WEL = '1' THEN + IF not(PWDMLB='0' AND PSTMLB='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSE + REPORT "Password programming is not allowed" & + " in Password Protection Mode." + SEVERITY warning; + END IF; + ELSIF Instruct = PASSU AND WEL= '1' AND WIP= '0' THEN + PASSULCK_in <= '1'; + ELSIF Instruct = BRWR THEN + Bank_Addr_reg(7) := Bank_Addr_reg_in(7); + Bank_Addr_reg(1) := Bank_Addr_reg_in(1); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + ELSIF Instruct = WRR AND BAR_ACC = '1' THEN + IF (P_ERR = '0' AND E_ERR = '0') THEN + Bank_Addr_reg(1) := Bank_Addr_reg_in(1); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + END IF; + ELSIF Instruct = ASPP AND WEL = '1' THEN + IF not(ASPOTPFLAG) THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSE + WEL := '0'; + P_ERR := '1'; + REPORT "Once the Protection Mode is selected," & + "no further changes to the ASP register" & + "is allowed." + SEVERITY warning; + END IF; + ELSIF Instruct = ABWR AND WEL = '1' THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = PPBP AND WEL = '1' THEN + sect := Address/(SecSize+1); + Addr := Address; + pgm_page := Address/PageSize; + + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = PPBERS AND WEL = '1' THEN + IF PPBOTP = '1' THEN + PPBERASE_in <= '1'; + WIP := '1'; + ELSE + E_ERR := '1'; + END IF; + ELSIF Instruct = PLBWR AND WEL = '1' AND + RdPswdProtEnable = '0' THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = DYBWR AND WEL = '1' THEN + sect := Address/(SecSize+1); + Addr := Address; + pgm_page := Address/PageSize; + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = PNVDLR AND WEL = '1' THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = WVDLR AND WEL = '1' THEN + VDLR_reg := VDLR_reg_in; + WEL := '0'; + ELSIF Instruct = CLSR THEN + --The Clear Status Register Command resets bit SR1[5] + --(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + E_ERR := '0'; + P_ERR := '0'; + END IF; + + IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' THEN + BAR_ACC <= '1'; + ELSE + BAR_ACC <= '0'; + END IF; + ELSIF oe_z THEN + IF Instruct = READ OR Instruct = RD4 OR + Instruct = RES OR Instruct = DLPRD THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSIF Instruct = DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + ELSIF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = READ OR Instruct = RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = DDRFR OR Instruct = DDRFR4 THEN + --Read Memory array + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + IF ((bus_cycle_state = DUMMY_BYTES OR + DummyBytes_act='1') AND VDLR_reg/="00000000") THEN + DummyBytes_act := '0'; + IF (Instruct = DDRFR OR Instruct = DDRFR4) THEN + IF EHP THEN + IF Latency_code = 1 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3 OR + Latency_code = 0) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + dlp_act := FALSE; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + SecAddr := ReturnSectorID(read_addr); + Sec_addr := read_addr - SecAddr*(SecSize+1); + SecAddr := ReturnSectorIDRdPswdMd(TBPROT); + IF RdPswdProtMode = '0' THEN + SecAddr := ReturnSectorID(read_addr); + END IF; + READ_DATA(SecAddr,Sec_addr,mem_data); + IF mem_data /= -1 THEN + data_out := to_slv((mem_data),8); + SOut_zd <= data_out(7-read_cnt); + ELSE + SOut_zd <= 'U'; + END IF; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct = DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + --Read Memory array + IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct = DDRDIOR OR Instruct = DDRDIOR4) THEN + IF EHP THEN + IF Latency_code = 0 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + SecAddr := ReturnSectorID(read_addr); + Sec_addr := read_addr - SecAddr*(SecSize+1); + SecAddr := ReturnSectorIDRdPswdMd(TBPROT); + IF RdPswdProtMode = '0' THEN + SecAddr := ReturnSectorID(read_addr); + END IF; + READ_DATA(SecAddr,Sec_addr,mem_data); + data_out := to_slv((mem_data),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF (Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 OR + Instruct = DDRQIOR OR Instruct= DDRQIOR4) + AND QUAD = '1' THEN + --Read Memory array + IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF ((Instruct = DDRQIOR OR Instruct = DDRQIOR4) AND + QUAD = '1') THEN + IF EHP THEN + IF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + SecAddr := ReturnSectorID(read_addr); + Sec_addr := read_addr - SecAddr*(SecSize+1); + SecAddr := ReturnSectorIDRdPswdMd(TBPROT); + IF RdPswdProtMode = '0' THEN + SecAddr := ReturnSectorID(read_addr); + END IF; + READ_DATA(SecAddr,Sec_addr,mem_data); + data_out := to_slv((mem_data),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct = OTPR THEN + IF (read_addr>=OTPLoAddr) AND + (read_addr<=OTPHiAddr) AND RdPswdProtMode = '0' THEN + --Read OTP Memory array + fast_rd <= true; + rd <= false; + data_out := to_slv(OTPMem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + ELSIF (read_addr > OTPHiAddr) + OR RdPswdProtMode = '1' THEN + --OTP Read operation will not wrap to the + --starting address after the OTP address is at + --its maximum or Read Password Protection Mode + --is selected; instead, the data beyond the + --maximum OTP address will be undefined. + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF Instruct = REMS THEN + --Read Manufacturer and Device ID + IF read_addr MOD 2 = 0 THEN + data_out := to_slv(Manuf_ID,8); + SOut_zd <= data_out(7 - read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + ELSE + data_out := to_slv(DeviceID,8); + SOut_zd <= data_out(7 - read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := 0; + END IF; + END IF; + ELSIF Instruct = RDID THEN + ident_out := CFI_array_tmp; + IF read_cnt < 648 THEN + SOut_zd <= ident_out(647-read_cnt); + read_cnt := read_cnt + 1; + ELSE + --Continued shifting of output beyond the end of + --the defined ID-CFI address space will provide + --undefined data. + SOut_zd <= 'U'; + END IF; + ELSIF Instruct = RES THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + data_out := to_slv(ESignature,8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = DLPRD THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + SOut_zd <= VDLR_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = ABRD THEN + --Read AutoBoot register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= AutoBoot_reg(31-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 32 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = BRRD THEN + --Read Bank Address Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Bank_Addr_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = ASPRD THEN + --Read ASP Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= ASP_reg(15-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 16 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = PASSRD THEN + --Read Password Register + IF not (PWDMLB='0' AND PSTMLB='1') THEN + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Password_reg((8*byte_cnt-1)-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + byte_cnt := byte_cnt + 1; + IF byte_cnt = 9 THEN + byte_cnt := 1; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 64 THEN + read_cnt := 0; + END IF; + IF read_cnt = 0 THEN + ASSERT false + REPORT "Verification of password is not " & + " allowed in Password Protection Mode." + SEVERITY warning; + END IF; + END IF; + ELSIF Instruct = PLBRD THEN + --Read PPB Lock Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= PPBL(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = DYBRD THEN + --Read DYB Access Register + sect := Address/(SecSize+1); + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + DYBAR(7 downto 0) := "UUUUUUUU"; + IF RdPswdProtMode = '0' THEN + IF DYB_bits(sect) = '1' THEN + DYBAR(7 downto 0) := "11111111"; + ELSE + DYBAR(7 downto 0) := "00000000"; + END IF; + END IF; + SOut_zd <= DYBAR(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = PPBRD THEN + --Read PPB Access Register + sect := Address/(SecSize+1); + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + PPBAR(7 downto 0) := "UUUUUUUU"; + IF RdPswdProtMode = '0' THEN + IF PPB_bits(sect) = '1' THEN + PPBAR(7 downto 0) := "11111111"; + ELSE + PPBAR(7 downto 0) := "00000000"; + END IF; + END IF; + SOut_zd <= PPBAR(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + + WHEN AUTOBOOT => + IF start_autoboot = '1' THEN + IF (oe) THEN + any_read <= true; + IF QUAD = '1' THEN + IF ABSD > 0 THEN --If ABSD > 0, + fast_rd <= false; --max SCK frequency is 104MHz + rd <= false; + dual <= true; + ddr <= false; + ELSE -- If ABSD = 0, max SCK frequency is 50 MHz + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + END IF; + SecAddr := ReturnSectorID(read_addr); + Sec_addr := read_addr - SecAddr*(SecSize+1); + READ_DATA(SecAddr,Sec_addr,mem_data); + data_out := to_slv((mem_data),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + ELSE + IF ABSD > 0 THEN --If ABSD > 0, + fast_rd <= true; --max SCK frequency is 133MHz + rd <= false; + dual <= false; + ddr <= false; + ELSE -- If ABSD = 0, max SCK frequency is 50 MHz + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + END IF; + SecAddr := ReturnSectorID(read_addr); + Sec_addr := read_addr - SecAddr*(SecSize+1); + READ_DATA(SecAddr,Sec_addr,mem_data); + data_out := to_slv((mem_data),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + END IF; + ELSIF oe_z THEN + IF QUAD = '1' THEN + IF ABSD > 0 THEN --If ABSD > 0, + fast_rd <= false; --max SCK frequency is 104MHz + rd <= false; + dual <= true; + ddr <= false; + ELSE -- If ABSD = 0, max SCK frequency is 50 MHz + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + END IF; + ELSE + IF ABSD > 0 THEN --If ABSD > 0, + fast_rd <= true; --max SCK frequency is 133MHz + rd <= false; + dual <= false; + ddr <= false; + ELSE -- If ABSD = 0, max SCK frequency is 50 MHz + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + END IF; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + END IF; + + WHEN WRITE_SR => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF WDONE = '1' THEN + WIP := '0'; + WEL := '0'; + SRWD := Status_reg1_in(7);--MSB first + + IF LOCK='0' THEN + IF FREEZE='0' THEN + --The Freeze Bit, when set to 1, locks the current + --state of the BP2-0 bits in Status Register and + --the TBPROT bit in the Config Register + --As long as the FREEZE bit remains cleared to logic + --'0', the other bits of the Configuration register + --including FREEZE are writeable. + BP2 := Status_reg1_in(4); + BP1 := Status_reg1_in(3); + BP0 := Status_reg1_in(2); + + BP_bits := BP2 & BP1 & BP0; + + IF TBPROT = '0' AND INITIAL_CONFIG = '0' THEN + TBPROT := Config_reg1_in(5); + END IF; + + change_BP <= '1', '0' AFTER 1 ns; + + LC1 := Config_reg1_in(7); + LC0 := Config_reg1_in(6); + QUAD := Config_reg1_in(1); + + IF FREEZE = '0' THEN + FREEZE := Config_reg1_in(0); + END IF; + + IF WRLOCKENABLE AND LOCK = '0' THEN + LOCK := Config_reg1_in(4); + WRLOCKENABLE <= false; + END IF; + + IF BPNV = '0' THEN + BPNV := Config_reg1_in(3); + END IF; + END IF; + END IF; + END IF; + + WHEN PAGE_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF falling_edge(PDONE) THEN + IF (Instruct = QPP OR Instruct = QPP4) THEN + QPP_page(pgm_page) := '1'; + END IF; + + ADDRHILO_PG(AddrLo, AddrHi,Sec_addr,Page_addr,Addr); + cnt := 0; + + FOR i IN 0 TO wr_cnt LOOP + new_int := WData(i); + SecAddr := ReturnSectorID(Addr); + READ_DATA(SecAddr, + Sec_addr+i-cnt, + mem_data); + old_int := mem_data; + + IF new_int > -1 THEN + new_bit := to_slv(new_int,8); + IF old_int > -1 THEN + old_bit := to_slv(old_int,8); + FOR j IN 0 TO 7 LOOP + IF old_bit(j) = '0' THEN + new_bit(j) := '0'; + END IF; + END LOOP; + new_int := to_nat(new_bit); + END IF; + WData(i) := new_int; + ELSE + WData(i) := -1; + END IF; + + write_mem(linked_list(SecAddr), + Sec_addr + i - cnt, + -1); + IF (Sec_addr + i) = AddrHi THEN + Sec_addr := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + cnt :=0; + END IF; + + IF PDONE = '1' THEN + WIP := '0'; + WEL := '0'; + ADDRHILO_PG(AddrLo, AddrHi,Sec_addr,Page_addr,Addr); + FOR i IN 0 TO wr_cnt LOOP + SecAddr := ReturnSectorID(Addr); + WRITE_DATA(SecAddr, + Sec_addr + i - cnt, + WData(i)); + IF (Sec_addr + i) = AddrHi THEN + Sec_addr := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + + ELSIF Instruct = PGSP AND PRGSUSP_in = '0' THEN + IF RES_TO_SUSP_MIN_TIME = '0' THEN + PGSUSP <= '1', '0' AFTER 1 ns; + PRGSUSP_in <= '1'; + ASSERT RES_TO_SUSP_TYP_TIME = '0' + REPORT "Typical periods are needed for " & + "Program to progress to completion" + SEVERITY warning; + ELSE + ASSERT FALSE + REPORT "Minimum for tPRS is not satisfied! " & + "PGSP command is ignored" + SEVERITY warning; + END IF; + END IF; + + WHEN PG_SUSP => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF PRGSUSP_out = '1' AND PRGSUSP_in = '1' THEN + PRGSUSP_in <= '0'; + --The RDY/BSY bit in the Status Register will indicate that + --the device is ready for another operation. + WIP := '0'; + --The Program Suspend (PS) bit in the Status Register will + --be set to the logical “1” state to indicate that the + --program operation has been suspended. + PS := '1'; + END IF; + + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = BRRD THEN + --Read Bank Address Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Bank_Addr_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + --Read Array Operations + ELSIF Instruct = READ OR Instruct = RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = DDRFR OR Instruct = DDRFR4 THEN + --Read Memory array + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + IF pgm_page /= read_addr/PageSize THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRFR OR Instruct=DDRFR4) THEN + IF EHP THEN + IF Latency_code = 1 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3 OR + Latency_code = 0) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:= VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + read_cnt:=read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + SecAddr := ReturnSectorID(read_addr); + Sec_addr := read_addr - SecAddr*(SecSize+1); + READ_DATA(SecAddr,Sec_addr,mem_data); + data_out := to_slv((mem_data),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + --Read Memory array + IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF pgm_page /= read_addr/PageSize THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRDIOR OR Instruct=DDRDIOR4) THEN + IF EHP THEN + IF Latency_code = 0 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency"& + " is set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:=VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + SIOut_zd<=data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + SecAddr := ReturnSectorID(read_addr); + Sec_addr := read_addr - SecAddr*(SecSize+1); + READ_DATA(SecAddr,Sec_addr,mem_data); + data_out := to_slv((mem_data),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF (Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 OR + Instruct = DDRQIOR OR Instruct= DDRQIOR4) + AND QUAD = '1' THEN + --Read Memory array + IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF pgm_page /= read_addr/PageSize THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF EHP THEN + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + ELSE + SecAddr := ReturnSectorID(read_addr); + Sec_addr := read_addr - SecAddr*(SecSize+1); + READ_DATA(SecAddr,Sec_addr,mem_data); + data_out := to_slv((mem_data),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + HOLDNegOut_zd <= 'U'; + WPNegOut_zd <= 'U'; + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + END IF; + ELSIF oe_z THEN + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + ELSIF falling_edge(write) THEN + IF Instruct = BRWR THEN + Bank_Addr_reg(7) := Bank_Addr_reg_in(7); + Bank_Addr_reg(1) := Bank_Addr_reg_in(1); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + ELSIF Instruct = WRR AND BAR_ACC = '1' THEN + -- Write to the lower address bits of the BAR + IF (P_ERR = '0' AND E_ERR = '0')THEN + Bank_Addr_reg(1) := Bank_Addr_reg_in(1); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + END IF; + ELSIF Instruct = PGRS THEN + PGRES <= '1', '0' AFTER 5 ns; + PS := '0'; + WIP := '1'; + RES_TO_SUSP_MIN_TIME <= '1', '0' AFTER 60 ns; + RES_TO_SUSP_TYP_TIME <= '1', '0' AFTER 100 us; + END IF; + + IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' AND + RdPswdProtMode = '0' THEN + BAR_ACC <= '1'; + ELSE + BAR_ACC <= '0'; + END IF; + END IF; + + WHEN ERS_SUSP_PG_SUSP => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF PRGSUSP_out = '1' AND PRGSUSP_in = '1' THEN + PRGSUSP_in <= '0'; + --The RDY/BSY bit in the Status Register will indicate that + --the device is ready for another operation. + WIP := '0'; + --The Program Suspend (PS) bit in the Status Register will + --be set to the logical “1” state to indicate that the + --program operation has been suspended. + PS := '1'; + END IF; + + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = BRRD THEN + --Read Bank Address Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Bank_Addr_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + --Read Array Operations + ELSIF Instruct = READ OR Instruct = RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = DDRFR OR Instruct = DDRFR4 THEN + --Read Memory array + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + IF (SectorSuspend /= read_addr/(SecSize+1) AND + pgm_page /= read_addr/PageSize) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRFR OR Instruct=DDRFR4) THEN + IF EHP THEN + IF Latency_code = 1 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3 OR + Latency_code = 0) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:= VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + read_cnt:=read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + SecAddr := ReturnSectorID(read_addr); + Sec_addr := read_addr - SecAddr*(SecSize+1); + READ_DATA(SecAddr,Sec_addr,mem_data); + data_out := to_slv((mem_data),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + --Read Memory array + IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF (SectorSuspend /= read_addr/(SecSize+1) AND + pgm_page /= read_addr/PageSize) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRDIOR OR Instruct=DDRDIOR4) THEN + IF EHP THEN + IF Latency_code = 0 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency"& + " is set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:=VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + SIOut_zd<=data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + SecAddr := ReturnSectorID(read_addr); + Sec_addr := read_addr - SecAddr*(SecSize+1); + READ_DATA(SecAddr,Sec_addr,mem_data); + data_out := to_slv((mem_data),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF (Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 OR + Instruct = DDRQIOR OR Instruct= DDRQIOR4) + AND QUAD = '1' THEN + --Read Memory array + IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF (SectorSuspend /= read_addr/(SecSize+1) AND + pgm_page /= read_addr/PageSize) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF EHP THEN + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + ELSE + SecAddr := ReturnSectorID(read_addr); + Sec_addr := read_addr - SecAddr*(SecSize+1); + READ_DATA(SecAddr,Sec_addr,mem_data); + data_out := to_slv((mem_data),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + HOLDNegOut_zd <= 'U'; + WPNegOut_zd <= 'U'; + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + END IF; + ELSIF oe_z THEN + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + ELSIF falling_edge(write) THEN + IF Instruct = BRWR THEN + Bank_Addr_reg(7) := Bank_Addr_reg_in(7); + Bank_Addr_reg(1) := Bank_Addr_reg_in(1); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + ELSIF Instruct = WRR AND BAR_ACC = '1' THEN + -- Write to the lower address bits of the BAR + IF (P_ERR = '0' AND E_ERR = '0')THEN + Bank_Addr_reg(1) := Bank_Addr_reg_in(1); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + END IF; + ELSIF Instruct = PGRS THEN + PGRES <= '1', '0' AFTER 5 ns; + PS := '0'; + WIP := '1'; + RES_TO_SUSP_MIN_TIME <= '1', '0' AFTER 60 ns; + RES_TO_SUSP_TYP_TIME <= '1', '0' AFTER 100 us; + END IF; + + IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' AND + RdPswdProtMode = '0' THEN + BAR_ACC <= '1'; + ELSE + BAR_ACC <= '0'; + END IF; + END IF; + + WHEN OTP_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF Address + wr_cnt <= OTPHiAddr THEN + FOR i IN 0 TO wr_cnt LOOP + new_int := WData(i); + old_int := OTPMem(Addr + i); + IF new_int > -1 THEN + new_bit := to_slv(new_int,8); + IF old_int > -1 THEN + old_bit := to_slv(old_int,8); + FOR j IN 0 TO 7 LOOP + IF old_bit(j) = '0' THEN + new_bit(j) := '0'; + END IF; + END LOOP; + new_int := to_nat(new_bit); + END IF; + WData(i) := new_int; + ELSE + WData(i) := -1; + END IF; + + OTPMem(Addr + i) := -1; + END LOOP; + ELSE + ASSERT false + REPORT "Programming will reach over address limit"& + " of OTP array" + SEVERITY warning; + END IF; + + IF PDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO wr_cnt LOOP + OTPMem(Addr_tmp + i) := WData(i); + END LOOP; + LOCK_BYTE1 := to_slv(OTPMem(16#10#),8); + LOCK_BYTE2 := to_slv(OTPMem(16#11#),8); + LOCK_BYTE3 := to_slv(OTPMem(16#12#),8); + LOCK_BYTE4 := to_slv(OTPMem(16#13#),8); + END IF; + + WHEN SECTOR_ERS => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + SecAddr := ReturnSectorID(Addr); + Corrupt_Sec(SecAddr) := '1'; + erase_mem( + 0, + SecSize, + linked_list(SecAddr) + ); + + IF EDONE = '1' THEN + WIP := '0'; + WEL := '0'; + Corrupt_Sec(SecAddr) := '0'; + erase_mem( + 0, + SecSize, + linked_list(SecAddr) + ); + ELSIF Instruct = ERSP AND ERSSUSP_in = '0' THEN + ESUSP <= '1', '0' AFTER 10 ns; + ERSSUSP_in <= '1'; + ASSERT RES_TO_SUSP_TYP_TIME = '0' + REPORT "Typical periods are needed for " & + "Program to progress to completion" + SEVERITY warning; + END IF; + + WHEN BULK_ERS => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF falling_edge(EDONE) THEN + FOR i IN 0 TO SecNum LOOP + IF PPB_bits(i) = '1' AND DYB_bits(i) = '1' THEN + Corrupt_Sec(i) := '1'; + erase_mem( + 0, + SecSize, + linked_list(i) + ); + END IF; + END LOOP; + END IF; + + IF EDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO SecNum LOOP + IF PPB_bits(i) = '1' AND DYB_bits(i) = '1' THEN + Corrupt_Sec(i) := '0'; + erase_mem( + 0, + SecSize, + linked_list(i) + ); + END IF; + END LOOP; + END IF; + + WHEN ERS_SUSP => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF ERSSUSP_out = '1' THEN + ERSSUSP_in <= '0'; + --The Erase Suspend (ES) bit in the Status Register will + --be set to the logical “1” state to indicate that the + --erase operation has been suspended. + ES := '1'; + --The WIP bit in the Status Register will indicate that + --the device is ready for another operation. + WIP := '0'; + END IF; + + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = DYBRD THEN + --Read DYB Access Register + sect := Address/(SecSize+1); + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF DYB_bits(sect) = '1' THEN + DYBAR(7 downto 0) := "11111111"; + ELSE + DYBAR(7 downto 0) := "00000000"; + END IF; + SOut_zd <= DYBAR(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = BRRD THEN + --Read Bank Address Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Bank_Addr_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = PPBRD THEN + --Read PPB Access Register + sect := Address/(SecSize+1); + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + PPBAR(7 downto 0) := "UUUUUUUU"; + IF RdPswdProtMode = '0' THEN + IF PPB_bits(sect) = '1' THEN + PPBAR(7 downto 0) := "11111111"; + ELSE + PPBAR(7 downto 0) := "00000000"; + END IF; + END IF; + SOut_zd <= PPBAR(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + --Read Array Operations + ELSIF Instruct = READ OR Instruct = RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = DDRFR OR Instruct = DDRFR4 THEN + --Read Memory array + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + IF SectorSuspend /= read_addr/(SecSize+1) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRFR OR Instruct=DDRFR4) THEN + IF EHP THEN + IF Latency_code = 1 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3 OR + Latency_code = 0) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:= VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + read_cnt:=read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + SecAddr := ReturnSectorID(read_addr); + Sec_addr := read_addr - SecAddr*(SecSize+1); + READ_DATA(SecAddr,Sec_addr,mem_data); + data_out := to_slv((mem_data),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + --Read Memory array + IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF SectorSuspend /= read_addr/(SecSize+1) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRDIOR OR Instruct=DDRDIOR4) THEN + IF EHP THEN + IF Latency_code = 0 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency"& + " is set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:=VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + SIOut_zd<=data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + SecAddr := ReturnSectorID(read_addr); + Sec_addr := read_addr - SecAddr*(SecSize+1); + READ_DATA(SecAddr,Sec_addr,mem_data); + data_out := to_slv((mem_data),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF (Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 OR + Instruct = DDRQIOR OR Instruct= DDRQIOR4) + AND QUAD = '1' THEN + --Read Memory array + IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF SectorSuspend /= read_addr/(SecSize+1) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF EHP THEN + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + ELSE + SecAddr := ReturnSectorID(read_addr); + Sec_addr := read_addr - SecAddr*(SecSize+1); + READ_DATA(SecAddr,Sec_addr,mem_data); + data_out := to_slv((mem_data),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + HOLDNegOut_zd <= 'U'; + WPNegOut_zd <= 'U'; + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + + END IF; + END IF; + ELSIF oe_z THEN + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF falling_edge(write) THEN + IF (Instruct = PP OR Instruct = PP4) AND WEL = '1' THEN + sect := Address/(SecSize+1); + pgm_page := Address/PageSize; + IF SectorSuspend /= sect THEN + IF (Sec_Prot(sect) = '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + WIP := '1' ; + SA <= sect; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSIF (Instruct = QPP OR Instruct = QPP4) AND WEL = '1' THEN + sect := Address/(SecSize+1); + pgm_page := Address/PageSize; + IF SectorSuspend /= sect THEN + IF (Sec_Prot(sect)='0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + WIP := '1' ; + SA <= sect; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSIF Instruct = WREN THEN + WEL := '1'; + ELSIF Instruct = CLSR THEN + --The Clear Status Register Command resets bit SR1[5] + --(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + E_ERR := '0'; + P_ERR := '0'; + ELSIF Instruct = BRWR THEN + Bank_Addr_reg(7) := Bank_Addr_reg_in(7); + Bank_Addr_reg(1) := Bank_Addr_reg_in(1); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + ELSIF Instruct = WRR AND BAR_ACC = '1' THEN + -- Write to the lower address bits of the BAR + IF (P_ERR = '0' AND E_ERR = '0')THEN + Bank_Addr_reg(1) := Bank_Addr_reg_in(1); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + END IF; + ELSIF Instruct = DYBWR AND WEL = '1' THEN + sect := Address/(SecSize+1); + pgm_page := Address/PageSize; + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = ERRS THEN + ERES <= '1', '0' AFTER 5 ns; + ES := '0'; + WIP := '1'; + Addr := SectorSuspend*(SecSize+1); + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + RES_TO_SUSP_TYP_TIME <= '1', '0' AFTER 100 us; + END IF; + + IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' AND + RdPswdProtMode = '0' THEN + BAR_ACC <= '1'; + ELSE + BAR_ACC <= '0'; + END IF; + END IF; + + WHEN ERS_SUSP_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF (Instruct = QPP OR Instruct = QPP4) THEN + QPP_page(pgm_page) := '1'; + END IF; + + ADDRHILO_PG(AddrLo, AddrHi,Sec_addr,Page_addr,Addr); + cnt := 0; + + FOR i IN 0 TO wr_cnt LOOP + new_int := WData(i); + SecAddr := ReturnSectorID(Addr + i - cnt); + Sec_addr := Addr + i - cnt - SecAddr*(SecSize+1); + READ_DATA(SecAddr,Sec_addr,mem_data); + old_int := mem_data; + IF new_int > -1 THEN + new_bit := to_slv(new_int,8); + IF old_int > -1 THEN + old_bit := to_slv(old_int,8); + FOR j IN 0 TO 7 LOOP + IF old_bit(j) = '0' THEN + new_bit(j) := '0'; + END IF; + END LOOP; + new_int := to_nat(new_bit); + END IF; + WData(i) := new_int; + ELSE + WData(i) := -1; + END IF; + + IF (Addr + i) = AddrHi THEN + Addr := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + cnt :=0; + + IF PDONE = '1' THEN + ADDRHILO_PG(AddrLo, AddrHi,Sec_addr,Page_addr,Addr); + SecAddr := ReturnSectorID(Addr); + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO wr_cnt LOOP + WRITE_DATA(SecAddr, + Sec_addr + i - cnt, + WData(i)); + IF (Sec_addr + i) = AddrHi THEN + Sec_addr := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + ELSIF Instruct = PGSP AND PRGSUSP_in = '0' THEN + IF RES_TO_SUSP_MIN_TIME = '0' THEN + PGSUSP <= '1', '0' AFTER 1 ns; + PRGSUSP_in <= '1'; + ASSERT RES_TO_SUSP_TYP_TIME = '0' + REPORT "Typical periods are needed for " & + "Program to progress to completion" + SEVERITY warning; + ELSE + ASSERT FALSE + REPORT "Minimum for tPRS is not satisfied! " & + "PGSP command is ignored" + SEVERITY warning; + END IF; + END IF; + + WHEN PASS_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + new_pass := Password_reg_in; + old_pass := Password_reg; + FOR j IN 0 TO 63 LOOP + IF old_pass(j) = '0' THEN + new_pass(j) := '0'; + END IF; + END LOOP; + + IF PDONE = '1' THEN + Password_reg := new_pass; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN PASS_UNLOCK => + WIP := '1'; + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PASS_TEMP = Password_reg THEN + PASS_UNLOCKED <= TRUE; + ELSE + PASS_UNLOCKED <= FALSE; + END IF; + + IF PASSULCK_out = '1' THEN + IF PASS_UNLOCKED AND PWDMLB = '0' THEN + PPB_LOCK := '1'; + PPB_LOCK_temp <= '1'; + WIP := '0'; + ELSE + P_ERR := '1'; + REPORT "Incorrect Password!" + SEVERITY warning; + PASSACC_in <= '1'; + END IF; + WEL := '0'; + PASSULCK_in <= '0'; + END IF; + + WHEN PPB_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + IF PPB_LOCK /= '0' THEN + PPB_bits(sect):= '0'; + WIP := '0'; + WEL := '0'; + ELSE + P_ERR := '0'; + WIP := '0'; + WEL := '0'; + END IF; + END IF; + + WHEN PPB_ERS => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PPBERASE_out = '1' THEN + IF PPB_LOCK /= '0' AND PPBOTP = '1' THEN + PPB_bits:= (OTHERS => '1'); + ELSE + E_ERR := '1'; + END IF; + WIP := '0'; + WEL := '0'; + PPBERASE_in <= '0'; + END IF; + + WHEN AUTOBOOT_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + AutoBoot_reg := AutoBoot_reg_in; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN PLB_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + PPB_LOCK := '0'; + PPB_LOCK_temp <= '0'; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN DYB_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + DYBAR := DYBAR_in; + IF DYBAR = "11111111" THEN + DYB_bits(sect):= '1'; + ELSIF DYBAR = "00000000" THEN + DYB_bits(sect):= '0'; + ELSE + P_ERR := '1'; + END IF; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN ASP_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + + IF (RPME = '0' AND ASP_reg_in(5) = '1') THEN + P_ERR := '1'; + REPORT "RPME bit is allready programmed" + SEVERITY warning; + ELSE + RPME := ASP_reg_in(5); + END IF; + + IF (PPBOTP = '0' AND ASP_reg_in(3) ='1') THEN + P_ERR := '1'; + REPORT "PPBOTP bit is allready programmed" + SEVERITY warning; + ELSE + PPBOTP := ASP_reg_in(3); + END IF; + + IF (PWDMLB = '1' AND PSTMLB = '1') THEN + IF (ASP_reg_in(2) = '0' AND ASP_reg_in(1) = '0') THEN + REPORT "ASPR[2:1] = 00 Illegal condition" + SEVERITY warning; + P_ERR := '1'; + ELSE + IF (ASP_reg_in(2) /= '1' OR + ASP_reg_in(1) /= '1') THEN + ASPOTPFLAG <= TRUE; + END IF; + PWDMLB := ASP_reg_in(2); + PSTMLB := ASP_reg_in(1); + END IF; + END IF; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN NVDLR_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + IF NVDLR_reg = "00000000" THEN + NVDLR_reg :=NVDLR_reg_in; + VDLR_reg := NVDLR_reg_in; + WIP := '0'; + WEL := '0'; + ELSE + WIP := '0'; + WEL := '0'; + P_ERR := '1'; + REPORT "NVDLR is allready programmed" + SEVERITY warning; + END IF; + END IF; + + WHEN RESET_STATE => + --the default condition hardware reset + --The Bank Address Register is loaded to all zeroes + Bank_Addr_reg := (others => '0'); + IF BPNV = '1' AND LOCK='0' AND FREEZE = '0' THEN + BP0 := '1'; + BP1 := '1'; + BP2 := '1'; + BP_bits := BP2 & BP1 & BP0; + change_BP <= '1', '0' AFTER 1 ns; + END IF; + --Resets the Status register 1 + P_ERR := '0'; + E_ERR := '0'; + WEL := '0'; + WIP := '0'; + --Resets the Status register 2 + ES := '0'; + PS := '0'; + --Resets the Configuration register 1 + FREEZE := '0'; + --On reset cycles the data pattern reverts back + --to what is in the NVDLR + VDLR_reg := NVDLR_reg; + dlp_act := FALSE; + --Loads the Program Buffer with all ones + WData := (OTHERS => MaxData); + + IF PWDMLB = '0' THEN + PPB_LOCK := '0'; + PPB_LOCK_temp <= '0'; + ELSE + PPB_LOCK := '1'; + PPB_LOCK_temp <= '1'; + END IF; + + END CASE; + + --Output Disable Control + IF (CSNeg_ipd = '1') THEN + SIOut_zd <= 'Z'; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + END IF; + + END PROCESS Functional; + + --------------------------------------------------------------------------- + -- CFI Process + --------------------------------------------------------------------------- + CFIPreload: PROCESS + + BEGIN + ------------------------------------------------------------------------ + --CFI array data + ------------------------------------------------------------------------ + -- Manufacturer and Device ID + CFI_array(16#00#) := 16#01#; + CFI_array(16#01#) := 16#02#; + CFI_array(16#02#) := 16#20#; + CFI_array(16#03#) := 16#00#; + CFI_array(16#04#) := 16#00#;--Uniform 256KB sectors + CFI_array(16#05#) := 16#80#; + CFI_array(16#06#) := 16#00#; + CFI_array(16#07#) := 16#00#; + CFI_array(16#08#) := 16#00#; + CFI_array(16#09#) := 16#00#; + CFI_array(16#0A#) := 16#00#; + CFI_array(16#0B#) := 16#00#; + CFI_array(16#0C#) := 16#00#; + CFI_array(16#0D#) := 16#00#; + CFI_array(16#0E#) := 16#00#; + CFI_array(16#0F#) := 16#00#; + --CFI Query Identification String + CFI_array(16#10#) := 16#51#; + CFI_array(16#11#) := 16#52#; + CFI_array(16#12#) := 16#59#; + CFI_array(16#13#) := 16#02#; + CFI_array(16#14#) := 16#00#; + CFI_array(16#15#) := 16#40#; + CFI_array(16#16#) := 16#00#; + CFI_array(16#17#) := 16#53#; + CFI_array(16#18#) := 16#46#; + CFI_array(16#19#) := 16#51#; + CFI_array(16#1A#) := 16#00#; + --CFI system interface string + CFI_array(16#1B#) := 16#27#; + CFI_array(16#1C#) := 16#36#; + CFI_array(16#1D#) := 16#00#; + CFI_array(16#1E#) := 16#00#; + CFI_array(16#1F#) := 16#06#; + CFI_array(16#20#) := 16#09#;-- 512B page + CFI_array(16#21#) := 16#09#;-- 256KB + CFI_array(16#22#) := 16#11#; + CFI_array(16#23#) := 16#02#; + CFI_array(16#24#) := 16#02#; + CFI_array(16#25#) := 16#03#; + CFI_array(16#26#) := 16#03#; + -- Device Geometry Definition + CFI_array(16#27#) := 16#1A#; + CFI_array(16#28#) := 16#02#; + CFI_array(16#29#) := 16#01#; + CFI_array(16#2A#) := 16#09#; + CFI_array(16#2B#) := 16#00#; + CFI_array(16#2C#) := 16#01#; + CFI_array(16#2D#) := 16#FF#; + CFI_array(16#2E#) := 16#00#; + CFI_array(16#2F#) := 16#00#; + CFI_array(16#30#) := 16#04#; + CFI_array(16#31#) := 16#FF#; + CFI_array(16#32#) := 16#FF#; + CFI_array(16#33#) := 16#FF#; + CFI_array(16#34#) := 16#FF#; + CFI_array(16#35#) := 16#FF#; + CFI_array(16#36#) := 16#FF#; + CFI_array(16#37#) := 16#FF#; + CFI_array(16#38#) := 16#FF#; + CFI_array(16#39#) := 16#FF#; + CFI_array(16#3A#) := 16#FF#; + CFI_array(16#3B#) := 16#FF#; + CFI_array(16#3C#) := 16#FF#; + CFI_array(16#3D#) := 16#FF#; + CFI_array(16#3E#) := 16#FF#; + CFI_array(16#3F#) := 16#FF#; + -- CFI Primary Vendor-Specific Extended Query + CFI_array(16#40#) := 16#50#; + CFI_array(16#41#) := 16#52#; + CFI_array(16#42#) := 16#49#; + CFI_array(16#43#) := 16#31#; + CFI_array(16#44#) := 16#33#; + CFI_array(16#45#) := 16#21#; + CFI_array(16#46#) := 16#02#; + CFI_array(16#47#) := 16#01#; + CFI_array(16#48#) := 16#00#; + CFI_array(16#49#) := 16#08#; + + CFI_array(16#4A#) := 16#00#; + CFI_array(16#4B#) := 16#01#; + CFI_array(16#4C#) := 16#04#; + CFI_array(16#4D#) := 16#00#; + CFI_array(16#4E#) := 16#00#; + CFI_array(16#4F#) := 16#07#; + CFI_array(16#50#) := 16#01#; + + CFI_array_tmp :=to_slv(CFI_array(16#00#), 8) & + to_slv(CFI_array(16#01#), 8) & + to_slv(CFI_array(16#02#), 8) & + to_slv(CFI_array(16#03#), 8) & + to_slv(CFI_array(16#04#), 8) & + to_slv(CFI_array(16#05#), 8) & + to_slv(CFI_array(16#06#), 8) & + to_slv(CFI_array(16#07#), 8) & + to_slv(CFI_array(16#08#), 8) & + to_slv(CFI_array(16#09#), 8) & + to_slv(CFI_array(16#0A#), 8) & + to_slv(CFI_array(16#0B#), 8) & + to_slv(CFI_array(16#0C#), 8) & + to_slv(CFI_array(16#0D#), 8) & + to_slv(CFI_array(16#0E#), 8) & + to_slv(CFI_array(16#0F#), 8) & + to_slv(CFI_array(16#10#), 8) & + to_slv(CFI_array(16#11#), 8) & + to_slv(CFI_array(16#12#), 8) & + to_slv(CFI_array(16#13#), 8) & + to_slv(CFI_array(16#14#), 8) & + to_slv(CFI_array(16#15#), 8) & + to_slv(CFI_array(16#16#), 8) & + to_slv(CFI_array(16#17#), 8) & + to_slv(CFI_array(16#18#), 8) & + to_slv(CFI_array(16#19#), 8) & + to_slv(CFI_array(16#1A#), 8) & + to_slv(CFI_array(16#1B#), 8) & + to_slv(CFI_array(16#1C#), 8) & + to_slv(CFI_array(16#1D#), 8) & + to_slv(CFI_array(16#1E#), 8) & + to_slv(CFI_array(16#1F#), 8) & + to_slv(CFI_array(16#20#), 8) & + to_slv(CFI_array(16#21#), 8) & + to_slv(CFI_array(16#22#), 8) & + to_slv(CFI_array(16#23#), 8) & + to_slv(CFI_array(16#24#), 8) & + to_slv(CFI_array(16#25#), 8) & + to_slv(CFI_array(16#26#), 8) & + to_slv(CFI_array(16#27#), 8) & + to_slv(CFI_array(16#28#), 8) & + to_slv(CFI_array(16#29#), 8) & + to_slv(CFI_array(16#2A#), 8) & + to_slv(CFI_array(16#2B#), 8) & + to_slv(CFI_array(16#2C#), 8) & + to_slv(CFI_array(16#2D#), 8) & + to_slv(CFI_array(16#2E#), 8) & + to_slv(CFI_array(16#2F#), 8) & + to_slv(CFI_array(16#30#), 8) & + to_slv(CFI_array(16#31#), 8) & + to_slv(CFI_array(16#32#), 8) & + to_slv(CFI_array(16#33#), 8) & + to_slv(CFI_array(16#34#), 8) & + to_slv(CFI_array(16#35#), 8) & + to_slv(CFI_array(16#36#), 8) & + to_slv(CFI_array(16#37#), 8) & + to_slv(CFI_array(16#38#), 8) & + to_slv(CFI_array(16#39#), 8) & + to_slv(CFI_array(16#3A#), 8) & + to_slv(CFI_array(16#3B#), 8) & + to_slv(CFI_array(16#3C#), 8) & + to_slv(CFI_array(16#3D#), 8) & + to_slv(CFI_array(16#3E#), 8) & + to_slv(CFI_array(16#3F#), 8) & + to_slv(CFI_array(16#40#), 8) & + to_slv(CFI_array(16#41#), 8) & + to_slv(CFI_array(16#42#), 8) & + to_slv(CFI_array(16#43#), 8) & + to_slv(CFI_array(16#44#), 8) & + to_slv(CFI_array(16#45#), 8) & + to_slv(CFI_array(16#46#), 8) & + to_slv(CFI_array(16#47#), 8) & + to_slv(CFI_array(16#48#), 8) & + to_slv(CFI_array(16#49#), 8) & + to_slv(CFI_array(16#4A#), 8) & + to_slv(CFI_array(16#4B#), 8) & + to_slv(CFI_array(16#4C#), 8) & + to_slv(CFI_array(16#4D#), 8) & + to_slv(CFI_array(16#4E#), 8) & + to_slv(CFI_array(16#4F#), 8) & + to_slv(CFI_array(16#50#), 8); + + WAIT; + + END PROCESS CFIPreload; + + AspRegInit: PROCESS(ASP_INIT) + BEGIN + IF ASP_INIT = 0 THEN + ASP_reg := to_slv(16#FE4F#,16); + ELSE + ASP_reg := to_slv(16#FE7F#,16); + END IF; + END PROCESS AspRegInit; + + Protect : PROCESS(change_BP) + BEGIN + IF rising_edge(change_BP) THEN + + CASE BP_bits IS + WHEN "000" => + Sec_Prot := (OTHERS => '0'); + WHEN "001" => + IF TBPROT = '0' THEN + Sec_Prot(SecNum downto (SecNum+1)*63/64) + := (OTHERS => '1'); + Sec_Prot((SecNum+1)*63/64 - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/64 - 1 downto 0) + := (OTHERS => '1'); + Sec_Prot(SecNum downto (SecNum+1)/64) + := (OTHERS => '0'); + END IF; + WHEN "010" => + IF TBPROT = '0' THEN + Sec_Prot(SecNum downto (SecNum+1)*31/32) + := (OTHERS => '1'); + Sec_Prot((SecNum+1)*31/32 - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/32 - 1 downto 0) + := (others => '1'); + Sec_Prot(SecNum downto (SecNum+1)/32) + := (OTHERS => '0'); + END IF; + WHEN "011" => + IF TBPROT = '0' THEN + Sec_Prot(SecNum downto (SecNum+1)*15/16) + := (OTHERS => '1'); + Sec_Prot((SecNum+1)*15/16 - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/16 - 1 downto 0) + := (OTHERS => '1'); + Sec_Prot(SecNum downto (SecNum+1)/16) + := (OTHERS => '0'); + END IF; + WHEN "100" => + IF TBPROT = '0' THEN + Sec_Prot(SecNum downto (SecNum+1)*7/8) + := (OTHERS => '1'); + Sec_Prot((SecNum+1)*7/8 - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/8 - 1 downto 0) := (OTHERS => '1'); + Sec_Prot(SecNum downto (SecNum+1)/8):= (OTHERS => '0'); + END IF; + WHEN "101" => + IF TBPROT = '0' THEN + Sec_Prot(SecNum downto (SecNum+1)*3/4) + := (OTHERS => '1'); + Sec_Prot((SecNum+1)*3/4 - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/4 - 1 downto 0) := (OTHERS => '1'); + Sec_Prot(SecNum downto (SecNum+1)/4):= (OTHERS => '0'); + END IF; + + WHEN "110" => + IF TBPROT = '0' THEN + Sec_Prot(SecNum downto (SecNum+1)/2):= (OTHERS => '1'); + Sec_Prot((SecNum+1)/2 - 1 downto 0) := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/2 - 1 downto 0) := (OTHERS => '1'); + Sec_Prot(SecNum downto (SecNum+1)/2):= (OTHERS => '0'); + END IF; + + WHEN OTHERS => + Sec_Prot := (OTHERS => '1'); + END CASE; + END IF; + END PROCESS Protect; + + HOLD_FRAME_ON_PO_ZD : PROCESS(SOut_zd, SIOut_zd, HOLDNeg_pullup) + BEGIN + IF (HOLDNeg_pullup = '0' AND QUAD /= '1') THEN + hold_mode := TRUE; + SIOut_z <= 'Z'; + SOut_z <= 'Z'; + ELSE + IF hold_mode THEN + SIOut_z <= SIOut_zd AFTER tpd_HOLDNeg_SO(trz0); + SOut_z <= SOut_zd AFTER tpd_HOLDNeg_SO(trz0); + hold_mode := FALSE; + ELSE + SIOut_z <= SIOut_zd; + SOut_z <= SOut_zd; + hold_mode := FALSE; + END IF; + END IF; + END PROCESS HOLD_FRAME_ON_PO_ZD; + + HOLD_PULL_UP : PROCESS(HOLDNegIn) + BEGIN + IF (QUAD = '0') THEN + IF (HOLDNegIn = 'Z') THEN + HOLDNeg_pullup <= '1'; + ELSE + HOLDNeg_pullup <= HOLDNegIn; + END IF; + END IF; + END PROCESS HOLD_PULL_UP; + + WP_PULL_UP : PROCESS(WPNegIn) + BEGIN + IF (QUAD = '0') THEN + IF (WPNegIn = 'Z') THEN + WPNeg_pullup <= '1'; + ELSE + WPNeg_pullup <= WPNegIn; + END IF; + END IF; + END PROCESS WP_PULL_UP; + + RST_PULL_UP : PROCESS(RSTNeg) + BEGIN + IF (RSTNeg = 'Z') THEN + RSTNeg_pullup <= '1'; + ELSE + RSTNeg_pullup <= RSTNeg; + END IF; + END PROCESS RST_PULL_UP; + + --------------------------------------------------------------------------- + ---- File Read Section - Preload Control + --------------------------------------------------------------------------- + MemPreload : PROCESS + + -- text file input variables + FILE mem_file : text is mem_file_name; + FILE otp_file : text is otp_file_name; + VARIABLE ind : NATURAL RANGE 0 TO AddrRANGE := 0; + VARIABLE S_ind : NATURAL RANGE 0 TO SecNum:= 0; + VARIABLE index : NATURAL RANGE 0 TO SecSize:=0; + VARIABLE otp_ind : NATURAL RANGE 16#000# TO 16#3FF# := 16#000#; + VARIABLE buf : line; + VARIABLE reported : NATURAL; + VARIABLE mem_data : INTEGER; + + BEGIN + --------------------------------------------------------------------------- + --s25fl512s memory preload file format +----------------------------------- + --------------------------------------------------------------------------- + -- / - comment + -- @aaaaaa - stands for address + -- dd -
is byte to be written at Mem(aaaaaa++) + -- (aaaaaa is incremented at every load) + -- only first 1-7 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + --------------------------------------------------------------------------- + -- memory preload + configure_memory(16#FF#); + initialize; + IF (mem_file_name /= "none" AND UserPreload ) THEN + ind := 0; + reported := 0; + WHILE (not ENDFILE (mem_file)) LOOP + READLINE (mem_file, buf); + IF buf(1) = '/' THEN --comment + NEXT; + ELSIF buf(1) = '@' THEN --address + ind := h(buf(2 to 8)); + ELSE + IF ind <= AddrRANGE THEN + mem_data := h(buf(1 to 2)); + IF ind=0 THEN + S_ind := 0; + index := 0; + ELSIF ind < SecSize+1 THEN + S_ind := 0; + index := ind; + ELSE + S_ind := NATURAL(ind / (SecSize +1)); + index := ind - S_ind*(SecSize+1); + END IF; + WRITE_DATA(S_ind,index,mem_data); + IF ind < AddrRANGE THEN + ind := ind + 1; + END IF; + ELSIF reported = 0 THEN + REPORT " Memory address out of range" + SEVERITY warning; + reported := 1; + END IF; + END IF; + END LOOP; + END IF; + + --------------------------------------------------------------------------- + --s25fl512s_otp memory preload file format + --------------------------------------------------------------------------- + -- / - comment + -- @aaa - stands for address + -- dd -
is byte to be written at OTPMem(aaa++) + -- (aaa is incremented at every load) + -- only first 1-4 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + --------------------------------------------------------------------------- + + -- memory preload + IF (otp_file_name /= "none" AND UserPreload) THEN + otp_ind := 16#000#; + OTPMem := (OTHERS => MaxData); + WHILE (not ENDFILE (otp_file)) LOOP + READLINE (otp_file, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + IF otp_ind > 16#3FF# OR otp_ind < 16#000# THEN + ASSERT false + REPORT "Given preload address is out of" & + "OTP address range" + SEVERITY warning; + ELSE + otp_ind := h(buf(2 to 4)); --address + END IF; + ELSE + OTPMem(otp_ind) := h(buf(1 to 2)); + otp_ind := otp_ind + 1; + END IF; + END LOOP; + END IF; + + LOCK_BYTE1 := to_slv(OTPMem(16#10#),8); + LOCK_BYTE2 := to_slv(OTPMem(16#11#),8); + LOCK_BYTE3 := to_slv(OTPMem(16#12#),8); + LOCK_BYTE4 := to_slv(OTPMem(16#13#),8); + + WAIT; + END PROCESS MemPreload; + + ---------------------------------------------------------------------------- + -- Path Delay Section + ---------------------------------------------------------------------------- + + S_Out_PathDelay_Gen : PROCESS(SOut_z) + + VARIABLE SO_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => SOut, + OutSignalName => "SO", + OutTemp => SOut_z, + Mode => VitalTransport, + GlitchData => SO_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal), + PathCondition => NOT(ddr)), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR), + PathCondition => (ddr OR fast_rd)), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1'), + 3 => (InputChangeTime => HOLDNegIn'LAST_EVENT, + PathDelay => tpd_HOLDNeg_SO, + PathCondition => QUAD = '0') + ) + ); + END PROCESS; + + SI_Out_PathDelay : PROCESS(SIOut_z) + + VARIABLE SI_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => SIOut, + OutSignalName => "SI", + OutTemp => SIOut_z, + Mode => VitalTransport, + GlitchData => SI_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal), + PathCondition => dual AND NOT(ddr)), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR), + PathCondition => dual AND ddr), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1'), + 3 => (InputChangeTime => HOLDNegIn'LAST_EVENT, + PathDelay => tpd_HOLDNeg_SO, + PathCondition => dual AND QUAD = '0') + ) + ); + END PROCESS; + + HOLD_Out_PathDelay : PROCESS(HOLDNegOut_zd) + + VARIABLE HOLD_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => HOLDNegOut, + OutSignalName => "HOLDNeg", + OutTemp => HOLDNegOut_zd, + Mode => VitalTransport, + GlitchData => HOLD_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal), + PathCondition => dual AND not(ddr) AND QUAD = '1'), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR), + PathCondition => ddr AND QUAD = '1'), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND + HOLDNegOut_zd = 'Z' AND QUAD = '1') + ) + ); + END PROCESS; + + WP_Out_PathDelay : PROCESS(WPNegOut_zd) + + VARIABLE WP_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => WPNegOut, + OutSignalName => "WPNeg", + OutTemp => WPNegOut_zd, + Mode => VitalTransport, + GlitchData => WP_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal), + PathCondition => dual AND not(ddr) AND QUAD = '1'), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR), + PathCondition => ddr AND QUAD = '1'), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND + WPNegOut_zd = 'Z' AND QUAD = '1') + ) + ); + END PROCESS; + + END BLOCK behavior; +END vhdl_behavioral_dynamic_memory_allocation; +ARCHITECTURE vhdl_behavioral_static_memory_allocation of s25fl512s IS + ATTRIBUTE VITAL_LEVEL0 OF + vhdl_behavioral_static_memory_allocation : ARCHITECTURE IS TRUE; + + --------------------------------------------------------------------------- + -- CONSTANT AND SIGNAL DECLARATION + --------------------------------------------------------------------------- + --Declaration of constants - memory characteristics + -- The constant declared here are used to enable the creation of models + -- of memories within a family with a minimum amount of editing + + CONSTANT PartID : STRING := "s25fl512s"; + CONSTANT MaxData : NATURAL := 16#FF#; --255; + CONSTANT MemSize : NATURAL := 16#3FFFFFF#; + CONSTANT SecNum : NATURAL := 255; + CONSTANT SecSize : NATURAL := 16#3FFFF#; --256KB + CONSTANT PageNum : NATURAL := 16#1FFFF#; + CONSTANT PageSize : NATURAL := 512; + CONSTANT AddrRANGE : NATURAL := 16#3FFFFFF#; + CONSTANT HiAddrBit : NATURAL := 31; + CONSTANT OTPSize : NATURAL := 1023; + CONSTANT OTPLoAddr : NATURAL := 16#000#; + CONSTANT OTPHiAddr : NATURAL := 16#3FF#; + CONSTANT BYTE : NATURAL := 8; + + --Manufacturer Identification + CONSTANT Manuf_ID : NATURAL := 16#01#; + CONSTANT DeviceID : NATURAL := 16#19#; + --Electronic Signature + CONSTANT ESignature : NATURAL := 16#19#; + --Device ID + --Manufacturer Identification && Memory Type && Memory Capacity + CONSTANT Jedec_ID : NATURAL := 16#01#; -- first byte of Device ID + CONSTANT DeviceID1 : NATURAL := 16#02#; + CONSTANT DeviceID2 : NATURAL := 16#20#; + CONSTANT ExtendedBytes : NATURAL := 16#4D#; + CONSTANT ExtendedID : NATURAL := 16#00#; + CONSTANT DieRev : NATURAL := 16#00#; + CONSTANT MaskRev : NATURAL := 16#00#; + + -- Declaration of signals that will hold the delayed values of ports + SIGNAL SI_ipd : std_ulogic := 'U'; + SIGNAL SO_ipd : std_ulogic := 'U'; + SIGNAL SCK_ipd : std_ulogic := 'U'; + SIGNAL CSNeg_ipd : std_ulogic := 'U'; + SIGNAL RSTNeg_ipd : std_ulogic := 'U'; + SIGNAL WPNeg_ipd : std_ulogic := 'U'; + SIGNAL HOLDNeg_ipd : std_ulogic := 'U'; + SIGNAL HOLDNeg_pullup : std_ulogic := 'U'; + SIGNAL WPNeg_pullup : std_ulogic := 'U'; + SIGNAL RSTNeg_pullup : std_ulogic := 'U'; + + -- internal delays + SIGNAL PP_in : std_ulogic := '0'; + SIGNAL PP_out : std_ulogic := '0'; + SIGNAL BP_in : std_ulogic := '0'; + SIGNAL BP_out : std_ulogic := '0'; + SIGNAL SE_in : std_ulogic := '0'; + SIGNAL SE_out : std_ulogic := '0'; + SIGNAL BE_in : std_ulogic := '0'; + SIGNAL BE_out : std_ulogic := '0'; + SIGNAL WRR_in : std_ulogic := '0'; + SIGNAL WRR_out : std_ulogic := '0'; + SIGNAL ERSSUSP_in : std_ulogic := '0'; + SIGNAL ERSSUSP_out : std_ulogic := '0'; + SIGNAL PRGSUSP_in : std_ulogic := '0'; + SIGNAL PRGSUSP_out : std_ulogic := '0'; + SIGNAL PU_in : std_ulogic := '0'; + SIGNAL PU_out : std_ulogic := '0'; + SIGNAL RST_in : std_ulogic := '0';-- Hardware Reset Timeout + SIGNAL RST_out : std_ulogic := '1';-- + SIGNAL PPBERASE_in : std_ulogic := '0'; + SIGNAL PPBERASE_out : std_ulogic := '0'; + SIGNAL PASSULCK_in : std_ulogic := '0'; + SIGNAL PASSULCK_out : std_ulogic := '0'; + SIGNAL PASSACC_in : std_ulogic := '0'; + SIGNAL PASSACC_out : std_ulogic := '0'; + + FUNCTION ReturnSectorID(ADDR : NATURAL) RETURN NATURAL IS + VARIABLE result : NATURAL; + BEGIN + IF ADDR <= AddrRange THEN + result := ADDR / (SecSize+1); + ELSE + result := SecNum+1; + END IF; + RETURN result; + END ReturnSectorID; + + FUNCTION ReturnSectorIDRdPswdMd(TBPROT : std_logic) RETURN NATURAL IS + VARIABLE result : NATURAL; + BEGIN + result := SecNum; + IF TBPROT = '0' THEN + result := 0; + END IF; + RETURN result; + END ReturnSectorIDRdPswdMd; + +BEGIN + --------------------------------------------------------------------------- + -- Internal Delays + --------------------------------------------------------------------------- + -- Artificial VITAL primitives to incorporate internal delays + -- Because a tdevice generics is used, there must be a VITAL_primitives + -- assotiated with them + PP :VitalBuf(PP_out, PP_in, (tdevice_PP ,UnitDelay)); + BP :VitalBuf(BP_out, BP_in, (tdevice_BP ,UnitDelay)); + SE :VitalBuf(SE_out, SE_in, (tdevice_SE ,UnitDelay)); + BE :VitalBuf(BE_out, BE_in, (tdevice_BE ,UnitDelay)); + WRR :VitalBuf(WRR_out, WRR_in, (tdevice_WRR ,UnitDelay)); + ERSSUSP :VitalBuf(ERSSUSP_out, ERSSUSP_in, (tdevice_ERSSUSP ,UnitDelay)); + PRGSUSP :VitalBuf(PRGSUSP_out, PRGSUSP_in, (tdevice_PRGSUSP ,UnitDelay)); + PU :VitalBuf(PU_out, PU_in, (tdevice_PU ,UnitDelay)); + PPBERASE :VitalBuf(PPBERASE_out,PPBERASE_in,(tdevice_PPBERASE,UnitDelay)); + PASSULCK :VitalBuf(PASSULCK_out,PASSULCK_in,(tdevice_PASSULCK,UnitDelay)); + PASSACC :VitalBuf(PASSACC_out, PASSACC_in, (tdevice_PASSACC ,UnitDelay)); + + --------------------------------------------------------------------------- + -- Wire Delays + --------------------------------------------------------------------------- + WireDelay : BLOCK + BEGIN + + w_1 : VitalWireDelay (SI_ipd, SI, tipd_SI); + w_2 : VitalWireDelay (SO_ipd, SO, tipd_SO); + w_3 : VitalWireDelay (SCK_ipd, SCK, tipd_SCK); + w_4 : VitalWireDelay (CSNeg_ipd, CSNeg, tipd_CSNeg); + w_5 : VitalWireDelay (RSTNeg_ipd, RSTNeg, tipd_RSTNeg); + w_6 : VitalWireDelay (WPNeg_ipd, WPNeg, tipd_WPNeg); + w_7 : VitalWireDelay (HOLDNeg_ipd, HOLDNeg, tipd_HOLDNeg); + + END BLOCK; + + --------------------------------------------------------------------------- + -- Main Behavior Block + --------------------------------------------------------------------------- + Behavior: BLOCK + + PORT ( + SIIn : IN std_ulogic := 'U'; + SIOut : OUT std_ulogic := 'U'; + SOIn : IN std_logic := 'U'; + SOut : OUT std_logic := 'U'; + SCK : IN std_ulogic := 'U'; + CSNeg : IN std_ulogic := 'U'; + RSTNeg : IN std_ulogic := 'U'; + HOLDNegIn : IN std_ulogic := 'U'; + HOLDNegOut : OUT std_ulogic := 'U'; + WPNegIn : IN std_ulogic := 'U'; + WPNegOut : OUT std_ulogic := 'U' + ); + + PORT MAP ( + SIIn => SI_ipd, + SIOut => SI, + SOIn => SO_ipd, + SOut => SO, + SCK => SCK_ipd, + CSNeg => CSNeg_ipd, + RSTNeg => RSTNeg_ipd, + HOLDNegIn => HOLDNeg_ipd, + HOLDNegOut => HOLDNeg, + WPNegIn => WPNeg_ipd, + WPNegOut => WPNeg + ); + + -- State Machine : State_Type + TYPE state_type IS (IDLE, + RESET_STATE, + AUTOBOOT, + WRITE_SR, + PAGE_PG, + OTP_PG, + PG_SUSP, + SECTOR_ERS, + BULK_ERS, + ERS_SUSP, + ERS_SUSP_PG, + ERS_SUSP_PG_SUSP, + PASS_PG, + PASS_UNLOCK, + PPB_PG, + PPB_ERS, + AUTOBOOT_PG, + ASP_PG, + PLB_PG, + DYB_PG, + NVDLR_PG + ); + + -- Instruction Type + TYPE instruction_type IS ( NONE, + WREN, -- Write Enable + WRDI, -- Write Disable + WRR, -- Write Register + READ, -- Read Normal (3Byte Address) + RD4, -- Read Normal (4Byte +) + OTPR, -- OTP Read + RDSR, -- Read Status Register 1 + RDSR2, -- Read Status Register 2 + RDCR, -- Read Configuration Register 1 + REMS, -- Read ID (SST) + RDID, -- Read ID JEDEC + RES, -- Read ID + FSTRD, -- Fast Read (3Byte Address) + FSTRD4, -- Fast Read (4Byte +) + DDRFR, -- Fast Read DDR (3Byte Address) + DDRFR4, -- Fast Read DDR (4Byte +) + DOR, -- Read Dual Out (3Byte Address) + DOR4, -- Read Dual Out (4Byte +) + DIOR, -- Read Dual I/O (3Byte Address) + DIOR4, -- Read Dual I/O (4Byte +) + DDRDIOR, -- Read DDR Dual I/O (3Byte) + DDRDIOR4, -- Read DDR Dual I/O (4Byte +) + QOR, -- Read Quad Out (3Byte Address) + QOR4, -- Read Quad Out (4Byte +) + QIOR, -- Read Quad I/O (3Byte Address) + QIOR4, -- Read Quad I/O (4Byte +) + DDRQIOR, -- Read DDR Quad I/O (3Byte) + DDRQIOR4, -- Read DDR Quad I/O (4Byte +) + PP, -- Program Page (3Byte Address) + PP4, -- Program Page (4Byte +) + QPP, -- Quad Page Program (3Byte) + QPP4, -- Quad Page Program (4Byte +) + OTPP, -- OTP Program + PGSP, -- Program Suspend + PGRS, -- Program Resume + BE, -- Bulk Erase + SE, -- Erase 128/256KB (3Byte) + SE4, -- Erase 128/256KB (4Byte +) + P4E, -- 4KB-sector Erase (3Byte Addr) + P4E4, -- 4KB-sector Erase (4Byte Addr) + ERSP, -- Erase Suspend + ERRS, -- Erase Resume + ABRD, -- AutoBoot Register Read + ABWR, -- AutoBoot Register Write + BRRD, -- Bank Register Read + BRWR, -- Bank Register Write + BRAC, -- Bank Register Access + DLPRD, -- Read Data Learning Pattern + PNVDLR, -- Program NVDLP Reg + WVDLR, -- Write Volatile DLP Reg + ASPRD, -- ASP Read + ASPP, -- ASP Program + DYBRD, -- DYB Read + DYBWR, -- DYB Write + PPBRD, -- PPB Read + PPBP, -- PPB Program + PPBERS, -- PPB Erase + PLBWR, -- PPB Lock Bit Write + PLBRD, -- PPB Lock Bit Read + PASSRD, -- Password Read + PASSP, -- Password Program + PASSU, -- Password Unlock + RESET, -- Reset + MBR, -- Mode Bit Reset + MPM, -- Multi-I/O-High Perf Mode + CLSR -- Clear Status Register + ); + + TYPE WByteType IS ARRAY (0 TO 511) OF INTEGER RANGE -1 TO MaxData; + -- Flash Memory Array + TYPE MemArray IS ARRAY (0 TO AddrRANGE) OF INTEGER RANGE -1 TO MaxData; + -- OTP Memory Array + TYPE OTPArray IS ARRAY (OTPLoAddr TO OTPHiAddr) OF INTEGER + RANGE -1 TO MaxData; + --CFI Array (Common Flash Interface Query codes) + TYPE CFItype IS ARRAY (16#00# TO 16#55#) OF + INTEGER RANGE -1 TO 16#FF#; + ----------------------------------------------------------------------- + -- memory declaration + ----------------------------------------------------------------------- + -- Memory + SHARED VARIABLE Mem : MemArray := (OTHERS => MaxData); + -- OTP Sector + SHARED VARIABLE OTPMem : OTPArray := (OTHERS => MaxData); + --CFI Array + SHARED VARIABLE CFI_array : CFItype := (OTHERS => 0); + -- Programming Buffer + SIGNAL WByte : WByteType := (OTHERS => MaxData); + + -- states + SIGNAL current_state : state_type; + SIGNAL next_state : state_type; + + SIGNAL Instruct : instruction_type; + --zero delay signal + SIGNAL SOut_zd : std_logic := 'Z'; + SIGNAL SIOut_zd : std_logic := 'Z'; + SIGNAL HOLDNegOut_zd : std_logic := 'Z'; + SIGNAL WPNegOut_zd : std_logic := 'Z'; + --HOLD delay on output data + SIGNAL SOut_z : std_logic := 'Z'; + SIGNAL SIOut_z : std_logic := 'Z'; + -- powerup + SIGNAL PoweredUp : std_logic := '0'; + + ----------------------------------------------------------------------- + -- Registers + ----------------------------------------------------------------------- + -- *** Status Register 1 *** + SHARED VARIABLE Status_reg1 : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Status_reg1_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Status Register Write Disable Bit + ALIAS SRWD :std_logic IS Status_reg1(7); + -- Status Register Programming Error Bit + ALIAS P_ERR :std_logic IS Status_reg1(6); + -- Status Register Erase Error Bit + ALIAS E_ERR :std_logic IS Status_reg1(5); + -- Status Register Block Protection Bits + ALIAS BP2 :std_logic IS Status_reg1(4); + ALIAS BP1 :std_logic IS Status_reg1(3); + ALIAS BP0 :std_logic IS Status_reg1(2); + -- Status Register Write Enable Latch Bit + ALIAS WEL :std_logic IS Status_reg1(1); + -- Status Register Write In Progress Bit + ALIAS WIP :std_logic IS Status_reg1(0); + + -- *** Status Register 2 *** + SHARED VARIABLE Status_reg2 : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Status_reg2_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Status Register Write Enable Latch Bit + ALIAS ES :std_logic IS Status_reg2(1); + -- Status Register Write In Progress Bit + ALIAS PS :std_logic IS Status_reg2(0); + + -- *** Configuration Register 1 *** + SHARED VARIABLE Config_reg1 : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Config_reg1_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Latency code + ALIAS LC1 :std_logic IS Config_reg1(7); + ALIAS LC0 :std_logic IS Config_reg1(6); + -- Configuration Register TBPROT bit + ALIAS TBPROT :std_logic IS Config_reg1(5); + -- Configuration Register LOCK bit + ALIAS LOCK :std_logic IS Config_reg1(4); + -- Configuration Register BPNV bit + ALIAS BPNV :std_logic IS Config_reg1(3); + -- Configuration Register QUAD bit + ALIAS QUAD :std_logic IS Config_reg1(1); + -- Configuration Register FREEZE bit + ALIAS FREEZE :std_logic IS Config_reg1(0); + + -- *** VDLR Register *** + SHARED VARIABLE VDLR_reg : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL VDLR_reg_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- *** NVDLR Register *** + SHARED VARIABLE NVDLR_reg : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL NVDLR_reg_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- *** AutoBoot Register *** + SHARED VARIABLE AutoBoot_reg : std_logic_vector(31 downto 0) + := (others => '0'); + SIGNAL AutoBoot_reg_in : std_logic_vector(31 downto 0) + := (others => '0'); + + --AutoBoot Enable Bit + ALIAS ABE :std_logic IS AutoBoot_reg(0); + + -- *** Bank Address Register *** + SHARED VARIABLE Bank_Addr_reg : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL Bank_Addr_reg_in : std_logic_vector(7 downto 0) + := (others => '0'); + --Bank Address Register EXTADD bit + ALIAS EXTADD :std_logic IS Bank_Addr_reg(7); + + -- *** ASP Register *** + SHARED VARIABLE ASP_reg : std_logic_vector(15 downto 0); + SIGNAL ASP_reg_in : std_logic_vector(15 downto 0) + := (others => '1'); + --Read Password Mode Enable Bit + ALIAS RPME :std_logic IS ASP_reg(5); + --PPB OTP Bit + ALIAS PPBOTP :std_logic IS ASP_reg(3); + -- Password Protection Mode Lock Bit + ALIAS PWDMLB :std_logic IS ASP_reg(2); + --Persistent Protection Mode Lock Bit + ALIAS PSTMLB :std_logic IS ASP_reg(1); + + -- *** Password Register *** + SHARED VARIABLE Password_reg : std_logic_vector(63 downto 0) + := (others => '1'); + SIGNAL Password_reg_in : std_logic_vector(63 downto 0) + := (others => '1'); + -- *** PPB Lock Register *** + SHARED VARIABLE PPBL : std_logic_vector(7 downto 0) + := (others => '0'); + SIGNAL PPBL_in : std_logic_vector(7 downto 0) + := (others => '0'); + --Persistent Protection Mode Lock Bit + ALIAS PPB_LOCK : std_logic IS PPBL(0); + SIGNAL PPB_LOCK_temp : std_ulogic := '0'; + + -- *** PPB Access Register *** + SHARED VARIABLE PPBAR : std_logic_vector(7 downto 0) + := (others => '1'); + SIGNAL PPBAR_in : std_logic_vector(7 downto 0) + := (others => '1'); + -- PPB_bits(Sec) + SHARED VARIABLE PPB_bits : std_logic_vector(SecNum downto 0) + := (OTHERS => '1'); + -- *** DYB Access Register *** + SHARED VARIABLE DYBAR : std_logic_vector(7 downto 0) + := (others => '1'); + SIGNAL DYBAR_in : std_logic_vector(7 downto 0) + := (others => '1'); + -- DYB(Sec) + SHARED VARIABLE DYB_bits : std_logic_vector(SecNum downto 0); + + -- The Lock Protection Registers for OTP Memory space + SHARED VARIABLE LOCK_BYTE1 :std_logic_vector(7 downto 0); + SHARED VARIABLE LOCK_BYTE2 :std_logic_vector(7 downto 0); + SHARED VARIABLE LOCK_BYTE3 :std_logic_vector(7 downto 0); + SHARED VARIABLE LOCK_BYTE4 :std_logic_vector(7 downto 0); + + --Command Register + SIGNAL write : std_logic := '0'; + SIGNAL cfg_write : std_logic := '0'; + SIGNAL read_out : std_logic := '0'; + + SIGNAL rd : boolean := false; + SIGNAL dual : boolean := false; + SIGNAL fast_rd : boolean := true; + SIGNAL ddr : boolean := false; + SIGNAL any_read : boolean := false; + + SIGNAL quadpg : boolean := false; + + SIGNAL oe : boolean := false; + SIGNAL oe_z : boolean := false; + + SHARED VARIABLE hold_mode : boolean := false; + + --FSM control signals + SIGNAL PDONE : std_logic := '1'; --Page Prog. Done + SIGNAL PSTART : std_logic := '0'; --Start Page Programming + SIGNAL PGSUSP : std_logic := '0'; --Suspend Program + SIGNAL PGRES : std_logic := '0'; --Resume Program + + SIGNAL RES_TO_SUSP_MIN_TIME : std_logic := '0';--Resume to Suspend Flag + SIGNAL RES_TO_SUSP_TYP_TIME : std_logic := '0';--Resume to Suspend Flag + + SIGNAL WDONE : std_logic := '1'; --Write operation Done + SIGNAL WSTART : std_logic := '0'; --Start Write operation + + SIGNAL ESTART : std_logic := '0'; --Start Erase operation + SIGNAL EDONE : std_logic := '1'; --Erase operation Done + SIGNAL ESUSP : std_logic := '0'; --Suspend Erase + SIGNAL ERES : std_logic := '0'; --Resume Erase + + --reset timing + SIGNAL RST : std_logic := '0'; + SIGNAL Reseted : std_logic := '0'; --Reset Timing Control + --Lock Bit is enabled for customer programming + SIGNAL WRLOCKENABLE : BOOLEAN := TRUE; + --Flag that mark if ASP Register is allready programmed + SIGNAL ASPOTPFLAG : BOOLEAN := FALSE; + SIGNAL ASP_INIT : NATURAL RANGE 0 TO 1; + SIGNAL INITIAL_CONFIG : std_logic := '0'; + + SHARED VARIABLE SecAddr : NATURAL RANGE 0 TO SecNum:= 0; + + SHARED VARIABLE Sec_addr : NATURAL := 0; + + SHARED VARIABLE Page_addr : NATURAL; + SHARED VARIABLE pgm_page : NATURAL; + + SHARED VARIABLE QPP_page : std_logic_vector(PageNum downto 0) + := (OTHERS => '0'); + + --Flag for Password unlock command + SIGNAL PASS_UNLOCKED : boolean := FALSE; + SIGNAL PASS_TEMP : std_logic_vector(63 downto 0) + := (others => '1'); + + SHARED VARIABLE DOUBLE : BOOLEAN := FALSE; + SHARED VARIABLE EHP : BOOLEAN := FALSE; + + SHARED VARIABLE read_cnt : NATURAL := 0; + SHARED VARIABLE byte_cnt : NATURAL := 1; + SHARED VARIABLE read_addr : NATURAL RANGE 0 TO AddrRANGE ; + SHARED VARIABLE read_addr_tmp : NATURAL RANGE 0 TO AddrRANGE ; + + SHARED VARIABLE start_delay : NATURAL RANGE 0 TO 7; + SHARED VARIABLE ABSD : NATURAL RANGE 0 TO 7; + SIGNAL start_autoboot : std_logic := '0'; + + SIGNAL change_addr : std_logic := '0'; + SIGNAL Address : NATURAL RANGE 0 TO AddrRANGE := 0; + SIGNAL SectorSuspend : NATURAL RANGE 0 TO SecNum := 0; + + -- Sector address + SIGNAL SA : NATURAL RANGE 0 TO SecNum := 0; + + -- Sector is protect if Sec_Prot(SecNum) = '1' + SHARED VARIABLE Sec_Prot : std_logic_vector(SecNum downto 0) := + (OTHERS => '0'); + + SIGNAL change_BP : std_logic := '0'; + SHARED VARIABLE BP_bits : std_logic_vector(2 downto 0) := "000"; + + SHARED VARIABLE CFI_array_tmp : std_logic_vector(647 downto 0); + + SIGNAL Byte_number : NATURAL RANGE 0 TO 511 := 0; + + TYPE bus_cycle_type IS (STAND_BY, + OPCODE_BYTE, + ADDRESS_BYTES, + DUMMY_BYTES, + MODE_BYTE, + DATA_BYTES + ); + SHARED VARIABLE bus_cycle_state : bus_cycle_type; + -- switch between Data bytes and Dummy bytes + SHARED VARIABLE DummyBytes_act : X01 := '0'; + SIGNAL dummy_cnt_act_temp : NATURAL := 0; + SIGNAL dummy_cnt_act : NATURAL := 0; + --Read Password Protection Mode Active flag + SIGNAL RdPswdProtMode : std_ulogic := '0'; + --Read Password Protection Mode Support flag + SIGNAL RdPswdProtEnable : std_ulogic := '0'; + SIGNAL BAR_ACC : std_ulogic := '0'; + + SHARED VARIABLE Latency_code : NATURAL RANGE 0 TO 7; + SHARED VARIABLE opcode_cnt : NATURAL := 0; + SHARED VARIABLE addr_cnt : NATURAL := 0; + SHARED VARIABLE mode_cnt : NATURAL := 0; + SHARED VARIABLE dummy_cnt : NATURAL := 0; + SHARED VARIABLE data_cnt : NATURAL := 0; + + -- timing check violation + SIGNAL Viol : X01 := '0'; + + PROCEDURE ADDRHILO_SEC( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE Addr : NATURAL) IS + VARIABLE sector : NATURAL RANGE 0 TO SecNum; + BEGIN + sector := Addr/16#40000#; + AddrLOW := sector*16#40000#; + AddrHIGH := sector*16#40000# + 16#3FFFF#; + END ADDRHILO_SEC; + + PROCEDURE ADDRHILO_PG( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE Addr : NATURAL) IS + VARIABLE page : NATURAL RANGE 0 TO PageNum; + BEGIN + page := Addr/PageSize; + AddrLOW := Page*PageSize; + AddrHIGH := Page*PageSize + (PageSize-1); + END AddrHILO_PG; + + BEGIN + --------------------------------------------------------------------------- + --Power Up time + --------------------------------------------------------------------------- + + PoweredUp <= '1' AFTER tdevice_PU; + + TimingModelSel: PROCESS + BEGIN + --Enhanced High Performance Flag + IF (TimingModel(15) = '0' OR TimingModel(15) = '2' OR + TimingModel(15) = '3' OR TimingModel(15) = 'R' OR + TimingModel(15) = 'A' OR TimingModel(15) = 'B' OR + TimingModel(15) = 'C' OR TimingModel(15) = 'D' OR + TimingModel(15) = 'Y' OR TimingModel(15) = 'Z' OR + TimingModel(15) = 'S' OR TimingModel(15) = 'T' OR + TimingModel(15) = 'K' OR TimingModel(15) = 'L') THEN + EHP := TRUE; + IF (TimingModel(15) = 'Y' OR TimingModel(15) = 'Z' OR + TimingModel(15) = 'S' OR TimingModel(15) = 'T' OR + TimingModel(15) = 'K' OR TimingModel(15) = 'L') THEN + RdPswdProtEnable <= '1'; + END IF; + ELSIF (TimingModel(15) = '4' OR TimingModel(15) = '6' OR + TimingModel(15) = '7' OR TimingModel(15) = '8' OR + TimingModel(15) = '9' OR TimingModel(15) = 'Q') THEN + EHP := FALSE; + END IF; + + IF (TimingModel(15) ='0' OR TimingModel(15) ='2' OR + TimingModel(15) ='3' OR TimingModel(15) ='R' OR + TimingModel(15) ='A' OR TimingModel(15) ='B' OR + TimingModel(15) ='C' OR TimingModel(15) ='D' OR + TimingModel(15) ='4' OR TimingModel(15) ='6' OR + TimingModel(15) ='7' OR TimingModel(15) ='8' OR + TimingModel(15) ='9' OR TimingModel(15) ='Q') THEN + ASP_INIT <= 1; + ELSIF (TimingModel(15) ='Y' OR TimingModel(15) ='Z' OR + TimingModel(15) ='S' OR TimingModel(15) ='T' OR + TimingModel(15) ='K' OR TimingModel(15) ='L') THEN + ASP_INIT <= 0; + END IF; + WAIT; + END PROCESS; + + RSTtiming: PROCESS(RSTNeg_pullup,Instruct) + BEGIN + IF falling_edge(RSTNeg_pullup) THEN + RST <= '1', '0' AFTER 200 ns; + ELSIF Instruct = RESET THEN + Reseted <= '0', '1' AFTER 10 ns; + END IF; + END PROCESS; + + DUMMYcnt: PROCESS(dummy_cnt_act_temp) + BEGIN + dummy_cnt_act <= dummy_cnt_act_temp; + END PROCESS; + + ReadPasswordProtectionMode: PROCESS(PPB_LOCK_temp, + ASP_reg_in(2), ASP_reg_in(5)) + BEGIN + IF (PPB_LOCK = '0' AND PWDMLB = '0' AND RPME = '0' AND + RdPswdProtEnable = '1') THEN + RdPswdProtMode <= '1'; + ABE := '0'; + ELSE + RdPswdProtMode <= '0'; + END IF; + END PROCESS; + --------------------------------------------------------------------------- + -- autoboot control logic + --------------------------------------------------------------------------- + AutoBootControl: PROCESS(SCK_ipd, current_state) + BEGIN + IF (current_state = AUTOBOOT) THEN + IF rising_edge(SCK_ipd) THEN + IF (start_delay > 0) THEN + start_delay := start_delay - 1; + END IF; + END IF; + + IF (start_delay = 0) THEN + start_autoboot <= '1'; + ELSE + start_autoboot <= '0'; + END IF; + END IF; + END PROCESS; + + --------------------------------------------------------------------------- + -- VITAL Timing Checks Procedures + --------------------------------------------------------------------------- + VITALTimingCheck: PROCESS(SIIn, SOIn, SCK_ipd, CSNeg_ipd, RSTNeg_ipd, + HOLDNegIn, WPNegIn) + + -- Timing Check Variables + -- Setup/Hold Checks variables + VARIABLE Tviol_CSNeg_SCK_normal : X01 := '0'; + VARIABLE TD_CSNeg_SCK_normal : VitalTimingDataType; + + VARIABLE Tviol_CSNeg_SCK_DDR : X01 := '0'; + VARIABLE TD_CSNeg_SCK_DDR : VitalTimingDataType; + + VARIABLE Tviol_CSNeg_RSTNeg : X01 := '0'; + VARIABLE TD_CSNeg_RSTNeg : VitalTimingDataType; + + VARIABLE Tviol_SI_SCK : X01 := '0'; + VARIABLE TD_SI_SCK : VitalTimingDataType; + + VARIABLE Tviol_WPNeg_CSNeg_setup : X01 := '0'; + VARIABLE TD_WPNeg_CSNeg_setup : VitalTimingDataType; + + VARIABLE Tviol_WPNeg_CSNeg_hold : X01 := '0'; + VARIABLE TD_WPNeg_CSNeg_hold : VitalTimingDataType; + + VARIABLE Tviol_HOLDNeg_SCK : X01 := '0'; + VARIABLE TD_HOLDNeg_SCK : VitalTimingDataType; + + VARIABLE Tviol_SI_SCK_DDR_R : X01 := '0'; + VARIABLE TD_SI_SCK_DDR_R : VitalTimingDataType; + + VARIABLE Tviol_SI_SCK_DDR_F : X01 := '0'; + VARIABLE TD_SI_SCK_DDR_F : VitalTimingDataType; + + VARIABLE Tviol_RSTNeg_CSNeg : X01 := '0'; + VARIABLE TD_RSTNeg_CSNeg : VitalTimingDataType; + + --Pulse Width and Period Check Variables + VARIABLE Pviol_SCK_serial : X01 := '0'; + VARIABLE PD_SCK_serial : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_dual : X01 := '0'; + VARIABLE PD_SCK_dual : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_fast : X01 := '0'; + VARIABLE PD_SCK_fast : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_quadpg : X01 := '0'; + VARIABLE PD_SCK_quadpg : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_DDR : X01 := '0'; + VARIABLE PD_SCK_DDR : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_CSNeg_read : X01 := '0'; + VARIABLE PD_CSNeg_read : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_CSNeg_pgers : X01 := '0'; + VARIABLE PD_CSNeg_pgers : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_RSTNeg : X01 := '0'; + VARIABLE PD_RSTNeg : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_serial_rd : X01 := '0'; + VARIABLE PD_SCK_serial_rd : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_fast_rd : X01 := '0'; + VARIABLE PD_SCK_fast_rd : VitalPeriodDataType:=VitalPeriodDataInit; + + VARIABLE Pviol_SCK_dual_rd : X01 := '0'; + VARIABLE PD_SCK_dual_rd : VitalPeriodDataType:=VitalPeriodDataInit; + + VARIABLE Pviol_SCK_DDR_rd : X01 := '0'; + VARIABLE PD_SCK_DDR_rd : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Pviol_SCK_quad_pg : X01 := '0'; + VARIABLE PD_SCK_quad_pg : VitalPeriodDataType:= VitalPeriodDataInit; + + VARIABLE Violation : X01 := '0'; + + BEGIN + --------------------------------------------------------------------------- + -- Timing Check Section + --------------------------------------------------------------------------- + IF (TimingChecksOn) THEN + + -- Setup/Hold Check between CS# and SCK + VitalSetupHoldCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_CSNeg_SCK_normal_noedge_posedge, + SetupLow => tsetup_CSNeg_SCK_normal_noedge_posedge, + HoldHigh => thold_CSNeg_SCK_normal_noedge_posedge, + HoldLow => thold_CSNeg_SCK_normal_noedge_posedge, + CheckEnabled => ddr = false, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_CSNeg_SCK_normal, + Violation => Tviol_CSNeg_SCK_normal + ); + + -- Setup/Hold Check between CS# and SCK + VitalSetupHoldCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_CSNeg_SCK_DDR_noedge_posedge, + SetupLow => tsetup_CSNeg_SCK_DDR_noedge_posedge, + HoldHigh => thold_CSNeg_SCK_DDR_noedge_posedge, + HoldLow => thold_CSNeg_SCK_DDR_noedge_posedge, + CheckEnabled => ddr, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_CSNeg_SCK_DDR, + Violation => Tviol_CSNeg_SCK_DDR + ); + + -- Hold Check between CSNeg and RSTNeg + VitalSetupHoldCheck ( + TestSignal => CSNeg, + TestSignalName => "CSNeg", + RefSignal => RSTNeg, + RefSignalName => "RSTNeg", + HoldHigh => thold_CSNeg_RSTNeg, + CheckEnabled => TRUE, + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_CSNeg_RSTNeg, + Violation => Tviol_CSNeg_RSTNeg + ); + + -- Setup/Hold Check between SI and SCK, serial mode + VitalSetupHoldCheck ( + TestSignal => SIIn, + TestSignalName => "SI", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_normal_noedge_posedge, + SetupLow => tsetup_SI_SCK_normal_noedge_posedge, + HoldHigh => thold_SI_SCK_normal_noedge_posedge, + HoldLow => thold_SI_SCK_normal_noedge_posedge, + CheckEnabled => NOT(DOUBLE) AND SIOut_z /= SIIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_SI_SCK, + Violation => Tviol_SI_SCK + ); + + -- Setup Check between WP# and CS# \ + VitalSetupHoldCheck ( + TestSignal => WPNegIn, + TestSignalName => "WP#", + RefSignal => CSNeg_ipd, + RefSignalName => "CS#", + SetupHigh => tsetup_WPNeg_CSNeg, + CheckEnabled => true, + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WPNeg_CSNeg_setup, + Violation => Tviol_WPNeg_CSNeg_setup + ); + + -- Hold Check between WP# and CS# / + VitalSetupHoldCheck ( + TestSignal => WPNegIn, + TestSignalName => "WP#", + RefSignal => CSNeg_ipd, + RefSignalName => "CS#", + HoldHigh => thold_WPNeg_CSNeg, + CheckEnabled => SRWD = '1' AND WEL = '1', + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WPNeg_CSNeg_hold, + Violation => Tviol_WPNeg_CSNeg_hold + ); + + -- Setup/Hold Check between HOLD# and SCK / + VitalSetupHoldCheck ( + TestSignal => HOLDNegIn, + TestSignalName => "HOLD#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupLow => tsetup_HOLDNeg_SCK, + SetupHigh => tsetup_HOLDNeg_SCK, + HoldLow => thold_HOLDNeg_SCK, + HoldHigh => thold_HOLDNeg_SCK, + CheckEnabled => QUAD = '0' + AND HOLDNegOut_zd /= HOLDNegIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_HOLDNeg_SCK, + Violation => Tviol_HOLDNeg_SCK + ); + + -- Setup/Hold Check between SI and SCK, DDR mode + VitalSetupHoldCheck ( + TestSignal => SIIn, + TestSignalName => "SI", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_DDR_noedge_posedge, + SetupLow => tsetup_SI_SCK_DDR_noedge_posedge, + HoldHigh => thold_SI_SCK_DDR_noedge_posedge, + HoldLow => thold_SI_SCK_DDR_noedge_posedge, + CheckEnabled => DOUBLE AND dual = false + AND SIOut_z /= SIIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_SI_SCK_DDR_R, + Violation => Tviol_SI_SCK_DDR_R + ); + + -- Setup/Hold Check between SI and SCK, DDR mode + VitalSetupHoldCheck ( + TestSignal => SIIn, + TestSignalName => "SI", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK_DDR_noedge_negedge, + SetupLow => tsetup_SI_SCK_DDR_noedge_negedge, + HoldHigh => thold_SI_SCK_DDR_noedge_negedge, + HoldLow => thold_SI_SCK_DDR_noedge_negedge, + CheckEnabled => ddr AND dual = false + AND SIOut_z /= SIIn, + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_SI_SCK_DDR_F, + Violation => Tviol_SI_SCK_DDR_F + ); + + -- Setup Check between RSTNeg and SCK, DDR fast mode + VitalSetupHoldCheck ( + TestSignal => RSTNeg, + TestSignalName => "RSTNeg", + RefSignal => CSNeg, + RefSignalName => "CSNeg", + SetupHigh => tsetup_RSTNeg_CSNeg, + CheckEnabled => TRUE, + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_RSTNeg_CSNeg, + Violation => Tviol_RSTNeg_CSNeg + ); + + --Pulse Width and Period Check Variables + -- Pulse Width Check SCK for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_serial_negedge, + PulseWidthHigh => tpw_SCK_serial_posedge, + PeriodData => PD_SCK_serial, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_serial, + HeaderMsg => InstancePath & PartID, + CheckEnabled => rd); + + -- Pulse Width Check SCK for DUAL_READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_dual_negedge, + PulseWidthHigh => tpw_SCK_dual_posedge, + PeriodData => PD_SCK_dual, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_dual, + HeaderMsg => InstancePath & PartID, + CheckEnabled => dual); + + -- Pulse Width Check SCK for FAST_READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_fast_negedge, + PulseWidthHigh => tpw_SCK_fast_posedge, + PeriodData => PD_SCK_fast, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_fast, + HeaderMsg => InstancePath & PartID, + CheckEnabled => fast_rd ); + + -- Pulse Width Check SCK for QPP + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_quadpg_negedge, + PulseWidthHigh => tpw_SCK_quadpg_posedge, + PeriodData => PD_SCK_quadpg, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_quadpg, + HeaderMsg => InstancePath & PartID, + CheckEnabled => quadpg); + + -- Pulse Width Check CS# for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + PulseWidthHigh => tpw_CSNeg_read_posedge, + PeriodData => PD_CSNeg_read, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_CSNeg_read, + HeaderMsg => InstancePath & PartID, + CheckEnabled => any_read ); + + -- Pulse Width Check CS# for Program/Erase, serial mode + VitalPeriodPulseCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + PulseWidthHigh => tpw_CSNeg_pgers_posedge, + PeriodData => PD_CSNeg_pgers, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_CSNeg_pgers, + HeaderMsg => InstancePath & PartID, + CheckEnabled => NOT(any_read)); + + -- Pulse Width Check RSTNeg + VitalPeriodPulseCheck ( + TestSignal => RSTNeg_ipd, + TestSignalName => "RSTNeg", + PulseWidthLow => tpw_RSTNeg_negedge, + PulseWidthHigh => tpw_RSTNeg_posedge, + CheckEnabled => TRUE, + HeaderMsg => InstancePath & PartID, + PeriodData => PD_RSTNeg, + Violation => Pviol_RSTNeg + ); + + -- Pulse Width Check SCK for DDR READ + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_DDR_negedge, + PulseWidthHigh => tpw_SCK_DDR_posedge, + PeriodData => PD_SCK_DDR, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_DDR, + HeaderMsg => InstancePath & PartID, + CheckEnabled => ddr); + + -- Period Check SCK for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_serial_rd, + PeriodData => PD_SCK_serial_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_serial_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => rd ); + + -- Period Check SCK for FAST READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_fast_rd, + PeriodData => PD_SCK_fast_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_fast_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => fast_rd ); + + -- Period Check SCK for DUAL READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_dual_rd, + PeriodData => PD_SCK_dual_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_dual_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => dual ); + + -- Period Check SCK for QPP + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_quadpg, + PeriodData => PD_SCK_quad_pg, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_quad_pg, + HeaderMsg => InstancePath & PartID, + CheckEnabled => quadpg ); + + -- Period Check SCK for DDR READ + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_DDR_rd, + PeriodData => PD_SCK_DDR_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_DDR_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => ddr ); + + Violation := Tviol_CSNeg_SCK_normal OR + Tviol_CSNeg_SCK_DDR OR + Tviol_CSNeg_RSTNeg OR + Tviol_SI_SCK OR + Tviol_WPNeg_CSNeg_setup OR + Tviol_WPNeg_CSNeg_hold OR + Tviol_HOLDNeg_SCK OR + Tviol_SI_SCK_DDR_R OR + Tviol_SI_SCK_DDR_F OR + Tviol_RSTNeg_CSNeg OR + Pviol_SCK_serial OR + Pviol_SCK_dual OR + Pviol_SCK_fast OR + Pviol_SCK_quadpg OR + Pviol_CSNeg_read OR + Pviol_CSNeg_pgers OR + Pviol_SCK_DDR OR + Pviol_SCK_serial_rd OR + Pviol_SCK_fast_rd OR + Pviol_SCK_dual_rd OR + Pviol_SCK_quad_pg OR + Pviol_SCK_DDR_rd; + + Viol <= Violation; + + ASSERT Violation = '0' + REPORT InstancePath & partID & ": simulation may be" & + " inaccurate due to timing violations" + SEVERITY WARNING; + + END IF; + END PROCESS VITALTimingCheck; + + ---------------------------------------------------------------------------- + -- sequential process for FSM state transition + ---------------------------------------------------------------------------- + StateTransition : PROCESS(next_state, RST, PoweredUp, RST_out) + + BEGIN + IF PoweredUp = '1' THEN + IF RSTNeg_pullup = '1' and RST_out= '1' THEN + IF next_state'EVENT THEN + current_state <= next_state; + END IF; + ELSIF RSTNeg_pullup = '0' AND falling_edge(RST) THEN + --no state transition while RESET# low + current_state <= RESET_STATE; + RST_in <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END PROCESS StateTransition; + + Threset : PROCESS(RST_in) + BEGIN + IF rising_edge(RST_in) THEN + RST_out <= '0', '1' AFTER (thold_CSNeg_RSTNeg-200 ns); + END IF; + END PROCESS Threset; + + --------------------------------------------------------------------------- + -- Write cycle decode + --------------------------------------------------------------------------- + + BusCycleDecode : PROCESS(SCK_ipd, CSNeg_ipd, HOLDNeg_pullup, SIIn, RST_out, + WPNeg_pullup) + + TYPE quad_data_type IS ARRAY (0 TO 1023) OF INTEGER RANGE 0 TO 15; + + VARIABLE bit_cnt : NATURAL := 0; + VARIABLE Data_in : std_logic_vector(4095 downto 0) + := (others => '0'); + + VARIABLE opcode : std_logic_vector(7 downto 0); + VARIABLE opcode_in : std_logic_vector(7 downto 0); + VARIABLE addr_bytes : std_logic_vector(31 downto 0); + VARIABLE hiaddr_bytes : std_logic_vector(31 downto 0); + VARIABLE Address_in : std_logic_vector(31 downto 0); + VARIABLE mode_bytes : std_logic_vector(7 downto 0); + VARIABLE mode_in : std_logic_vector(7 downto 0); + VARIABLE quad_data_in : quad_data_type; + VARIABLE quad_nybble : std_logic_vector(3 downto 0); + VARIABLE Quad_slv : std_logic_vector(3 downto 0); + VARIABLE Byte_slv : std_logic_vector(7 downto 0); + + VARIABLE CLK_PER : time; + VARIABLE LAST_CLK : time; + VARIABLE Check_freq : boolean := FALSE; + + BEGIN + + IF rising_edge(CSNeg_ipd) AND NOT(bus_cycle_state = DATA_BYTES) + AND NOT(bus_cycle_state = DUMMY_BYTES) THEN + bus_cycle_state := STAND_BY; + ELSE + CASE bus_cycle_state IS + WHEN STAND_BY => + IF falling_edge(CSNeg_ipd) THEN + Instruct <= NONE; + write <= '1'; + cfg_write <= '0'; + opcode_cnt:= 0; + addr_cnt := 0; + mode_cnt := 0; + dummy_cnt := 0; + dummy_cnt_act_temp <= dummy_cnt; + data_cnt := 0; + DOUBLE := FALSE; + CLK_PER := 0 ns; + LAST_CLK := 0 ns; + IF current_state = AUTOBOOT THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := OPCODE_BYTE; + END IF; + END IF; + + WHEN OPCODE_BYTE => + IF rising_edge(SCK_ipd) THEN + + Latency_code := to_nat(LC1 & LC0); + CLK_PER := NOW - LAST_CLK; + LAST_CLK := NOW; + IF Check_freq THEN + IF (CLK_PER < 20 ns AND Latency_code = 3) OR + (CLK_PER < 12.5 ns AND Latency_code = 0) OR + (CLK_PER < 11.1 ns AND Latency_code = 1) OR + (CLK_PER < 9.6 ns AND Latency_code = 2) THEN + ASSERT FALSE + REPORT "More wait states are required for " & + "this clock frequency value" + SEVERITY warning; + END IF; + END IF; + Check_freq := FALSE; + + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1') THEN + --One-byte of instruction opcode is shifted into the + --device on the SI serial input pin with the most + --significant bit (MSB) first.Each bit input on the + --SI serial input pin is latched on the rising edge of + --the SCK serial clock signal. + opcode_in(opcode_cnt) := SIIn; + opcode_cnt := opcode_cnt + 1; + IF opcode_cnt = BYTE THEN + --MSB first + FOR I IN 7 DOWNTO 0 LOOP + opcode(i) := opcode_in(7-i); + END LOOP; + + CASE opcode IS + WHEN "00000110" => --06h + Instruct <= WREN; + bus_cycle_state := DATA_BYTES; + WHEN "00000100" => --04h + Instruct <= WRDI; + bus_cycle_state := DATA_BYTES; + WHEN "00000001" => --01h + Instruct <= WRR; + bus_cycle_state := DATA_BYTES; + WHEN "00000011" => --03h + Instruct <= READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00010011" => --13h + Instruct <= RD4; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01001011" => --4Bh + Instruct <= OTPR; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00000101" => --05h + Instruct <= RDSR; + bus_cycle_state := DATA_BYTES; + WHEN "00000111" => --07h + Instruct <= RDSR2; + bus_cycle_state := DATA_BYTES; + WHEN "00110101" => --35h + Instruct <= RDCR; + bus_cycle_state := DATA_BYTES; + WHEN "10010000" => --90h + Instruct <= REMS; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10011111" => --9Fh + Instruct <= RDID; + bus_cycle_state := DATA_BYTES; + WHEN "10101011" => --ABh + Instruct <= RES; + bus_cycle_state := DUMMY_BYTES; + WHEN "00001011" => --0Bh + Instruct <= FSTRD; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00001100" => --0Ch + Instruct <= FSTRD4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00001101" => --0Dh + Instruct <= DDRFR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00001110" => --0Eh + Instruct <= DDRFR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00111011" => --3Bh + Instruct <= DOR; + Check_freq := TRUE; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00111100" => --3Ch + Instruct <= DOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "10111011" => --BBh + Instruct <= DIOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "10111100" => --BCh + Instruct <= DIOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "10111101" => --BDh + Instruct <= DDRDIOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "10111110" => --BEh + Instruct <= DDRDIOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "01101011" => --6Bh + Instruct <= QOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "01101100" => --6Ch + Instruct <= QOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "11101011" => --EBh + Instruct <= QIOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "11101100" => --ECh + Instruct <= QIOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "11101101" => --EDh + Instruct <= DDRQIOR; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "11101110" => --EEh + Instruct <= DDRQIOR4; + bus_cycle_state := ADDRESS_BYTES; + Check_freq := TRUE; + WHEN "00000010" => --02h + Instruct <= PP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00010010" => --12h + Instruct <= PP4; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00110010" => --32h + Instruct <= QPP; + bus_cycle_state := ADDRESS_BYTES; + quadpg <= TRUE; + WHEN "00111000" => --38h + Instruct <= QPP; + bus_cycle_state := ADDRESS_BYTES; + quadpg <= TRUE; + WHEN "00110100" => --34h + Instruct <= QPP4; + bus_cycle_state := ADDRESS_BYTES; + quadpg <= TRUE; + WHEN "01000010" => --42h + Instruct <= OTPP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10000101" => --85h + Instruct <= PGSP; + bus_cycle_state := DATA_BYTES; + WHEN "10001010" => --8Ah + Instruct <= PGRS; + bus_cycle_state := DATA_BYTES; + WHEN "11000111" => --C7h + Instruct <= BE; + bus_cycle_state := DATA_BYTES; + WHEN "01100000" => --60h + Instruct <= BE; + bus_cycle_state := DATA_BYTES; + WHEN "11011000" => --D8h + Instruct <= SE; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11011100" => --DCh + Instruct <= SE4; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00100000" => --20h + Instruct <= P4E; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00100001" => --21h + Instruct <= P4E4; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01110101" => --75h + Instruct <= ERSP; + bus_cycle_state := DATA_BYTES; + WHEN "01111010" => --7Ah + Instruct <= ERRS; + bus_cycle_state := DATA_BYTES; + WHEN "00010100" => --14h + Instruct <= ABRD; + bus_cycle_state := DATA_BYTES; + WHEN "00010101" => --15h + Instruct <= ABWR; + bus_cycle_state := DATA_BYTES; + WHEN "00010110" => --16h + Instruct <= BRRD; + bus_cycle_state := DATA_BYTES; + WHEN "00010111" => --17h + Instruct <= BRWR; + bus_cycle_state := DATA_BYTES; + WHEN "10111001" => --B9h + Instruct <= BRAC; + bus_cycle_state := DATA_BYTES; + WHEN "00101011" => --2Bh + Instruct <= ASPRD; + bus_cycle_state := DATA_BYTES; + WHEN "00101111" => --2Fh + Instruct <= ASPP; + bus_cycle_state := DATA_BYTES; + WHEN "11100000" => --E0h + Instruct <= DYBRD; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11100001" => --E1h + Instruct <= DYBWR; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11100010" => --E2h + Instruct <= PPBRD; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11100011" => --E3h + Instruct <= PPBP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11100100" => --E4h + Instruct <= PPBERS; + bus_cycle_state := DATA_BYTES; + WHEN "10100110" => --A6h + Instruct <= PLBWR; + bus_cycle_state := DATA_BYTES; + WHEN "10100111" => --A7h + Instruct <= PLBRD; + bus_cycle_state := DATA_BYTES; + WHEN "11100111" => --E7h + Instruct <= PASSRD; + bus_cycle_state := DATA_BYTES; + WHEN "11101000" => --E8h + Instruct <= PASSP; + bus_cycle_state := DATA_BYTES; + WHEN "11101001" => --E9h + Instruct <= PASSU; + bus_cycle_state := DATA_BYTES; + WHEN "11110000" => --F0h + Instruct <= RESET; + bus_cycle_state := DATA_BYTES; + WHEN "11111111" => --FFh + Instruct <= MBR; + bus_cycle_state := MODE_BYTE; + WHEN "01000001" => -- 41h + Instruct <= DLPRD; + bus_cycle_state := DATA_BYTES; + WHEN "01000011" => -- 43h + Instruct <= PNVDLR; + bus_cycle_state := DATA_BYTES; + WHEN "01001010" => -- 4Ah + Instruct <= WVDLR; + bus_cycle_state := DATA_BYTES; + WHEN "00110000" => --30h + Instruct <= CLSR; + bus_cycle_state := DATA_BYTES; + WHEN others => + null; + + END CASE; + END IF; + END IF; + END IF; + + WHEN ADDRESS_BYTES => + IF Instruct= DDRFR OR Instruct= DDRFR4 OR Instruct= DDRDIOR + OR Instruct = DDRDIOR4 OR Instruct = DDRQIOR OR + Instruct = DDRQIOR4 THEN + DOUBLE := TRUE; + ELSE + DOUBLE := FALSE; + END IF; + + IF (rising_edge(SCK_ipd) AND NOT(DOUBLE) AND + (CSNeg_ipd= '0')) THEN + IF (((Instruct=FSTRD AND EXTADD= '0' ) + OR (Instruct=DOR AND EXTADD= '0') + OR Instruct=OTPR) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) + OR (Instruct=QOR AND QUAD= '1' AND EXTADD='0') THEN + --Instruction + 3 Bytes Address + Dummy Byte + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 3*BYTE THEN + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 26) := "000000"; + addr_bytes(25 downto 24) := + Bank_Addr_reg (1 downto 0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF (Instruct=FSTRD OR Instruct=DOR OR + Instruct=QOR) THEN + IF (Latency_code = 3) THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF ((((Instruct=FSTRD4) OR (Instruct=DOR4) OR + ((Instruct=FSTRD) AND EXTADD= '1') OR + ((Instruct=DOR) AND EXTADD= '1')) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) OR + ((Instruct=QOR4) AND QUAD='1') OR + ((Instruct=QOR) AND QUAD='1' AND EXTADD='1')) THEN + --Instruction + 4 Bytes Address + Dummy Byte + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 4*BYTE THEN + FOR I IN 31 DOWNTO 0 LOOP + hiaddr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(hiaddr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF Latency_code = 3 THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := DUMMY_BYTES; + IF (DOUBLE AND NOT(hold_mode) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + ELSIF Instruct = DIOR AND EXTADD= '0' AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1') THEN + -- DUAL I/O High Performance Read (3Bytes Address) + IF SOIn /= 'Z' THEN + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt+1) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = (3*BYTE) / 2 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 26) := "000000"; + addr_bytes(25 downto 24) := + Bank_Addr_reg (1 downto 0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSE + bus_cycle_state := STAND_BY; + END IF; + ELSIF ((Instruct = DIOR4 OR + (Instruct = DIOR AND EXTADD= '1')) AND + ((HOLDNeg_pullup = '1' AND QUAD = '0') OR + QUAD = '1')) THEN + -- DUAL I/O High Performance Read (4Bytes Address) + IF SOIn /= 'Z' THEN + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt+1) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = (4*BYTE) / 2 THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + hiaddr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(hiaddr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSE + bus_cycle_state := STAND_BY; + END IF; + ELSIF (Instruct = QIOR AND EXTADD= '0') THEN + -- QUAD I/O High Performance Read (3Bytes Address) + IF QUAD = '1' THEN + IF SOIn /= 'Z' THEN + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = (3*BYTE) / 4 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 26) := "000000"; + addr_bytes(25 downto 24) := + Bank_Addr_reg (1 downto 0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + END IF; + ELSE + bus_cycle_state := STAND_BY; + END IF; + ELSIF (Instruct = QIOR4 OR + (Instruct = QIOR AND EXTADD= '1')) THEN + -- QUAD I/O High Performance Read (4Bytes Address) + IF QUAD = '1' THEN + IF SOIn /= 'Z' THEN + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = (4*BYTE) / 4 THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + hiaddr_bytes(31-i) + := Address_in(i); + END LOOP; + Address <= to_nat(hiaddr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + END IF; + ELSE + bus_cycle_state := STAND_BY; + END IF; + ELSIF (((Instruct = RD4 OR Instruct = PP4 OR + Instruct = SE4 OR Instruct = PPBRD OR + Instruct = DYBRD OR Instruct = DYBWR OR + Instruct = PPBP OR Instruct = P4E4 OR + (Instruct = READ AND EXTADD= '1' ) OR + (Instruct = PP AND EXTADD= '1' ) OR + (Instruct = P4E AND EXTADD= '1' ) OR + (Instruct = SE AND EXTADD= '1' )) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) + OR (QUAD ='1' AND (Instruct=QPP4 OR + (Instruct = QPP AND EXTADD= '1' ))))THEN + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 4*BYTE THEN + FOR I IN 31 DOWNTO 0 LOOP + hiaddr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(hiaddr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (((HOLDNeg_pullup='1' AND QUAD='0') + OR QUAD='1') AND EXTADD= '0') THEN + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 3*BYTE THEN + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 26) := "000000"; + addr_bytes(25 downto 24) := + Bank_Addr_reg (1 downto 0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF (SCK_ipd'EVENT AND DOUBLE AND addr_cnt /= 0 ) OR + (rising_edge(SCK_ipd) AND DOUBLE AND addr_cnt = 0 ) THEN + IF (Instruct=DDRFR AND EXTADD= '0' ) THEN + --Fast DDR Read Mode + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = 3*BYTE THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 26) := "000000"; + addr_bytes(25 downto 24) := + Bank_Addr_reg (1 downto 0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF (Instruct=DDRFR4 OR + (Instruct=DDRFR AND EXTADD= '1' )) THEN + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = 4*BYTE THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + addr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + ELSIF (Instruct= DDRDIOR AND EXTADD= '0' ) THEN + --Dual I/O DDR Read Mode + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt+1):= SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = (3*BYTE)/2 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 26) := "000000"; + addr_bytes(25 downto 24) := + Bank_Addr_reg (1 downto 0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF (Instruct=DDRDIOR4 OR + (Instruct=DDRDIOR AND EXTADD= '1' )) THEN + --Dual I/O DDR Read Mode + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt+1) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = (4*BYTE)/2 THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + addr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + IF EHP THEN + bus_cycle_state := MODE_BYTE; + ELSE + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + ELSIF (Instruct=DDRQIOR AND EXTADD= '0' ) AND + QUAD = '1' THEN + --Quad I/O DDR Read Mode + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = (3*BYTE)/4 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 0 LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + addr_bytes(31 downto 26) := "000000"; + addr_bytes(25 downto 24) := + Bank_Addr_reg (1 downto 0); + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 5 ns; + bus_cycle_state := MODE_BYTE; + END IF; + ELSIF QUAD = '1' AND (Instruct=DDRQIOR4 OR + (Instruct=DDRQIOR AND EXTADD= '1' )) THEN + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + addr_cnt := addr_cnt + 1; + read_cnt := 0; + IF addr_cnt = (4*BYTE)/4 THEN + addr_cnt := 0; + FOR I IN 31 DOWNTO 0 LOOP + addr_bytes(31-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + END IF; + END IF; + + WHEN MODE_BYTE => + IF rising_edge(SCK_ipd) THEN + IF ((Instruct=DIOR OR Instruct = DIOR4) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) THEN + mode_in(2*mode_cnt) := SOIn; + mode_in(2*mode_cnt+1) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/2 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + IF Latency_code = 0 OR Latency_code = 3 THEN + bus_cycle_state := DATA_BYTES; + ELSE + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + ELSIF (Instruct=QIOR OR Instruct = QIOR4) + AND QUAD = '1' THEN + mode_in(4*mode_cnt) := HOLDNegIn; + mode_in(4*mode_cnt+1) := WPNegIn; + mode_in(4*mode_cnt+2) := SOIn; + mode_in(4*mode_cnt+3) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/4 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DUMMY_BYTES; + END IF; + ELSIF Instruct=DDRFR OR Instruct = DDRFR4 THEN + mode_in(2*mode_cnt) := SIIn; + ELSIF Instruct=DDRDIOR OR Instruct = DDRDIOR4 THEN + mode_in(4*mode_cnt) := SOIn; + mode_in(4*mode_cnt+1) := SIIn; + ELSIF (Instruct=DDRQIOR OR Instruct = DDRQIOR4) + AND QUAD = '1' THEN + mode_in(0) := HOLDNegIn; + mode_in(1) := WPNegIn; + mode_in(2) := SOIn; + mode_in(3) := SIIn; + END IF; + dummy_cnt := 0; + dummy_cnt_act_temp <= dummy_cnt; + ELSIF falling_edge(SCK_ipd) THEN + IF Instruct=DDRFR OR Instruct = DDRFR4 THEN + mode_in(2*mode_cnt+1) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/2 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + ELSIF Instruct=DDRDIOR OR Instruct = DDRDIOR4 THEN + mode_in(4*mode_cnt+2) := SOIn; + mode_in(4*mode_cnt+3) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/4 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + ELSIF (Instruct=DDRQIOR OR Instruct = DDRQIOR4) + AND QUAD = '1' THEN + mode_in(4) := HOLDNegIn; + mode_in(5) := WPNegIn; + mode_in(6) := SOIn; + mode_in(7) := SIIn; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DUMMY_BYTES; + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + + WHEN DUMMY_BYTES => + IF rising_edge(SCK_ipd) THEN + IF ((DOUBLE AND NOT(hold_mode)) AND + VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + IF (((Instruct=FSTRD OR Instruct=FSTRD4 OR + Instruct=DOR OR Instruct=DOR4 OR + Instruct=OTPR) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) OR + ((Instruct = QOR OR Instruct = QOR4) AND + QUAD = '1'))THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF dummy_cnt = BYTE THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct=DDRFR OR Instruct=DDRFR4) THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF EHP THEN + IF ((Latency_code = 3 AND dummy_cnt=1) OR + (Latency_code = 0 AND dummy_cnt=2) OR + (Latency_code = 1 AND dummy_cnt=4) OR + (Latency_code = 2 AND dummy_cnt=5)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + ELSE + IF ((Latency_code = 3 AND dummy_cnt = 4) OR + (Latency_code = 0 AND dummy_cnt = 5) OR + (Latency_code = 1 AND dummy_cnt = 6) OR + (Latency_code = 2 AND dummy_cnt = 7)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF Instruct=RES THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF dummy_cnt = 3*BYTE THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct = DIOR OR Instruct = DIOR4) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1') THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF EHP THEN + IF ((Latency_code = 1 AND dummy_cnt = 1) OR + (Latency_code = 2 AND dummy_cnt = 2)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + ELSE + IF ((Latency_code = 3 AND dummy_cnt = 4) OR + (Latency_code = 0 AND dummy_cnt = 4) OR + (Latency_code = 1 AND dummy_cnt = 5) OR + (Latency_code = 2 AND dummy_cnt = 6)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF EHP THEN + IF ((Latency_code = 3 AND dummy_cnt = 2) OR + (Latency_code = 0 AND dummy_cnt = 4) OR + (Latency_code = 1 AND dummy_cnt = 5) OR + (Latency_code = 2 AND dummy_cnt = 6)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + ELSE + IF ((Latency_code = 3 AND dummy_cnt = 4) OR + (Latency_code = 0 AND dummy_cnt = 6) OR + (Latency_code = 1 AND dummy_cnt = 7) OR + (Latency_code = 2 AND dummy_cnt = 8)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF ((Instruct = QIOR OR Instruct = QIOR4) AND + QUAD = '1') THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF ((Latency_code = 3 AND dummy_cnt = 1) OR + (Latency_code = 0 AND dummy_cnt = 4) OR + (Latency_code = 1 AND dummy_cnt = 4) OR + (Latency_code = 2 AND dummy_cnt = 5)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF (Instruct = DDRQIOR OR Instruct = DDRQIOR4) + AND QUAD = '1' THEN + dummy_cnt := dummy_cnt + 1; + dummy_cnt_act_temp <= dummy_cnt; + IF ((Latency_code = 3 AND dummy_cnt = 3) OR + (Latency_code = 0 AND dummy_cnt = 6) OR + (Latency_code = 1 AND dummy_cnt = 7) OR + (Latency_code = 2 AND dummy_cnt = 8)) THEN + DummyBytes_act := '1'; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + ELSIF falling_edge(SCK_ipd) THEN + IF NOT(hold_mode) THEN + IF (DOUBLE AND VDLR_reg /= "00000000") THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + END IF; + + WHEN DATA_BYTES => + IF rising_edge(CSNeg_ipd) THEN + IF ((mode_bytes(7 downto 4) = "1010" AND + (Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QIOR OR Instruct = QIOR4)) OR + ((mode_bytes(7 downto 4) = + NOT(mode_bytes(3 downto 0))) AND + (Instruct = DDRFR OR Instruct = DDRFR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 OR + Instruct = DDRQIOR OR Instruct = DDRQIOR4))) THEN + bus_cycle_state := ADDRESS_BYTES; + ELSE + bus_cycle_state := STAND_BY; + END IF; + END IF; + IF falling_edge(SCK_ipd) AND CSNeg_ipd = '0' AND + NOT(DOUBLE) THEN + IF ((Instruct = READ OR Instruct=RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = RDSR OR Instruct = RDSR2 OR + Instruct = RDCR OR Instruct = OTPR OR + Instruct = DOR OR Instruct = DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = ABRD OR Instruct = BRRD OR + Instruct = ASPRD OR Instruct = DYBRD OR + Instruct = PPBRD OR + Instruct = PASSRD OR Instruct = RDID OR + Instruct = RES OR Instruct = REMS OR + Instruct = PLBRD OR Instruct = DLPRD) + AND ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD='1')) + OR (current_state = AUTOBOOT AND start_delay = 0)OR + ((Instruct=QOR OR Instruct=QIOR OR Instruct=QOR4 + OR Instruct= QIOR4) AND QUAD = '1') THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + ELSIF SCK_ipd'EVENT AND CSNeg_ipd = '0' AND DOUBLE THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + + IF rising_edge(SCK_ipd) THEN + IF QUAD = '1' AND (Instruct=QPP OR Instruct = QPP4)THEN + quad_nybble := HOLDNegIn & WPNegIn & SOIn & SIIn; + IF data_cnt > (PageSize*2-1) THEN + --In case of quad mode and QPP, + --if more than 512 bytes are sent to the device + FOR I IN 0 TO (PageSize*2-2) LOOP + quad_data_in(i) := quad_data_in(i+1); + END LOOP; + quad_data_in((PageSize*2-1)) := + to_nat(quad_nybble); + data_cnt := data_cnt +1; + ELSE + IF quad_nybble /= "ZZZZ" THEN + quad_data_in(data_cnt) := + to_nat(quad_nybble); + END IF; + data_cnt := data_cnt +1; + END IF; + ELSIF ((HOLDNeg_pullup='1' AND QUAD='0') + OR QUAD='1') THEN + IF data_cnt > (PageSize*8-1) THEN + --In case of serial mode and PP, + -- if more than 512 bytes are sent to the device + -- previously latched data are discarded and last + -- 512 data bytes are guaranteed to be programmed + -- correctly within the same page. + IF bit_cnt = 0 THEN + FOR I IN 0 TO ((PageSize-1)*BYTE - 1) LOOP + Data_in(i) := Data_in(i+8); + END LOOP; + END IF; + Data_in((PageSize-1)*BYTE + bit_cnt) := SIIn; + bit_cnt := bit_cnt + 1; + IF bit_cnt = 8 THEN + bit_cnt := 0; + END IF; + data_cnt := data_cnt + 1; + ELSE + Data_in(data_cnt) := SIIn; + data_cnt := data_cnt + 1; + bit_cnt := 0; + END IF; + END IF; + END IF; + + IF rising_edge(CSNeg_ipd) THEN + CASE Instruct IS + WHEN WREN | WRDI | BE | SE | SE4 | CLSR | RESET | + PPBP | PPBERS | PGSP | PGRS | ERSP | BRAC | + ERRS | P4E | P4E4 | PLBWR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') + OR QUAD='1') THEN + IF data_cnt = 0 THEN + write <= '0'; + END IF; + END IF; + + WHEN WRR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') + OR QUAD='1') THEN + IF ((data_cnt mod 8) = 0 AND data_cnt > 0) THEN + IF data_cnt = 8 THEN + --If CS# is driven high after eight + --cycle,only the Status Register is + --written to. + write <= '0'; + IF BAR_ACC = '0' THEN + FOR i IN 0 TO 7 LOOP + Status_reg1_in(i) <= + Data_in(7-i); + END LOOP; + ELSIF P_ERR = '0' AND E_ERR = '0' THEN + FOR i IN 0 TO 7 LOOP + Bank_Addr_reg_in(i) <= + Data_in(7-i); + END LOOP; + END IF; + ELSIF data_cnt = 16 THEN + --After the 16th cycle both the + --Status and Configuration Registers + --are written to. + write <= '0'; + IF BAR_ACC = '0' THEN + FOR i IN 0 TO 7 LOOP + cfg_write <= '1'; + FOR i IN 0 TO 7 LOOP + Status_reg1_in(i) <= + Data_in(7-i); + Config_reg1_in(i) <= + Data_in(15-i); + END LOOP; + END LOOP; + ELSIF P_ERR = '0' AND E_ERR = '0' THEN + FOR i IN 0 TO 7 LOOP + Bank_Addr_reg_in(i) <= + Data_in(7-i); + END LOOP; + END IF; + END IF; + END IF; + END IF; + + WHEN PP | PP4 | OTPP => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt > 0 THEN + IF (data_cnt mod 8) = 0 THEN + write <= '0'; + FOR I IN 0 TO (PageSize-1) LOOP + FOR J IN 7 DOWNTO 0 LOOP + IF Data_in((i*8) + (7-j)) + /= 'X' THEN + Byte_slv(j) := + Data_in((i*8) + (7-j)); + END IF; + END LOOP; + WByte(i) <= + to_nat(Byte_slv); + END LOOP; + IF data_cnt > PageSize*BYTE THEN + Byte_number <= PageSize-1; + ELSE + Byte_number <= data_cnt/8-1; + END IF; + END IF; + END IF; + END IF; + + WHEN QPP | QPP4=> + IF data_cnt > 0 THEN + IF data_cnt mod 2 = 0 THEN + quadpg <= FALSE; + write <= '0'; + FOR I IN 0 TO (PageSize-1) LOOP + FOR J IN 1 DOWNTO 0 LOOP + Quad_slv := + to_slv(quad_data_in((i*2) + + (1-j)),4); + + Byte_slv(4*j+3 DOWNTO 4*j) := + Quad_slv; + END LOOP; + WByte(i) <= to_nat(Byte_slv); + END LOOP; + IF data_cnt > PageSize*2 THEN + Byte_number <= PageSize-1; + ELSE + Byte_number <= data_cnt/2-1; + END IF; + END IF; + END IF; + + WHEN ABWR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 32 THEN + write <= '0'; + FOR J IN 0 TO 31 LOOP + AutoBoot_reg_in(J) <= + Data_in(31-J); + END LOOP; + END IF; + END IF; + + WHEN BRWR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 8 THEN + write <= '0'; + FOR J IN 0 TO 7 LOOP + Bank_Addr_reg_in(J) <= + Data_in(7-J); + END LOOP; + END IF; + END IF; + + WHEN ASPP => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 16 THEN + write <= '0'; + FOR J IN 0 TO 15 LOOP + ASP_reg_in(J) <= + Data_in(15-J); + END LOOP; + END IF; + END IF; + + WHEN DYBWR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 8 THEN + write <= '0'; + FOR J IN 0 TO 7 LOOP + DYBAR_in(J) <= + Data_in(7-J); + END LOOP; + END IF; + END IF; + + WHEN PNVDLR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 8 THEN + write <= '0'; + FOR J IN 0 TO 7 LOOP + NVDLR_reg_in(J) <= Data_in(7-J); + END LOOP; + END IF; + END IF; + + WHEN WVDLR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 8 THEN + write <= '0'; + FOR J IN 0 TO 7 LOOP + VDLR_reg_in(J) <= Data_in(7-J); + END LOOP; + END IF; + END IF; + + WHEN PASSP => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 64 THEN + write <= '0'; + FOR J IN 1 TO 8 LOOP + FOR K IN 1 TO 8 LOOP + Password_reg_in(J*8-K) <= + Data_in(8*(J-1)+K-1); + END LOOP; + END LOOP; + END IF; + END IF; + + WHEN PASSU => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD='1') THEN + IF data_cnt = 64 THEN + write <= '0'; + FOR J IN 1 TO 8 LOOP + FOR K IN 1 TO 8 LOOP + PASS_TEMP(J*8-K) <= + Data_in(8*(J-1)+K-1); + END LOOP; + END LOOP; + END IF; + END IF; + + WHEN others => + null; + + END CASE; + END IF; + END CASE; + END IF; + + END PROCESS BusCycleDecode; + + --------------------------------------------------------------------------- + -- Timing control for the Page Program + --------------------------------------------------------------------------- + ProgTime : PROCESS(PSTART, PGSUSP, PGRES, RST, Reseted) + VARIABLE pob : time; + VARIABLE elapsed : time; + VARIABLE start : time; + VARIABLE duration : time; + BEGIN + IF rising_edge(PSTART) AND PDONE = '1' THEN + IF Instruct = PP OR Instruct = PP4 OR Instruct = OTPP OR + Instruct = QPP OR Instruct = QPP4 THEN + pob := tdevice_PP; + ELSE + pob := tdevice_BP; + END IF; + elapsed := 0 ns; + start := NOW; + PDONE <= '0', '1' AFTER pob; + ELSIF PGSUSP'EVENT AND PGSUSP = '1' AND PDONE /= '1' THEN + elapsed := NOW - start; + duration := pob - elapsed; + PDONE <= '0'; + ELSIF PGRES'EVENT AND PGRES = '1' AND PDONE /= '1'THEN + start := NOW; + PDONE <= '0', '1' AFTER duration; + END IF; + + IF (RST'EVENT AND RST = '0') THEN + PDONE <= '1'; -- reset done, programing terminated + ELSIF rising_edge(Reseted) THEN + PDONE <= '1'; -- reset done, programing terminated + END IF; + + END PROCESS ProgTime; + + --------------------------------------------------------------------------- + -- Timing control for the Write Status Register + --------------------------------------------------------------------------- + WriteTime : PROCESS(WSTART) + VARIABLE wob : time; + BEGIN + IF LongTimming THEN + wob := tdevice_WRR; + ELSE + wob := tdevice_WRR / 100; + END IF; + IF rising_edge(WSTART) AND WDONE = '1' THEN + WDONE <= '0', '1' AFTER wob; + END IF; + + IF (RST'EVENT AND RST = '0') THEN + WDONE <= '1'; -- reset done, programing terminated + ELSIF rising_edge(Reseted) THEN + WDONE <= '1'; -- reset done, programing terminated + END IF; + + END PROCESS WriteTime; + + --------------------------------------------------------------------------- + -- Timing control for the Bulk Erase + --------------------------------------------------------------------------- + ErsTime : PROCESS(ESTART, ESUSP, ERES, RST, Reseted) + VARIABLE seo : time; + VARIABLE beo : time; + VARIABLE elapsed : time; + VARIABLE start : time; + VARIABLE duration : time; + BEGIN + IF LongTimming THEN + seo := tdevice_SE; + beo := tdevice_BE; + ELSE + seo := tdevice_SE / 1000; + beo := tdevice_BE / 1000; + END IF; + IF rising_edge(ESTART) AND EDONE = '1' THEN + IF Instruct = BE THEN + duration := beo; + ELSE --Instruct = SE OR SE4 + duration := seo; + END IF; + elapsed := 0 ns; + EDONE <= '0', '1' AFTER duration; + start := NOW; + ELSIF ESUSP'EVENT AND ESUSP = '1' AND EDONE /= '1' THEN + elapsed := NOW - start; + duration := duration - elapsed; + EDONE <= '0'; + ELSIF ERES'EVENT AND ERES = '1' AND EDONE /= '1' THEN + start := NOW; + EDONE <= '0', '1' AFTER duration; + END IF; + + IF (RST'EVENT AND RST = '0') THEN + EDONE <= '1'; -- reset done, eras terminated + ELSIF rising_edge(Reseted) THEN + EDONE <= '1'; -- reset done, erase terminated + END IF; + + END PROCESS ErsTime; + + CheckCEOnPowerUP :PROCESS(CSNeg_ipd) + BEGIN + IF (PoweredUp = '0' AND falling_edge(CSNeg_ipd)) THEN + REPORT InstancePath & partID & + ": Device is selected during Power Up" + SEVERITY WARNING; + END IF; + END PROCESS; + + --------------------------------------------------------------------------- + -- Main Behavior Process + -- combinational process for next state generation + --------------------------------------------------------------------------- + StateGen :PROCESS(PoweredUp, write, CSNeg_ipd, RSTNeg_pullup, WDONE, PDONE, + ERSSUSP_out, PRGSUSP_out, EDONE, RST_out, PPBERASE_in, + PASSULCK_in) + + VARIABLE sect : NATURAL RANGE 0 TO SecNum; + + BEGIN + + IF rising_edge(PoweredUp) THEN + IF ABE = '1' AND RPME /= '0' THEN + --Autoboot is enabled and The Read Password feature is not enabled + next_state <= AUTOBOOT; + read_cnt := 0; + byte_cnt := 1; + read_addr := to_nat(AutoBoot_reg(31 DOWNTO 9)&"000000000"); + start_delay := to_nat(AutoBoot_reg(8 DOWNTO 1)); + ABSD := to_nat(AutoBoot_reg(8 DOWNTO 1)); + ELSE + next_state <= IDLE; + END IF; + ELSE + IF RST_out= '0' then + next_state <= current_state; + ELSIF falling_edge(write) AND Instruct = RESET THEN + IF ABE = '1' AND RPME /= '0' THEN + read_cnt := 0; + byte_cnt := 1; + read_addr := to_nat(AutoBoot_reg(31 DOWNTO 9)& + "000000000"); + start_delay:= to_nat(AutoBoot_reg(8 DOWNTO 1)); + ABSD := to_nat(AutoBoot_reg(8 DOWNTO 1)); + next_state <= AUTOBOOT; + ELSE + next_state <= IDLE; + END IF; + ELSE + CASE current_state IS + WHEN RESET_STATE => + IF rising_edge(RST_out) THEN + IF ABE = '1' AND RPME /= '0' + AND RdPswdProtMode = '0' THEN + next_state <= AUTOBOOT; + read_cnt := 0; + byte_cnt := 1; + read_addr := to_nat(AutoBoot_reg(31 DOWNTO 9)& + "000000000"); + start_delay := to_nat(AutoBoot_reg(8 DOWNTO 1)); + ABSD := to_nat(AutoBoot_reg(8 DOWNTO 1)); + ELSE + next_state <= IDLE; + END IF; + END IF; + + WHEN IDLE => + IF falling_edge(write) AND RdPswdProtMode = '0' THEN + IF (Instruct = WRR AND WEL = '1' AND BAR_ACC = '0') THEN + IF ((not(SRWD = '1' AND WPNeg_pullup = '0') AND + QUAD = '0') OR QUAD = '1') THEN + -- can not execute if HPM is entered + -- or if WEL bit is zero + IF ((TBPROT='1' AND Config_reg1_in(5)='0') OR + (BPNV ='1' AND Config_reg1_in(3)='0')) AND + cfg_write = '1' THEN + ASSERT cfg_write = '0' + REPORT "Changing value of Configuration " & + "Register OTP bit from 1 to 0 is " & + "not allowed!!!" + SEVERITY WARNING; + ELSE + next_state <= WRITE_SR; + END IF; + END IF; + ELSIF (Instruct = PP OR Instruct = QPP OR + Instruct = PP4 OR Instruct = QPP4) AND + WEL = '1' THEN + sect := Address/(SecSize+1); + pgm_page := Address/PageSize; + IF (Sec_Prot(sect) = '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + next_state <= PAGE_PG; + IF (Instruct = QPP OR Instruct = QPP4) AND + QPP_page(pgm_page) = '1' THEN + REPORT "WARNING:The same page must not be" & + " programmed more than once!!!" + SEVERITY WARNING; + END IF; + END IF; + ELSIF Instruct=OTPP AND WEL = '1' AND FREEZE = '0' THEN + IF ((((Address >= 16#10# AND Address <= 16#13#) OR + (Address >= 16#20# AND Address <= 16#FF#)) + AND LOCK_BYTE1(Address/32) = '1') OR + ((Address >= 16#100# AND Address <= 16#1FF#) + AND LOCK_BYTE2((Address-16#100#)/32) = '1') OR + ((Address >= 16#200# AND Address <= 16#2FF#) + AND LOCK_BYTE3((Address-16#200#)/32) = '1') OR + ((Address >= 16#300# AND Address <= 16#3FF#) + AND LOCK_BYTE4((Address-16#300#)/32) = '1')) AND + (Address + Byte_number <= OTPHiAddr) THEN + next_state <= OTP_PG; + END IF; + ELSIF (Instruct= SE OR Instruct= SE4) AND WEL = '1' THEN + sect := Address/(SecSize+1); + IF Sec_Prot(sect) = '0' AND PPB_bits(sect)='1' + AND DYB_bits(sect)='1' THEN + next_state <= SECTOR_ERS; + END IF; + ELSIF (Instruct=P4E OR Instruct=P4E4) AND WEL='1' THEN + --A P4E instruction applied to a sector that + --is larger than 4 KB will not be executed + --and will not set the E_ERR status. + REPORT "Warning! Parameter 4KB-sector Erase "& + "Instruction is not allowed for "& + "512Mbit memory size!!! "& + "Instruction is ignored!!!" + SEVERITY warning; + ELSIF Instruct = BE AND WEL = '1' AND + (BP0='0' AND BP1='0' AND BP2='0') THEN + next_state <= BULK_ERS; + ELSIF Instruct = ABWR AND WEL = '1' THEN + --Autoboot Register Write Command + next_state <= AUTOBOOT_PG; + ELSIF Instruct = ASPP AND WEL = '1' THEN + --ASP Register Program Command + IF not(ASPOTPFLAG) THEN + next_state <= ASP_PG; + END IF; + ELSIF Instruct = PLBWR AND WEL = '1' AND + RdPswdProtEnable = '0' THEN + next_state <= PLB_PG; + ELSIF Instruct = PASSP AND WEL = '1' THEN + IF not(PWDMLB='0' AND PSTMLB='1') THEN + next_state <= PASS_PG; + END IF; + ELSIF Instruct = PASSU AND WEL= '1' AND WIP= '0' THEN + next_state <= PASS_UNLOCK; + ELSIF Instruct = PPBP AND WEL = '1' THEN + next_state <= PPB_PG; + ELSIF (Instruct=PPBERS AND WEL='1' AND PPBOTP='1') THEN + next_state <= PPB_ERS; + ELSIF Instruct = DYBWR AND WEL = '1' THEN + next_state <= DYB_PG; + ELSIF Instruct = PNVDLR AND WEL = '1' THEN + next_state <= NVDLR_PG; + ELSE + next_state <= IDLE; + END IF; + END IF; + IF falling_edge(write) AND RdPswdProtMode = '1' AND + WIP = '0' THEN + IF Instruct = PASSU THEN + next_state <= PASS_UNLOCK; + END IF; + END IF; + + WHEN AUTOBOOT => + IF rising_edge(CSNeg_ipd) THEN + next_state <= IDLE; + END IF; + + WHEN WRITE_SR => + IF rising_edge(WDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PAGE_PG => + IF PRGSUSP_out'EVENT AND PRGSUSP_out = '1' THEN + next_state <= PG_SUSP; + ELSIF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PG_SUSP => + IF falling_edge(write) THEN + IF Instruct = PGRS THEN + next_state <= PAGE_PG; + ELSE + next_state <= PG_SUSP; + END IF; + ELSE + next_state <= PG_SUSP; + END IF; + + WHEN OTP_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN BULK_ERS => + IF rising_edge(EDONE) THEN + next_state <= IDLE; + END IF; + + WHEN SECTOR_ERS => + IF ERSSUSP_out'EVENT AND ERSSUSP_out = '1' THEN + next_state <= ERS_SUSP; + ELSIF rising_edge(EDONE) THEN + next_state <= IDLE; + END IF; + + WHEN ERS_SUSP => + IF falling_edge(write) THEN + IF (Instruct = PP OR Instruct = QPP OR + Instruct = PP4 OR Instruct = QPP4) AND + WEL = '1' THEN + IF SectorSuspend /= (Address/(SecSize+1)) THEN + pgm_page := Address / PageSize; + IF PPB_bits(Address/SecSize)='1' AND + DYB_bits(Address/SecSize)='1' THEN + next_state <= ERS_SUSP_PG; + IF (Instruct = QPP OR Instruct = QPP4) AND + QPP_page(pgm_page) = '1' THEN + REPORT "WARNING:The same page must " & + "not be programmed more than once!!!" + SEVERITY WARNING; + END IF; + END IF; + END IF; + ELSIF (Instruct = DYBWR AND WEL = '1') THEN + next_state <= DYB_PG; + ELSIF Instruct = ERRS THEN + next_state <= SECTOR_ERS; + END IF; + ELSE + next_state <= ERS_SUSP; + END IF; + + WHEN ERS_SUSP_PG => + IF PRGSUSP_out'EVENT AND PRGSUSP_out = '1' THEN + next_state <= ERS_SUSP_PG_SUSP; + ELSIF rising_edge(PDONE) THEN + next_state <= ERS_SUSP; + END IF; + + WHEN ERS_SUSP_PG_SUSP => + IF falling_edge(write) THEN + IF Instruct = PGRS THEN + next_state <= ERS_SUSP_PG; + ELSE + next_state <= ERS_SUSP_PG_SUSP; + END IF; + ELSE + next_state <= ERS_SUSP_PG_SUSP; + END IF; + + WHEN PASS_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PASS_UNLOCK => + IF falling_edge(PASSULCK_in) THEN + next_state <= IDLE; + END IF; + + WHEN PPB_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PPB_ERS => + IF falling_edge(PPBERASE_in) THEN + next_state <= IDLE; + END IF; + + WHEN AUTOBOOT_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PLB_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN DYB_PG => + IF rising_edge(PDONE) THEN + IF ES = '1' THEN + next_state <= ERS_SUSP; + ELSE + next_state <= IDLE; + END IF; + END IF; + + WHEN ASP_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN NVDLR_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + END CASE; + END IF; + END IF; + + END PROCESS StateGen; + + ReadEnable: PROCESS (read_out) + BEGIN + oe_z <= rising_edge(read_out) AND PoweredUp = '1'; + + IF read_out'EVENT AND read_out = '0' AND PoweredUp = '1' THEN + oe <= TRUE, FALSE AFTER 1 ns; + END IF; + END PROCESS ReadEnable; + + --------------------------------------------------------------------------- + --FSM Output generation and general funcionality + --------------------------------------------------------------------------- + Functional : PROCESS(write,current_state,start_autoboot,CSNeg_ipd, + HOLDNeg_pullup, Instruct, Address, WByte,change_addr, + PoweredUp, WPNeg_pullup, WDONE, PDONE, EDONE, + PRGSUSP_out,ERSSUSP_out, PASSACC_out, oe, oe_z) + + VARIABLE WData : WByteType:= (OTHERS => MaxData); + + VARIABLE AddrLo : NATURAL; + VARIABLE AddrHi : NATURAL; + VARIABLE Addr : NATURAL; + VARIABLE Addr_tmp : NATURAL; + + VARIABLE data_out : std_logic_vector(7 downto 0); + VARIABLE ident_out : std_logic_vector(647 downto 0); + + VARIABLE ExtendedID : NATURAL; + + VARIABLE old_bit : std_logic_vector(7 downto 0); + VARIABLE new_bit : std_logic_vector(7 downto 0); + VARIABLE old_int : INTEGER RANGE -1 to MaxData; + VARIABLE new_int : INTEGER RANGE -1 to MaxData; + VARIABLE old_pass : std_logic_vector(63 downto 0); + VARIABLE new_pass : std_logic_vector(63 downto 0); + VARIABLE wr_cnt : NATURAL RANGE 0 TO 511; + --Data Learning Pattern Enable + VARIABLE dlp_act : BOOLEAN := FALSE; + + VARIABLE sect : NATURAL RANGE 0 TO SecNum; + VARIABLE cnt : NATURAL RANGE 0 TO 512 := 0; + + BEGIN + + ----------------------------------------------------------------------- + -- Functionality Section + ----------------------------------------------------------------------- + + IF Instruct'EVENT THEN + read_cnt := 0; + byte_cnt := 1; + fast_rd <= true; + dual <= false; + rd <= false; + any_read <= false; + END IF; + + IF PASSACC_out'EVENT AND PASSACC_out = '1' THEN + WIP := '0'; + PASSACC_in <= '0'; + END IF; + + IF rising_edge(PoweredUp) THEN + --the default condition after power-up + --The Bank Address Register is loaded to all zeroes + Bank_Addr_reg := (others => '0'); + --The Configuration Register FREEZE bit is cleared. + FREEZE := '0'; + --The WEL bit is cleared. + WEL := '0'; + --When BPNV is set to '1'. the BP2-0 bits in Status Register are + --volatile and will be reset binary 111 after power-on reset + IF BPNV = '1' AND LOCK='0' AND FREEZE = '0' THEN + BP0 := '1'; + BP1 := '1'; + BP2 := '1'; + BP_bits := BP2 & BP1 & BP0; + change_BP <= '1', '0' AFTER 1 ns; + END IF; + --As shipped from the factory, all devices default ASP to the + --Persistent Protection mode, with all sectors unprotected, + --when power is applied. The device programmer or host system must + --then choose which sector protection method to use. + --For Persistent Protection mode, PPBLOCK defaults to "1" + PPB_LOCK := '1'; + PPB_LOCK_temp <= '1'; + DYB_bits := (OTHERS => '1'); + END IF; + + IF falling_edge(write) AND Instruct = RESET THEN + --The Configuration Register is set for Address mode + Bank_Addr_reg := (others => '0'); + --P_ERR bit is cleared + P_ERR := '0'; + --E_ERR bit is cleared + E_ERR := '0'; + --The WEL bit is cleared. + WEL := '0'; + --The WIP bit is cleared. + WIP := '0'; + --The ES bit is cleared. + ES := '0'; + --The PS bit is cleared. + PS := '0'; + + DummyBytes_act := '0'; + --When BPNV is set to '1'. the BP2-0 bits in Status + --Register are volatile and will be reseted after + --reset command + IF BPNV = '1' AND LOCK='0' AND FREEZE = '0' THEN + BP0 := '1'; + BP1 := '1'; + BP2 := '1'; + BP_bits := BP2 & BP1 & BP0; + change_BP <= '1', '0' AFTER 1 ns; + END IF; + END IF; + + IF change_addr'EVENT THEN + read_addr := Address; + END IF; + + CASE current_state IS + WHEN IDLE => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF falling_edge(write) AND RdPswdProtMode = '1' THEN + IF Instruct = PASSU THEN + IF WIP = '0' THEN + PASSULCK_in <= '1'; + ELSE + REPORT "The PASSU command cannot be accepted"& + " any faster than once every 100us" + SEVERITY WARNING; + END IF; + ELSIF Instruct = CLSR THEN + --The Clear Status Register Command resets bit SR1[5] + --(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + E_ERR := '0'; + P_ERR := '0'; + END IF; + END IF; + IF falling_edge(write) AND RdPswdProtMode = '0' THEN + read_cnt := 0; + byte_cnt := 1; + IF Instruct = WREN THEN + WEL := '1'; + ELSIF Instruct = WRDI THEN + WEL := '0'; + ELSIF Instruct = WRR AND WEL = '1' AND BAR_ACC = '0' THEN + IF (not(SRWD = '1' AND WPNeg_pullup = '0') AND + QUAD ='0') OR QUAD ='1' THEN + -- can not execute if Hardware Protection Mode + -- is entered or if WEL bit is zero + + IF ((TBPROT='1' AND Config_reg1_in(5)='0') OR + (BPNV ='1' AND Config_reg1_in(3)='0')) AND + cfg_write = '1' THEN + P_ERR := '1'; + ELSE + WSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + END IF; + ELSE + WEL := '0'; + END IF; + ELSIF (Instruct = PP OR Instruct = PP4) AND WEL = '1' THEN + sect := Address/(SecSize+1); + pgm_page := Address/PageSize; + IF (Sec_Prot(sect) = '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + SA <= sect; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + P_ERR := '1'; + WEL := '0'; + END IF; + ELSIF (Instruct = QPP OR Instruct = QPP4) AND WEL = '1' THEN + sect := Address/(SecSize+1); + pgm_page := Address/PageSize; + IF (Sec_Prot(sect)= '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + SA <= sect; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + P_ERR := '1'; + WEL := '0'; + END IF; + ELSIF Instruct = OTPP AND WEL = '1' THEN + -- As long as the FREEZE bit remains cleared to a logic '0' + --the OTP address space is programmable. + IF FREEZE = '0' THEN + IF ((((Address >= 16#0010# AND Address <= 16#13#)OR + (Address >= 16#0020# AND Address <= 16#FF#)) + AND LOCK_BYTE1(Address/32) = '1') OR + ((Address >= 16#100# AND Address <= 16#1FF#) + AND LOCK_BYTE2((Address-16#100#)/32) = '1') OR + ((Address >= 16#200# AND Address <= 16#2FF#) + AND LOCK_BYTE3((Address-16#200#)/32) = '1') OR + ((Address >= 16#300# AND Address <= 16#3FF#) + AND LOCK_BYTE4((Address-16#300#)/32) = '1')) AND + (Address + Byte_number <= OTPHiAddr) THEN + PSTART <= '1', '0' AFTER 1 ns; + WIP := '1'; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSIF (Address < 16#0010# OR (Address > 16#0013# AND + Address < 16#0020#) OR Address > 16#3FF# ) THEN + P_ERR := '1'; + WEL := '0'; + IF Address < 16#0020# THEN + ASSERT false + REPORT "Given address is in" & + "reserved address range" + SEVERITY warning; + ELSIF Address > 16#3FF# THEN + ASSERT false + REPORT "Given address is out of" & + "OTP address range" + SEVERITY warning; + END IF; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSIF (Instruct = SE OR Instruct = SE4) AND WEL = '1' THEN + sect := Address/(SecSize+1); + SectorSuspend <= sect; + IF (Sec_Prot(sect) = '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + Addr := Address; + ELSE + E_ERR := '1'; + WEL := '0'; + END IF; + ELSIF (Instruct = P4E OR Instruct = P4E4) AND WEL = '1' THEN + WEL := '0'; + ELSIF Instruct = BE AND WEL = '1' THEN + IF (BP0='0' AND BP1='0' AND BP2='0') THEN + ESTART <= '1', '0' AFTER 5 ns; + ESUSP <= '0'; + ERES <= '0'; + INITIAL_CONFIG <= '1'; + WIP := '1'; + ELSE + --The Bulk Erase command will not set E_ERR if a + --protected sector is found during the command + --execution. + WEL := '0'; + END IF; + ELSIF Instruct = PASSP AND WEL = '1' THEN + IF not(PWDMLB='0' AND PSTMLB='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSE + REPORT "Password programming is not allowed" & + " in Password Protection Mode." + SEVERITY warning; + END IF; + ELSIF Instruct = PASSU AND WEL= '1' AND WIP= '0' THEN + PASSULCK_in <= '1'; + ELSIF Instruct = BRWR THEN + Bank_Addr_reg(7) := Bank_Addr_reg_in(7); + Bank_Addr_reg(1) := Bank_Addr_reg_in(1); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + ELSIF Instruct = WRR AND BAR_ACC = '1' THEN + IF (P_ERR = '0' AND E_ERR = '0') THEN + Bank_Addr_reg(1) := Bank_Addr_reg_in(1); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + END IF; + ELSIF Instruct = ASPP AND WEL = '1' THEN + IF not(ASPOTPFLAG) THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSE + WEL := '0'; + P_ERR := '1'; + REPORT "Once the Protection Mode is selected," & + "no further changes to the ASP register" & + "is allowed." + SEVERITY warning; + END IF; + ELSIF Instruct = ABWR AND WEL = '1' THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = PPBP AND WEL = '1' THEN + sect := Address/(SecSize+1); + Addr := Address; + pgm_page := Address/PageSize; + + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = PPBERS AND WEL = '1' THEN + IF PPBOTP = '1' THEN + PPBERASE_in <= '1'; + WIP := '1'; + ELSE + E_ERR := '1'; + END IF; + ELSIF Instruct = PLBWR AND WEL = '1' AND + RdPswdProtEnable = '0' THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = DYBWR AND WEL = '1' THEN + sect := Address/(SecSize+1); + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = PNVDLR AND WEL = '1' THEN + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = WVDLR AND WEL = '1' THEN + VDLR_reg := VDLR_reg_in; + WEL := '0'; + ELSIF Instruct = CLSR THEN + --The Clear Status Register Command resets bit SR1[5] + --(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + E_ERR := '0'; + P_ERR := '0'; + END IF; + + IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' THEN + BAR_ACC <= '1'; + ELSE + BAR_ACC <= '0'; + END IF; + ELSIF oe_z THEN + IF Instruct = READ OR Instruct = RD4 OR + Instruct = RES OR Instruct = DLPRD THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSIF Instruct = DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + ELSIF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = READ OR Instruct = RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = DDRFR OR Instruct = DDRFR4 THEN + --Read Memory array + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + IF ((bus_cycle_state = DUMMY_BYTES OR + DummyBytes_act='1') AND VDLR_reg/="00000000") THEN + DummyBytes_act := '0'; + IF (Instruct = DDRFR OR Instruct = DDRFR4) THEN + IF EHP THEN + IF Latency_code = 1 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3 OR + Latency_code = 0) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + dlp_act := FALSE; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + read_addr_tmp := read_addr; + SecAddr := ReturnSectorID(read_addr); + Sec_addr := read_addr - SecAddr*(SecSize+1); + SecAddr := ReturnSectorIDRdPswdMd(TBPROT); + read_addr := Sec_addr + SecAddr*(SecSize+1); + IF RdPswdProtMode = '0' THEN + read_addr := read_addr_tmp; + END IF; + + IF Mem(read_addr) /= -1 THEN + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + ELSE + SOut_zd <= 'U'; + END IF; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct = DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + --Read Memory array + IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct = DDRDIOR OR Instruct = DDRDIOR4) THEN + IF EHP THEN + IF Latency_code = 0 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + read_addr_tmp := read_addr; + SecAddr := ReturnSectorID(read_addr); + Sec_addr := read_addr - SecAddr*(SecSize+1); + SecAddr := ReturnSectorIDRdPswdMd(TBPROT); + read_addr := Sec_addr + SecAddr*(SecSize+1); + IF RdPswdProtMode = '0' THEN + read_addr := read_addr_tmp; + END IF; + + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF (Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 OR + Instruct = DDRQIOR OR Instruct= DDRQIOR4) + AND QUAD = '1' THEN + --Read Memory array + IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF ((Instruct = DDRQIOR OR Instruct = DDRQIOR4) AND + QUAD = '1') THEN + IF EHP THEN + IF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + read_addr_tmp := read_addr; + SecAddr := ReturnSectorID(read_addr); + Sec_addr := read_addr - SecAddr*(SecSize+1); + SecAddr := ReturnSectorIDRdPswdMd(TBPROT); + read_addr := Sec_addr + SecAddr*(SecSize+1); + IF RdPswdProtMode = '0' THEN + read_addr := read_addr_tmp; + END IF; + + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct = OTPR THEN + IF (read_addr>=OTPLoAddr) AND + (read_addr<=OTPHiAddr) AND RdPswdProtMode = '0' THEN + --Read OTP Memory array + fast_rd <= true; + rd <= false; + data_out := to_slv(OTPMem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + ELSIF (read_addr > OTPHiAddr) + OR RdPswdProtMode = '1' THEN + --OTP Read operation will not wrap to the + --starting address after the OTP address is at + --its maximum or Read Password Protection Mode + --is selected; instead, the data beyond the + --maximum OTP address will be undefined. + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF Instruct = REMS THEN + --Read Manufacturer and Device ID + IF read_addr MOD 2 = 0 THEN + data_out := to_slv(Manuf_ID,8); + SOut_zd <= data_out(7 - read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + ELSE + data_out := to_slv(DeviceID,8); + SOut_zd <= data_out(7 - read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := 0; + END IF; + END IF; + ELSIF Instruct = RDID THEN + ident_out := CFI_array_tmp; + IF read_cnt < 648 THEN + SOut_zd <= ident_out(647-read_cnt); + read_cnt := read_cnt + 1; + ELSE + --Continued shifting of output beyond the end of + --the defined ID-CFI address space will provide + --undefined data. + SOut_zd <= 'U'; + END IF; + ELSIF Instruct = RES THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + data_out := to_slv(ESignature,8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = DLPRD THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + SOut_zd <= VDLR_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = ABRD THEN + --Read AutoBoot register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= AutoBoot_reg(31-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 32 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = BRRD THEN + --Read Bank Address Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Bank_Addr_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = ASPRD THEN + --Read ASP Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= ASP_reg(15-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 16 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = PASSRD THEN + --Read Password Register + IF not (PWDMLB='0' AND PSTMLB='1') THEN + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Password_reg((8*byte_cnt-1)-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + byte_cnt := byte_cnt + 1; + IF byte_cnt = 9 THEN + byte_cnt := 1; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 64 THEN + read_cnt := 0; + END IF; + IF read_cnt = 0 THEN + ASSERT false + REPORT "Verification of password is not " & + " allowed in Password Protection Mode." + SEVERITY warning; + END IF; + END IF; + ELSIF Instruct = PLBRD THEN + --Read PPB Lock Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= PPBL(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = DYBRD THEN + --Read DYB Access Register + sect := Address/(SecSize+1); + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + DYBAR(7 downto 0) := "UUUUUUUU"; + IF RdPswdProtMode = '0' THEN + IF DYB_bits(sect) = '1' THEN + DYBAR(7 downto 0) := "11111111"; + ELSE + DYBAR(7 downto 0) := "00000000"; + END IF; + END IF; + SOut_zd <= DYBAR(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = PPBRD THEN + --Read PPB Access Register + sect := Address/(SecSize+1); + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + PPBAR(7 downto 0) := "UUUUUUUU"; + IF RdPswdProtMode = '0' THEN + IF PPB_bits(sect) = '1' THEN + PPBAR(7 downto 0) := "11111111"; + ELSE + PPBAR(7 downto 0) := "00000000"; + END IF; + END IF; + SOut_zd <= PPBAR(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + + WHEN AUTOBOOT => + IF start_autoboot = '1' THEN + IF (oe) THEN + any_read <= true; + IF QUAD = '1' THEN + IF ABSD > 0 THEN --If ABSD > 0, + fast_rd <= false; --max SCK frequency is 104MHz + rd <= false; + dual <= true; + ddr <= false; + ELSE -- If ABSD = 0, max SCK frequency is 50 MHz + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + END IF; + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + ELSE + IF ABSD > 0 THEN --If ABSD > 0, + fast_rd <= true; --max SCK frequency is 133MHz + rd <= false; + dual <= false; + ddr <= false; + ELSE -- If ABSD = 0, max SCK frequency is 50 MHz + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + END IF; + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + END IF; + ELSIF oe_z THEN + IF QUAD = '1' THEN + IF ABSD > 0 THEN --If ABSD > 0, + fast_rd <= false; --max SCK frequency is 104MHz + rd <= false; + dual <= true; + ddr <= false; + ELSE -- If ABSD = 0, max SCK frequency is 50 MHz + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + END IF; + ELSE + IF ABSD > 0 THEN --If ABSD > 0, + fast_rd <= true; --max SCK frequency is 133MHz + rd <= false; + dual <= false; + ddr <= false; + ELSE -- If ABSD = 0, max SCK frequency is 50 MHz + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + END IF; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + END IF; + + WHEN WRITE_SR => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF WDONE = '1' THEN + WIP := '0'; + WEL := '0'; + SRWD := Status_reg1_in(7);--MSB first + + IF LOCK='0' THEN + IF FREEZE='0' THEN + --The Freeze Bit, when set to 1, locks the current + --state of the BP2-0 bits in Status Register and + --the TBPROT bit in the Config Register + --As long as the FREEZE bit remains cleared to logic + --'0', the other bits of the Configuration register + --including FREEZE are writeable. + BP2 := Status_reg1_in(4); + BP1 := Status_reg1_in(3); + BP0 := Status_reg1_in(2); + + BP_bits := BP2 & BP1 & BP0; + + IF TBPROT = '0' AND INITIAL_CONFIG = '0' THEN + TBPROT := Config_reg1_in(5); + END IF; + + change_BP <= '1', '0' AFTER 1 ns; + + LC1 := Config_reg1_in(7); + LC0 := Config_reg1_in(6); + QUAD := Config_reg1_in(1); + + IF FREEZE = '0' THEN + FREEZE := Config_reg1_in(0); + END IF; + + IF WRLOCKENABLE AND LOCK = '0' THEN + LOCK := Config_reg1_in(4); + WRLOCKENABLE <= false; + END IF; + + IF BPNV = '0' THEN + BPNV := Config_reg1_in(3); + END IF; + END IF; + END IF; + END IF; + + WHEN PAGE_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF falling_edge(PDONE) THEN + IF (Instruct = QPP OR Instruct = QPP4) THEN + QPP_page(pgm_page) := '1'; + END IF; + + ADDRHILO_PG(AddrLo, AddrHi, Addr); + cnt := 0; + + FOR i IN 0 TO wr_cnt LOOP + new_int := WData(i); + old_int := Mem(Addr + i - cnt); + IF new_int > -1 THEN + new_bit := to_slv(new_int,8); + IF old_int > -1 THEN + old_bit := to_slv(old_int,8); + FOR j IN 0 TO 7 LOOP + IF old_bit(j) = '0' THEN + new_bit(j) := '0'; + END IF; + END LOOP; + new_int := to_nat(new_bit); + END IF; + WData(i) := new_int; + ELSE + WData(i) := -1; + END IF; + + Mem(Addr + i - cnt) := -1; + + IF (Addr + i) = AddrHi THEN + Addr := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + cnt :=0; + END IF; + + IF PDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO wr_cnt LOOP + Mem(Addr_tmp + i - cnt) := WData(i); + IF (Addr_tmp + i) = AddrHi THEN + Addr_tmp := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + ELSIF Instruct = PGSP AND PRGSUSP_in = '0' THEN + IF RES_TO_SUSP_MIN_TIME = '0' THEN + PGSUSP <= '1', '0' AFTER 1 ns; + PRGSUSP_in <= '1'; + ASSERT RES_TO_SUSP_TYP_TIME = '0' + REPORT "Typical periods are needed for " & + "Program to progress to completion" + SEVERITY warning; + ELSE + ASSERT FALSE + REPORT "Minimum for tPRS is not satisfied! " & + "PGSP command is ignored" + SEVERITY warning; + END IF; + END IF; + + WHEN PG_SUSP => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF PRGSUSP_out = '1' AND PRGSUSP_in = '1' THEN + PRGSUSP_in <= '0'; + --The RDY/BSY bit in the Status Register will indicate that + --the device is ready for another operation. + WIP := '0'; + --The Program Suspend (PS) bit in the Status Register will + --be set to the logical “1” state to indicate that the + --program operation has been suspended. + PS := '1'; + END IF; + + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = BRRD THEN + --Read Bank Address Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Bank_Addr_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + --Read Array Operations + ELSIF Instruct = READ OR Instruct = RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = DDRFR OR Instruct = DDRFR4 THEN + --Read Memory array + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + IF pgm_page /= read_addr/PageSize THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRFR OR Instruct=DDRFR4) THEN + IF EHP THEN + IF Latency_code = 1 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3 OR + Latency_code = 0) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:= VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + read_cnt:=read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + --Read Memory array + IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF pgm_page /= read_addr/PageSize THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRDIOR OR Instruct=DDRDIOR4) THEN + IF EHP THEN + IF Latency_code = 0 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency"& + " is set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:=VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + SIOut_zd<=data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF (Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 OR + Instruct = DDRQIOR OR Instruct= DDRQIOR4) + AND QUAD = '1' THEN + --Read Memory array + IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF pgm_page /= read_addr/PageSize THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF EHP THEN + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + HOLDNegOut_zd <= 'U'; + WPNegOut_zd <= 'U'; + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + END IF; + ELSIF oe_z THEN + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + ELSIF falling_edge(write) THEN + IF Instruct = BRWR THEN + Bank_Addr_reg(7) := Bank_Addr_reg_in(7); + Bank_Addr_reg(1) := Bank_Addr_reg_in(1); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + ELSIF Instruct = WRR AND BAR_ACC = '1' THEN + -- Write to the lower address bits of the BAR + IF (P_ERR = '0' AND E_ERR = '0')THEN + Bank_Addr_reg(1) := Bank_Addr_reg_in(1); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + END IF; + ELSIF Instruct = PGRS THEN + PGRES <= '1', '0' AFTER 5 ns; + PS := '0'; + WIP := '1'; + RES_TO_SUSP_MIN_TIME <= '1', '0' AFTER 60 ns; + RES_TO_SUSP_TYP_TIME <= '1', '0' AFTER 100 us; + END IF; + + IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' AND + RdPswdProtMode = '0' THEN + BAR_ACC <= '1'; + ELSE + BAR_ACC <= '0'; + END IF; + END IF; + + WHEN ERS_SUSP_PG_SUSP => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF PRGSUSP_out = '1' AND PRGSUSP_in = '1' THEN + PRGSUSP_in <= '0'; + --The RDY/BSY bit in the Status Register will indicate that + --the device is ready for another operation. + WIP := '0'; + --The Program Suspend (PS) bit in the Status Register will + --be set to the logical “1” state to indicate that the + --program operation has been suspended. + PS := '1'; + END IF; + + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = BRRD THEN + --Read Bank Address Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Bank_Addr_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + --Read Array Operations + ELSIF Instruct = READ OR Instruct = RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = DDRFR OR Instruct = DDRFR4 THEN + --Read Memory array + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + IF (SectorSuspend /= read_addr/(SecSize+1) AND + pgm_page /= read_addr/PageSize) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRFR OR Instruct=DDRFR4) THEN + IF EHP THEN + IF Latency_code = 1 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3 OR + Latency_code = 0) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:= VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + read_cnt:=read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + --Read Memory array + IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF (SectorSuspend /= read_addr/(SecSize+1) AND + pgm_page /= read_addr/PageSize) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRDIOR OR Instruct=DDRDIOR4) THEN + IF EHP THEN + IF Latency_code = 0 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency"& + " is set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:=VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + SIOut_zd<=data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF (Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 OR + Instruct = DDRQIOR OR Instruct= DDRQIOR4) + AND QUAD = '1' THEN + --Read Memory array + IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF (SectorSuspend /= read_addr/(SecSize+1) AND + pgm_page /= read_addr/PageSize) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF EHP THEN + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + HOLDNegOut_zd <= 'U'; + WPNegOut_zd <= 'U'; + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + END IF; + ELSIF oe_z THEN + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + ELSIF falling_edge(write) THEN + IF Instruct = BRWR THEN + Bank_Addr_reg(7) := Bank_Addr_reg_in(7); + Bank_Addr_reg(1) := Bank_Addr_reg_in(1); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + ELSIF Instruct = WRR AND BAR_ACC = '1' THEN + -- Write to the lower address bits of the BAR + IF (P_ERR = '0' AND E_ERR = '0')THEN + Bank_Addr_reg(1) := Bank_Addr_reg_in(1); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + END IF; + ELSIF Instruct = PGRS THEN + PGRES <= '1', '0' AFTER 5 ns; + PS := '0'; + WIP := '1'; + RES_TO_SUSP_MIN_TIME <= '1', '0' AFTER 60 ns; + RES_TO_SUSP_TYP_TIME <= '1', '0' AFTER 100 us; + END IF; + + IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' AND + RdPswdProtMode = '0' THEN + BAR_ACC <= '1'; + ELSE + BAR_ACC <= '0'; + END IF; + END IF; + + WHEN OTP_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF Address + wr_cnt <= OTPHiAddr THEN + FOR i IN 0 TO wr_cnt LOOP + new_int := WData(i); + old_int := OTPMem(Addr + i); + IF new_int > -1 THEN + new_bit := to_slv(new_int,8); + IF old_int > -1 THEN + old_bit := to_slv(old_int,8); + FOR j IN 0 TO 7 LOOP + IF old_bit(j) = '0' THEN + new_bit(j) := '0'; + END IF; + END LOOP; + new_int := to_nat(new_bit); + END IF; + WData(i) := new_int; + ELSE + WData(i) := -1; + END IF; + + OTPMem(Addr + i) := -1; + END LOOP; + ELSE + ASSERT false + REPORT "Programming will reach over address limit"& + " of OTP array" + SEVERITY warning; + END IF; + + IF PDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO wr_cnt LOOP + OTPMem(Addr_tmp + i) := WData(i); + END LOOP; + LOCK_BYTE1 := to_slv(OTPMem(16#10#),8); + LOCK_BYTE2 := to_slv(OTPMem(16#11#),8); + LOCK_BYTE3 := to_slv(OTPMem(16#12#),8); + LOCK_BYTE4 := to_slv(OTPMem(16#13#),8); + END IF; + + WHEN SECTOR_ERS => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := -1; + END LOOP; + IF EDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := MaxData; + END LOOP; + ELSIF Instruct = ERSP AND ERSSUSP_in = '0' THEN + ESUSP <= '1', '0' AFTER 10 ns; + ERSSUSP_in <= '1'; + ASSERT RES_TO_SUSP_TYP_TIME = '0' + REPORT "Typical periods are needed for " & + "Program to progress to completion" + SEVERITY warning; + END IF; + + WHEN BULK_ERS => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF falling_edge(EDONE) THEN + FOR i IN 0 TO AddrRANGE LOOP + sect := i/(SecSize+1); + IF PPB_bits(sect) = '1' AND DYB_bits(sect) = '1' THEN + Mem(i) := -1; + END IF; + END LOOP; + END IF; + + IF EDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO AddrRANGE LOOP + sect := i/(SecSize+1); + IF PPB_bits(sect) = '1' AND DYB_bits(sect) = '1' THEN + Mem(i) := MaxData; + END IF; + END LOOP; + END IF; + + WHEN ERS_SUSP => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF ERSSUSP_out = '1' THEN + ERSSUSP_in <= '0'; + --The Erase Suspend (ES) bit in the Status Register will + --be set to the logical “1” state to indicate that the + --erase operation has been suspended. + ES := '1'; + --The WIP bit in the Status Register will indicate that + --the device is ready for another operation. + WIP := '0'; + END IF; + + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = DYBRD THEN + --Read DYB Access Register + sect := Address/(SecSize+1); + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF DYB_bits(sect) = '1' THEN + DYBAR(7 downto 0) := "11111111"; + ELSE + DYBAR(7 downto 0) := "00000000"; + END IF; + SOut_zd <= DYBAR(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = BRRD THEN + --Read Bank Address Register + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + SOut_zd <= Bank_Addr_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = PPBRD THEN + --Read PPB Access Register + sect := Address/(SecSize+1); + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + PPBAR(7 downto 0) := "UUUUUUUU"; + IF RdPswdProtMode = '0' THEN + IF PPB_bits(sect) = '1' THEN + PPBAR(7 downto 0) := "11111111"; + ELSE + PPBAR(7 downto 0) := "00000000"; + END IF; + END IF; + SOut_zd <= PPBAR(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + --Read Array Operations + ELSIF Instruct = READ OR Instruct = RD4 OR + Instruct = FSTRD OR Instruct = FSTRD4 OR + Instruct = DDRFR OR Instruct = DDRFR4 THEN + --Read Memory array + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + IF SectorSuspend /= read_addr/(SecSize+1) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRFR OR Instruct=DDRFR4) THEN + IF EHP THEN + IF Latency_code = 1 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3 OR + Latency_code = 0) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:= VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + read_cnt:=read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) is + -- enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + --Read Memory array + IF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF SectorSuspend /= read_addr/(SecSize+1) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF (Instruct=DDRDIOR OR Instruct=DDRDIOR4) THEN + IF EHP THEN + IF Latency_code = 0 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 1) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency"& + " is set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out:=VDLR_reg; + SOut_zd <=data_out(7-read_cnt); + SIOut_zd<=data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF Latency_code = 3 THEN + dlp_act := TRUE; + ELSIF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + END IF; + -- Data Learning Pattern (DLP) + -- is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND + dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSIF (Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 OR + Instruct = DDRQIOR OR Instruct= DDRQIOR4) + AND QUAD = '1' THEN + --Read Memory array + IF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + END IF; + IF SectorSuspend /= read_addr/(SecSize+1) THEN + IF ((bus_cycle_state = DUMMY_BYTES + OR DummyBytes_act = '1') + AND VDLR_reg /= "00000000") THEN + DummyBytes_act := '0'; + IF EHP THEN + IF (Latency_code=0 + AND dummy_cnt_act>=2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSE + IF (Latency_code = 0 AND + dummy_cnt_act >= 2) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 1 AND + dummy_cnt_act >= 3) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 2 AND + dummy_cnt_act >= 4) THEN + dlp_act := TRUE; + ELSIF (Latency_code = 3) THEN + dlp_act := FALSE; + REPORT "Inappropriate latency is"& + " set during DPL mode" + SEVERITY WARNING; + END IF; + -- Data Learning Pattern (DLP) is enabled + -- Optional DLP + IF (VDLR_reg/="00000000" AND dlp_act) THEN + dlp_act := FALSE; + data_out := VDLR_reg; + HOLDNegOut_zd <= data_out(7-read_cnt); + WPNegOut_zd <= data_out(7-read_cnt); + SOut_zd <= data_out(7-read_cnt); + SIOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + END IF; + ELSE + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + END IF; + ELSE + HOLDNegOut_zd <= 'U'; + WPNegOut_zd <= 'U'; + SOut_zd <= 'U'; + SIOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + + END IF; + END IF; + ELSIF oe_z THEN + IF Instruct = READ OR Instruct = RD4 THEN + fast_rd <= false; + rd <= true; + dual <= false; + ddr <= false; + ELSIF Instruct = DDRFR OR Instruct = DDRFR4 THEN + fast_rd <= false; + rd <= false; + dual <= false; + ddr <= true; + ELSIF Instruct = DDRDIOR OR Instruct = DDRDIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSIF Instruct =DOR OR Instruct=DOR4 OR + Instruct = DIOR OR Instruct = DIOR4 OR + Instruct = QOR OR Instruct=QOR4 OR + Instruct = QIOR OR Instruct= QIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= false; + ELSIF Instruct = DDRQIOR OR Instruct = DDRQIOR4 THEN + fast_rd <= false; + rd <= false; + dual <= true; + ddr <= true; + ELSE + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + END IF; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF falling_edge(write) THEN + IF (Instruct = PP OR Instruct = PP4) AND WEL = '1' THEN + sect := Address/(SecSize+1); + pgm_page := Address/PageSize; + IF SectorSuspend /= sect THEN + IF (Sec_Prot(sect) = '0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + WIP := '1' ; + SA <= sect; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSIF (Instruct = QPP OR Instruct = QPP4) AND WEL = '1' THEN + sect := Address/(SecSize+1); + pgm_page := Address/PageSize; + IF SectorSuspend /= sect THEN + IF (Sec_Prot(sect)='0' AND + PPB_bits(sect)='1' AND DYB_bits(sect)='1') THEN + PSTART <= '1', '0' AFTER 5 ns; + PGSUSP <= '0'; + PGRES <= '0'; + WIP := '1' ; + SA <= sect; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSE + WEL := '0'; + P_ERR := '1'; + END IF; + ELSIF Instruct = WREN THEN + WEL := '1'; + ELSIF Instruct = CLSR THEN + --The Clear Status Register Command resets bit SR1[5] + --(Erase Fail Flag) and bit SR1[6] (Program Fail Flag) + E_ERR := '0'; + P_ERR := '0'; + ELSIF Instruct = BRWR THEN + Bank_Addr_reg(7) := Bank_Addr_reg_in(7); + Bank_Addr_reg(1) := Bank_Addr_reg_in(1); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + ELSIF Instruct = WRR AND BAR_ACC = '1' THEN + -- Write to the lower address bits of the BAR + IF (P_ERR = '0' AND E_ERR = '0')THEN + Bank_Addr_reg(1) := Bank_Addr_reg_in(1); + Bank_Addr_reg(0) := Bank_Addr_reg_in(0); + END IF; + ELSIF Instruct = DYBWR AND WEL = '1' THEN + sect := Address/(SecSize+1); + PSTART <= '1', '0' AFTER 5 ns; + WIP := '1'; + ELSIF Instruct = ERRS THEN + ERES <= '1', '0' AFTER 5 ns; + ES := '0'; + WIP := '1'; + Addr := SectorSuspend*(SecSize+1); + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + RES_TO_SUSP_TYP_TIME <= '1', '0' AFTER 100 us; + END IF; + + IF Instruct = BRAC AND P_ERR = '0' AND E_ERR = '0' AND + RdPswdProtMode = '0' THEN + BAR_ACC <= '1'; + ELSE + BAR_ACC <= '0'; + END IF; + END IF; + + WHEN ERS_SUSP_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF (Instruct = QPP OR Instruct = QPP4) THEN + QPP_page(pgm_page) := '1'; + END IF; + + ADDRHILO_PG(AddrLo, AddrHi, Addr); + cnt := 0; + + FOR i IN 0 TO wr_cnt LOOP + new_int := WData(i); + old_int := Mem(Addr + i - cnt); + IF new_int > -1 THEN + new_bit := to_slv(new_int,8); + IF old_int > -1 THEN + old_bit := to_slv(old_int,8); + FOR j IN 0 TO 7 LOOP + IF old_bit(j) = '0' THEN + new_bit(j) := '0'; + END IF; + END LOOP; + new_int := to_nat(new_bit); + END IF; + WData(i) := new_int; + ELSE + WData(i) := -1; + END IF; + + IF (Addr + i) = AddrHi THEN + Addr := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + cnt :=0; + + IF PDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO wr_cnt LOOP + Mem(Addr_tmp + i - cnt) := WData(i); + IF (Addr_tmp + i) = AddrHi THEN + Addr_tmp := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + ELSIF Instruct = PGSP AND PRGSUSP_in = '0' THEN + IF RES_TO_SUSP_MIN_TIME = '0' THEN + PGSUSP <= '1', '0' AFTER 1 ns; + PRGSUSP_in <= '1'; + ASSERT RES_TO_SUSP_TYP_TIME = '0' + REPORT "Typical periods are needed for " & + "Program to progress to completion" + SEVERITY warning; + ELSE + ASSERT FALSE + REPORT "Minimum for tPRS is not satisfied! " & + "PGSP command is ignored" + SEVERITY warning; + END IF; + END IF; + + WHEN PASS_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + new_pass := Password_reg_in; + old_pass := Password_reg; + FOR j IN 0 TO 63 LOOP + IF old_pass(j) = '0' THEN + new_pass(j) := '0'; + END IF; + END LOOP; + + IF PDONE = '1' THEN + Password_reg := new_pass; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN PASS_UNLOCK => + WIP := '1'; + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PASS_TEMP = Password_reg THEN + PASS_UNLOCKED <= TRUE; + ELSE + PASS_UNLOCKED <= FALSE; + END IF; + + IF PASSULCK_out = '1' THEN + IF PASS_UNLOCKED AND PWDMLB = '0' THEN + PPB_LOCK := '1'; + PPB_LOCK_temp <= '1'; + WIP := '0'; + ELSE + P_ERR := '1'; + REPORT "Incorrect Password!" + SEVERITY warning; + PASSACC_in <= '1'; + END IF; + WEL := '0'; + PASSULCK_in <= '0'; + END IF; + + WHEN PPB_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + IF PPB_LOCK /= '0' THEN + PPB_bits(sect):= '0'; + WIP := '0'; + WEL := '0'; + ELSE + P_ERR := '0'; + WIP := '0'; + WEL := '0'; + END IF; + END IF; + + WHEN PPB_ERS => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PPBERASE_out = '1' THEN + IF PPB_LOCK /= '0' AND PPBOTP = '1' THEN + PPB_bits:= (OTHERS => '1'); + ELSE + E_ERR := '1'; + END IF; + WIP := '0'; + WEL := '0'; + PPBERASE_in <= '0'; + END IF; + + WHEN AUTOBOOT_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + AutoBoot_reg := AutoBoot_reg_in; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN PLB_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + PPB_LOCK := '0'; + PPB_LOCK_temp <= '0'; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN DYB_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + DYBAR := DYBAR_in; + IF DYBAR = "11111111" THEN + DYB_bits(sect):= '1'; + ELSIF DYBAR = "00000000" THEN + DYB_bits(sect):= '0'; + ELSE + P_ERR := '1'; + END IF; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN ASP_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + + IF (RPME = '0' AND ASP_reg_in(5) = '1') THEN + P_ERR := '1'; + REPORT "RPME bit is allready programmed" + SEVERITY warning; + ELSE + RPME := ASP_reg_in(5); + END IF; + + IF (PPBOTP = '0' AND ASP_reg_in(3) ='1') THEN + P_ERR := '1'; + REPORT "PPBOTP bit is allready programmed" + SEVERITY warning; + ELSE + PPBOTP := ASP_reg_in(3); + END IF; + + IF (PWDMLB = '1' AND PSTMLB = '1') THEN + IF (ASP_reg_in(2) = '0' AND ASP_reg_in(1) = '0') THEN + REPORT "ASPR[2:1] = 00 Illegal condition" + SEVERITY warning; + P_ERR := '1'; + ELSE + IF (ASP_reg_in(2) /= '1' OR + ASP_reg_in(1) /= '1') THEN + ASPOTPFLAG <= TRUE; + END IF; + PWDMLB := ASP_reg_in(2); + PSTMLB := ASP_reg_in(1); + END IF; + END IF; + WIP := '0'; + WEL := '0'; + END IF; + + WHEN NVDLR_PG => + fast_rd <= true; + rd <= false; + dual <= false; + ddr <= false; + IF oe THEN + any_read <= true; + IF Instruct = RDSR THEN + --Read Status Register 1 + SOut_zd <= Status_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDSR2 THEN + --Read Status Register 2 + SOut_zd <= Status_reg2(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RDCR THEN + --Read Configuration Register 1 + SOut_zd <= Config_reg1(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF oe_z THEN + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + SIOut_zd <= 'Z'; + END IF; + + IF PDONE = '1' THEN + IF NVDLR_reg = "00000000" THEN + NVDLR_reg :=NVDLR_reg_in; + VDLR_reg := NVDLR_reg_in; + WIP := '0'; + WEL := '0'; + ELSE + WIP := '0'; + WEL := '0'; + P_ERR := '1'; + REPORT "NVDLR is allready programmed" + SEVERITY warning; + END IF; + END IF; + + WHEN RESET_STATE => + --the default condition hardware reset + --The Bank Address Register is loaded to all zeroes + Bank_Addr_reg := (others => '0'); + IF BPNV = '1' AND LOCK='0' AND FREEZE = '0' THEN + BP0 := '1'; + BP1 := '1'; + BP2 := '1'; + BP_bits := BP2 & BP1 & BP0; + change_BP <= '1', '0' AFTER 1 ns; + END IF; + --Resets the Status register 1 + P_ERR := '0'; + E_ERR := '0'; + WEL := '0'; + WIP := '0'; + --Resets the Status register 2 + ES := '0'; + PS := '0'; + --Resets the Configuration register 1 + FREEZE := '0'; + --On reset cycles the data pattern reverts back + --to what is in the NVDLR + VDLR_reg := NVDLR_reg; + dlp_act := FALSE; + --Loads the Program Buffer with all ones + WData := (OTHERS => MaxData); + + IF PWDMLB = '0' THEN + PPB_LOCK := '0'; + PPB_LOCK_temp <= '0'; + ELSE + PPB_LOCK := '1'; + PPB_LOCK_temp <= '1'; + END IF; + + END CASE; + + --Output Disable Control + IF (CSNeg_ipd = '1') THEN + SIOut_zd <= 'Z'; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + END IF; + + END PROCESS Functional; + + --------------------------------------------------------------------------- + -- CFI Process + --------------------------------------------------------------------------- + CFIPreload: PROCESS + + BEGIN + ------------------------------------------------------------------------ + --CFI array data + ------------------------------------------------------------------------ + -- Manufacturer and Device ID + CFI_array(16#00#) := 16#01#; + CFI_array(16#01#) := 16#02#; + CFI_array(16#02#) := 16#20#; + CFI_array(16#03#) := 16#00#; + CFI_array(16#04#) := 16#00#;--Uniform 256KB sectors + CFI_array(16#05#) := 16#80#; + CFI_array(16#06#) := 16#00#; + CFI_array(16#07#) := 16#00#; + CFI_array(16#08#) := 16#00#; + CFI_array(16#09#) := 16#00#; + CFI_array(16#0A#) := 16#00#; + CFI_array(16#0B#) := 16#00#; + CFI_array(16#0C#) := 16#00#; + CFI_array(16#0D#) := 16#00#; + CFI_array(16#0E#) := 16#00#; + CFI_array(16#0F#) := 16#00#; + --CFI Query Identification String + CFI_array(16#10#) := 16#51#; + CFI_array(16#11#) := 16#52#; + CFI_array(16#12#) := 16#59#; + CFI_array(16#13#) := 16#02#; + CFI_array(16#14#) := 16#00#; + CFI_array(16#15#) := 16#40#; + CFI_array(16#16#) := 16#00#; + CFI_array(16#17#) := 16#53#; + CFI_array(16#18#) := 16#46#; + CFI_array(16#19#) := 16#51#; + CFI_array(16#1A#) := 16#00#; + --CFI system interface string + CFI_array(16#1B#) := 16#27#; + CFI_array(16#1C#) := 16#36#; + CFI_array(16#1D#) := 16#00#; + CFI_array(16#1E#) := 16#00#; + CFI_array(16#1F#) := 16#06#; + CFI_array(16#20#) := 16#09#;-- 512B page + CFI_array(16#21#) := 16#09#;-- 256KB + CFI_array(16#22#) := 16#11#; + CFI_array(16#23#) := 16#02#; + CFI_array(16#24#) := 16#02#; + CFI_array(16#25#) := 16#03#; + CFI_array(16#26#) := 16#03#; + -- Device Geometry Definition + CFI_array(16#27#) := 16#1A#; + CFI_array(16#28#) := 16#02#; + CFI_array(16#29#) := 16#01#; + CFI_array(16#2A#) := 16#09#; + CFI_array(16#2B#) := 16#00#; + CFI_array(16#2C#) := 16#01#; + CFI_array(16#2D#) := 16#FF#; + CFI_array(16#2E#) := 16#00#; + CFI_array(16#2F#) := 16#00#; + CFI_array(16#30#) := 16#04#; + CFI_array(16#31#) := 16#FF#; + CFI_array(16#32#) := 16#FF#; + CFI_array(16#33#) := 16#FF#; + CFI_array(16#34#) := 16#FF#; + CFI_array(16#35#) := 16#FF#; + CFI_array(16#36#) := 16#FF#; + CFI_array(16#37#) := 16#FF#; + CFI_array(16#38#) := 16#FF#; + CFI_array(16#39#) := 16#FF#; + CFI_array(16#3A#) := 16#FF#; + CFI_array(16#3B#) := 16#FF#; + CFI_array(16#3C#) := 16#FF#; + CFI_array(16#3D#) := 16#FF#; + CFI_array(16#3E#) := 16#FF#; + CFI_array(16#3F#) := 16#FF#; + -- CFI Primary Vendor-Specific Extended Query + CFI_array(16#40#) := 16#50#; + CFI_array(16#41#) := 16#52#; + CFI_array(16#42#) := 16#49#; + CFI_array(16#43#) := 16#31#; + CFI_array(16#44#) := 16#33#; + CFI_array(16#45#) := 16#21#; + CFI_array(16#46#) := 16#02#; + CFI_array(16#47#) := 16#01#; + CFI_array(16#48#) := 16#00#; + CFI_array(16#49#) := 16#08#; + + CFI_array(16#4A#) := 16#00#; + CFI_array(16#4B#) := 16#01#; + CFI_array(16#4C#) := 16#04#; + CFI_array(16#4D#) := 16#00#; + CFI_array(16#4E#) := 16#00#; + CFI_array(16#4F#) := 16#07#; + CFI_array(16#50#) := 16#01#; + + CFI_array_tmp :=to_slv(CFI_array(16#00#), 8) & + to_slv(CFI_array(16#01#), 8) & + to_slv(CFI_array(16#02#), 8) & + to_slv(CFI_array(16#03#), 8) & + to_slv(CFI_array(16#04#), 8) & + to_slv(CFI_array(16#05#), 8) & + to_slv(CFI_array(16#06#), 8) & + to_slv(CFI_array(16#07#), 8) & + to_slv(CFI_array(16#08#), 8) & + to_slv(CFI_array(16#09#), 8) & + to_slv(CFI_array(16#0A#), 8) & + to_slv(CFI_array(16#0B#), 8) & + to_slv(CFI_array(16#0C#), 8) & + to_slv(CFI_array(16#0D#), 8) & + to_slv(CFI_array(16#0E#), 8) & + to_slv(CFI_array(16#0F#), 8) & + to_slv(CFI_array(16#10#), 8) & + to_slv(CFI_array(16#11#), 8) & + to_slv(CFI_array(16#12#), 8) & + to_slv(CFI_array(16#13#), 8) & + to_slv(CFI_array(16#14#), 8) & + to_slv(CFI_array(16#15#), 8) & + to_slv(CFI_array(16#16#), 8) & + to_slv(CFI_array(16#17#), 8) & + to_slv(CFI_array(16#18#), 8) & + to_slv(CFI_array(16#19#), 8) & + to_slv(CFI_array(16#1A#), 8) & + to_slv(CFI_array(16#1B#), 8) & + to_slv(CFI_array(16#1C#), 8) & + to_slv(CFI_array(16#1D#), 8) & + to_slv(CFI_array(16#1E#), 8) & + to_slv(CFI_array(16#1F#), 8) & + to_slv(CFI_array(16#20#), 8) & + to_slv(CFI_array(16#21#), 8) & + to_slv(CFI_array(16#22#), 8) & + to_slv(CFI_array(16#23#), 8) & + to_slv(CFI_array(16#24#), 8) & + to_slv(CFI_array(16#25#), 8) & + to_slv(CFI_array(16#26#), 8) & + to_slv(CFI_array(16#27#), 8) & + to_slv(CFI_array(16#28#), 8) & + to_slv(CFI_array(16#29#), 8) & + to_slv(CFI_array(16#2A#), 8) & + to_slv(CFI_array(16#2B#), 8) & + to_slv(CFI_array(16#2C#), 8) & + to_slv(CFI_array(16#2D#), 8) & + to_slv(CFI_array(16#2E#), 8) & + to_slv(CFI_array(16#2F#), 8) & + to_slv(CFI_array(16#30#), 8) & + to_slv(CFI_array(16#31#), 8) & + to_slv(CFI_array(16#32#), 8) & + to_slv(CFI_array(16#33#), 8) & + to_slv(CFI_array(16#34#), 8) & + to_slv(CFI_array(16#35#), 8) & + to_slv(CFI_array(16#36#), 8) & + to_slv(CFI_array(16#37#), 8) & + to_slv(CFI_array(16#38#), 8) & + to_slv(CFI_array(16#39#), 8) & + to_slv(CFI_array(16#3A#), 8) & + to_slv(CFI_array(16#3B#), 8) & + to_slv(CFI_array(16#3C#), 8) & + to_slv(CFI_array(16#3D#), 8) & + to_slv(CFI_array(16#3E#), 8) & + to_slv(CFI_array(16#3F#), 8) & + to_slv(CFI_array(16#40#), 8) & + to_slv(CFI_array(16#41#), 8) & + to_slv(CFI_array(16#42#), 8) & + to_slv(CFI_array(16#43#), 8) & + to_slv(CFI_array(16#44#), 8) & + to_slv(CFI_array(16#45#), 8) & + to_slv(CFI_array(16#46#), 8) & + to_slv(CFI_array(16#47#), 8) & + to_slv(CFI_array(16#48#), 8) & + to_slv(CFI_array(16#49#), 8) & + to_slv(CFI_array(16#4A#), 8) & + to_slv(CFI_array(16#4B#), 8) & + to_slv(CFI_array(16#4C#), 8) & + to_slv(CFI_array(16#4D#), 8) & + to_slv(CFI_array(16#4E#), 8) & + to_slv(CFI_array(16#4F#), 8) & + to_slv(CFI_array(16#50#), 8); + + WAIT; + + END PROCESS CFIPreload; + + AspRegInit: PROCESS(ASP_INIT) + BEGIN + IF ASP_INIT = 0 THEN + ASP_reg := to_slv(16#FE4F#,16); + ELSE + ASP_reg := to_slv(16#FE7F#,16); + END IF; + END PROCESS AspRegInit; + + Protect : PROCESS(change_BP) + BEGIN + IF rising_edge(change_BP) THEN + + CASE BP_bits IS + WHEN "000" => + Sec_Prot := (OTHERS => '0'); + WHEN "001" => + IF TBPROT = '0' THEN + Sec_Prot(SecNum downto (SecNum+1)*63/64) + := (OTHERS => '1'); + Sec_Prot((SecNum+1)*63/64 - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/64 - 1 downto 0) + := (OTHERS => '1'); + Sec_Prot(SecNum downto (SecNum+1)/64) + := (OTHERS => '0'); + END IF; + WHEN "010" => + IF TBPROT = '0' THEN + Sec_Prot(SecNum downto (SecNum+1)*31/32) + := (OTHERS => '1'); + Sec_Prot((SecNum+1)*31/32 - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/32 - 1 downto 0) + := (others => '1'); + Sec_Prot(SecNum downto (SecNum+1)/32) + := (OTHERS => '0'); + END IF; + WHEN "011" => + IF TBPROT = '0' THEN + Sec_Prot(SecNum downto (SecNum+1)*15/16) + := (OTHERS => '1'); + Sec_Prot((SecNum+1)*15/16 - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/16 - 1 downto 0) + := (OTHERS => '1'); + Sec_Prot(SecNum downto (SecNum+1)/16) + := (OTHERS => '0'); + END IF; + WHEN "100" => + IF TBPROT = '0' THEN + Sec_Prot(SecNum downto (SecNum+1)*7/8) + := (OTHERS => '1'); + Sec_Prot((SecNum+1)*7/8 - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/8 - 1 downto 0) := (OTHERS => '1'); + Sec_Prot(SecNum downto (SecNum+1)/8):= (OTHERS => '0'); + END IF; + WHEN "101" => + IF TBPROT = '0' THEN + Sec_Prot(SecNum downto (SecNum+1)*3/4) + := (OTHERS => '1'); + Sec_Prot((SecNum+1)*3/4 - 1 downto 0) + := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/4 - 1 downto 0) := (OTHERS => '1'); + Sec_Prot(SecNum downto (SecNum+1)/4):= (OTHERS => '0'); + END IF; + + WHEN "110" => + IF TBPROT = '0' THEN + Sec_Prot(SecNum downto (SecNum+1)/2):= (OTHERS => '1'); + Sec_Prot((SecNum+1)/2 - 1 downto 0) := (OTHERS => '0'); + ELSE + Sec_Prot((SecNum+1)/2 - 1 downto 0) := (OTHERS => '1'); + Sec_Prot(SecNum downto (SecNum+1)/2):= (OTHERS => '0'); + END IF; + + WHEN OTHERS => + Sec_Prot := (OTHERS => '1'); + END CASE; + END IF; + END PROCESS Protect; + + HOLD_FRAME_ON_PO_ZD : PROCESS(SOut_zd, SIOut_zd, HOLDNeg_pullup) + BEGIN + IF (HOLDNeg_pullup = '0' AND QUAD /= '1') THEN + hold_mode := TRUE; + SIOut_z <= 'Z'; + SOut_z <= 'Z'; + ELSE + IF hold_mode THEN + SIOut_z <= SIOut_zd AFTER tpd_HOLDNeg_SO(trz0); + SOut_z <= SOut_zd AFTER tpd_HOLDNeg_SO(trz0); + hold_mode := FALSE; + ELSE + SIOut_z <= SIOut_zd; + SOut_z <= SOut_zd; + hold_mode := FALSE; + END IF; + END IF; + END PROCESS HOLD_FRAME_ON_PO_ZD; + + HOLD_PULL_UP : PROCESS(HOLDNegIn) + BEGIN + IF (QUAD = '0') THEN + IF (HOLDNegIn = 'Z') THEN + HOLDNeg_pullup <= '1'; + ELSE + HOLDNeg_pullup <= HOLDNegIn; + END IF; + END IF; + END PROCESS HOLD_PULL_UP; + + WP_PULL_UP : PROCESS(WPNegIn) + BEGIN + IF (QUAD = '0') THEN + IF (WPNegIn = 'Z') THEN + WPNeg_pullup <= '1'; + ELSE + WPNeg_pullup <= WPNegIn; + END IF; + END IF; + END PROCESS WP_PULL_UP; + + RST_PULL_UP : PROCESS(RSTNeg) + BEGIN + IF (RSTNeg = 'Z') THEN + RSTNeg_pullup <= '1'; + ELSE + RSTNeg_pullup <= RSTNeg; + END IF; + END PROCESS RST_PULL_UP; + + --------------------------------------------------------------------------- + ---- File Read Section - Preload Control + --------------------------------------------------------------------------- + MemPreload : PROCESS + + -- text file input variables + FILE mem_file : text is mem_file_name; + FILE otp_file : text is otp_file_name; + VARIABLE ind : NATURAL RANGE 0 TO AddrRANGE := 0; + VARIABLE otp_ind : NATURAL RANGE 16#000# TO 16#3FF# := 16#000#; + VARIABLE buf : line; + + BEGIN + --------------------------------------------------------------------------- + --s25fl512s memory preload file format +----------------------------------- + --------------------------------------------------------------------------- + -- / - comment + -- @aaaaaa - stands for address + -- dd -
is byte to be written at Mem(aaaaaa++) + -- (aaaaaa is incremented at every load) + -- only first 1-7 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + --------------------------------------------------------------------------- + + -- memory preload + IF (mem_file_name /= "none" AND UserPreload) THEN + ind := 0; + Mem := (OTHERS => MaxData); + WHILE (not ENDFILE (mem_file)) LOOP + READLINE (mem_file, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + IF ind > AddrRANGE THEN + ASSERT false + REPORT "Given preload address is out of" & + "memory address range" + SEVERITY warning; + ELSE + ind := h(buf(2 to 8)); --address + END IF; + ELSE + Mem(ind) := h(buf(1 to 2)); + IF ind < AddrRANGE THEN + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + --------------------------------------------------------------------------- + --s25fl512s_otp memory preload file format + --------------------------------------------------------------------------- + -- / - comment + -- @aaa - stands for address + -- dd -
is byte to be written at OTPMem(aaa++) + -- (aaa is incremented at every load) + -- only first 1-4 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + --------------------------------------------------------------------------- + + -- memory preload + IF (otp_file_name /= "none" AND UserPreload) THEN + otp_ind := 16#000#; + OTPMem := (OTHERS => MaxData); + WHILE (not ENDFILE (otp_file)) LOOP + READLINE (otp_file, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + IF otp_ind > 16#3FF# OR otp_ind < 16#000# THEN + ASSERT false + REPORT "Given preload address is out of" & + "OTP address range" + SEVERITY warning; + ELSE + otp_ind := h(buf(2 to 4)); --address + END IF; + ELSE + OTPMem(otp_ind) := h(buf(1 to 2)); + otp_ind := otp_ind + 1; + END IF; + END LOOP; + END IF; + + LOCK_BYTE1 := to_slv(OTPMem(16#10#),8); + LOCK_BYTE2 := to_slv(OTPMem(16#11#),8); + LOCK_BYTE3 := to_slv(OTPMem(16#12#),8); + LOCK_BYTE4 := to_slv(OTPMem(16#13#),8); + + WAIT; + END PROCESS MemPreload; + + ---------------------------------------------------------------------------- + -- Path Delay Section + ---------------------------------------------------------------------------- + + S_Out_PathDelay_Gen : PROCESS(SOut_z) + + VARIABLE SO_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => SOut, + OutSignalName => "SO", + OutTemp => SOut_z, + Mode => VitalTransport, + GlitchData => SO_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal), + PathCondition => NOT(ddr)), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR), + PathCondition => (ddr OR fast_rd)), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1'), + 3 => (InputChangeTime => HOLDNegIn'LAST_EVENT, + PathDelay => tpd_HOLDNeg_SO, + PathCondition => QUAD = '0') + ) + ); + END PROCESS; + + SI_Out_PathDelay : PROCESS(SIOut_z) + + VARIABLE SI_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => SIOut, + OutSignalName => "SI", + OutTemp => SIOut_z, + Mode => VitalTransport, + GlitchData => SI_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal), + PathCondition => dual AND NOT(ddr)), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR), + PathCondition => dual AND ddr), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1'), + 3 => (InputChangeTime => HOLDNegIn'LAST_EVENT, + PathDelay => tpd_HOLDNeg_SO, + PathCondition => dual AND QUAD = '0') + ) + ); + END PROCESS; + + HOLD_Out_PathDelay : PROCESS(HOLDNegOut_zd) + + VARIABLE HOLD_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => HOLDNegOut, + OutSignalName => "HOLDNeg", + OutTemp => HOLDNegOut_zd, + Mode => VitalTransport, + GlitchData => HOLD_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal), + PathCondition => dual AND not(ddr) AND QUAD = '1'), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR), + PathCondition => ddr AND QUAD = '1'), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND + HOLDNegOut_zd = 'Z' AND QUAD = '1') + ) + ); + END PROCESS; + + WP_Out_PathDelay : PROCESS(WPNegOut_zd) + + VARIABLE WP_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => WPNegOut, + OutSignalName => "WPNeg", + OutTemp => WPNegOut_zd, + Mode => VitalTransport, + GlitchData => WP_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_normal), + PathCondition => dual AND not(ddr) AND QUAD = '1'), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO_DDR), + PathCondition => ddr AND QUAD = '1'), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND + WPNegOut_zd = 'Z' AND QUAD = '1') + ) + ); + END PROCESS; + + END BLOCK behavior; +END vhdl_behavioral_static_memory_allocation; \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl512s/model/s25fl512s_ver.ftm b/lib/models/memory/flash/serial/S25fl512s/model/s25fl512s_ver.ftm new file mode 100644 index 0000000..fbc6513 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl512s/model/s25fl512s_ver.ftm @@ -0,0 +1,511 @@ + +FMF Timing for s25fl512s Parts + + +version: | author: | mod date: | changes made: + V1.0 R. Prokopovic 09 Nov 27 Initial release + V1.1 V.Mancev 10 Oct 20 Latest datasheet aligned + V1.2 B.Colakovic 11 July 11 Latest datasheet aligned + V1.3 V.Mancev 11 Nov 17 Time tHO is changed to 1 ns + +1ns +s25fl512s + +S25FL512SAGMFI010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFI011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFI013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFIR10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFIR11_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFIR13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFV010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFV011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFV013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFVR10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFVR11_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFVR13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI210_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI213_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI310_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI313_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIA10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIA13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIB10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIB13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIC10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIC13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHID10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHID13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV210_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV213_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV310_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV313_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVA10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVA13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVB10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVB13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVC10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVC13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVD10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVD13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIY10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIY13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIZ10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIZ13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIS10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIS13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIT10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIT13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIK10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIK13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIL10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIL13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for VIO=VCC=2.7V to 3.6V, CL=30pF + +(DELAY (ABSOLUTE + (COND ~ddr (IOPATH SCK SO (5.4:6.7:8) (5.4:6.7:8) (1) (5.4:6.7:8) (1) (5.4:6.7:8))) + (COND (ddr || rd_fast) (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && dual (IOPATH SCK SI (5.4:6.7:8) (5.4:6.7:8) (1) (5.4:6.7:8) (1) (5.4:6.7:8))) + (COND ddr && dual (IOPATH SCK SI (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND ~ddr && QUAD (IOPATH SCK HOLDNeg (5.4:6.7:8) (5.4:6.7:8) (1) (5.4:6.7:8) (1) (5.4:6.7:8))) + (COND ddr && QUAD (IOPATH SCK HOLDNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && QUAD (IOPATH SCK WPNeg (5.4:6.7:8) (5.4:6.7:8) (1) (5.4:6.7:8) (1) (5.4:6.7:8))) + (COND ddr && QUAD (IOPATH SCK WPNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && dual (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~QUAD (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND ~QUAD && dual (IOPATH HOLDNeg SI () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP CSNeg (COND sdr_rd SCK) (3)) + (SETUP CSNeg (COND ddr_rd SCK) (3)) + (SETUP SI (COND deg_sin(posedge SCK)) (3)) + (SETUP SI (COND ddro(posedge SCK)) (2)) + (SETUP SI (COND ddro(negedge SCK)) (2)) + (SETUP WPNeg (COND wr_prot(negedge CSNeg)) (20)) + (SETUP HOLDNeg (COND quad_rd (posedge SCK)) (3)) + (SETUP RSTNeg CSNeg (50)) + + (HOLD CSNeg (COND sdr_rd SCK) (3)) + (HOLD CSNeg (COND ddr_rd SCK) (3)) + (HOLD SI (COND deg_sin (posedge SCK)) (2)) + (HOLD SI (COND ddro (posedge SCK)) (2)) + (HOLD SI (COND ddro (negedge SCK)) (2)) + (HOLD WPNeg (COND wr_prot (posedge CSNeg)) (100)) + (HOLD HOLDNeg (COND quad_rd (posedge SCK)) (3)) + (HOLD CSNeg RSTNeg (35000)) + + (WIDTH (COND rd (posedge SCK)) (10)) + (WIDTH (COND rd (negedge SCK)) (10)) + (WIDTH (COND dual_rd (posedge SCK)) (4.8)) + (WIDTH (COND dual_rd (negedge SCK)) (4.8)) + (WIDTH (COND fast_rd (negedge SCK)) (3.75)) + (WIDTH (COND fast_rd (posedge SCK)) (3.75)) + (WIDTH (COND quadpg (posedge SCK)) (6.25)) + (WIDTH (COND quadpg (negedge SCK)) (6.25)) + (WIDTH (COND ddrd (posedge SCK)) (7.5)) + (WIDTH (COND ddrd (negedge SCK)) (7.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (7.52)) + (PERIOD (COND dual_rd SCK) (9.6)) + (PERIOD (COND quadpg SCK) (12.5)) + (PERIOD (COND ddrd SCK) (15)) +) + + + +S25FL512SAGMFI010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFI011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFI013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFIR10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFIR11_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFIR13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFV010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFV011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFV013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFVR10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFVR11_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFVR13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI210_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI213_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI310_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI313_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIA10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIA13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIB10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIB13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIC10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIC13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHID10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHID13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV210_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV213_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV310_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV313_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVA10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVA13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVB10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVB13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVC10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVC13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVD10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVD13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIY10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIY13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIZ10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIZ13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIS10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIS13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIT10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIT13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIK10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIK13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIL10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIL13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=30pF + +(DELAY (ABSOLUTE + (COND ~ddr (IOPATH SCK SO (4.3:6.0:7.65) (4.3:6.0:7.65) (1) (4.3:6.0:7.65) (1) (4.3:6.0:7.65))) + (COND (ddr || rd_fast) (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && dual (IOPATH SCK SI (4.3:6.0:7.65) (4.3:6.0:7.65) (1) (4.3:6.0:7.65) (1) (4.3:6.0:7.65))) + (COND ddr && dual (IOPATH SCK SI (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND ~ddr && QUAD (IOPATH SCK HOLDNeg (4.3:6.0:7.65) (4.3:6.0:7.65) (1) (4.3:6.0:7.65) (1) (4.3:6.0:7.65))) + (COND ddr && QUAD (IOPATH SCK HOLDNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && QUAD (IOPATH SCK WPNeg (4.3:6.0:7.65) (4.3:6.0:7.65) (1) (4.3:6.0:7.65) (1) (4.3:6.0:7.65))) + (COND ddr && QUAD (IOPATH SCK WPNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && dual (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~QUAD (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND ~QUAD && dual (IOPATH HOLDNeg SI () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP CSNeg (COND sdr_rd SCK) (3)) + (SETUP CSNeg (COND ddr_rd SCK) (3)) + (SETUP SI (COND deg_sin(posedge SCK)) (3)) + (SETUP SI (COND ddro(posedge SCK)) (2)) + (SETUP SI (COND ddro(negedge SCK)) (2)) + (SETUP WPNeg (COND wr_prot(negedge CSNeg)) (20)) + (SETUP HOLDNeg (COND quad_rd (posedge SCK)) (3)) + (SETUP RSTNeg CSNeg (50)) + + (HOLD CSNeg (COND sdr_rd SCK) (3)) + (HOLD CSNeg (COND ddr_rd SCK) (3)) + (HOLD SI (COND deg_sin (posedge SCK)) (2)) + (HOLD SI (COND ddro (posedge SCK)) (2)) + (HOLD SI (COND ddro (negedge SCK)) (2)) + (HOLD WPNeg (COND wr_prot (posedge CSNeg)) (100)) + (HOLD HOLDNeg (COND quad_rd (posedge SCK)) (3)) + (HOLD CSNeg RSTNeg (35000)) + + (WIDTH (COND rd (posedge SCK)) (10)) + (WIDTH (COND rd (negedge SCK)) (10)) + (WIDTH (COND dual_rd (posedge SCK)) (4.8)) + (WIDTH (COND dual_rd (negedge SCK)) (4.8)) + (WIDTH (COND fast_rd (negedge SCK)) (3.75)) + (WIDTH (COND fast_rd (posedge SCK)) (3.75)) + (WIDTH (COND quadpg (posedge SCK)) (6.25)) + (WIDTH (COND quadpg (negedge SCK)) (6.25)) + (WIDTH (COND ddrd (posedge SCK)) (7.5)) + (WIDTH (COND ddrd (negedge SCK)) (7.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (7.52)) + (PERIOD (COND dual_rd SCK) (9.6)) + (PERIOD (COND quadpg SCK) (12.5)) + (PERIOD (COND ddrd SCK) (15)) +) + + + +S25FL512SAGMFI010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFI011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFI013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFIR10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFIR11_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFIR13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFV010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFV011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFV013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFVR10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFVR11_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFVR13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI210_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI213_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI310_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI313_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIA10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIA13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIB10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIB13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIC10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIC13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHID10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHID13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV210_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV213_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV310_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV313_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVA10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVA13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVB10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVB13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVC10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVC13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVD10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVD13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIY10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIY13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIZ10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIZ13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIS10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIS13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIT10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIT13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIK10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIK13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIL10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIL13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=15pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND ~ddr (IOPATH SCK SO (4.5:5.5:6.5) (4.5:5.5:6.5) (1) (4.5:5.5:6.5) (1) (4.5:5.5:6.5))) + (COND (ddr || rd_fast) (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && dual (IOPATH SCK SI (4.5:5.5:6.5) (4.5:5.5:6.5) (1) (4.5:5.5:6.5) (1) (4.5:5.5:6.5))) + (COND ddr && dual (IOPATH SCK SI (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND ~ddr && QUAD (IOPATH SCK HOLDNeg (4.5:5.5:6.5) (4.5:5.5:6.5) (1) (4.5:5.5:6.5) (1) (4.5:5.5:6.5))) + (COND ddr && QUAD (IOPATH SCK HOLDNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && QUAD (IOPATH SCK WPNeg (4.5:5.5:6.5) (4.5:5.5:6.5) (1) (4.5:5.5:6.5) (1) (4.5:5.5:6.5))) + (COND ddr && QUAD (IOPATH SCK WPNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && dual (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~QUAD (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND ~QUAD && dual (IOPATH HOLDNeg SI () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP CSNeg (COND sdr_rd SCK) (3)) + (SETUP CSNeg (COND ddr_rd SCK) (3)) + (SETUP SI (COND deg_sin(posedge SCK)) (3)) + (SETUP SI (COND ddro(posedge SCK)) (2)) + (SETUP SI (COND ddro(negedge SCK)) (2)) + (SETUP WPNeg (COND wr_prot(negedge CSNeg)) (20)) + (SETUP HOLDNeg (COND quad_rd (posedge SCK)) (3)) + (SETUP RSTNeg CSNeg (50)) + + (HOLD CSNeg (COND sdr_rd SCK) (3)) + (HOLD CSNeg (COND ddr_rd SCK) (3)) + (HOLD SI (COND deg_sin (posedge SCK)) (2)) + (HOLD SI (COND ddro (posedge SCK)) (2)) + (HOLD SI (COND ddro (negedge SCK)) (2)) + (HOLD WPNeg (COND wr_prot (posedge CSNeg)) (100)) + (HOLD HOLDNeg (COND quad_rd (posedge SCK)) (3)) + (HOLD CSNeg RSTNeg (35000)) + + (WIDTH (COND rd (posedge SCK)) (10)) + (WIDTH (COND rd (negedge SCK)) (10)) + (WIDTH (COND dual_rd (posedge SCK)) (4.8)) + (WIDTH (COND dual_rd (negedge SCK)) (4.8)) + (WIDTH (COND fast_rd (negedge SCK)) (3.75)) + (WIDTH (COND fast_rd (posedge SCK)) (3.75)) + (WIDTH (COND quadpg (posedge SCK)) (6.25)) + (WIDTH (COND quadpg (negedge SCK)) (6.25)) + (WIDTH (COND ddrd (posedge SCK)) (7.5)) + (WIDTH (COND ddrd (negedge SCK)) (7.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (7.52)) + (PERIOD (COND dual_rd SCK) (9.6)) + (PERIOD (COND quadpg SCK) (12.5)) + (PERIOD (COND ddrd SCK) (15)) +) + + + +S25FL512SDPMFIR10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPMFIR11_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPMFIR13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHI210_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHI213_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHI310_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHI313_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHIC10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHIC13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHID10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHID13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for Vcc range VCC=2.7V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND ~ddr (IOPATH SCK SO (1.5:8:14.5) (1.5:8:14.5) (1) (1.5:8:14.5) (1) (1.5:8:14.5))) + (COND (ddr || rd_fast) (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && dual (IOPATH SCK SI (1.5:8:14.5) (1.5:8:14.5) (1) (1.5:8:14.5) (1) (1.5:8:14.5))) + (COND ddr && dual (IOPATH SCK SI (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND ~ddr && QUAD (IOPATH SCK HOLDNeg (1.5:8:14.5) (1.5:8:14.5) (1) (1.5:8:14.5) (1) (1.5:8:14.5))) + (COND ddr && QUAD (IOPATH SCK HOLDNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && QUAD (IOPATH SCK WPNeg (1.5:8:14.5) (1.5:8:14.5) (1) (1.5:8:14.5) (1) (1.5:8:14.5))) + (COND ddr && QUAD (IOPATH SCK WPNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && dual (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~QUAD (IOPATH HOLDNeg SO () () (7:10.5:14) (7:10.5:14) (7:10.5:14) (7:10.5:14))) + (COND ~QUAD && dual (IOPATH HOLDNeg SI () () (7:10.5:14) (7:10.5:14) (7:10.5:14) (7:10.5:14))) + + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP CSNeg (COND sdr_rd SCK) (3)) + (SETUP CSNeg (COND ddr_rd SCK) (3)) + (SETUP SI (COND deg_sin(posedge SCK)) (5)) + (SETUP SI (COND ddro(posedge SCK)) (2)) + (SETUP SI (COND ddro(negedge SCK)) (2)) + (SETUP WPNeg (COND wr_prot(negedge CSNeg)) (20)) + (SETUP HOLDNeg (COND quad_rd (posedge SCK)) (5)) + (SETUP RSTNeg CSNeg (50)) + + (HOLD CSNeg (COND sdr_rd SCK) (3)) + (HOLD CSNeg (COND ddr_rd SCK) (3)) + (HOLD SI (COND deg_sin (posedge SCK)) (4)) + (HOLD SI (COND ddro (posedge SCK)) (2)) + (HOLD SI (COND ddro (negedge SCK)) (2)) + (HOLD WPNeg (COND wr_prot (posedge CSNeg)) (100)) + (HOLD HOLDNeg (COND quad_rd (posedge SCK)) (5)) + (HOLD CSNeg RSTNeg (35000)) + + (WIDTH (COND rd (posedge SCK)) (10)) + (WIDTH (COND rd (negedge SCK)) (10)) + (WIDTH (COND dual_rd (posedge SCK)) (7.5)) + (WIDTH (COND dual_rd (negedge SCK)) (7.5)) + (WIDTH (COND fast_rd (negedge SCK)) (7.5)) + (WIDTH (COND fast_rd (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (negedge SCK)) (7.5)) + (WIDTH (COND ddrd (posedge SCK)) (7.5)) + (WIDTH (COND ddrd (negedge SCK)) (7.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (15)) + (PERIOD (COND dual_rd SCK) (15)) + (PERIOD (COND quadpg SCK) (15)) + (PERIOD (COND ddrd SCK) (15)) +) + + + +S25FL512SDPMFIR10_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPMFIR11_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPMFIR13_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHI210_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHI213_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHI310_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHI313_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHIC10_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHIC13_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHID10_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHID13_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for Vcc range VCC=2.7V to 3.6V, CL=15pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND ~ddr (IOPATH SCK SO (2:7:12) (2:7:12) (1) (2:7:12) (1) (2:7:12))) + (COND (ddr || rd_fast) (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && dual (IOPATH SCK SI (2:7:12) (2:7:12) (1) (2:7:12) (1) (2:7:12))) + (COND ddr && dual (IOPATH SCK SI (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND ~ddr && QUAD (IOPATH SCK HOLDNeg (2:7:12) (2:7:12) (1) (2:7:12) (1) (2:7:12))) + (COND ddr && QUAD (IOPATH SCK HOLDNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (COND ~ddr && QUAD (IOPATH SCK WPNeg (2:7:12) (2:7:12) (1) (2:7:12) (1) (2:7:12))) + (COND ddr && QUAD (IOPATH SCK WPNeg (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && dual (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + (COND CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~QUAD (IOPATH HOLDNeg SO () () (7:10.5:14) (7:10.5:14) (7:10.5:14) (7:10.5:14))) + (COND ~QUAD && dual (IOPATH HOLDNeg SI () () (7:10.5:14) (7:10.5:14) (7:10.5:14) (7:10.5:14))) + + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP CSNeg (COND sdr_rd SCK) (3)) + (SETUP CSNeg (COND ddr_rd SCK) (3)) + (SETUP SI (COND deg_sin(posedge SCK)) (5)) + (SETUP SI (COND ddro(posedge SCK)) (2)) + (SETUP SI (COND ddro(negedge SCK)) (2)) + (SETUP WPNeg (COND wr_prot(negedge CSNeg)) (20)) + (SETUP HOLDNeg (COND quad_rd (posedge SCK)) (5)) + (SETUP RSTNeg CSNeg (50)) + + (HOLD CSNeg (COND sdr_rd SCK) (3)) + (HOLD CSNeg (COND ddr_rd SCK) (3)) + (HOLD SI (COND deg_sin (posedge SCK)) (4)) + (HOLD SI (COND ddro (posedge SCK)) (2)) + (HOLD SI (COND ddro (negedge SCK)) (2)) + (HOLD WPNeg (COND wr_prot (posedge CSNeg)) (100)) + (HOLD HOLDNeg (COND quad_rd (posedge SCK)) (5)) + (HOLD CSNeg RSTNeg (35000)) + + (WIDTH (COND rd (posedge SCK)) (10)) + (WIDTH (COND rd (negedge SCK)) (10)) + (WIDTH (COND dual_rd (posedge SCK)) (7.5)) + (WIDTH (COND dual_rd (negedge SCK)) (7.5)) + (WIDTH (COND fast_rd (negedge SCK)) (7.5)) + (WIDTH (COND fast_rd (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (negedge SCK)) (7.5)) + (WIDTH (COND ddrd (posedge SCK)) (7.5)) + (WIDTH (COND ddrd (negedge SCK)) (7.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (15)) + (PERIOD (COND dual_rd SCK) (15)) + (PERIOD (COND quadpg SCK) (15)) + (PERIOD (COND ddrd SCK) (15)) +) + + \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl512s/model/s25fl512s_vhd.ftm b/lib/models/memory/flash/serial/S25fl512s/model/s25fl512s_vhd.ftm new file mode 100644 index 0000000..4bef23a --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl512s/model/s25fl512s_vhd.ftm @@ -0,0 +1,547 @@ + +FMF Timing for s25fl512s Parts + + +version: | author: | mod date: | changes made: + V1.0 V.Mancev 09 Nov 26 Initial release + V1.1 V.Mancev 11 July 11 Latest datasheet aligned + V1.2 V.Mancev 11 Nov 17 Time tHO is changed to 1 ns + +1ns +s25fl512s + +S25FL512SAGMFI010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFI011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFI013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFIR10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFIR11_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFIR13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFV010_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFV011_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFV013_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFVR10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFVR11_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFVR13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI210_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI213_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI310_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI313_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIA10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIA13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIB10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIB13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIC10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIC13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHID10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHID13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV210_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV213_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV310_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV313_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVA10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVA13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVB10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVB13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVC10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVC13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVD10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVD13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIY10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIY13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIZ10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIZ13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIS10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIS13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIT10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIT13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIK10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIK13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIL10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIL13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for VCC=2.7V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND normal (IOPATH SCK SO (5.4:6.7:8) (5.4:6.7:8) (1) (5.4:6.7:8) (1) (5.4:6.7:8))) + (COND DDR (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP (COND normal CSNeg) (posedge SCK) (3)) + (SETUP (COND DDR CSNeg) (posedge SCK) (3)) + (SETUP (COND normal SI) (posedge SCK) (3)) + (SETUP WPNeg CSNeg (20)) + (SETUP HOLDNeg SCK (3)) + (SETUP RSTNeg CSNeg (50)) + (SETUP (COND DDR SI) (posedge SCK) (2)) + (SETUP (COND DDR SI) (negedge SCK) (2)) + + (HOLD (COND normal CSNeg) (posedge SCK) (3)) + (HOLD (COND DDR CSNeg) (posedge SCK) (3)) + (HOLD (COND normal SI) (posedge SCK) (2)) + (HOLD WPNeg CSNeg (100)) + (HOLD HOLDNeg SCK (3)) + (HOLD CSNeg RSTNeg (35000)) + (HOLD (COND DDR SI) (posedge SCK) (2)) + (HOLD (COND DDR SI) (negedge SCK) (2)) + + (WIDTH (COND serial (posedge SCK)) (10)) + (WIDTH (COND serial (negedge SCK)) (10)) + (WIDTH (COND dual (posedge SCK)) (4.8)) + (WIDTH (COND dual (negedge SCK)) (4.8)) + (WIDTH (COND fast (negedge SCK)) (3.75)) + (WIDTH (COND fast (posedge SCK)) (3.75)) + (WIDTH (COND quadpg (posedge SCK)) (6.25)) + (WIDTH (COND quadpg (negedge SCK)) (6.25)) + (WIDTH (COND DDR (posedge SCK)) (7.5)) + (WIDTH (COND DDR (negedge SCK)) (7.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgers (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND serial_rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (7.52)) + (PERIOD (COND dual_rd SCK) (9.6)) + (PERIOD (COND quadpg SCK) (12.5)) + (PERIOD (COND DDR_rd SCK) (15)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP) (DELAY (ABSOLUTE (DEVICE(200e3:340e3:750e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BP) (DELAY (ABSOLUTE (DEVICE(100e3:150e3:400e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE) (DELAY (ABSOLUTE (DEVICE(200e6:400e6:1875e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(55e9:103e9:460e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WRR) (DELAY (ABSOLUTE(DEVICE(200e6:200e6:200e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300e3:300e3:300e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PRGSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/ERSSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PPBERASE) (DELAY (ABSOLUTE (DEVICE(15e6:15e6:15e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSULCK) (DELAY (ABSOLUTE (DEVICE(1000:1000:1000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSACC) (DELAY (ABSOLUTE (DEVICE(100e3:100e3:100e3) ) ) ) + + + +S25FL512SAGMFI010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFI011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFI013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFIR10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFIR11_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFIR13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFV010_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFV011_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFV013_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFVR10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFVR11_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFVR13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI210_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI213_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI310_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI313_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIA10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIA13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIB10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIB13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIC10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIC13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHID10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHID13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV210_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV213_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV310_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV313_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVA10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVA13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVB10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVB13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVC10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVC13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVD10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVD13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIY10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIY13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIZ10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIZ13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIS10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIS13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIT10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIT13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIK10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIK13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIL10_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIL13_R_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND normal (IOPATH SCK SO (4.3:6.0:7.65) (4.3:6.0:7.65) (1) (4.3:6.0:7.65) (1) (4.3:6.0:7.65))) + (COND DDR (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP (COND normal CSNeg) (posedge SCK) (3)) + (SETUP (COND DDR CSNeg) (posedge SCK) (3)) + (SETUP (COND normal SI) (posedge SCK) (3)) + (SETUP WPNeg CSNeg (20)) + (SETUP HOLDNeg SCK (3)) + (SETUP RSTNeg CSNeg (50)) + (SETUP (COND DDR SI) (posedge SCK) (2)) + (SETUP (COND DDR SI) (negedge SCK) (2)) + + (HOLD (COND normal CSNeg) (posedge SCK) (3)) + (HOLD (COND DDR CSNeg) (posedge SCK) (3)) + (HOLD (COND normal SI) (posedge SCK) (2)) + (HOLD WPNeg CSNeg (100)) + (HOLD HOLDNeg SCK (3)) + (HOLD CSNeg RSTNeg (35000)) + (HOLD (COND DDR SI) (posedge SCK) (2)) + (HOLD (COND DDR SI) (negedge SCK) (2)) + + (WIDTH (COND serial (posedge SCK)) (10)) + (WIDTH (COND serial (negedge SCK)) (10)) + (WIDTH (COND dual (posedge SCK)) (4.8)) + (WIDTH (COND dual (negedge SCK)) (4.8)) + (WIDTH (COND fast (negedge SCK)) (3.75)) + (WIDTH (COND fast (posedge SCK)) (3.75)) + (WIDTH (COND quadpg (posedge SCK)) (6.25)) + (WIDTH (COND quadpg (negedge SCK)) (6.25)) + (WIDTH (COND DDR (posedge SCK)) (7.5)) + (WIDTH (COND DDR (negedge SCK)) (7.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgers (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND serial_rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (7.52)) + (PERIOD (COND dual_rd SCK) (9.6)) + (PERIOD (COND quadpg SCK) (12.5)) + (PERIOD (COND DDR_rd SCK) (15)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP) (DELAY (ABSOLUTE (DEVICE(200e3:340e3:750e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BP) (DELAY (ABSOLUTE (DEVICE(100e3:150e3:400e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE) (DELAY (ABSOLUTE (DEVICE(200e6:400e6:1875e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(55e9:103e9:460e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WRR) (DELAY (ABSOLUTE(DEVICE(200e6:200e6:200e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300e3:300e3:300e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PRGSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/ERSSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PPBERASE) (DELAY (ABSOLUTE (DEVICE(15e6:15e6:15e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSULCK) (DELAY (ABSOLUTE (DEVICE(1000:1000:1000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSACC) (DELAY (ABSOLUTE (DEVICE(100e3:100e3:100e3) ) ) ) + + + +S25FL512SAGMFI010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFI011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFI013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFIR10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFIR11_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFIR13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFV010_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFV011_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFV013_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFVR10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFVR11_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGMFVR13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI210_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI213_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI310_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHI313_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIA10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIA13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIB10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIB13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIC10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIC13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHID10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHID13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV210_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV213_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV310_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHV313_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVA10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVA13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVB10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVB13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVC10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVC13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVD10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHVD13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIY10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIY13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIZ10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIZ13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIS10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIS13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIT10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIT13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIK10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIK13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIL10_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SAGBHIL13_R_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=15pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND normal (IOPATH SCK SO (4.5:5.5:6.5) (4.5:5.5:6.5) (1) (4.5:5.5:6.5) (1) (4.5:5.5:6.5))) + (COND DDR (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP (COND normal CSNeg) (posedge SCK) (3)) + (SETUP (COND DDR CSNeg) (posedge SCK) (3)) + (SETUP (COND normal SI) (posedge SCK) (3)) + (SETUP WPNeg CSNeg (20)) + (SETUP HOLDNeg SCK (3)) + (SETUP RSTNeg CSNeg (50)) + (SETUP (COND DDR SI) (posedge SCK) (2)) + (SETUP (COND DDR SI) (negedge SCK) (2)) + + (HOLD (COND normal CSNeg) (posedge SCK) (3)) + (HOLD (COND DDR CSNeg) (posedge SCK) (3)) + (HOLD (COND normal SI) (posedge SCK) (2)) + (HOLD WPNeg CSNeg (100)) + (HOLD HOLDNeg SCK (3)) + (HOLD CSNeg RSTNeg (35000)) + (HOLD (COND DDR SI) (posedge SCK) (2)) + (HOLD (COND DDR SI) (negedge SCK) (2)) + + (WIDTH (COND serial (posedge SCK)) (10)) + (WIDTH (COND serial (negedge SCK)) (10)) + (WIDTH (COND dual (posedge SCK)) (4.8)) + (WIDTH (COND dual (negedge SCK)) (4.8)) + (WIDTH (COND fast (negedge SCK)) (3.75)) + (WIDTH (COND fast (posedge SCK)) (3.75)) + (WIDTH (COND quadpg (posedge SCK)) (6.25)) + (WIDTH (COND quadpg (negedge SCK)) (6.25)) + (WIDTH (COND DDR (posedge SCK)) (7.5)) + (WIDTH (COND DDR (negedge SCK)) (7.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgers (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND serial_rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (7.52)) + (PERIOD (COND dual_rd SCK) (9.6)) + (PERIOD (COND quadpg SCK) (12.5)) + (PERIOD (COND DDR_rd SCK) (15)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP) (DELAY (ABSOLUTE (DEVICE(200e3:340e3:750e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BP) (DELAY (ABSOLUTE (DEVICE(100e3:150e3:400e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE) (DELAY (ABSOLUTE (DEVICE(200e6:400e6:1875e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(55e9:103e9:460e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WRR) (DELAY (ABSOLUTE(DEVICE(200e6:200e6:200e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300e3:300e3:300e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PRGSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/ERSSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PPBERASE) (DELAY (ABSOLUTE (DEVICE(15e6:15e6:15e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSULCK) (DELAY (ABSOLUTE (DEVICE(1000:1000:1000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSACC) (DELAY (ABSOLUTE (DEVICE(100e3:100e3:100e3) ) ) ) + + + +S25FL512SDPMFIR10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPMFIR11_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPMFIR13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHI210_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHI213_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHI310_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHI313_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHIC10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHIC13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHID10_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHID13_F_30pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND normal (IOPATH SCK SO (1.5:8:14.5) (1.5:8:14.5) (1) (1.5:8:14.5) (1) (1.5:8:14.5))) + (COND DDR (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + (IOPATH HOLDNeg SO () () (10:12:14) (10:12:14) (10:12:14) (10:12:14)) + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP (COND normal CSNeg) (posedge SCK) (3)) + (SETUP (COND DDR CSNeg) (posedge SCK) (3)) + (SETUP (COND normal SI) (posedge SCK) (5)) + (SETUP WPNeg CSNeg (20)) + (SETUP HOLDNeg SCK (5)) + (SETUP RSTNeg CSNeg (50)) + (SETUP (COND DDR SI) (posedge SCK) (2)) + (SETUP (COND DDR SI) (negedge SCK) (2)) + + (HOLD (COND normal CSNeg) (posedge SCK) (3)) + (HOLD (COND DDR CSNeg) (posedge SCK) (3)) + (HOLD (COND normal SI) (posedge SCK) (4)) + (HOLD WPNeg CSNeg (100)) + (HOLD HOLDNeg SCK (5)) + (HOLD CSNeg RSTNeg (35000)) + (HOLD (COND DDR SI) (posedge SCK) (2)) + (HOLD (COND DDR SI) (negedge SCK) (2)) + + (WIDTH (COND serial (posedge SCK)) (10)) + (WIDTH (COND serial (negedge SCK)) (10)) + (WIDTH (COND dual (posedge SCK)) (7.5)) + (WIDTH (COND dual (negedge SCK)) (7.5)) + (WIDTH (COND fast (negedge SCK)) (7.5)) + (WIDTH (COND fast (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (negedge SCK)) (7.5)) + (WIDTH (COND DDR (posedge SCK)) (7.5)) + (WIDTH (COND DDR (negedge SCK)) (7.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgers (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND serial_rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (15)) + (PERIOD (COND dual_rd SCK) (15)) + (PERIOD (COND quadpg SCK) (15)) + (PERIOD (COND DDR_rd SCK) (15)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP) (DELAY (ABSOLUTE (DEVICE(200e3:340e3:750e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BP) (DELAY (ABSOLUTE (DEVICE(100e3:150e3:400e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE) (DELAY (ABSOLUTE (DEVICE(200e6:400e6:1875e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(55e9:103e9:460e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WRR) (DELAY (ABSOLUTE(DEVICE(200e6:200e6:200e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300e3:300e3:300e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PRGSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/ERSSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PPBERASE) (DELAY (ABSOLUTE (DEVICE(15e6:15e6:15e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSULCK) (DELAY (ABSOLUTE (DEVICE(1000:1000:1000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSACC) (DELAY (ABSOLUTE (DEVICE(100e3:100e3:100e3) ) ) ) + + + +S25FL512SDPMFIR10_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPMFIR11_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPMFIR13_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHI210_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHI213_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHI310_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHI313_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHIC10_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHIC13_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHID10_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +S25FL512SDPBHID13_F_15pF Spansion, FL-S_PPD_2.0 April 1, 2011 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=15pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (COND normal (IOPATH SCK SO (2:7:12) (2:7:12) (1) (2:7:12) (1) (2:7:12))) + (COND DDR (IOPATH SCK SO (1.5:4:6.5) (1.5:4:6.5) (1) (1.5:4:6.5) (1) (1.5:4:6.5))) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + (IOPATH HOLDNeg SO () () (10:12:14) (10:12:14) (10:12:14) (10:12:14)) + (IOPATH RSTNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + )) + (TIMINGCHECK + (SETUP (COND normal CSNeg) (posedge SCK) (3)) + (SETUP (COND DDR CSNeg) (posedge SCK) (3)) + (SETUP (COND normal SI) (posedge SCK) (5)) + (SETUP WPNeg CSNeg (20)) + (SETUP HOLDNeg SCK (5)) + (SETUP RSTNeg CSNeg (50)) + (SETUP (COND DDR SI) (posedge SCK) (2)) + (SETUP (COND DDR SI) (negedge SCK) (2)) + + (HOLD (COND normal CSNeg) (posedge SCK) (3)) + (HOLD (COND DDR CSNeg) (posedge SCK) (3)) + (HOLD (COND normal SI) (posedge SCK) (4)) + (HOLD WPNeg CSNeg (100)) + (HOLD HOLDNeg SCK (5)) + (HOLD CSNeg RSTNeg (35000)) + (HOLD (COND DDR SI) (posedge SCK) (2)) + (HOLD (COND DDR SI) (negedge SCK) (2)) + + (WIDTH (COND serial (posedge SCK)) (10)) + (WIDTH (COND serial (negedge SCK)) (10)) + (WIDTH (COND dual (posedge SCK)) (7.5)) + (WIDTH (COND dual (negedge SCK)) (7.5)) + (WIDTH (COND fast (negedge SCK)) (7.5)) + (WIDTH (COND fast (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (posedge SCK)) (7.5)) + (WIDTH (COND quadpg (negedge SCK)) (7.5)) + (WIDTH (COND DDR (posedge SCK)) (7.5)) + (WIDTH (COND DDR (negedge SCK)) (7.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgers (posedge CSNeg)) (50)) + (WIDTH (negedge RSTNeg) (200)) + (WIDTH (posedge RSTNeg) (50)) + (PERIOD (COND serial_rd SCK) (20)) + (PERIOD (COND fast_rd SCK) (15)) + (PERIOD (COND dual_rd SCK) (15)) + (PERIOD (COND quadpg SCK) (15)) + (PERIOD (COND DDR_rd SCK) (15)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP) (DELAY (ABSOLUTE (DEVICE(200e3:340e3:750e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BP) (DELAY (ABSOLUTE (DEVICE(100e3:150e3:400e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE) (DELAY (ABSOLUTE (DEVICE(200e6:400e6:1875e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(55e9:103e9:460e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WRR) (DELAY (ABSOLUTE(DEVICE(200e6:200e6:200e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300e3:300e3:300e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PRGSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/ERSSUSP) (DELAY (ABSOLUTE (DEVICE(40e3:40e3:40e3) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PPBERASE) (DELAY (ABSOLUTE (DEVICE(15e6:15e6:15e6) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSULCK) (DELAY (ABSOLUTE (DEVICE(1000:1000:1000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PASSACC) (DELAY (ABSOLUTE (DEVICE(100e3:100e3:100e3) ) ) ) + + \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl512s/utilities/CreateSDF/mk_sdf.cmd b/lib/models/memory/flash/serial/S25fl512s/utilities/CreateSDF/mk_sdf.cmd new file mode 100644 index 0000000..f6d6cc7 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl512s/utilities/CreateSDF/mk_sdf.cmd @@ -0,0 +1,10 @@ +SET sdffile_suffix .sdf +SET use_global_timing_dir false +SET timingfile_dir /user/USERNAME/CreateSDF +SET timingfile_suffix .ftm +SET time_scale 1ns +SET local_path . +SET vendor MODELSIM_HOME +SET diagnostics on +SET vhdl_file testbench.vhd +SET lwb false diff --git a/lib/models/memory/flash/serial/S25fl512s/utilities/CreateSDF/mk_sdf_204.pl b/lib/models/memory/flash/serial/S25fl512s/utilities/CreateSDF/mk_sdf_204.pl new file mode 100644 index 0000000..5f2f2b8 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl512s/utilities/CreateSDF/mk_sdf_204.pl @@ -0,0 +1,462 @@ +#!/usr/local/bin/perl +# +# mk_sdf : Perl replacement for C mk_sdf +# +# Copyright (C) 2000, 1999 Free Model Foundry; http:/vhdl.org/fmf/ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# Author : R. Munden +# Date : 20001115 +# Version : 2.0.4 +# +# Revision history: +# 2.0: 19990702 +# o Intial release of perl version +# 2.0.1: 19990722 +# o fixed problem with . in path for TimingModels +# 2.0.2: 20000616 +# o changed instance search to work with Mentor +# 2.0.3: 20001115 +# o changed to parse ":" without leading space +# o fixed problem with . in path for TimingModels again +# 2.0.4: 20030405 +# o chaged SDF version to 3.0 +# +################################################################# +# +# command line arguments: + +# ARGV[0] - name of VHDL netlist + +# global variables: + +# %component_list - list of instance names by component name +# %instance_isin - list architectures by instances contained therein +# %instance_comp - list of component names by instance name +# %comp_lib - library each component (by name) is configured to +# @instance_list - array of all instance names in design in order found + +$version = "2.0.4"; +$design_name = ''; +$timing_dir = ''; +$diags = "off"; + +%keywords = (architecture => 1, + component => 1, + timingmodel => 1); + +# INPUT files +$CMD = "mk_sdf.cmd"; +$VHD = ''; # name of VHDL netlist + +# OUTPUT files +$RFV = "/tmp/short.vhd"; # reformatted VHDL +$sdf_file = ''; # name of SDF file + +&read_cmd_file; +&get_names; +&reformat; + +open INPUT, $RFV; +@lines = ; +close INPUT; + +$current_architecture = ""; + +foreach $line (@lines) +{ + @words = split / /, $line; + foreach $word (@words) + { + $keywords{$word} == "1" and do { &$word(@words);}; + if ($component_list{$word}) + { + $line =~ /(.+) : $word/ and do { + if ($1 !~ /for/) { # instantiation found + $component_list{$word} = $component_list{$word} . $1; + push (@instance_list, $1); + $instance_name = $1; + } + }; + $instance_comp{$1} = $word; + $instance_isin{$1} = $current_architecture; + if ( $diags ne off ) { + print "reading instance $instance_name: $word in $current_architecture\n"; + } + $line =~ /for all : $word use entity (.+)/ and do + { + @config = split(/\./, $1); + $comp_lib{$word} = $config[0];}; + } + } +} +if ( $diags ne off ) { + print "finished with netlist\n\n"; +} + +&begin_sdf; +&build_paths; +&close_sdf; +`rm $RFV`; + +print "$time\n"; + +sub architecture +{ + $current_architecture = $_[3]; + push (@architectures, $current_architecture); +} + +sub component +{ + if ($_[0] ne "end") + { + $name = $_[1]; + $arch_list{$current_architecture} = + $arch_list{$current_architecture} . " " . $name; + unless ($component_list{$name}) { $component_list{$name} = " ";} + } +} + +sub timingmodel +{ + $line =~ /timingmodel => \"(.+)\"/ and do { + $model = $1; + $model_name{$instance_name} = $model; + }; +} + +sub begin_sdf +{ + if ( $diags ne off ) { + print "writing SDF boilerplate\n"; + } + $time = localtime; + if (open(SDF, ">$sdf_file") !=1) { die "can't open $sdf_file\n";} + print "Opening $sdf_file\n"; + print SDF "(DELAYFILE\n"; + print SDF " (SDFVERSION \"3.0\")\n"; + print SDF " (DESIGN \"$design_name\")\n"; + print SDF " (DATE \"$time\")\n"; + print SDF " (VENDOR \"Free Model Foundry\")\n"; + print SDF " (PROGRAM \"SDF timing utility(tm)\")\n"; + print SDF " (VERSION \"$version\")\n"; + print SDF " (DIVIDER /)\n"; + print SDF " (VOLTAGE)\n"; + print SDF " (PROCESS)\n"; + print SDF " (TEMPERATURE)\n"; + print SDF " (TIMESCALE 1ns)\n"; +} + +sub build_paths +{ + foreach $instance_list (@instance_list) + { + @instance = $instance_list; + foreach $instance (@instance) + { + if ( $diags ne off ) { + print "working on $instance\n"; + } + if ($gtd =~ /true/i) { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; +# $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}./$timing_dir"; + } else { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; + } + $timing_file = "$path/$instance_comp{$instance}_vhd.ftm"; + $timing_file =~ s/\s//; + if ( $diags ne off ) { + print "$instance should be in $timing_file\n"; + } + if (-e $timing_file) { + if ($model_name{$instance} ne "") { + print SDF " (CELL\n"; + print SDF " (CELLTYPE \"$instance_comp{$instance}\")\n"; + $inst = $instance; + $full_inst = $instance; + while ($component_list{$instance_isin{$inst}}) { + $full_inst = "$component_list{$instance_isin{$inst}}/$full_inst"; + $full_inst =~ s/\s+//; + $inst = $component_list{$instance_isin{$inst}}; + $inst =~ s/\s+//; +# print SDF " (INSTANCE $component_list{$instance_isin{$instance}}/$instance)\n"; + } + print SDF " (INSTANCE $full_inst)\n"; + &add_timing; + } + } else { + if ( $diags ne off ) { + print "$timing_file not found!\n"; + } + } + } + } +} + +sub add_timing +{ + $timing_found = "false"; + $part_found = "false"; +# unless ($lib_path{$comp_lib{$instance_comp{$instance}}}) + unless ($timing_file) + { + print "path to $timing_file not found\n"; + exit; + } + if ($gtd =~ /true/i) { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; +# $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}./$timing_dir"; + } else { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; + } + $timing_file = "$path/$instance_comp{$instance}_vhd.ftm"; + if (open(TF, "<$timing_file") !=1) { warn "can't open $timing_file\n"; } + if ( $diags ne off ) { + print "reading $timing_file\n"; + } + $section_found = "false"; + while () + { + next unless (/$model_name{$instance}/i || ($part_found eq "true")); + $part_found = "true"; + if ( $diags ne off ) { + print "found entry for $model_name{$instance}\n"; + } + next unless (//i || ($timing_found eq "true")); + $timing_found = "true"; + next if (//i); + if (/<\/timing>/i) + { + print SDF " )\n"; + $timing_found = "false"; + $part_found = "false"; + $section_found = "true"; + last; + } else { + if (/%LABEL%/) + { + if ($component_list{$instance_isin{$instance}}) + { + $_ =~ s/%LABEL%/$component_list{$instance_isin{$instance}}\/$instance/; + } else { + $_ =~ s/%LABEL%/$instance/; + } + } + print SDF $_; + } + } + unless ($section_found eq "true") { + print "$model_name not found\n"; + } +} + +sub close_sdf +{ + print SDF ")\n"; + print "closing $sdf_file\n"; + close(SDF); +} + +# read mk_sdf.cmd + +sub read_cmd_file { + + if (open(CMD, $CMD) !=1) { die "can't open $CMD\n"; } + while () { + chop; + @fields = ''; + @fields = split; + unless ($fields[0] =~ /#/) { + if ($fields[0] =~ /SET/) { + if ($fields[1] =~ /vhdl_file/) {$VHD = $fields[2]} + if ($fields[1] =~ /sdffile_suffix/) {$suffix = $fields[2]} + if ($fields[1] =~ /use_global_timing_dir/) {$gtd = $fields[2]} + if ($fields[1] =~ /timingfile_dir/) {$timing_dir = $fields[2]} + if ($fields[1] =~ /vendor/) {$vendor = $fields[2]} + if ($fields[1] =~ /diagnostics/) {$diags = $fields[2]} + } + } + } + if ( $diags ne off ) { + print "\nmk_sdf diagnostics on\n\n"; + print "vhdl_file $VHD\n"; + print "sdffile_suffix $suffix\n"; + print "use_global_timing_dir $gtd\n"; + print "timingfile_dir $timing_dir\n"; + print "vendor $vendor\n\n"; + } +} +# + +# get name of netlist + +sub get_names +{ + + if ($ARGV[0] ne "") { $VHD = "$ARGV[0]"; } + + if ($ARGV[1] eq "") + { + @name = split(/\./,$VHD); + $design_name = $name[0]; + } else { + $design_name = "$ARGV[1]"; + } + $sdf_file = $design_name . $suffix; + if ($gtd =~ /false/i) + { + if ($vendor =~ /modeltech/i) { &read_mti; } + if ($vendor =~ /cadence/i) { &read_cds; } + } + if ( $diags ne off ) { + print "design name is $design_name\n\n"; + } +} +# +################################################################ +# + +# reformat netlist + +sub reformat +{ + $entfound = false; + + if (open(VHD, $VHD) !=1) { die "can't open $VHD\n"; } + if (open(OUT, ">$RFV") !=1) { die "can't open $OUT\n"; } + + while () { + if (/^--|library|package/i) { next } + if (/--/) { # strip embeded comments + @line = split("--"); + $_ = $line[0]; + } + s/:/ : /g; + s/;/ ;/g; + s/\s+/ /g; # reduces spaces and tabs + s/^\s//g; # no leading spaces + if (/entity/i) { + $entfound = "true"; + } + chomp; + if ( $entfound eq true ) { + print OUT lc($_); + if (/;|is|begin/i) { print OUT "\n"; } + } + } + + close OUT; + if ( $diags ne off ) { + print "reformatted netlist written to $RFV\n\n"; + } + +} + +# read ModelTech's modelsim.ini file + +sub read_mti +{ + $lib_found = "false"; + if ($ENV{MODELPATH}) + { + $ini_file = "$ENV{MODELPATH}/../modelsim.ini"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + if ($lib_found eq "true") + { + chomp; + if (/\[.+\]/) { last; } + s/\s+//; + @lib_line = split(/=/); + $lib_line[1] =~ s/\/work//; + $lib_path{$lib_line[0]} = $lib_line[1]; + } elsif (/\[Library\]/i) + { + $lib_found = "true"; + next; + } + } + } else { + print "\$MODELPATH environment variable not found\n"; + } + $lib_found = "false"; + if (-e "modelsim.ini") + { + $ini_file = "modelsim.ini"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + if ($lib_found eq "true") + { + chomp; + if (/\[.+\]/) { last; } + s/\s+//; + @lib_line = split(/=/); + $lib_line[1] =~ s/\/work//; + $lib_path{$lib_line[0]} = $lib_line[1]; + } elsif (/\[Library\]/i) + { + $lib_found = "true"; + next; + } + } + } else { + print "local modelsim.ini file not found, may not be needed\n"; + } +} + +# read Cadence's cds.lib file + +sub read_cds +{ + if ($ENV{CDS_VHDL}) + { + $ini_file = "$ENV{CDS_VHDL}/files/cds.lib"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + chomp; + s/\s+/ /; + if (/define/i) + { + @lib_line = split; + $lib_path{$lib_line[1]} = $lib_line[2]; + } + } + } else { + print "\$CDS_VHDL environment variable not found\n"; + } + if (-e "cds.lib") + { + $ini_file = "cds.lib"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + chomp; + s/\s+/ /; + if (/define/i) + { + @lib_line = split; + $lib_path{$lib_line[1]} = $lib_line[2]; + } + } + } else { + print "local cds.lib file not found, may not be needed\n"; + } +} diff --git a/lib/models/memory/flash/serial/S25fl512s/utilities/CreateSDF/my_mem_vhd.ftm b/lib/models/memory/flash/serial/S25fl512s/utilities/CreateSDF/my_mem_vhd.ftm new file mode 100644 index 0000000..2fc35c2 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl512s/utilities/CreateSDF/my_mem_vhd.ftm @@ -0,0 +1,205 @@ + +FMF Timing for testbench Parts + + +version: | author: | mod date: | changes made: + V1.0 VHD2FTM 03 July 11 Initial release + +1ns +am29lv640m + +MY_MEM +AM29LV640MH90R +AM29LV640ML90R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (90:90:90) (90:90:90)) + (IOPATH A0 DQ1 (25:25:25) (25:25:25)) + (IOPATH CENeg DQ0 (85:85:85) (85:85:85) (11:11:11) (85:85:85) (11:11:11) (85:85:85)) + (IOPATH OENeg DQ0 (20:20:20) (20:20:20) (11:11:11) (20:20:20) (11:11:11) (20:20:20)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (90)) + (IOPATH WENeg RY (0) (90)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (90:90:90)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH101 +AM29LV640ML101 +AM29LV640MH101R +AM29LV640ML101R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (100:100:100) (100:100:100)) + (IOPATH A0 DQ1 (30:30:30) (30:30:30)) + (IOPATH CENeg DQ0 (95:95:95) (95:95:95) (11:11:11) (95:95:95) (11:11:11) (95:95:95)) + (IOPATH OENeg DQ0 (25:25:25) (25:25:25) (11:11:11) (25:25:25) (11:11:11) (25:25:25)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (100)) + (IOPATH WENeg RY (0) (100)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (100:100:100)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH112 +AM29LV640ML112 +AM29LV640MH112R +AM29LV640ML112R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (110:110:110) (110:110:110)) + (IOPATH A0 DQ1 (40:40:40) (40:40:40)) + (IOPATH CENeg DQ0 (105:105:105) (105:105:105) (11:11:11) (105:105:105) (11:11:11) (105:105:105)) + (IOPATH OENeg DQ0 (35:35:35) (35:35:35) (11:11:11) (35:35:35) (11:11:11) (35:35:35)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (110)) + (IOPATH WENeg RY (0) (110)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (110:110:110)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH120 +AM29LV640ML120 +AM29LV640MH120R +AM29LV640ML120R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (120:120:120) (120:120:120)) + (IOPATH A0 DQ1 (40:40:40) (40:40:40)) + (IOPATH CENeg DQ0 (115:115:115) (115:115:115) (11:11:11) (115:115:115) (11:11:11) (115:115:115)) + (IOPATH OENeg DQ0 (35:35:35) (35:35:35) (11:11:11) (35:35:35) (11:11:11) (35:35:35)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (120)) + (IOPATH WENeg RY (0) (120)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (120:120:120)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + diff --git a/lib/models/memory/flash/serial/S25fl512s/utilities/CreateSDF/testbench.sdf b/lib/models/memory/flash/serial/S25fl512s/utilities/CreateSDF/testbench.sdf new file mode 100644 index 0000000..02495dd --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl512s/utilities/CreateSDF/testbench.sdf @@ -0,0 +1,58 @@ +(DELAYFILE + (SDFVERSION "3.0") + (DESIGN "testbench") + (DATE "Wed Jan 28 15:15:41 2004") + (VENDOR "Free Model Foundry") + (PROGRAM "SDF timing utility(tm)") + (VERSION "2.0.4") + (DIVIDER /) + (VOLTAGE) + (PROCESS) + (TEMPERATURE) + (TIMESCALE 1ns) + (CELL + (CELLTYPE "my_mem") + (INSTANCE dut) + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (90:90:90) (90:90:90)) + (IOPATH A0 DQ1 (25:25:25) (25:25:25)) + (IOPATH CENeg DQ0 (85:85:85) (85:85:85) (11:11:11) (85:85:85) (11:11:11) (85:85:85)) + (IOPATH OENeg DQ0 (20:20:20) (20:20:20) (11:11:11) (20:20:20) (11:11:11) (20:20:20)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (90)) + (IOPATH WENeg RY (0) (90)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (90:90:90)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + ) +) diff --git a/lib/models/memory/flash/serial/S25fl512s/utilities/CreateSDF/testbench.vhd b/lib/models/memory/flash/serial/S25fl512s/utilities/CreateSDF/testbench.vhd new file mode 100644 index 0000000..c7d852a --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl512s/utilities/CreateSDF/testbench.vhd @@ -0,0 +1,1606 @@ +------------------------------------------------------------------------------ +-- File name : testbench_640.vhd +------------------------------------------------------------------------------- +-- Copyright (C) 2003 AMD. +-- +-- MODIFICATION HISTORY : +-- +-- version: | author: | mod date: | changes made: +-- V0.1 M.Marinkovic 11 July 03 Initial +-- v0.2 M.Marinkovic 28 Aug 03 Changed protected sector selection +-- +------------------------------------------------------------------------------- +-- PART DESCRIPTION: +-- +-- Description: +-- Generic test enviroment for verification of AMD flash memory +-- VITAL models.my_mem +-- +------------------------------------------------------------------------------- +-- Note: VHDL code formating not done +-- For High/Low sector protection selection change: +-- TimingModel constant and TimingModel generic value +-- +------------------------------------------------------------------------------- +LIBRARY IEEE; + USE IEEE.std_logic_1164.ALL; +--USE IEEE.VITAL_timing.ALL; +--USE IEEE.VITAL_primitives.ALL; + USE STD.textio.ALL; + +LIBRARY VITAL2000; + USE VITAL2000.vital_timing.ALL; + USE VITAL2000.vital_primitives.ALL; + +LIBRARY FMF; + USE FMF.gen_utils.ALL; + USE FMF.conversions.ALL; + + +LIBRARY work; + USE work.amd_tc_pkg.ALL; + +------------------------------------------------------------------------------- +-- ENTITY DECLARATION +------------------------------------------------------------------------------- +ENTITY testbench_640 IS +END testbench_640; + + +------------------------------------------------------------------------------- +-- ARCHITECTURE DECLARATION +------------------------------------------------------------------------------- +ARCHITECTURE vhdl_behavioral of testbench_640 IS + COMPONENT my_mem + GENERIC ( + -- tipd delays: interconnect path delays + tipd_A0 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A1 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A2 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A3 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A4 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A5 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A6 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A7 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A8 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A9 : VitalDelayType01 := VitalZeroDelay01; --address + tipd_A10 : VitalDelayType01 := VitalZeroDelay01; --lines + tipd_A11 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A12 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A13 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A14 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A15 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A16 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A17 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A18 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A19 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A20 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A21 : VitalDelayType01 := VitalZeroDelay01; -- + + tipd_DQ0 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ1 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ2 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ3 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ4 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ5 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ6 : VitalDelayType01 := VitalZeroDelay01; -- data + tipd_DQ7 : VitalDelayType01 := VitalZeroDelay01; -- lines + tipd_DQ8 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ9 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ10 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ11 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ12 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ13 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ14 : VitalDelayType01 := VitalZeroDelay01; -- + + tipd_DQ15 : VitalDelayType01 := VitalZeroDelay01; -- DQ15/A-1 + + tipd_CENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_OENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_RESETNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; --WP#/ACC + tipd_BYTENeg : VitalDelayType01 := VitalZeroDelay01; + + -- tpd delays + tpd_A0_DQ0 : VitalDelayType01 := UnitDelay01;--tACC + tpd_A0_DQ1 : VitalDelayType01 := UnitDelay01;--tPACC + tpd_CENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(tCE,tCE,tDF,-,tDF,-) + tpd_OENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(tOE,tOE,tDF,-,tDF,-) + tpd_RESETNeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(-,-,0,-,0,-) + tpd_CENeg_RY : VitalDelayType01 := UnitDelay01; --tBUSY + tpd_WENeg_RY : VitalDelayType01 := UnitDelay01; --tBUSY + + --tsetup values + tsetup_A0_CENeg : VitalDelayType := UnitDelay; --tAS edge \ + tsetup_A0_OENeg : VitalDelayType := UnitDelay; --tASO edge \ + tsetup_DQ0_CENeg : VitalDelayType := UnitDelay; --tDS edge / + + --thold values + thold_CENeg_RESETNeg: VitalDelayType := UnitDelay; --tRH edge / + thold_OENeg_WENeg : VitalDelayType := UnitDelay; --tOEH edge / + thold_A0_CENeg : VitalDelayType := UnitDelay; --tAH edge \ + thold_A0_OENeg : VitalDelayType := UnitDelay; --tAHT edge \ + thold_DQ0_CENeg : VitalDelayType := UnitDelay; --tDH edge / + thold_WENeg_OENeg : VitalDelayType := UnitDelay; --tGHWL edge / + + --tpw values: pulse width + tpw_RESETNeg_negedge: VitalDelayType := UnitDelay; --tRP + tpw_OENeg_posedge : VitalDelayType := UnitDelay; --tOEPH + tpw_WENeg_negedge : VitalDelayType := UnitDelay; --tWP + tpw_WENeg_posedge : VitalDelayType := UnitDelay; --tWPH + tpw_CENeg_negedge : VitalDelayType := UnitDelay; --tCP + tpw_CENeg_posedge : VitalDelayType := UnitDelay; --tCEPH + tpw_A0_negedge : VitalDelayType := UnitDelay; --tWC tRC + + + -- tdevice values: values for internal delays + --Effective Write Buffer Program Operation tWHWH1 + tdevice_WBPB : VitalDelayType := 11 us; + --Program Operation + tdevice_POB : VitalDelayType := 100 us; + --Sector Erase Operation tWHWH2 + tdevice_SEO : VitalDelayType := 500 ms; + --Timing Limit Exceeded + tdevice_HANG : VitalDelayType := 400 ms; --? + --program/erase suspend timeout + tdevice_START_T1 : VitalDelayType := 5 us; + --sector erase command sequence timeout + tdevice_CTMOUT : VitalDelayType := 50 us; + --device ready after Hardware reset(during embeded algorithm) + tdevice_READY : VitalDelayType := 20 us; --tReady + + -- generic control parameters + InstancePath : STRING := DefaultInstancePath; + TimingChecksOn : BOOLEAN := DefaultTimingChecks; + MsgOn : BOOLEAN := DefaultMsgOn; + XOn : BOOLEAN := DefaultXon; + -- memory file to be loaded + mem_file_name : STRING ;--:= "am29lv640m.mem"; + prot_file_name : STRING ;--:= "am29lv640m_prot.mem"; + secsi_file_name : STRING ;--:= "am29lv_secsi.mem"; + + UserPreload : BOOLEAN ;--:= TRUE; + LongTimming : BOOLEAN ;--:= TRUE; + + -- For FMF SDF technology file usage + TimingModel : STRING --:= "AM29LV640MH90R" + ); + PORT ( + A21 : IN std_logic := 'U'; -- + A20 : IN std_logic := 'U'; -- + A19 : IN std_logic := 'U'; -- + A18 : IN std_logic := 'U'; -- + A17 : IN std_logic := 'U'; -- + A16 : IN std_logic := 'U'; -- + A15 : IN std_logic := 'U'; -- + A14 : IN std_logic := 'U'; -- + A13 : IN std_logic := 'U'; --address + A12 : IN std_logic := 'U'; --lines + A11 : IN std_logic := 'U'; -- + A10 : IN std_logic := 'U'; -- + A9 : IN std_logic := 'U'; -- + A8 : IN std_logic := 'U'; -- + A7 : IN std_logic := 'U'; -- + A6 : IN std_logic := 'U'; -- + A5 : IN std_logic := 'U'; -- + A4 : IN std_logic := 'U'; -- + A3 : IN std_logic := 'U'; -- + A2 : IN std_logic := 'U'; -- + A1 : IN std_logic := 'U'; -- + A0 : IN std_logic := 'U'; -- + + DQ15 : INOUT std_logic := 'U'; -- DQ15/A-1 + DQ14 : INOUT std_logic := 'U'; -- + DQ13 : INOUT std_logic := 'U'; -- + DQ12 : INOUT std_logic := 'U'; -- + DQ11 : INOUT std_logic := 'U'; -- + DQ10 : INOUT std_logic := 'U'; -- + DQ9 : INOUT std_logic := 'U'; -- data + DQ8 : INOUT std_logic := 'U'; -- lines + DQ7 : INOUT std_logic := 'U'; -- + DQ6 : INOUT std_logic := 'U'; -- + DQ5 : INOUT std_logic := 'U'; -- + DQ4 : INOUT std_logic := 'U'; -- + DQ3 : INOUT std_logic := 'U'; -- + DQ2 : INOUT std_logic := 'U'; -- + DQ1 : INOUT std_logic := 'U'; -- + DQ0 : INOUT std_logic := 'U'; -- + + CENeg : IN std_logic := 'U'; + OENeg : IN std_logic := 'U'; + WENeg : IN std_logic := 'U'; + RESETNeg : IN std_logic := 'U'; + WPNeg : IN std_logic := 'U'; --WP#/ACC + BYTENeg : IN std_logic := 'U'; + RY : OUT std_logic := 'U' --RY/BY# + ); + END COMPONENT; + + FOR ALL: my_mem USE ENTITY WORK.my_mem(VHDL_BEHAVIORAL); + + --------------------------------------------------------------------------- + --memory configuration + --------------------------------------------------------------------------- + CONSTANT MaxData : NATURAL := 16#FF#; --255; + CONSTANT SecSize : NATURAL := 16#FFFF#; --65535 + CONSTANT SecSiSize : NATURAL := 255; + CONSTANT SecNum : NATURAL := 127; + CONSTANT HiAddrBit : NATURAL := 21; + --Address of the Protected Sector +-- CONSTANT ProtSecNum : NATURAL := SecNum; + + --------------------------------------------------------------------------- + --model configuration + --------------------------------------------------------------------------- + CONSTANT mem_file : STRING := "am29lv640m.mem"; + CONSTANT prot_file : STRING := "am29lv640m_prot.mem"; + CONSTANT secsi_file : STRING := "am29lv_secsi.mem"; + + CONSTANT UserPreload : boolean := TRUE; + CONSTANT DebugInfo : boolean := FALSE; + CONSTANT LongTimming : boolean := TRUE; + CONSTANT TimingModel : STRING := "MY_MEM"; + -- "AM29LV640MH90R";--High sect prot. + -- "AM29LV128ML93R";--Low sect. prot. + --------------------------------------------------------------------------- + SIGNAL ProtSecNum : NATURAL := SecNum ; + + --Flash Memory Array + TYPE SecType IS ARRAY (0 TO SecSize) OF + INTEGER RANGE -1 TO MaxData; + TYPE MemArray IS ARRAY (0 TO SecNum) OF + SecType; + + --Common Flash Interface Query codes + TYPE CFItype IS ARRAY (16#10# TO 16#50#) OF + NATURAL RANGE 0 TO 16#FF#; + + --SecSi Sector + TYPE SecSiType IS ARRAY ( 0 TO SecSiSize) OF + INTEGER RANGE -1 TO MaxData; + + --------------------------------------------------------------------------- + -- memory declaration + --------------------------------------------------------------------------- + -- -- Mem(SecAddr)(Address).... + SHARED VARIABLE Mem : MemArray := (OTHERS => (OTHERS=> MaxData)); + SHARED VARIABLE CFI_array : CFItype :=(OTHERS=>0); + SHARED VARIABLE SecSi : SecSiType :=(OTHERS=>0); + + --command sequence + SHARED VARIABLE cmd_seq : cmd_seq_type; + + SIGNAL status : status_type := none; + SIGNAL sts_check : std_logic_vector(7 downto 0); + + + SIGNAL check_err : std_logic := '0'; + SIGNAL ErrorInTest : std_logic := '0'; -- + ---------------------------------------------------------------------------- + --Personality module: + -- + -- instanciates the DUT module and adapts generic test signals to it + -- TBD: block port + ---------------------------------------------------------------------------- + --DUT port + SIGNAL T_DQ : std_logic_vector(15 downto 0) := (OTHERS=>'U'); + SIGNAL T_A : std_logic_vector(HiAddrBit downto 0) := (OTHERS=>'U'); + SIGNAL T_RESETNeg : std_logic := 'U'; + SIGNAL T_CENeg : std_logic := 'U'; + SIGNAL T_WENeg : std_logic := 'U'; + SIGNAL T_OENeg : std_logic := 'U'; + SIGNAL T_WPNeg : std_logic := 'U'; + SIGNAL T_BYTENeg : std_logic := 'U'; + SIGNAL T_RY : std_logic := 'U'; + + --------------------------------------------------------------------------- + -- + --------------------------------------------------------------------------- + --SecSi ProtectionStatus + SHARED VARIABLE FactoryProt : std_logic := '1'; + --Sector Protection Status + SHARED VARIABLE Sec_Prot : std_logic_vector (SecNum downto 0) := + (OTHERS => '0'); + SHARED VARIABLE Sect : NATURAL RANGE 0 TO SecNum := 0; + SHARED VARIABLE Addr : NATURAL RANGE 0 TO SecSize := 0; + SHARED VARIABLE WriteData : NATURAL RANGE 0 TO MaxData := 0; + + + --CONSTANT + --timming parameters + CONSTANT RESETNeg_pw : time := 500 ns; --tRP + + SIGNAL pwron : std_logic := '0'; + + SIGNAL Tseries : NATURAL; + SIGNAL Tcase : NATURAL; + + SHARED VARIABLE ts_cnt : NATURAL RANGE 1 TO 30:=1; -- testseries counter + SHARED VARIABLE tc_cnt : NATURAL RANGE 0 TO 10:=0; -- testcase counter + + + BEGIN + DUT : my_mem + GENERIC MAP ( + -- tipd delays: interconnect path delays + tipd_A0 => VitalZeroDelay01, -- + tipd_A1 => VitalZeroDelay01, -- + tipd_A2 => VitalZeroDelay01, -- + tipd_A3 => VitalZeroDelay01, -- + tipd_A4 => VitalZeroDelay01, -- + tipd_A5 => VitalZeroDelay01, -- + tipd_A6 => VitalZeroDelay01, -- + tipd_A7 => VitalZeroDelay01, -- + tipd_A8 => VitalZeroDelay01, -- + tipd_A9 => VitalZeroDelay01, --address + tipd_A10 => VitalZeroDelay01, --lines + tipd_A11 => VitalZeroDelay01, -- + tipd_A12 => VitalZeroDelay01, -- + tipd_A13 => VitalZeroDelay01, -- + tipd_A14 => VitalZeroDelay01, -- + tipd_A15 => VitalZeroDelay01, -- + tipd_A16 => VitalZeroDelay01, -- + tipd_A17 => VitalZeroDelay01, -- + tipd_A18 => VitalZeroDelay01, -- + tipd_A19 => VitalZeroDelay01, -- + tipd_A20 => VitalZeroDelay01, -- + tipd_A21 => VitalZeroDelay01, -- + + tipd_DQ0 => VitalZeroDelay01, -- + tipd_DQ1 => VitalZeroDelay01, -- + tipd_DQ2 => VitalZeroDelay01, -- + tipd_DQ3 => VitalZeroDelay01, -- + tipd_DQ4 => VitalZeroDelay01, -- + tipd_DQ5 => VitalZeroDelay01, -- + tipd_DQ6 => VitalZeroDelay01, -- data + tipd_DQ7 => VitalZeroDelay01, -- lines + tipd_DQ8 => VitalZeroDelay01, -- + tipd_DQ9 => VitalZeroDelay01, -- + tipd_DQ10 => VitalZeroDelay01, -- + tipd_DQ11 => VitalZeroDelay01, -- + tipd_DQ12 => VitalZeroDelay01, -- + tipd_DQ13 => VitalZeroDelay01, -- + tipd_DQ14 => VitalZeroDelay01, -- + + tipd_DQ15 => VitalZeroDelay01, -- DQ15/A-1 + + tipd_CENeg => VitalZeroDelay01, + tipd_OENeg => VitalZeroDelay01, + tipd_WENeg => VitalZeroDelay01, + tipd_RESETNeg => VitalZeroDelay01, + tipd_WPNeg => VitalZeroDelay01,--WP#/ACC + tipd_BYTENeg => VitalZeroDelay01, + + -- tpd delays + tpd_A0_DQ0 => UnitDelay01,--tACC + tpd_A0_DQ1 => UnitDelay01,--tPACC + tpd_CENeg_DQ0 => UnitDelay01Z, + --(tCE,tCE,tDF,-,tDF + tpd_OENeg_DQ0 => UnitDelay01Z, + --(tOE,tOE,tDF,-,tDF + tpd_RESETNeg_DQ0 => UnitDelay01Z, + --(-,-,0,-,0,-) + tpd_CENeg_RY => UnitDelay01, --tBUSY + tpd_WENeg_RY => UnitDelay01, --tBUSY + + --tsetup values + tsetup_A0_CENeg => UnitDelay, --tAS edge \ + tsetup_A0_OENeg => UnitDelay, --tASO edge \ + tsetup_DQ0_CENeg => UnitDelay, --tDS edge / + + --thold values + thold_CENeg_RESETNeg=> UnitDelay, --tRH edge / + thold_OENeg_WENeg => UnitDelay, --tOEH edge / + thold_A0_CENeg => UnitDelay, --tAH edge \ + thold_A0_OENeg => UnitDelay, --tAHT edge \ + thold_DQ0_CENeg => UnitDelay, --tDH edge / + thold_WENeg_OENeg => UnitDelay, --tGHVL edge / + + --tpw values: pulse width + tpw_RESETNeg_negedge=> UnitDelay, --tRP + tpw_OENeg_posedge => UnitDelay, --tOEPH + tpw_WENeg_negedge => UnitDelay, --tWP + tpw_WENeg_posedge => UnitDelay, --tWPH + tpw_CENeg_negedge => UnitDelay, --tCP + tpw_CENeg_posedge => UnitDelay, --tCEPH + tpw_A0_negedge => UnitDelay, --tWC tRC + -- tdevice values: values for internal delays + --Effective Write Buffer Program Operation tWHWH1 + tdevice_WBPB => 11 us, + --Program Operation + tdevice_POB => 100 us, + --Sector Erase Operation tWHWH2 + tdevice_SEO => 500 ms, + --Timing Limit Exceeded + tdevice_HANG => 400 ms, --? + --program/erase suspend timeout + tdevice_START_T1 => 5 us, + --sector erase command sequence timeout + tdevice_CTMOUT => 50 us, + --device ready after Hardware reset(during embeded algorithm) + tdevice_READY => 20 us, --tReady + + -- generic control parameters + InstancePath => DefaultInstancePath, + TimingChecksOn => TRUE,--DefaultTimingChecks, + MsgOn => DefaultMsgOn, + XOn => DefaultXon, + -- memory file to be loaded + mem_file_name => mem_file, + prot_file_name => prot_file , + secsi_file_name => secsi_file, + + UserPreload => UserPreload, + LongTimming => LongTimming, + -- For FMF SDF technology file usage + TimingModel => "AM29LV640MH90R" -- TimingModel + ) + PORT MAP( + A21 => T_A(21), -- + A20 => T_A(20), -- + A19 => T_A(19), -- + A18 => T_A(18), -- + A17 => T_A(17), -- + A16 => T_A(16), -- + A15 => T_A(15), -- + A14 => T_A(14), -- + A13 => T_A(13), --address + A12 => T_A(12), --lines + A11 => T_A(11), -- + A10 => T_A(10), -- + A9 => T_A(9), -- + A8 => T_A(8), -- + A7 => T_A(7), -- + A6 => T_A(6), -- + A5 => T_A(5),-- + A4 => T_A(4),-- + A3 => T_A(3), -- + A2 => T_A(2), -- + A1 => T_A(1), -- + A0 => T_A(0), -- + + DQ15 => T_DQ(15), -- DQ15/A-1 + DQ14 => T_DQ(14), -- + DQ13 => T_DQ(13), -- + DQ12 => T_DQ(12), -- + DQ11 => T_DQ(11), -- + DQ10 => T_DQ(10), -- + DQ9 => T_DQ(9), -- data + DQ8 => T_DQ(8), -- lines + DQ7 => T_DQ(7), -- + DQ6 => T_DQ(6), -- + DQ5 => T_DQ(5), -- + DQ4 => T_DQ(4), -- + DQ3 => T_DQ(3), -- + DQ2 => T_DQ(2), -- + DQ1 => T_DQ(1), -- + DQ0 => T_DQ(0), -- + + CENeg => T_CENeg, + OENeg => T_OENeg, + WENeg => T_WENeg, + RESETNeg => T_RESETNeg, + WPNeg => T_WPNeg, --WP#/ACC + BYTENeg => T_BYTENeg, + RY => T_RY --RY/BY# + ); + + --------------------------------------------------------------------------- + --protected sector + --------------------------------------------------------------------------- + ProtSecNum <= SecNum WHEN TimingModel(11) = 'H' ELSE + 0 ;-- WHEN TimingModel = "AM29LV128ML93R" + + pwron <= '0', '1' after 1 ns; + +--At the end of the simulation, if ErrorInTest='0' there were no errors +err_ctrl : PROCESS ( check_err ) + BEGIN + IF check_err = '1' THEN + ErrorInTest <= '1'; + END IF; + END PROCESS err_ctrl; + +tb :PROCESS + + -------------------------------------------------------------------------- + --= PROCEDURE to select TC + -- can be modified to read TC list from file, or to generate random list + -------------------------------------------------------------------------- + PROCEDURE Pick_TC + (Model : IN STRING := "AM29LV640MH90R" ) + IS + BEGIN + IF TC_cnt < tc(TS_cnt) THEN + TC_cnt := TC_cnt+1; + ELSE + TC_cnt:=1; + IF TS_cnt<30 THEN + TS_cnt := TS_cnt+1; + ELSE + -- end test + IF ErrorInTest='0' THEN + REPORT "Test Ended without errors" + SEVERITY note; + ELSE + REPORT "There were errors in test" + SEVERITY note; + END IF; + WAIT; + END IF; + END IF; + END PROCEDURE Pick_TC; + + --------------------------------------------------------------------------- + --bus commands, device specific implementation + --------------------------------------------------------------------------- + TYPE bus_type IS (bus_idle, + bus_standby, --CE# deasseretd, others are don't care + bus_enable, --CE# asserted, others deasserted + bus_output_disable, + bus_reset, + bus_write, + bus_read); + + --bus drive for specific command sequence cycle + PROCEDURE bus_cycle( + bus_cmd :IN bus_type := bus_idle; + byte :IN boolean ; + data :IN INTEGER RANGE -2 TO MaxData := -2; -- -1 for all Z + dataHi :IN INTEGER RANGE -2 TO MaxData := -2; -- -2 for ignore + sector :IN INTEGER RANGE -1 TO SecNum := -1; -- -1 for ignore addr + address :IN NATURAL RANGE 0 TO SecSize := 0; + disable :IN boolean := false; + violate :IN boolean := false; + tm :IN TIME := 10 ns) + IS + + VARIABLE tmp : std_logic_vector(15 downto 0); + BEGIN + + IF data=-1 THEN -- HiZ + T_DQ(7 downto 0) <= (OTHERS => 'Z'); + END IF; + + IF (NOT byte)THEN --word access + IF dataHi=-1 THEN -- HiZ + T_DQ(15 downto 8) <= (OTHERS => 'Z'); + END IF; + T_BYTENeg <= '1'; + ELSE --byte access + T_BYTENeg <= '0'; + T_DQ(14 downto 8) <= (OTHERS => 'Z'); + END IF; + + IF sector > -1 THEN + T_A(HiAddrBit downto 15) <= to_slv(sector, HiAddrbit-14); + tmp := to_slv(address, 16); + IF byte THEN + T_A(14 downto 0) <= tmp(15 downto 1); + T_DQ(15) <= tmp(0); + ELSE + T_A(14 downto 0) <= tmp(14 downto 0); + END IF; + + END IF; + + wait for 1 ns; + + CASE bus_cmd IS + WHEN bus_output_disable => + T_OENeg <= '1'; + WAIT FOR 20 ns; + + WHEN bus_idle => + T_RESETNeg <= '1'; + T_WENeg <= '1'; + T_CENeg <= '1'; + T_OENeg <= '1'; + IF disable THEN + T_WPNeg <= '0'; + ELSE + T_WPNeg <= '1'; + END IF; + WAIT FOR 30 ns; + + WHEN bus_standby => + T_CENeg <= '1'; + WAIT FOR 30 ns; + + WHEN bus_reset => + T_RESETNeg <= '0', '1' AFTER tm ; + -- WAIT FOR 500 ns should follow this bus cmd for reset to + --complete + WAIT FOR 30 ns; + + WHEN bus_enable => + T_WENeg <= '1' AFTER 50 ns; --- + T_CENeg <= '0' AFTER 50 ns; --- + T_OENeg <= '1' AFTER 30 ns; --- + + WAIT FOR tm ; + + WHEN bus_write => + T_OENeg <= '1' ;-- AFTER 5 ns; + T_CENeg <= '0' AFTER 10 ns ; + T_WENeg <= '0' AFTER 20 ns; + + IF data>-1 THEN + T_DQ(7 downto 0) <= to_slv(data,8); + END IF; + IF NOT byte THEN + IF dataHi>-1 THEN + T_DQ(15 downto 8) <= to_slv(dataHi,8); + END IF; + END IF; + + IF violate THEN + T_WENeg <= '1'; + WAIT FOR 50 ns; + T_WENeg <= '0', '1' AFTER tm; + WAIT FOR 50 ns; + ELSE + WAIT FOR 100 ns; + END IF; + + WHEN bus_read => + + T_CENeg <= '0' ; + T_WENeg <= '1'AFTER 10 ns; + IF NOT disable THEN + T_OENeg <= '0' AFTER 15 ns; + ELSE + T_OENeg <= '1'; + END IF; + + IF NOT byte THEN + T_DQ(15 downto 8) <= (OTHERS => 'Z'); + END IF; + T_DQ(7 downto 0) <= (OTHERS => 'Z'); + + WAIT FOR 100 ns; + + -- T_OENeg <= '1' ; ----------- + + END CASE; + + + END PROCEDURE; + + + --------------------------------------------------------------------------- + --procedure to decode commands into specific bus command sequence + --------------------------------------------------------------------------- + PROCEDURE cmd_dc + ( command : IN cmd_rec ) + IS + VARIABLE D_hi : NATURAL ;--RANGE 0 to MaxData; + VARIABLE D_lo : NATURAL RANGE 0 to MaxData; + VARIABLE Addr : NATURAL RANGE 0 to SecSize :=0; + VARIABLE Addrfix : NATURAL RANGE 0 to SecSize/2:=0; + VARIABLE Sect : INTEGER RANGE -1 to SecNum :=0; + VARIABLE slv_1, slv_2 : std_logic_vector(7 downto 0); + VARIABLE byte : boolean; + VARIABLE i : NATURAL; + BEGIN + CASE command.cmd IS + WHEN idle => + bus_cycle(bus_cmd => bus_idle, + byte => command.byte, + disable => command.aux=disable); + + WHEN h_reset => + bus_cycle(bus_cmd => bus_reset, + byte => command.byte, + tm => command.wtime); + + WHEN rd => + bus_cycle(bus_cmd => bus_enable, + byte => command.byte, + data => -1, + sector => command.sect, + address => command.addr, + tm => 90 ns); + + bus_cycle(bus_cmd => bus_read, + byte => command.byte, + data => -1, + dataHi => -1, + sector => command.sect, + address => command.addr, + disable => command.aux=disable); + + bus_cycle(bus_cmd => bus_output_disable, + byte => command.byte); + + WHEN rd_page => + bus_cycle(bus_cmd => bus_enable, + byte => command.byte, + data => -1, + sector => 0, + address => 0, + tm => 90 ns); + + Addr := command.addr; + Sect := command.sect; + byte := command.byte; + ---- 08July---- + WAIT FOR 10 ns; + -------------- + i := 0; + WHILE i < command.d_hi LOOP + + IF command.wtime > 0 ns THEN + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + --byte toggle mode + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + byte := false; + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + Addrfix := Addr /2; + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + --word read; + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addrfix); + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + byte := true; + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 30 ns); + + --first byte read + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addr); + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + i := i +3; + wait for 10 ns; ------- + ELSE + byte := command.byte; + END IF; + --second byte read in byte toggle mode + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addr); + + + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + i := i +1; + WAIT FOR 10 ns; + END LOOP; + bus_cycle(bus_cmd => bus_output_disable, + byte => command.byte); + + + + WHEN w_cycle => + + D_lo := 16#AA# ; --first command data + Addr := 16#AAA#; --first command byte address + D_hi := 16#55#; --second command data + Addrfix := 16#555#; --second command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + Addrfix := 16#2AA#; --second command byte address + END IF; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_lo, + dataHi => 0, + sector => 0, + address => Addr, + violate => command.aux=violate, + tm => command.wtime); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_hi, + dataHi => 0, + sector => 0, + address => Addrfix); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_reset | w_prog | w_erase | w_unlock | + w_autoselect | w_enter_sec => + Addr := 16#AAA#; + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + + CASE command.cmd IS + WHEN w_reset => + d_lo := 16#F0#; + WHEN w_prog => + d_lo := 16#A0#; + WHEN w_erase => + d_lo := 16#80#; + WHEN w_unlock => + d_lo := 16#20#; + WHEN w_autoselect => + d_lo := 16#90#; + WHEN w_enter_sec => + d_lo := 16#88#; + WHEN OTHERS => + d_lo := 0; + END CASE; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => d_lo, + dataHi => 0, + sector => 0, + address => Addr); + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + + WHEN w_unlock_reset => + Addr := 16#AAA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#90#, + dataHi => 0, + sector => 0, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#F0#, + dataHi => 0, + sector => 0, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + WHEN w_chip_ers => + Addr := 16#AAA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#10#, + dataHi => 0, + sector => 0, + Address => Addr); + FOR i IN 0 TO SecNum LOOP + IF Sec_Prot(i)/='1' THEN + mem(i) := (OTHERS=>16#FF#); + END IF; + END LOOP; + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_cfi => + Addr := 16#AA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#55#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#98#, + dataHi => 0, + sector => 0, + Address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + + WHEN w_suspend => + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#B0#, + dataHi => 0, + sector => -1); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + WHEN w_resume => + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#30#, + dataHi => 0, + sector => -1); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_data => + + D_hi := command.d_hi MOD 16#100#; + D_lo := command.d_lo ; + Addr := command.addr; + Sect := command.sect; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_lo, + dataHi => D_hi, + sector => Sect, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + IF NOT command.byte THEN + Addr := Addr*2; + END IF; + + --write value(s) in default mem + IF status = erase_active AND Sec_Prot(Sect)/='1'THEN + --sector should be erased + mem(Sect) := (OTHERS=>16#FF#); + + ELSIF status = erase_na AND Sec_Prot(Sect)/='1'THEN + --sector erase terminated = data integrity violated + mem(Sect) := (OTHERS=>-1); + + ELSIF status = readX AND Sec_Prot(Sect)/='1' THEN + mem(Sect)(Addr) := -1; + IF NOT command.byte THEN + mem(Sect)(Addr+1) := -1; + END IF; + + -- Write to Secure Silicon Sector Region + ELSIF status = rd_SecSi AND FactoryProt/='1' THEN + slv_1 := to_slv(d_lo,8); + IF SecSi(Addr)>-1 THEN + slv_2 := to_slv(SecSi(Addr),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + SecSi(Addr) := to_nat(slv_1); + IF NOT command.byte THEN + slv_1 := to_slv(d_hi,8); + IF SecSi(Addr+1)>-1 THEN + slv_2 := to_slv(SecSi(Addr+1),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + SecSi(Addr+1) := to_nat(slv_1); + END IF; + + ELSIF status=buff_wr_busy THEN + --Write to Buffer command cycle + null; + + ELSIF status=erase_na THEN + --sector erase command sequence violation + null; + + -- Write to Flash Memory Array + ELSIF status /= err AND Sec_Prot(Sect)/='1'THEN + slv_1 := to_slv(d_lo,8); + IF mem(Sect)(Addr)>-1 THEN + slv_2 := to_slv(mem(Sect)(Addr),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + mem(Sect)(Addr) := to_nat(slv_1); + IF NOT command.byte THEN + slv_1 := to_slv(d_hi,8); + IF mem(Sect)(Addr+1)>-1 THEN + slv_2 := to_slv(mem(Sect)(Addr+1),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + mem(Sect)(Addr+1) := to_nat(slv_1); + END IF; + END IF; + + + WHEN wt => + WAIT FOR command.wtime; + + WHEN wt_rdy => + IF T_RY/='1' THEN + WAIT UNTIL rising_edge(T_RY) FOR command.wtime; + END IF; + + WHEN wt_bsy => + IF T_RY='1' THEN + WAIT UNTIL falling_edge(T_RY) FOR command.wtime; + END IF; + + WHEN OTHERS => null; + END CASE; + END PROCEDURE; + + + VARIABLE cmd_cnt : NATURAL; + VARIABLE command : cmd_rec; -- + +BEGIN + Pick_TC (Model => "AM29LV640MH90R" ); + + Tseries <= ts_cnt ; + Tcase <= tc_cnt ; + + Generate_TC + (Model => "AM29LV640MH90R" , + Series => ts_cnt, + TestCase => tc_cnt, + command_seq => cmd_seq); + + + cmd_cnt := 1; + WHILE cmd_seq(cmd_cnt).cmd/=done LOOP + command:= cmd_seq(cmd_cnt); + IF command.sect = -1 THEN + command.sect := ProtSecNum; + END IF; + status <= command.status; + sts_check<= to_slv(command.d_lo,8); --used only for toggle/status check + cmd_dc(command); + cmd_cnt :=cmd_cnt +1; + + END LOOP; + +END PROCESS tb; + +--process to monitor WP# +PROCESS(T_WPNeg) +VARIABLE reg : std_logic; +BEGIN + IF falling_edge(T_WPNeg) THEN + reg := Sec_Prot(ProtSecNum); + Sec_Prot(ProtSecNum) := '1'; + ELSIF rising_edge(T_WPNeg) THEN + Sec_Prot(ProtSecNum) := reg; + END IF; +END PROCESS; + +-------------------------------------------------------------------------------- +-- Checker process, +-- Bus transition extractor: when bus cycle is read samples addr and data +-- Transition checker : verifies correct read data using default memory +-------------------------------------------------------------------------------- +checker: PROCESS + VARIABLE RAddr : NATURAL; + VARIABLE RSect : NATURAL; + VARIABLE longread : boolean; + VARIABLE shortread : boolean; + VARIABLE toggle : boolean:=false; + VARIABLE toggle_sts : std_logic_vector(7 downto 0); + +BEGIN +-- Transition extractor + IF (T_CENeg='0'AND T_OENeg='0'AND T_WENeg='1') THEN + IF T_BYTENeg='1' THEN + RAddr := to_nat(T_A(14 downto 0)&'0'); + ELSE + RAddr := to_nat(T_A(14 downto 0)&T_DQ(15)); + END IF; + RSect := to_nat(T_A(HiAddrBit downto 15)); + + shortread:= false; + longread := false; + + --DUT specific timing + IF (T_CENeg'EVENT OR T_WENeg'EVENT OR T_A(HiAddrBit downto 2)'EVENT)AND -- + (status=read OR status=rd_cfi OR status=rd_secsi) THEN --OR status=readX) + longread := true; + CASE TimingModel IS + WHEN "AM29LV640MH90R" | + "AM29LV640ML90R" => WAIT FOR 95 ns; +-- WHEN "AM29LV640MH101" | +-- "AM29LV640ML101" => WAIT FOR 105 ns; +-- WHEN "AM29LV640MH101R" | +-- "AM29LV640ML101R" => WAIT FOR 105 ns; +-- WHEN "AM29LV640MH112" | +-- "AM29LV640ML112" => WAIT FOR 115 ns; +-- WHEN "AM29LV640MH112R" | +-- "AM29LV640ML112R" => WAIT FOR 115 ns; +-- WHEN "AM29LV640MH120" | +-- "AM29LV640ML120" => WAIT FOR 125 ns; +-- WHEN "AM29LV640MH120R" | +-- "AM29LV640ML120R" => WAIT FOR 125 ns; + WHEN OTHERS => + REPORT "Timing model NOT supported : "&TimingModel + SEVERITY error; + END CASE; + + ELSIF T_A(1 downto 0)'EVENT OR + (T_DQ(15)'EVENT AND T_BYTENeg='0')OR + (T_BYTENeg'EVENT) OR + T_OENeg'EVENT OR + (status/=read AND status/=rd_cfi AND + status/=rd_secsi) THEN --AND status/=readX) + shortread:=true; + CASE TimingModel IS + WHEN "AM29LV640MH90R" | + "AM29LV640ML90R" => WAIT FOR 30 ns; +-- WHEN "AM29LV640MH101" | +-- "AM29LV640ML101" => WAIT FOR 40 ns; +-- WHEN "AM29LV640MH101R" | +-- "AM29LV640ML101R" => WAIT FOR 40 ns; +-- WHEN "AM29LV640MH112" | +-- "AM29LV640ML112" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH112R" | +-- "AM29LV640ML112R" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH120" | +-- "AM29LV640ML120" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH120R" | +-- "AM29LV640ML120R" => WAIT FOR 45 ns; + WHEN OTHERS => + REPORT "Timing model NOT supported : "&TimingModel + SEVERITY error; + END CASE; + + END IF; + + + + --Checker + IF longread OR shortread THEN + + CASE status IS + WHEN none => + toggle := false; + + -- read memory array data + WHEN read => + toggle := false; + Check_read ( + DQ => T_DQ, + D_lo => mem(RSect)(RAddr), + D_hi => mem(RSect)(RAddr+1), + Byte => T_BYTENeg, + check_err=> check_err); + + -- read secure silicon region + WHEN rd_secsi => + toggle := false; + Check_SecSi ( + DQ => T_DQ, + D_lo => SecSi(RAddr), + D_hi => SecSi(RAddr+1), + Byte => T_BYTENeg, + check_err=>check_err); + + + --read CFI query codes + WHEN rd_cfi => + RAddr := to_nat(T_A(14 downto 0)); --x16 addressing + toggle := false; + Check_CFI ( + DQ => T_DQ, + D_lo => CFI_array(RAddr) , + D_hi => 0 , + Byte => T_BYTENeg, + check_err=>check_err); + + + + -- read Autoselect codes + WHEN rd_AS => + RAddr := to_nat(T_A(14 downto 0)); --x16 addressing + toggle := false; + Check_AS ( + DQ => T_DQ, + addr => RAddr, + ProtSecNum=>ProtSecNum, + secProt => Sec_Prot(RSect), + FactoryProt=>FactoryProt , + Byte => T_BYTENeg, + AS_E => to_slv(16#0C#,8), + AS_F => to_slv(1,8), + + check_err=>check_err); + + + WHEN rd_HiZ => + toggle:=false; + Check_Z ( + DQ => T_DQ, + check_err=>check_err); + + + + WHEN readX => + toggle:=false; + Check_X ( + DQ => T_DQ, + check_err=>check_err); + + + WHEN erase_na | erase_active => + IF toggle THEN + Check_Erase ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN ers_susp_e => + IF toggle THEN + Check_Ers_Susp ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + +-- + + WHEN ers_susp_prog_na | ers_susp_prog => + IF toggle THEN + Check_Ers_Susp_Prog ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + +-- + + WHEN prog_na | prog_active => + IF toggle THEN + Check_Progr ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN buff_wr_busy | buff_wr_N_busy => + IF toggle THEN + Check_Buff_Busy ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN buff_abort => + IF toggle THEN + Check_Abort ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + WHEN OTHERS => null; + END CASE; + + -- get firs data for toggle check + CASE status IS + WHEN prog_active | prog_na | + erase_active | erase_na | + ers_susp_e | + ers_susp_prog | ers_susp_prog_na | + buff_wr_busy | buff_wr_N_busy | + buff_abort | get_toggle => + + IF (NOT toggle) OR (status=get_toggle) THEN + toggle:=true; + toggle_sts := T_DQ(7 downto 0); + END IF; + + WHEN OTHERS => null; + END CASE; + + + END IF; + + END IF; + + WAIT ON T_A, T_CENeg, T_OENeg, T_WENeg, T_DQ(15), T_BYTENeg; + +END PROCESS checker; + + +default: PROCESS + -- text file input variables + FILE mem_f : text is mem_file; + FILE prot_f : text is prot_file; + FILE secsi_f : text is secsi_file; + + VARIABLE S_ind : NATURAL RANGE 0 TO SecNum:= 0; + VARIABLE ind : NATURAL RANGE 0 TO SecSize:= 0; + VARIABLE buf : line; + +BEGIN + --Preload Control + ----------------------------------------------------------------------- + -- File Read Section + ----------------------------------------------------------------------- + IF UserPreload THEN + --- Sector protection preload + IF (prot_file /= "none" ) THEN + ind := 0; + FactoryProt := '0'; + Sec_Prot := (OTHERS => '0'); + WHILE (not ENDFILE (prot_f)) LOOP + READLINE (prot_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 3)); --address + ELSE + IF ind > SecNum THEN + --SecSi Factory protect preload + IF buf(1)='1' THEN + FactoryProt := '1'; + END IF; + ELSE + -- Standard Sector prload + IF buf(1)='1' THEN + Sec_Prot(ind):= '1'; + END IF; + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + -- Secure Silicon Sector Region preload + IF (SecSi_file /= "none" ) THEN + SecSi := (OTHERS => MaxData); + ind := 0; + WHILE (not ENDFILE (SecSi_f)) LOOP + READLINE (SecSi_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 3)); --address + ELSE + IF ind <= SecSiSize THEN + SecSi(ind) := h(buf(1 TO 2)); + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + --- Memory Preload + IF (mem_file /= "none" ) THEN + ind := 0; + Mem := (OTHERS => (OTHERS => MaxData)); + -- load sector 0 + WHILE (not ENDFILE (mem_f)) LOOP + READLINE (mem_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 5)); --address + ELSE + IF ind <= SecSize THEN + Mem(0)(ind) := h(buf(1 to 2)); + ind := ind + 1; + END IF; + END IF; + END LOOP; + -- load other sectors + FOR i IN 1 TO SecNum LOOP + Mem(i) := Mem(0); + END LOOP; + END IF; + + END IF; + ----------------------------------------------------------------------- + --CFI array data / AM29LV640MH90R !!! DEVICE SPECIFIC + ----------------------------------------------------------------------- + --CFI query identification string + -- !!!!!! WORD ADDRESSES (x16) - for x8 addressing double addr + --CFI query identification string + CFI_array(16#10#) := 16#51#; + CFI_array(16#11#) := 16#52#; + CFI_array(16#12#) := 16#59#; + CFI_array(16#13#) := 16#02#; + CFI_array(16#14#) := 16#00#; + CFI_array(16#15#) := 16#40#; + CFI_array(16#16#) := 16#00#; + CFI_array(16#17#) := 16#00#; + CFI_array(16#18#) := 16#00#; + CFI_array(16#19#) := 16#00#; + CFI_array(16#1A#) := 16#00#; + --system interface string + CFI_array(16#1B#) := 16#27#; + CFI_array(16#1C#) := 16#36#; + CFI_array(16#1D#) := 16#00#; + CFI_array(16#1E#) := 16#00#; + CFI_array(16#1F#) := 16#07#; + CFI_array(16#20#) := 16#07#; + CFI_array(16#21#) := 16#0A#; + CFI_array(16#22#) := 16#00#; + CFI_array(16#23#) := 16#01#; + CFI_array(16#24#) := 16#05#; + CFI_array(16#25#) := 16#04#; + CFI_array(16#26#) := 16#00#; + --device geometry definition + CFI_array(16#27#) := 16#17#; + CFI_array(16#28#) := 16#02#; + CFI_array(16#29#) := 16#00#; + CFI_array(16#2A#) := 16#05#; + CFI_array(16#2B#) := 16#00#; + CFI_array(16#2C#) := 16#01#; + CFI_array(16#2D#) := 16#7F#; + CFI_array(16#2E#) := 16#00#; + CFI_array(16#2F#) := 16#00#; + CFI_array(16#30#) := 16#01#; + CFI_array(16#31#) := 16#00#; + CFI_array(16#32#) := 16#00#; + CFI_array(16#33#) := 16#00#; + CFI_array(16#34#) := 16#00#; + CFI_array(16#35#) := 16#00#; + CFI_array(16#36#) := 16#00#; + CFI_array(16#37#) := 16#00#; + CFI_array(16#38#) := 16#00#; + CFI_array(16#39#) := 16#00#; + CFI_array(16#3A#) := 16#00#; + CFI_array(16#3B#) := 16#00#; + CFI_array(16#3C#) := 16#00#; + --primary vendor-specific extended query + CFI_array(16#40#) := 16#50#; + CFI_array(16#41#) := 16#52#; + CFI_array(16#42#) := 16#49#; + CFI_array(16#43#) := 16#31#; + CFI_array(16#44#) := 16#33#; + CFI_array(16#45#) := 16#08#; + CFI_array(16#46#) := 16#02#; + CFI_array(16#47#) := 16#01#; + CFI_array(16#48#) := 16#01#; + CFI_array(16#49#) := 16#04#; + CFI_array(16#4A#) := 16#00#; + CFI_array(16#4B#) := 16#00#; + CFI_array(16#4C#) := 16#01#; + CFI_array(16#4D#) := 16#B5#; + CFI_array(16#4E#) := 16#C5#; + IF TimingModel(11) = 'L' THEN + CFI_array(16#4F#) := 16#04#; + ELSE + CFI_array(16#4F#) := 16#05#; --uniform sectors top protect + END IF; + CFI_array(16#50#) := 16#01#; + + WAIT; + +END PROCESS default; + + + +END vhdl_behavioral; + diff --git a/lib/models/memory/flash/serial/S25fl512s/utilities/conversions.vhd b/lib/models/memory/flash/serial/S25fl512s/utilities/conversions.vhd new file mode 100644 index 0000000..e5fc0d6 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl512s/utilities/conversions.vhd @@ -0,0 +1,1035 @@ +-------------------------------------------------------------------------------- +-- File Name: conversions_p.vhd +-------------------------------------------------------------------------------- +-- Copyright (C) 1997, 1998, 2001 Free Model Foundry; http://eda.org/fmf/ +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License version 2 as +-- published by the Free Software Foundation. +-- +-- This package was written by SEVA Technologies, Inc. and donated to the FMF. +-- www.seva.com +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 R. Steele 97 DEC 05 Added header and formatting to SEVA file +-- V1.1 R. Munden 98 NOV 28 Corrected some comments +-- Corrected function b +-- V1.2 R. Munden 01 MAY 27 Corrected function to_nat for weak values +-- and combined into a single file +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; + +-------------------------------------------------------------------------------- +-- CONVERSION FUNCTION SELECTION TABLES +-------------------------------------------------------------------------------- +-- +-- FROM TO: std_logic_vector std_logic natural time string +-- -----------------|---------------|---------|---------|---------|----------- +-- std_logic_vector | N/A | N/A | to_nat | combine | see below +-- std_logic | N/A | N/A | to_nat | combine | see below +-- natural | to_slv | to_sl | N/A | to_time | see below +-- time | N/A | N/A | to_nat | N/A | to_time_str +-- hex string | h | N/A | h | combine | N/A +-- decimal string | d | N/A | d | combine | N/A +-- octal string | o | N/A | o | combine | N/A +-- binary string | b | N/A | b | combine | N/A +-- -----------------|---------------|---------|---------|---------|----------- +-- +-- FROM TO: hex string decimal string octal string binary string +-- -----------------|------------|-------------|------------|---------------- +-- std_logic_vector | to_hex_str | to_int_str | to_oct_str | to_bin_str +-- std_logic | N/A | N/A | N/A | to_bin_str +-- natural | to_hex_str | to_int_str | to_oct_str | to_bin_str +-- -----------------|------------|-------------|------------|---------------- +-- +-------------------------------------------------------------------------------- + +PACKAGE conversions IS + + ---------------------------------------------------------------------------- + -- the conversions in this package are not guaranteed to be synthesizable. + -- + -- others functions available + -- fill creates a variable length string of the fill character + -- + -- + -- + -- input parameters of type natural or integer can be in the form: + -- normal -> 8, 99, 4_237 + -- base#value# -> 2#0101#, 16#fa4C#, 8#6_734# + -- with exponents(x10) -> 8e4, 16#2e#E4 + -- + -- input parameters of type string can be in the form: + -- "99", "4_237", "0101", "1010_1010" + -- + -- for bit/bit_vector <-> std_logic/std_logic_vector conversions use + -- package std_logic_1164 + -- to_bit(std_logic) + -- to_bitvector(std_logic_vector) + -- to_stdlogic(bit) + -- to_stdlogicvector(bit_vector) + -- + -- for "synthesizable" signed/unsigned/std_logic_vector/integer + -- conversions use + -- package std_logic_arith + -- conv_integer(signed/unsigned) + -- conv_unsigned(integer/signed,size) + -- conv_signed(integer/unsigned,size) + -- conv_std_logic_vector(integer/signed/unsigned,size) + -- + -- for "synthesizable" std_logic_vector -> integer conversions use + -- package std_logic_unsigned/std_logic_signed + -- + -- conv_integer(std_logic_vector) + -- + -- type1'(expression of type2) + -- + -- most conversions have 4 parmeters: + -- x : value to be converted + -- rtn_len : size of the return value + -- justify : justify value 'left' or 'right', default is right + -- basespec : print the base of the value - 'yes'/'no', default is yes + -- + -- Typical ways to call these functions: + -- simple, all defaults used + -- to_bin_str(x) + -- x will be converted to a string of minimum size with a + -- base specification appended for clarity + -- if x is 10101 then return is b"10101" + -- + -- to control size of return string + -- to_hex_str(x, + -- 6) + -- length of string returned will be 6 characters + -- value will be right justified in the field + -- if x is 10101 then return is ....h"15" + -- where '.' represents a blank + -- if 'rtn_len' parm defaults or is set to 0 then + -- return string will always be minimum size + -- + -- to left justify and suppress base specification + -- to_int_str(x, + -- 6, + -- justify => left, + -- basespec => yes) + -- length of return string will be 6 characters + -- the base specification will be suppressed + -- if x is 10101 then return is 21.... + -- where '.' represents a blank + -- + -- other usage notes + -- + -- if rtn_len less than or equal to x'length then ignore + -- rtn_len and return string of x'length + -- the 'justify' parm is effectively ignored in this case + -- + -- if rtn_len greater than x'length then return string + -- of rtn_len with blanks based on 'justify' parm + -- + -- these routines do not handle negative numbers + ---------------------------------------------------------------------------- + + type justify_side is (left, right); + type b_spec is (no , yes); + + -- std_logic_vector to binary string + function to_bin_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- std_logic to binary string + function to_bin_str(x : std_logic; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to binary string + function to_bin_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to hex string + function to_hex_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to hex string + function to_hex_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to octal string + function to_oct_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to octal string + function to_oct_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- natural to integer string + function to_int_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to integer string + function to_int_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- time to string + function to_time_str (x : time) + return string; + + -- add characters to a string + function fill (fill_char : character := '*'; + rtn_len : integer := 1) + return string; + -- usage: + -- fill + -- returns * + -- fill(' ',10) + -- returns .......... when '.' represents a blank + -- fill(lf) or fill(ht) + -- returns line feed character or tab character respectively + + -- std_logic_vector to natural + function to_nat (x : std_logic_vector) + return natural; + + -- std_logic to natural + function to_nat (x : std_logic) + return natural; + + -- time to natural + function to_nat (x : time) + return natural; + + -- hex string to std_logic_vector + function h (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or a,A to f,F + -- or x,X,z,Z,u,U,-,w,W, result will be 0 + + -- decimal string to std_logic_vector + function d (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- octal string to std_logic_vector + function o (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 7 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- binary string to std_logic_vector + function b (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 1 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- hex string to natural + function h (x : string) + return natural; + -- if x is other than characters 0 to 9 or a,A to f,F, result will be 0 + + -- decimal string to natural + function d (x : string) + return natural; + -- if x is other than characters 0 to 9, result will be 0 + + -- octal string to natural + function o (x : string) + return natural; + -- if x is other than characters 0 to 7, result will be 0 + + -- binary string to natural + function b (x : string) + return natural; + -- if x is other than characters 0 to 1, result will be 0 + + -- natural to std_logic_vector + function to_slv (x : natural; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than sizeof(x), result will be truncated on the left + -- see note above regarding possible formats for x + + -- natural to std_logic + function to_sl (x : natural) + return std_logic; + + -- natural to time + function to_time (x : natural) + return time; + -- see note above regarding possible formats for x + +END conversions; +-- +-------------------------------------------------------------------------------- +-- + +PACKAGE BODY conversions IS + + -- private declarations for this package + type basetype is (binary, octal, decimal, hex); + + function max(x,y: integer) return integer is + begin + if x > y then return x; else return y; end if; + end max; + + function min(x,y: integer) return integer is + begin + if x < y then return x; else return y; end if; + end min; + + -- consider function sizeof for string/slv/???, return natural + + -- function size(len: natural) return natural is + -- begin + -- if len=0 then + -- return 31; + -- else return len; + -- end if; + -- end size; + + function nextmultof (x : positive; + size : positive) return positive is + begin + case x mod size is + when 0 => return size * x/size; + when others => return size * (x/size + 1); + end case; + end nextmultof; + + function rtn_base (base : basetype) return character is + begin + case base is + when binary => return 'b'; + when octal => return 'o'; + when decimal => return 'd'; + when hex => return 'h'; + end case; + end rtn_base; + + function format (r : string; + base : basetype; + rtn_len : natural ; + justify : justify_side; + basespec : b_spec) return string is + variable int_rtn_len : integer; + begin + if basespec=yes then + int_rtn_len := rtn_len - 3; + else + int_rtn_len := rtn_len; + end if; + if int_rtn_len <= r'length then + case basespec is + when no => return r ; + when yes => return rtn_base(base) & '"' & r & '"'; + end case; + else + case justify is + when left => + case basespec is + when no => + return r & fill(' ',int_rtn_len - r'length); + when yes => + return rtn_base(base) & '"' & r & '"' & + fill(' ',int_rtn_len - r'length); + end case; + when right => + case basespec is + when no => + return fill(' ',int_rtn_len - r'length) & r ; + when yes => + return fill(' ',int_rtn_len - r'length) & + rtn_base(base) & '"' & r & '"'; + end case; + end case; + end if; + end format; + + -- convert numeric string of any base to natural + function cnvt_base (x : string; + inbase : natural range 2 to 16) return natural is + -- assumes x is an unsigned number string of base 'inbase' + -- values larger than natural'high are not supported + variable r,t : natural := 0; + variable place : positive := 1; + begin + for i in x'reverse_range loop + case x(i) is + when '0' => t := 0; + when '1' => t := 1; + when '2' => t := 2; + when '3' => t := 3; + when '4' => t := 4; + when '5' => t := 5; + when '6' => t := 6; + when '7' => t := 7; + when '8' => t := 8; + when '9' => t := 9; + when 'a'|'A' => t := 10; + when 'b'|'B' => t := 11; + when 'c'|'C' => t := 12; + when 'd'|'D' => t := 13; + when 'e'|'E' => t := 14; + when 'f'|'F' => t := 15; + when '_' => t := 0; -- ignore these characters + place := place / inbase; + when others => + assert false + report lf & + "CNVT_BASE found input value larger than base: " & lf & + "Input value: " & x(i) & + " Base: " & to_int_str(inbase) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + if t / inbase > 1 then -- invalid value for base + assert false + report lf & + "CNVT_BASE found input value larger than base: " & lf & + "Input value: " & x(i) & + " Base: " & to_int_str(inbase) & lf & + "converting input to integer 0" + severity warning; + return 0; + else + r := r + (t * place); + place := place * inbase; + end if; + end loop; + return r; + end cnvt_base; + + function extend (x : std_logic; + len : positive) return std_logic_vector is + variable v : std_logic_vector(1 to len) := (others => x); + begin + return v; + end extend; + + + -- implementation of public declarations + + function to_bin_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + + variable int : std_logic_vector(1 to x'length):=x; + variable r : string(1 to x'length):=(others=>'$'); + begin + for i in int'range loop + r(i to i) := to_bin_str(int(i),basespec=>no); + end loop; + return format (r,binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_bin_str(x : std_logic; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable r : string(1 to 1); + begin + case x is + when '0' => r(1) := '0'; + when '1' => r(1) := '1'; + when 'U' => r(1) := 'U'; + when 'X' => r(1) := 'X'; + when 'Z' => r(1) := 'Z'; + when 'W' => r(1) := 'W'; + when 'H' => r(1) := 'H'; + when 'L' => r(1) := 'L'; + when '-' => r(1) := '-'; + end case; + return format (r,binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_bin_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 2 to 32 := 32; + variable r : string(2 to 32):=(others=>'$'); + begin + if int = 0 then + return format ("0",binary,rtn_len,justify,basespec); + end if; + + while int > 0 loop + case int rem 2 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when others => + assert false report lf & "TO_BIN_STR, shouldn't happen" + severity failure; + return "$"; + null; + end case; + int := int / 2; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 32),binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_hex_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + -- will return x'length/4 + variable nxt : positive := nextmultof(x'length,4); + variable int : std_logic_vector(1 to nxt):= (others => '0'); + variable ptr : positive range 1 to (nxt/4)+1 := 1; + variable r : string(1 to nxt/4):=(others=>'$'); + subtype slv4 is std_logic_vector(1 to 4); + begin + int(nxt-x'length+1 to nxt) := x; + if nxt-x'length > 0 and x(x'left) /= '1' then + int(1 to nxt-x'length) := extend(x(x'left),nxt-x'length); + end if; + for i in int'range loop + next when i rem 4 /= 1; + case slv4'(int(i to i+3)) is + when "0000" => r(ptr) := '0'; + when "0001" => r(ptr) := '1'; + when "0010" => r(ptr) := '2'; + when "0011" => r(ptr) := '3'; + when "0100" => r(ptr) := '4'; + when "0101" => r(ptr) := '5'; + when "0110" => r(ptr) := '6'; + when "0111" => r(ptr) := '7'; + when "1000" => r(ptr) := '8'; + when "1001" => r(ptr) := '9'; + when "1010" => r(ptr) := 'A'; + when "1011" => r(ptr) := 'B'; + when "1100" => r(ptr) := 'C'; + when "1101" => r(ptr) := 'D'; + when "1110" => r(ptr) := 'E'; + when "1111" => r(ptr) := 'F'; + when "ZZZZ" => r(ptr) := 'Z'; + when "WWWW" => r(ptr) := 'W'; + when "LLLL" => r(ptr) := 'L'; + when "HHHH" => r(ptr) := 'H'; + when "UUUU" => r(ptr) := 'U'; + when "XXXX" => r(ptr) := 'X'; + when "----" => r(ptr) := '-'; + when others => + assert false + report lf & + "TO_HEX_STR found illegal value: " & + to_bin_str(int(i to i+3)) & lf & + "converting input to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr + 1; + end loop; + return format (r,hex,rtn_len,justify,basespec); + end to_hex_str; + + function to_hex_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 20 := 20; + variable r : string(1 to 20):=(others=>'$'); + begin + if x=0 then return format ("0",hex,rtn_len,justify,basespec); end if; + while int > 0 loop + case int rem 16 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when 8 => r(ptr) := '8'; + when 9 => r(ptr) := '9'; + when 10 => r(ptr) := 'A'; + when 11 => r(ptr) := 'B'; + when 12 => r(ptr) := 'C'; + when 13 => r(ptr) := 'D'; + when 14 => r(ptr) := 'E'; + when 15 => r(ptr) := 'F'; + when others => + assert false report lf & "TO_HEX_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 16; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 20),hex,rtn_len,justify,basespec); + end to_hex_str; + + function to_oct_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + -- will return x'length/3 + variable nxt : positive := nextmultof(x'length,3); + variable int : std_logic_vector(1 to nxt):= (others => '0'); + variable ptr : positive range 1 to (nxt/3)+1 := 1; + variable r : string(1 to nxt/3):=(others=>'$'); + subtype slv3 is std_logic_vector(1 to 3); + begin + int(nxt-x'length+1 to nxt) := x; + if nxt-x'length > 0 and x(x'left) /= '1' then + int(1 to nxt-x'length) := extend(x(x'left),nxt-x'length); + end if; + for i in int'range loop + next when i rem 3 /= 1; + case slv3'(int(i to i+2)) is + when "000" => r(ptr) := '0'; + when "001" => r(ptr) := '1'; + when "010" => r(ptr) := '2'; + when "011" => r(ptr) := '3'; + when "100" => r(ptr) := '4'; + when "101" => r(ptr) := '5'; + when "110" => r(ptr) := '6'; + when "111" => r(ptr) := '7'; + when "ZZZ" => r(ptr) := 'Z'; + when "WWW" => r(ptr) := 'W'; + when "LLL" => r(ptr) := 'L'; + when "HHH" => r(ptr) := 'H'; + when "UUU" => r(ptr) := 'U'; + when "XXX" => r(ptr) := 'X'; + when "---" => r(ptr) := '-'; + when others => + assert false + report lf & + "TO_OCT_STR found illegal value: " & + to_bin_str(int(i to i+2)) & lf & + "converting input to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr + 1; + end loop; + return format (r,octal,rtn_len,justify,basespec); + end to_oct_str; + + function to_oct_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 20 := 20; + variable r : string(1 to 20):=(others=>'$'); + begin + if x=0 then return format ("0",octal,rtn_len,justify,basespec); end if; + while int > 0 loop + case int rem 8 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when others => + assert false report lf & "TO_OCT_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 8; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 20),octal,rtn_len,justify,basespec); + end to_oct_str; + + function to_int_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 32 := 32; + variable r : string(1 to 32):=(others=>'$'); + begin + if x=0 then return format ("0",hex,rtn_len,justify,basespec); + else + while int > 0 loop + case int rem 10 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when 8 => r(ptr) := '8'; + when 9 => r(ptr) := '9'; + when others => + assert false report lf & "TO_INT_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 10; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 32),decimal,rtn_len,justify,basespec); + end if; + end to_int_str; + + function to_int_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string is + begin + return to_int_str(to_nat(x),rtn_len,justify,basespec); + end to_int_str; + + + function to_time_str (x : time) + return string is + begin + return to_int_str(to_nat(x),basespec=>no) & " ns"; + end to_time_str; + + function fill (fill_char : character := '*'; + rtn_len : integer := 1) + return string is + variable r : string(1 to max(rtn_len,1)) := (others => fill_char); + variable len : integer; + begin + if rtn_len < 2 then -- always returns at least 1 fill char + len := 1; + else + len := rtn_len; + end if; + return r(1 to len); + end fill; + + function to_nat(x : std_logic_vector) return natural is + -- assumes x is an unsigned number, lsb on right, + -- more than 31 bits are truncated on left + variable t : std_logic_vector(1 to x'length) := x; + variable int : std_logic_vector(1 to 31) := (others => '0'); + variable r : natural := 0; + variable place : positive := 1; + begin + if x'length < 32 then + int(max(32-x'length,1) to 31) := t(1 to x'length); + else -- x'length >= 32 + int(1 to 31) := t(x'length-30 to x'length); + end if; + for i in int'reverse_range loop + case int(i) is + when '1' | 'H' => r := r + place; + when '0' | 'L' => null; + when others => + assert false + report lf & + "TO_NAT found illegal value: " & to_bin_str(int(i)) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + exit when i=1; + place := place * 2; + end loop; + return r; + end to_nat; + + function to_nat (x : std_logic) + return natural is + begin + case x is + when '0' => return 0 ; + when '1' => return 1 ; + when others => + assert false + report lf & + "TO_NAT found illegal value: " & to_bin_str(x) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + end to_nat; + + function to_nat (x : time) + return natural is + begin + return x / 1 ns; + end to_nat; + + function h(x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or a,A to f,F or + -- x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length*4,rtn_len); + variable ptr : integer range -3 to size := size; + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr-3 to ptr) := "0000"; + when '1' => r(ptr-3 to ptr) := "0001"; + when '2' => r(ptr-3 to ptr) := "0010"; + when '3' => r(ptr-3 to ptr) := "0011"; + when '4' => r(ptr-3 to ptr) := "0100"; + when '5' => r(ptr-3 to ptr) := "0101"; + when '6' => r(ptr-3 to ptr) := "0110"; + when '7' => r(ptr-3 to ptr) := "0111"; + when '8' => r(ptr-3 to ptr) := "1000"; + when '9' => r(ptr-3 to ptr) := "1001"; + when 'a'|'A' => r(ptr-3 to ptr) := "1010"; + when 'b'|'B' => r(ptr-3 to ptr) := "1011"; + when 'c'|'C' => r(ptr-3 to ptr) := "1100"; + when 'd'|'D' => r(ptr-3 to ptr) := "1101"; + when 'e'|'E' => r(ptr-3 to ptr) := "1110"; + when 'f'|'F' => r(ptr-3 to ptr) := "1111"; + when 'U' => r(ptr-3 to ptr) := "UUUU"; + when 'X' => r(ptr-3 to ptr) := "XXXX"; + when 'Z' => r(ptr-3 to ptr) := "ZZZZ"; + when 'W' => r(ptr-3 to ptr) := "WWWW"; + when 'H' => r(ptr-3 to ptr) := "HHHH"; + when 'L' => r(ptr-3 to ptr) := "LLLL"; + when '-' => r(ptr-3 to ptr) := "----"; + when '_' => ptr := ptr + 4; + when others => + assert false + report lf & + "O conversion found illegal input character: " & + int(i) & lf & "converting character to '----'" + severity warning; + r(ptr-3 to ptr) := "----"; + end case; + ptr := ptr - 4; + end loop; + return r(size-rtn_len+1 to size); + end h; + + function d (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than binary length of x, result will be truncated on + -- the left + -- if x is other than characters 0 to 9, result will be 0 + begin + return to_slv(cnvt_base(x,10),rtn_len); + end d; + + function o (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length*3, result will be truncated on the left + -- if x is other than characters 0 to 7 or or x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length*3,rtn_len); + variable ptr : integer range -2 to size := size; + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr-2 to ptr) := "000"; + when '1' => r(ptr-2 to ptr) := "001"; + when '2' => r(ptr-2 to ptr) := "010"; + when '3' => r(ptr-2 to ptr) := "011"; + when '4' => r(ptr-2 to ptr) := "100"; + when '5' => r(ptr-2 to ptr) := "101"; + when '6' => r(ptr-2 to ptr) := "110"; + when '7' => r(ptr-2 to ptr) := "111"; + when 'U' => r(ptr-2 to ptr) := "UUU"; + when 'X' => r(ptr-2 to ptr) := "XXX"; + when 'Z' => r(ptr-2 to ptr) := "ZZZ"; + when 'W' => r(ptr-2 to ptr) := "WWW"; + when 'H' => r(ptr-2 to ptr) := "HHH"; + when 'L' => r(ptr-2 to ptr) := "LLL"; + when '-' => r(ptr-2 to ptr) := "---"; + when '_' => ptr := ptr + 3; + when others => + assert false + report lf & + "O conversion found illegal input character: " & + int(i) & lf & "converting character to '---'" + severity warning; + r(ptr-2 to ptr) := "---"; + end case; + ptr := ptr - 3; + end loop; + return r(size-rtn_len+1 to size); + end o; + + function b (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length, result will be truncated on the left + -- if x is other than characters 0 to 1 or x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length,rtn_len); + variable ptr : integer range 0 to size+1 := size; -- csa + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr) := '0'; + when '1' => r(ptr) := '1'; + when 'U' => r(ptr) := 'U'; + when 'X' => r(ptr) := 'X'; + when 'Z' => r(ptr) := 'Z'; + when 'W' => r(ptr) := 'W'; + when 'H' => r(ptr) := 'H'; + when 'L' => r(ptr) := 'L'; + when '-' => r(ptr) := '-'; + when '_' => ptr := ptr + 1; + when others => + assert false + report lf & + "B conversion found illegal input character: " & + int(i) & lf & "converting character to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr - 1; + end loop; + return r(size-rtn_len+1 to size); + end b; + + function h (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 9 + -- a,A to f,F + -- blanks, underscore + begin + return cnvt_base(x,16); + end h; + + function d (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 9 + -- blanks, underscore + begin + return cnvt_base(x,10); + end d; + + function o (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 7 + -- blanks, underscore + begin + return cnvt_base(x,8); + end o; + + function b (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 1 + -- blanks, underscore + begin + return cnvt_base(x,2); + end b; + + function to_slv(x : natural; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than sizeof(x), result will be truncated on the left + variable int : natural := x; + variable ptr : positive := 32; + variable r : std_logic_vector(1 to 32) := (others=>'0'); + begin + while int > 0 loop + case int rem 2 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when others => + assert false report lf & "TO_SLV, shouldn't happen" + severity failure; + return "0"; + end case; + int := int / 2; + ptr := ptr - 1; + end loop; + return r(33-rtn_len to 32); + end to_slv; + + function to_sl(x : natural) + return std_logic is + variable r : std_logic := '0'; + begin + case x is + when 0 => null; + when 1 => r := '1'; + when others => + assert false + report lf & + "TO_SL found illegal input character: " & + to_int_str(x) & lf & "converting character to '-'" + severity warning; + return '-'; + end case; + return r; + end to_sl; + + function to_time (x: natural) return time is + begin + return x * 1 ns; + end to_time; + +END conversions; diff --git a/lib/models/memory/flash/serial/S25fl512s/utilities/gen_utils.vhd b/lib/models/memory/flash/serial/S25fl512s/utilities/gen_utils.vhd new file mode 100644 index 0000000..65c0e77 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl512s/utilities/gen_utils.vhd @@ -0,0 +1,144 @@ +-------------------------------------------------------------------------------- +-- File name: gen_utils.vhd +-------------------------------------------------------------------------------- +-- Copyright (C) 1996, 1998, 2001 Free Model Foundry; http://eda.org/fmf/ +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License version 2 as +-- published by the Free Software Foundation. +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 R. Steele 96 SEP 26 Initial release +-- V1.1 REV3 97 Feb 27 Added Xon and MsgOn generics +-- V1.2 R. Steele 97 APR 16 Changed wired-or to wired-and +-- V1.3 R. Steele 97 APR 16 Added diff. receiver table +-- V1.4 R. Munden 98 APR 13 Added GenParity and CheckParity +-- V1.5 R. Munden 01 NOV 24 Added UnitDelay01ZX +-- +-------------------------------------------------------------------------------- +LIBRARY IEEE; USE IEEE.std_Logic_1164.ALL; + USE IEEE.VITAL_primitives.ALL; + USE IEEE.VITAL_timing.ALL; + +PACKAGE gen_utils IS + + ---------------------------------------------------------------------------- + -- Result map for Wired-and output values (open collector) + ---------------------------------------------------------------------------- + CONSTANT STD_wired_and_rmap : VitalResultMapType := ('U','X','0','Z'); + + ---------------------------------------------------------------------------- + -- Table for computing a single signal from a differential receiver input + -- pair. + ---------------------------------------------------------------------------- + CONSTANT diff_rec_tab : VitalStateTableType := ( + + ------INPUTS--|-PREV-|-OUTPUT---- + -- A ANeg | Aint | Aint' -- + --------------|------|----------- + ( 'X', '-', '-', 'X'), -- A unknown + ( '-', 'X', '-', 'X'), -- A unknown + ( '1', '-', 'X', '1'), -- Recover from 'X' + ( '0', '-', 'X', '0'), -- Recover from 'X' + ( '/', '0', '0', '1'), -- valid diff. rising edge + ( '1', '\', '0', '1'), -- valid diff. rising edge + ( '\', '1', '1', '0'), -- valid diff. falling edge + ( '0', '/', '1', '0'), -- valid diff. falling edge + ( '-', '-', '-', 'S') -- default + ); -- end of VitalStateTableType definition + + + ---------------------------------------------------------------------------- + -- Default Constants + ---------------------------------------------------------------------------- + CONSTANT UnitDelay : VitalDelayType := 1 ns; + CONSTANT UnitDelay01 : VitalDelayType01 := (1 ns, 1 ns); + CONSTANT UnitDelay01Z : VitalDelayType01Z := (others => 1 ns); + CONSTANT UnitDelay01ZX : VitalDelayType01ZX := (others => 1 ns); + + CONSTANT DefaultInstancePath : STRING := "*"; + CONSTANT DefaultTimingChecks : BOOLEAN := FALSE; + CONSTANT DefaultTimingModel : STRING := "UNIT"; + CONSTANT DefaultXon : BOOLEAN := TRUE; + CONSTANT DefaultMsgOn : BOOLEAN := TRUE; + + -- Older VITAL generic being phased out + CONSTANT DefaultXGeneration : BOOLEAN := TRUE; + + ------------------------------------------------------------------- + -- Generate Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION GenParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic_vector; + + ------------------------------------------------------------------- + -- Check Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION CheckParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic; -- '0' - Parity Error + +END gen_utils; + +PACKAGE BODY gen_utils IS + + function XOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 403 + variable result: STD_LOGIC; + begin + result := '0'; + for i in ARG'range loop + result := result xor ARG(i); + end loop; + return result; + end; + ------------------------------------------------------------------- + -- Generate Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION GenParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic_vector + IS + VARIABLE I: NATURAL; + VARIABLE Result: std_logic_vector (Data'Length - 1 DOWNTO 0); + BEGIN + I := 0; + WHILE (I < SIZE) LOOP + Result(I+7 DOWNTO I) := Data(I+7 downto I); + Result(I+8) := XOR_REDUCE( Data(I+7 downto I) ) XOR ODDEVEN; + I := I + 9; + END LOOP; + RETURN Result; + END GenParity; + + ------------------------------------------------------------------- + -- Check Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION CheckParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic -- '0' - Parity Error + IS + VARIABLE I: NATURAL; + VARIABLE Result: std_logic; + BEGIN + I := 0; Result := '1'; + WHILE (I < SIZE) LOOP + Result := Result AND + NOT (XOR_REDUCE( Data(I+8 downto I) ) XOR ODDEVEN); + I := I + 9; + END LOOP; + RETURN Result; + END CheckParity; + +END gen_utils; diff --git a/lib/models/memory/sdram/mt48lc16m16a2/dumpdata.txt b/lib/models/memory/sdram/mt48lc16m16a2/dumpdata.txt new file mode 100644 index 0000000..26790d8 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc16m16a2/dumpdata.txt @@ -0,0 +1,47 @@ +# Micron Technology, Inc. (FILE DUMP / MEMORY DUMP) +# BA ROWS COLS DQ +# -- ------------- --------- ---------------- + 00 0000000000000 000000000 0000000001100100 + 00 0000000000000 000000001 0000000001100101 + 00 0000000000000 000000010 0000000001100110 + 00 0000000000000 000000011 0000000001100111 + 00 0000000000000 000000100 0000000001101000 + 00 0000000000000 000000101 0000000001101001 + 00 0000000000000 000000110 0000000001101010 + 00 0000000000000 000000111 0000000001101011 + 00 0000000000000 000001000 0011111111111110 + 00 0000000000000 000001001 0011111111111110 + 00 0000000000000 000001010 0011111111111110 + 01 0000000000000 000000000 0000000011001000 + 01 0000000000000 000000001 0000000011001001 + 01 0000000000000 000000010 0000000011001010 + 01 0000000000000 000000011 0000000011001011 + 01 0000000000000 000000100 0000000011001100 + 01 0000000000000 000000101 0000000011001101 + 01 0000000000000 000000110 0000000011001110 + 01 0000000000000 000000111 0000000011001111 + 01 0000000000000 000001000 0111111111111101 + 01 0000000000000 000001001 0111111111111101 + 01 0000000000000 000001010 0111111111111101 + 10 0000000000000 000000000 0000000100101100 + 10 0000000000000 000000001 0000000100101101 + 10 0000000000000 000000010 0000000100101110 + 10 0000000000000 000000011 0000000100101111 + 10 0000000000000 000000100 0000000100110000 + 10 0000000000000 000000101 0000000100110001 + 10 0000000000000 000000110 0000000100110010 + 10 0000000000000 000000111 0000000100110011 + 10 0000000000000 000001000 1011111111111011 + 10 0000000000000 000001001 1011111111111011 + 10 0000000000000 000001010 1011111111111011 + 11 0000000000000 000000000 0000000110010000 + 11 0000000000000 000000001 0000000110010001 + 11 0000000000000 000000010 0000000110010010 + 11 0000000000000 000000011 0000000110010011 + 11 0000000000000 000000100 0000000110010100 + 11 0000000000000 000000101 0000000110010101 + 11 0000000000000 000000110 0000000110010110 + 11 0000000000000 000000111 0000000110010111 + 11 0000000000000 000001000 1111111111110111 + 11 0000000000000 000001001 1111111111110111 + 11 0000000000000 000001010 1111111111110111 diff --git a/lib/models/memory/sdram/mt48lc16m16a2/ed_comnd.vhd b/lib/models/memory/sdram/mt48lc16m16a2/ed_comnd.vhd new file mode 100644 index 0000000..d449df6 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc16m16a2/ed_comnd.vhd @@ -0,0 +1,349 @@ +--------------------------------------------------------------------------------- +--COMMAND FORMAT -- +-- -- +-- write(column address(integer), bank(bit_vector), first data(integer), dqm(bit), cke(bit));-- +-- read(column address(integer), bank(bit_vector), dqm(bit), cke(bit)); -- +-- active(row address(integer), bank(bit_vector), data bus (integer), dqm(bit), cke(bit));-- +-- precharge(bank(bit_vector), address (integer), data bus(integer), dqm(bit), cke(bit)); -- +-- nop(data bus(integer), dqm(bit), cke(bit), cs(bit)); -- +-- burst_term(data bus(integer), dqm(bit_vector), cke(bit)); -- +-- load_array('1'); -- +-- load_mode_reg(register(integer), cke(bit)); -- +-- next_cycle(clk); This is used after every command(incl. nop) to clock -- +-- at the correct clock frequency entered in the clock -- +-- period constant below -- +-- unload_array(row_start(integer), row_end(integer), bank(bit_vector)) -- +-- load_mode_reg(op_code(integer)) -- +-- -- +--------------------------------------------------------------------------------- + +LIBRARY work; +LIBRARY ieee; +USE ieee.std_logic_1164.all; +USE std.textio.all; +USE work.generate_vectors.all; + +ENTITY vector_generate IS +END vector_generate; + +ARCHITECTURE vector_generate OF vector_generate IS + + SIGNAL stim_done : BOOLEAN := FALSE; + SIGNAL clk : BIT := '0'; + CONSTANT clk_start : time := 15 ns; + CONSTANT clk_period : time := 10 ns; + CONSTANT Z : INTEGER := -100; + +BEGIN + +PROCESS + +BEGIN + +WAIT UNTIL clk = '1' AND clk'EVENT; + +--------------------ENTER COMMANDS BELOW THIS LINE----------------------------- +--******************DO NOT USE -100 FOR A DQ VALUE*************************---- +--*******************Z WILL PLACE HI-Z ON THE BUS**************************---- +--*******USE next_cycle(clk) FOR ADVANCING TO NEXT CLOCK CYCLE*************---- + +nop(Z, "00", '1', '1'); --Always begin with one nop when using Micron's testbench + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +load_array; + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +precharge("00", 1024, Z, "00", '1'); + +FOR i IN 1 to 2 LOOP + next_cycle(clk); + nop(Z, "00", '1', '1'); +END LOOP; + +next_cycle(clk); +auto_refresh; + +FOR i IN 1 TO 8 LOOP + next_cycle(clk); + nop(Z, "00", '1', '1'); +END LOOP; + +next_cycle(clk); +auto_refresh; + +FOR i IN 1 TO 8 LOOP + next_cycle(clk); + nop(Z, "00", '1', '1'); +END LOOP; + +next_cycle(clk); +load_mode_reg(51, '1'); -- 19 / 35 / 51 -> lat=3,bl=8,mode=seq + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +-- Write Section + +next_cycle(clk); +active(0, "00", Z, "00", '1'); -- Activate Bank 0 + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); -- Write Bank 0 +write(0, "00", 100, "00", '1'); + +next_cycle(clk); +nop(101, "00", '1', '1'); + +next_cycle(clk); +active(0, "01", 102, "00", '1'); -- Activate Bank 1 + +next_cycle(clk); +nop(103, "00", '1', '1'); + +next_cycle(clk); +nop(104, "00", '1', '1'); + +next_cycle(clk); +nop(105, "00", '1', '1'); + +next_cycle(clk); +nop(106, "00", '1', '1'); + +next_cycle(clk); +nop(107, "00", '1', '1'); + +next_cycle(clk); +write(0, "01", 200, "00", '1'); -- Write Bank 1 + +next_cycle(clk); +precharge("00", 0, 201, "00", '1'); -- Precharge Bank 0 + +next_cycle(clk); +active(0, "10", 202, "00", '1'); -- Activate Bank 2 + +next_cycle(clk); +nop(203, "00", '1', '1'); + +next_cycle(clk); +nop(204, "00", '1', '1'); + +next_cycle(clk); +nop(205, "00", '1', '1'); + +next_cycle(clk); +nop(206, "00", '1', '1'); + +next_cycle(clk); +nop(207, "00", '1', '1'); + +next_cycle(clk); +write(0, "10", 300, "00", '1'); -- Write Bank 2 + +next_cycle(clk); +precharge("01", 0, 301, "00", '1'); -- Precharge Bank 1 + +next_cycle(clk); +active(0, "11", 302, "00", '1'); -- Activate Bank 3 + +next_cycle(clk); +nop(303, "00", '1', '1'); + +next_cycle(clk); +nop(304, "00", '1', '1'); + +next_cycle(clk); +nop(305, "00", '1', '1'); + +next_cycle(clk); +nop(306, "00", '1', '1'); + +next_cycle(clk); +nop(307, "00", '1', '1'); + +next_cycle(clk); +write(0, "11", 400, "00", '1'); -- Write Bank 3 + +next_cycle(clk); +precharge("10", 0, 401, "00", '1'); -- Precharge Bank 2 + +next_cycle(clk); +active(0, "00", 402, "00", '1'); -- Activate Bank 0 + +next_cycle(clk); +nop(403, "00", '1', '1'); + +next_cycle(clk); +nop(404, "00", '1', '1'); + +next_cycle(clk); +nop(405, "00", '1', '1'); + +next_cycle(clk); +nop(406, "00", '1', '1'); + +next_cycle(clk); +nop(407, "00", '1', '1'); + +-- Read Section + +next_cycle(clk); +read(0, "00", "00", '1'); -- Read Bank 0 + +next_cycle(clk); +precharge("11", 0, Z, "00", '1'); -- Precharge Bank 3 + +next_cycle(clk); +active(0, "01", Z, "00", '1'); -- Activate Bank 1 + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +read(0, "01", "00", '1'); -- Read Bank 1 + +next_cycle(clk); +precharge("00", 0, Z, "00", '1'); -- Precharge Bank 0 + +next_cycle(clk); +active(0, "10", Z, "00", '1'); -- Activate Bank 2 + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +read(0, "10", "00", '1'); -- Read Bank 2 + +next_cycle(clk); +precharge("01", 0, Z, "00", '1'); -- Precharge Bank 1 + +next_cycle(clk); +active(0, "11", Z, "00", '1'); -- Activate Bank 3 + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +read(0, "11", "00", '1'); -- Read Bank 3 + +next_cycle(clk); +precharge("10", 0, Z, "00", '1'); -- Precharge Bank 2 + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +precharge("11", 0, Z, "00", '1'); -- Precharge Bank 3 + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +unload_array; + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +stim_done <= TRUE; --always include this line at the end of your stimulus + +------------------------------------------------------------------------------- +--*************************************************************************---- +END PROCESS; + + +clock: + PROCESS + VARIABLE done_time : time; + VARIABLE cycle_var : integer := 0; + BEGIN + cycle <= 0; + clk <= '0'; + WAIT for clk_start; + WHILE not stim_done loop + clk <= '1'; + cycle <= cycle_var; + WAIT for clk_period/2; + cycle_var := cycle_var + 1; + clk <= '0'; + WAIT for clk_period/2; + END LOOP; + + ASSERT (FALSE) + REPORT "Test Vectors Generated" + SEVERITY note; + + WAIT; + END PROCESS; + + +END; diff --git a/lib/models/memory/sdram/mt48lc16m16a2/loaddata.txt b/lib/models/memory/sdram/mt48lc16m16a2/loaddata.txt new file mode 100644 index 0000000..bee89c0 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc16m16a2/loaddata.txt @@ -0,0 +1,50 @@ +# Micron Technology, Inc. (FILE LOAD / MEMORY INITIALIZE) +# BA ROWS COLS DQ +# -- ------------- --------- ---------------- + 00 0000000000000 000000000 0011111111111110 + 00 0000000000000 000000001 0011111111111110 + 00 0000000000000 000000010 0011111111111110 + 00 0000000000000 000000011 0011111111111110 + 00 0000000000000 000000100 0011111111111110 + 00 0000000000000 000000101 0011111111111110 + 00 0000000000000 000000110 0011111111111110 + 00 0000000000000 000000111 0011111111111110 + 00 0000000000000 000001000 0011111111111110 + 00 0000000000000 000001001 0011111111111110 + 00 0000000000000 000001010 0011111111111110 + + 01 0000000000000 000000000 0111111111111101 + 01 0000000000000 000000001 0111111111111101 + 01 0000000000000 000000010 0111111111111101 + 01 0000000000000 000000011 0111111111111101 + 01 0000000000000 000000100 0111111111111101 + 01 0000000000000 000000101 0111111111111101 + 01 0000000000000 000000110 0111111111111101 + 01 0000000000000 000000111 0111111111111101 + 01 0000000000000 000001000 0111111111111101 + 01 0000000000000 000001001 0111111111111101 + 01 0000000000000 000001010 0111111111111101 + + 10 0000000000000 000000000 1011111111111011 + 10 0000000000000 000000001 1011111111111011 + 10 0000000000000 000000010 1011111111111011 + 10 0000000000000 000000011 1011111111111011 + 10 0000000000000 000000100 1011111111111011 + 10 0000000000000 000000101 1011111111111011 + 10 0000000000000 000000110 1011111111111011 + 10 0000000000000 000000111 1011111111111011 + 10 0000000000000 000001000 1011111111111011 + 10 0000000000000 000001001 1011111111111011 + 10 0000000000000 000001010 1011111111111011 + + 11 0000000000000 000000000 1111111111110111 + 11 0000000000000 000000001 1111111111110111 + 11 0000000000000 000000010 1111111111110111 + 11 0000000000000 000000011 1111111111110111 + 11 0000000000000 000000100 1111111111110111 + 11 0000000000000 000000101 1111111111110111 + 11 0000000000000 000000110 1111111111110111 + 11 0000000000000 000000111 1111111111110111 + 11 0000000000000 000001000 1111111111110111 + 11 0000000000000 000001001 1111111111110111 + 11 0000000000000 000001010 1111111111110111 diff --git a/lib/models/memory/sdram/mt48lc16m16a2/mt48lc16m16a2.vhd b/lib/models/memory/sdram/mt48lc16m16a2/mt48lc16m16a2.vhd new file mode 100644 index 0000000..fac375d --- /dev/null +++ b/lib/models/memory/sdram/mt48lc16m16a2/mt48lc16m16a2.vhd @@ -0,0 +1,1319 @@ +----------------------------------------------------------------------------------------- +-- +-- File Name: MT48LC16M16A2.VHD +-- Version: 0.0g +-- Date: June 29th, 2000 +-- Model: Behavioral +-- Simulator: Model Technology (PC version 5.3 PE) +-- +-- Dependencies: None +-- +-- Author: Son P. Huynh +-- Email: sphuynh@micron.com +-- Phone: (208) 368-3825 +-- Company: Micron Technology, Inc. +-- Part Number: MT48LC16M16A2 (4Mb x 16 x 4 Banks) +-- +-- Description: Micron 256Mb SDRAM +-- +-- Limitation: - Doesn't check for 4096-cycle refresh +-- +-- Note: - Set simulator resolution to "ps" accuracy +-- +-- Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY +-- WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY +-- IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR +-- A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT. +-- +-- Copyright (c) 1998 Micron Semiconductor Products, Inc. +-- All rights researved +-- +-- Rev Author Phone Date Changes +-- ---- ---------------------------- ---------- ------------------------------------- +-- 0.0g Son Huynh 208-368-3825 06/29/2000 Add Load/Dump memory array +-- Micron Technology Inc. Modify tWR + tRAS timing check +-- +-- 0.0f Son Huynh 208-368-3825 07/08/1999 Fix tWR = 1 Clk + 7.5 ns (Auto) +-- Micron Technology Inc. Fix tWR = 15 ns (Manual) +-- Fix tRP (Autoprecharge to AutoRefresh) +-- +-- 0.0c Son P. Huynh 208-368-3825 04/08/1999 Fix tWR + tRP in Write with AP +-- Micron Technology Inc. Fix tRC check in Load Mode Register +-- +-- 0.0b Son P. Huynh 208-368-3825 01/06/1998 Derive from 64Mb SDRAM model +-- Micron Technology Inc. +-- +----------------------------------------------------------------------------------------- + +LIBRARY STD; + USE STD.TEXTIO.ALL; +LIBRARY IEEE; + USE IEEE.STD_LOGIC_1164.ALL; + USE IEEE.STD_LOGIC_ARITH.ALL; +LIBRARY WORK; + USE WORK.MTI_PKG.ALL; + +ENTITY mt48lc16m16a2 IS + GENERIC ( + -- Timing Parameters for -75 (PC133) and CAS Latency = 2 + tAC : TIME := 6.0 ns; + tHZ : TIME := 7.0 ns; + tOH : TIME := 2.7 ns; + tMRD : INTEGER := 2; -- 2 Clk Cycles + tRAS : TIME := 44.0 ns; + tRC : TIME := 66.0 ns; + tRCD : TIME := 20.0 ns; + tRP : TIME := 20.0 ns; + tRRD : TIME := 15.0 ns; + tWRa : TIME := 7.5 ns; -- A2 Version - Auto precharge mode only (1 Clk + 7.5 ns) + tWRp : TIME := 15.0 ns; -- A2 Version - Precharge mode only (15 ns) + + tAH : TIME := 0.8 ns; + tAS : TIME := 1.5 ns; + tCH : TIME := 2.5 ns; + tCL : TIME := 2.5 ns; + tCK : TIME := 10.0 ns; + tDH : TIME := 0.8 ns; + tDS : TIME := 1.5 ns; + tCKH : TIME := 0.8 ns; + tCKS : TIME := 1.5 ns; + tCMH : TIME := 0.8 ns; + tCMS : TIME := 1.5 ns; + + addr_bits : INTEGER := 13; + data_bits : INTEGER := 16; + col_bits : INTEGER := 9 + ); + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC_VECTOR := "00"; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '1'; + Cs_n : IN STD_LOGIC := '1'; + Ras_n : IN STD_LOGIC := '1'; + Cas_n : IN STD_LOGIC := '1'; + We_n : IN STD_LOGIC := '1'; + Dqm : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"; + Load : IN STD_LOGIC := '0'; -- FOR LOADING MEMORY ARRAY + Dump : IN STD_LOGIC := '0' -- FOR DUMPING MEMORY ARRAY + ); +END mt48lc16m16a2; + +ARCHITECTURE behave OF mt48lc16m16a2 IS + TYPE State IS (ACT, A_REF, BST, LMR, NOP, PRECH, READ, READ_A, WRITE, WRITE_A, LOAD_FILE, DUMP_FILE); + TYPE Array4xI IS ARRAY (3 DOWNTO 0) OF INTEGER; + TYPE Array4xT IS ARRAY (3 DOWNTO 0) OF TIME; + TYPE Array4xB IS ARRAY (3 DOWNTO 0) OF BIT; + TYPE Array4x2BV IS ARRAY (3 DOWNTO 0) OF BIT_VECTOR (1 DOWNTO 0); + TYPE Array4xCBV IS ARRAY (4 DOWNTO 0) OF BIT_VECTOR (Col_bits - 1 DOWNTO 0); + TYPE Array_state IS ARRAY (4 DOWNTO 0) OF State; + SIGNAL Operation : State := NOP; + SIGNAL Mode_reg : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL Active_enable, Aref_enable, Burst_term : BIT := '0'; + SIGNAL Mode_reg_enable, Prech_enable, Read_enable, Write_enable : BIT := '0'; + SIGNAL Burst_length_1, Burst_length_2, Burst_length_4, Burst_length_8 : BIT := '0'; + SIGNAL Cas_latency_2, Cas_latency_3 : BIT := '0'; + SIGNAL Ras_in, Cas_in, We_in : BIT := '0'; + SIGNAL Write_burst_mode : BIT := '0'; + SIGNAL RAS_clk, Sys_clk, CkeZ : BIT := '0'; + + -- Checking internal wires + SIGNAL Pre_chk : BIT_VECTOR (3 DOWNTO 0) := "0000"; + SIGNAL Act_chk : BIT_VECTOR (3 DOWNTO 0) := "0000"; + SIGNAL Dq_in_chk, Dq_out_chk : BIT := '0'; + SIGNAL Bank_chk : BIT_VECTOR (1 DOWNTO 0) := "00"; + SIGNAL Row_chk : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL Col_chk : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + +BEGIN + -- CS# Decode + WITH Cs_n SELECT + Cas_in <= TO_BIT (Cas_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + WITH Cs_n SELECT + Ras_in <= TO_BIT (Ras_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + WITH Cs_n SELECT + We_in <= TO_BIT (We_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + + -- Commands Decode + Active_enable <= NOT(Ras_in) AND Cas_in AND We_in; + Aref_enable <= NOT(Ras_in) AND NOT(Cas_in) AND We_in; + Burst_term <= Ras_in AND Cas_in AND NOT(We_in); + Mode_reg_enable <= NOT(Ras_in) AND NOT(Cas_in) AND NOT(We_in); + Prech_enable <= NOT(Ras_in) AND Cas_in AND NOT(We_in); + Read_enable <= Ras_in AND NOT(Cas_in) AND We_in; + Write_enable <= Ras_in AND NOT(Cas_in) AND NOT(We_in); + + -- Burst Length Decode + Burst_length_1 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND NOT(Mode_reg(0)); + Burst_length_2 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND Mode_reg(0); + Burst_length_4 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND NOT(Mode_reg(0)); + Burst_length_8 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND Mode_reg(0); + + -- CAS Latency Decode + Cas_latency_2 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND NOT(Mode_reg(4)); + Cas_latency_3 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND Mode_reg(4); + + -- Write Burst Mode + Write_burst_mode <= Mode_reg(9); + + -- RAS Clock for checking tWR and tRP + PROCESS + variable Clk0, Clk1 : integer := 0; + begin + RAS_clk <= '1'; + wait for 0.5 ns; + RAS_clk <= '0'; + wait for 0.5 ns; + if Clk0 > 100 or Clk1 > 100 then + wait; + else + if Clk = '1' and Cke = '1' then + Clk0 := 0; + Clk1 := Clk1 + 1; + elsif Clk = '0' and Cke = '1' then + Clk0 := Clk0 + 1; + Clk1 := 0; + end if; + end if; + END PROCESS; + + -- System Clock + int_clk : PROCESS (Clk) + begin + IF Clk'LAST_VALUE = '0' AND Clk = '1' THEN + CkeZ <= TO_BIT(Cke, '1'); + END IF; + Sys_clk <= CkeZ AND TO_BIT(Clk, '0'); + END PROCESS; + + state_register : PROCESS + -- NOTE: The extra bits in RAM_TYPE is for checking memory access. A logic 1 means + -- the location is in use. This will be checked when doing memory DUMP. + TYPE ram_type IS ARRAY (2**col_bits - 1 DOWNTO 0) OF BIT_VECTOR (data_bits DOWNTO 0); + TYPE ram_pntr IS ACCESS ram_type; + TYPE ram_stor IS ARRAY (2**addr_bits - 1 DOWNTO 0) OF ram_pntr; + VARIABLE Bank0 : ram_stor; + VARIABLE Bank1 : ram_stor; + VARIABLE Bank2 : ram_stor; + VARIABLE Bank3 : ram_stor; + VARIABLE Row_index, Col_index : INTEGER := 0; + VARIABLE Dq_temp : BIT_VECTOR (data_bits DOWNTO 0) := (OTHERS => '0'); + + VARIABLE Col_addr : Array4xCBV; + VARIABLE Bank_addr : Array4x2BV; + VARIABLE Dqm_reg0, Dqm_reg1 : BIT_VECTOR (1 DOWNTO 0) := "00"; + + VARIABLE Bank, Previous_bank : BIT_VECTOR (1 DOWNTO 0) := "00"; + VARIABLE B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col_brst : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Row : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Burst_counter : INTEGER := 0; + + VARIABLE Command : Array_state; + VARIABLE Bank_precharge : Array4x2BV; + VARIABLE A10_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Auto_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Read_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Write_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_read : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_write : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_bank : BIT_VECTOR (1 DOWNTO 0) := "00"; + VARIABLE Count_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE Count_precharge : Array4xI := (0 & 0 & 0 & 0); + + VARIABLE Data_in_enable, Data_out_enable : BIT := '0'; + VARIABLE Pc_b0, Pc_b1, Pc_b2, Pc_b3 : BIT := '0'; + VARIABLE Act_b0, Act_b1, Act_b2, Act_b3 : BIT := '0'; + + -- Timing Check + VARIABLE MRD_chk : INTEGER := 0; + VARIABLE WR_counter : Array4xI := (0 & 0 & 0 & 0); + VARIABLE WR_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE WR_chkp : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE RC_chk, RRD_chk : TIME := 0 ns; + VARIABLE RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3 : TIME := 0 ns; + VARIABLE RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3 : TIME := 0 ns; + VARIABLE RP_chk0, RP_chk1, RP_chk2, RP_chk3 : TIME := 0 ns; + + -- Load and Dumb variables + FILE file_load : TEXT IS IN "loaddata.txt"; -- Data load + FILE file_dump : TEXT IS OUT "dumpdata.txt"; -- Data dump + VARIABLE bank_load : BIT_VECTOR ( 1 DOWNTO 0); + VARIABLE rows_load : BIT_VECTOR (12 DOWNTO 0); + VARIABLE cols_load : BIT_VECTOR ( 8 DOWNTO 0); + VARIABLE data_load : BIT_VECTOR (15 DOWNTO 0); + VARIABLE i, j : INTEGER; + VARIABLE good_load : BOOLEAN; + VARIABLE l : LINE; + + -- Initialize empty rows + PROCEDURE Init_mem (Bank : BIT_VECTOR (1 DOWNTO 0); Row_index : INTEGER) IS + VARIABLE i, j : INTEGER := 0; + BEGIN + IF Bank = "00" THEN + IF Bank0 (Row_index) = NULL THEN -- Check to see if row empty + Bank0 (Row_index) := NEW ram_type; -- Open new row for access + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP -- Filled row with zeros + FOR j IN (data_bits) DOWNTO 0 LOOP + Bank0 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "01" THEN + IF Bank1 (Row_index) = NULL THEN + Bank1 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits) DOWNTO 0 LOOP + Bank1 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "10" THEN + IF Bank2 (Row_index) = NULL THEN + Bank2 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits) DOWNTO 0 LOOP + Bank2 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "11" THEN + IF Bank3 (Row_index) = NULL THEN + Bank3 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits) DOWNTO 0 LOOP + Bank3 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + END IF; + END; + + -- Burst Counter + PROCEDURE Burst_decode IS + VARIABLE Col_int : INTEGER := 0; + VARIABLE Col_vec, Col_temp : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + BEGIN + -- Advance Burst Counter + Burst_counter := Burst_counter + 1; + + -- Burst Type + IF Mode_reg (3) = '0' THEN + Col_int := TO_INTEGER(Col); + Col_int := Col_int + 1; + TO_BITVECTOR (Col_int, Col_temp); + ELSIF Mode_reg (3) = '1' THEN + TO_BITVECTOR (Burst_counter, Col_vec); + Col_temp (2) := Col_vec (2) XOR Col_brst (2); + Col_temp (1) := Col_vec (1) XOR Col_brst (1); + Col_temp (0) := Col_vec (0) XOR Col_brst (0); + END IF; + + -- Burst Length + IF Burst_length_2 = '1' THEN + Col (0) := Col_temp (0); + ELSIF Burst_length_4 = '1' THEN + Col (1 DOWNTO 0) := Col_temp (1 DOWNTO 0); + ELSIF Burst_length_8 = '1' THEN + Col (2 DOWNTO 0) := Col_temp (2 DOWNTO 0); + ELSE + Col := Col_temp; + END IF; + + -- Burst Read Single Write + IF Write_burst_mode = '1' AND Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Data counter + IF Burst_length_1 = '1' THEN + IF Burst_counter >= 1 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_2 = '1' THEN + IF Burst_counter >= 2 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_4 = '1' THEN + IF Burst_counter >= 4 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_8 = '1' THEN + IF Burst_counter >= 8 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + END IF; + END; + + BEGIN + WAIT ON Sys_clk, RAS_clk; + IF Sys_clk'event AND Sys_clk = '1' AND Load = '0' AND Dump = '0' THEN + -- Internal Command Pipeline + Command(0) := Command(1); + Command(1) := Command(2); + Command(2) := Command(3); + Command(3) := NOP; + + Col_addr(0) := Col_addr(1); + Col_addr(1) := Col_addr(2); + Col_addr(2) := Col_addr(3); + Col_addr(3) := (OTHERS => '0'); + + Bank_addr(0) := Bank_addr(1); + Bank_addr(1) := Bank_addr(2); + Bank_addr(2) := Bank_addr(3); + Bank_addr(3) := "00"; + + Bank_precharge(0) := Bank_precharge(1); + Bank_precharge(1) := Bank_precharge(2); + Bank_precharge(2) := Bank_precharge(3); + Bank_precharge(3) := "00"; + + A10_precharge(0) := A10_precharge(1); + A10_precharge(1) := A10_precharge(2); + A10_precharge(2) := A10_precharge(3); + A10_precharge(3) := '0'; + + -- Operation Decode (Optional for showing current command on posedge clock / debug feature) + IF Active_enable = '1' THEN + Operation <= ACT; + ELSIF Aref_enable = '1' THEN + Operation <= A_REF; + ELSIF Burst_term = '1' THEN + Operation <= BST; + ELSIF Mode_reg_enable = '1' THEN + Operation <= LMR; + ELSIF Prech_enable = '1' THEN + Operation <= PRECH; + ELSIF Read_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= READ; + ELSE + Operation <= READ_A; + END IF; + ELSIF Write_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= WRITE; + ELSE + Operation <= WRITE_A; + END IF; + ELSE + Operation <= NOP; + END IF; + + -- Dqm pipeline for Read + Dqm_reg0 := Dqm_reg1; + Dqm_reg1 := TO_BITVECTOR(Dqm); + + -- Read or Write with Auto Precharge Counter + IF Auto_precharge (0) = '1' THEN + Count_precharge (0) := Count_precharge (0) + 1; + END IF; + IF Auto_precharge (1) = '1' THEN + Count_precharge (1) := Count_precharge (1) + 1; + END IF; + IF Auto_precharge (2) = '1' THEN + Count_precharge (2) := Count_precharge (2) + 1; + END IF; + IF Auto_precharge (3) = '1' THEN + Count_precharge (3) := Count_precharge (3) + 1; + END IF; + + -- Auto Precharge Timer for tWR + if (Burst_length_1 = '1' OR Write_burst_mode = '1') then + if (Count_precharge(0) = 1) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 1) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 1) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 1) then + Count_time(3) := NOW; + end if; + elsif (Burst_length_2 = '1') then + if (Count_precharge(0) = 2) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 2) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 2) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 2) then + Count_time(3) := NOW; + end if; + elsif (Burst_length_4 = '1') then + if (Count_precharge(0) = 4) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 4) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 4) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 4) then + Count_time(3) := NOW; + end if; + elsif (Burst_length_8 = '1') then + if (Count_precharge(0) = 8) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 8) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 8) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 8) then + Count_time(3) := NOW; + end if; + end if; + + -- tMRD Counter + MRD_chk := MRD_chk + 1; + + -- tWR Counter + WR_counter(0) := WR_counter(0) + 1; + WR_counter(1) := WR_counter(1) + 1; + WR_counter(2) := WR_counter(2) + 1; + WR_counter(3) := WR_counter(3) + 1; + + + -- Auto Refresh + IF Aref_enable = '1' THEN + -- Auto Refresh to Auto Refresh + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Auto Refresh" + SEVERITY WARNING; + -- Precharge to Auto Refresh + ASSERT (NOW - RP_chk0 >= tRP OR NOW - RP_chk1 >= tRP OR NOW - RP_chk2 >= tRP OR NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Auto Refresh" + SEVERITY WARNING; + -- All banks must be idle before refresh + IF (Pc_b3 ='0' OR Pc_b2 = '0' OR Pc_b1 ='0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All banks must be Precharge before Auto Refresh" + SEVERITY WARNING; + END IF; + -- Record current tRC time + RC_chk := NOW; + END IF; + + -- Load Mode Register + IF Mode_reg_enable = '1' THEN + Mode_reg <= TO_BITVECTOR (Addr); + IF (Pc_b3 ='0' OR Pc_b2 = '0' OR Pc_b1 ='0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All bank must be Precharge before Load Mode Register" + SEVERITY WARNING; + END IF; + -- REF to LMR + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Load Mode Register" + SEVERITY WARNING; + -- LMR to LMR + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Load Mode Register" + SEVERITY WARNING; + -- Record current tMRD time + MRD_chk := 0; + END IF; + + -- Active Block (latch Bank and Row Address) + IF Active_enable = '1' THEN + IF Ba = "00" AND Pc_b0 = '1' THEN + Act_b0 := '1'; + Pc_b0 := '0'; + B0_row_addr := TO_BITVECTOR (Addr); + RCD_chk0 := NOW; + RAS_chk0 := NOW; + -- Precharge to Active Bank 0 + ASSERT (NOW - RP_chk0 >= tRP) + REPORT "tRP violation during Activate Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '1' THEN + Act_b1 := '1'; + Pc_b1 := '0'; + B1_row_addr := TO_BITVECTOR (Addr); + RCD_chk1 := NOW; + RAS_chk1 := NOW; + -- Precharge to Active Bank 1 + ASSERT (NOW - RP_chk1 >= tRP) + REPORT "tRP violation during Activate Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '1' THEN + Act_b2 := '1'; + Pc_b2 := '0'; + B2_row_addr := TO_BITVECTOR (Addr); + RCD_chk2 := NOW; + RAS_chk2 := NOW; + -- Precharge to Active Bank 2 + ASSERT (NOW - RP_chk2 >= tRP) + REPORT "tRP violation during Activate Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '1' THEN + Act_b3 := '1'; + Pc_b3 := '0'; + B3_row_addr := TO_BITVECTOR (Addr); + RCD_chk3 := NOW; + RAS_chk3 := NOW; + -- Precharge to Active Bank 3 + ASSERT (NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Activate Bank 3" + SEVERITY WARNING; + ELSIF Ba = "00" AND Pc_b0 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 0 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 1 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 2 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 3 is not Precharged" + SEVERITY WARNING; + END IF; + -- Active Bank A to Active Bank B + IF ((Previous_bank /= TO_BITVECTOR (Ba)) AND (NOW - RRD_chk < tRRD)) THEN + ASSERT (FALSE) + REPORT "tRRD violation during Activate" + SEVERITY WARNING; + END IF; + -- LMR to ACT + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Activate" + SEVERITY WARNING; + -- AutoRefresh to Activate + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Activate" + SEVERITY WARNING; + -- Record variable for checking violation + RRD_chk := NOW; + Previous_bank := TO_BITVECTOR (Ba); + END IF; + + -- Precharge Block + IF Prech_enable = '1' THEN + IF Addr(10) = '1' THEN + Pc_b0 := '1'; + Pc_b1 := '1'; + Pc_b2 := '1'; + Pc_b3 := '1'; + Act_b0 := '0'; + Act_b1 := '0'; + Act_b2 := '0'; + Act_b3 := '0'; + RP_chk0 := NOW; + RP_chk1 := NOW; + RP_chk2 := NOW; + RP_chk3 := NOW; + -- Activate to Precharge all banks + ASSERT ((NOW - RAS_chk0 >= tRAS) OR (NOW - RAS_chk1 >= tRAS)) + REPORT "tRAS violation during Precharge all banks" + SEVERITY WARNING; + -- tWR violation check for Write + IF ((NOW - WR_chkp(0) < tWRp) OR (NOW - WR_chkp(1) < tWRp) OR + (NOW - WR_chkp(2) < tWRp) OR (NOW - WR_chkp(3) < tWRp)) THEN + ASSERT (FALSE) + REPORT "tWR violation during Precharge ALL banks" + SEVERITY WARNING; + END IF; + ELSIF Addr(10) = '0' THEN + IF Ba = "00" THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + -- Activate to Precharge bank 0 + ASSERT (NOW - RAS_chk0 >= tRAS) + REPORT "tRAS violation during Precharge bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + -- Activate to Precharge bank 1 + ASSERT (NOW - RAS_chk1 >= tRAS) + REPORT "tRAS violation during Precharge bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + -- Activate to Precharge bank 2 + ASSERT (NOW - RAS_chk2 >= tRAS) + REPORT "tRAS violation during Precharge bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + -- Activate to Precharge bank 3 + ASSERT (NOW - RAS_chk3 >= tRAS) + REPORT "tRAS violation during Precharge bank 3" + SEVERITY WARNING; + END IF; + -- tWR violation check for Write + ASSERT (NOW - WR_chkp(TO_INTEGER(Ba)) >= tWRp) + REPORT "tWR violation during Precharge" + SEVERITY WARNING; + END IF; + -- Terminate a Write Immediately (if same bank or all banks) + IF (Data_in_enable = '1' AND (Bank = TO_BITVECTOR(Ba) OR Addr(10) = '1')) THEN + Data_in_enable := '0'; + END IF; + -- Precharge Command Pipeline for READ + IF CAS_latency_3 = '1' THEN + Command(2) := PRECH; + Bank_precharge(2) := TO_BITVECTOR (Ba); + A10_precharge(2) := TO_BIT(Addr(10)); + ELSIF CAS_latency_2 = '1' THEN + Command(1) := PRECH; + Bank_precharge(1) := TO_BITVECTOR (Ba); + A10_precharge(1) := TO_BIT(Addr(10)); + END IF; + END IF; + + -- Burst Terminate + IF Burst_term = '1' THEN + -- Terminate a Write immediately + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + -- Terminate a Read depend on CAS Latency + IF CAS_latency_3 = '1' THEN + Command(2) := BST; + ELSIF CAS_latency_2 = '1' THEN + Command(1) := BST; + END IF; + END IF; + + -- Read, Write, Column Latch + IF Read_enable = '1' OR Write_enable = '1' THEN + -- Check to see if bank is open (ACT) for Read or Write + IF ((Ba="00" AND Pc_b0='1') OR (Ba="01" AND Pc_b1='1') OR (Ba="10" AND Pc_b2='1') OR (Ba="11" AND Pc_b3='1')) THEN + ASSERT (FALSE) + REPORT "Cannot Read or Write - Bank is not Activated" + SEVERITY WARNING; + END IF; + -- Activate to Read or Write + IF Ba = "00" THEN + ASSERT (NOW - RCD_chk0 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + ASSERT (NOW - RCD_chk1 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + ASSERT (NOW - RCD_chk2 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + ASSERT (NOW - RCD_chk3 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 3" + SEVERITY WARNING; + END IF; + + -- Read Command + IF Read_enable = '1' THEN + -- CAS Latency Pipeline + IF Cas_latency_3 = '1' THEN + IF Addr(10) = '1' THEN + Command(2) := READ_A; + ELSE + Command(2) := READ; + END IF; + Col_addr (2) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0)); + Bank_addr (2) := TO_BITVECTOR (Ba); + ELSIF Cas_latency_2 = '1' THEN + IF Addr(10) = '1' THEN + Command(1) := READ_A; + ELSE + Command(1) := READ; + END IF; + Col_addr (1) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0)); + Bank_addr (1) := TO_BITVECTOR (Ba); + END IF; + + -- Read intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Write Command + ELSIF Write_enable = '1' THEN + IF Addr(10) = '1' THEN + Command(0) := WRITE_A; + ELSE + Command(0) := WRITE; + END IF; + Col_addr (0) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0)); + Bank_addr (0) := TO_BITVECTOR (Ba); + + -- Write intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Write interrupt a Read (terminate Read immediately) + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + + -- Interrupt a Write with Auto Precharge + IF Auto_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' AND Write_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' THEN + RW_interrupt_write(TO_INTEGER(RW_Interrupt_Bank)) := '1'; + END IF; + + -- Interrupt a Read with Auto Precharge + IF Auto_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' AND Read_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' THEN + RW_interrupt_read(TO_INTEGER(RW_Interrupt_Bank)) := '1'; + END IF; + + -- Read or Write with Auto Precharge + IF Addr(10) = '1' THEN + Auto_precharge (TO_INTEGER(Ba)) := '1'; + Count_precharge (TO_INTEGER(Ba)) := 0; + RW_Interrupt_Bank := TO_BitVector(Ba); + IF Read_enable = '1' THEN + Read_precharge (TO_INTEGER(Ba)) := '1'; + ELSIF Write_enable = '1' THEN + Write_precharge (TO_INTEGER(Ba)) := '1'; + END IF; + END IF; + END IF; + + -- Read with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. BL/2 cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Read_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(0) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8))) OR + (RW_interrupt_read(0) = '1')) THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + Auto_precharge(0) := '0'; + Read_precharge(0) := '0'; + RW_interrupt_read(0) := '0'; + END IF; + END IF; + IF ((Auto_precharge(1) = '1') AND (Read_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(1) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8))) OR + (RW_interrupt_read(1) = '1')) THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + Auto_precharge(1) := '0'; + Read_precharge(1) := '0'; + RW_interrupt_read(1) := '0'; + END IF; + END IF; + IF ((Auto_precharge(2) = '1') AND (Read_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(2) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8))) OR + (RW_interrupt_read(2) = '1')) THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + Auto_precharge(2) := '0'; + Read_precharge(2) := '0'; + RW_interrupt_read(2) := '0'; + END IF; + END IF; + IF ((Auto_precharge(3) = '1') AND (Read_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(3) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8))) OR + (RW_interrupt_read(3) = '1')) THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + Auto_precharge(3) := '0'; + Read_precharge(3) := '0'; + RW_interrupt_read(3) := '0'; + END IF; + END IF; + + -- Internal Precharge or Bst + IF Command(0) = PRECH THEN -- PRECH terminate a read if same bank or all banks + IF Bank_precharge(0) = Bank OR A10_precharge(0) = '1' THEN + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Command(0) = BST THEN -- BST terminate a read regardless of bank + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + + IF Data_out_enable = '0' THEN + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tOH; + END IF; + + -- Detect Read or Write Command + IF Command(0) = READ OR Command(0) = READ_A THEN + Bank := Bank_addr (0); + Col := Col_addr (0); + Col_brst := Col_addr (0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '0'; + Data_out_enable := '1'; + ELSIF Command(0) = WRITE OR Command(0) = WRITE_A THEN + Bank := Bank_addr(0); + Col := Col_addr(0); + Col_brst := Col_addr(0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '1'; + Data_out_enable := '0'; + END IF; + + -- DQ (Driver / Receiver) + Row_index := TO_INTEGER (Row); + Col_index := TO_INTEGER (Col); + IF Data_in_enable = '1' THEN + IF Dqm /= "11" THEN + Init_mem (Bank, Row_index); + IF Bank = "00" THEN + Dq_temp := Bank0 (Row_index) (Col_index); + IF Dqm = "01" THEN + Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8)); + ELSIF Dqm = "10" THEN + Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0)); + ELSE + Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0)); + END IF; + Bank0 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0)); + ELSIF Bank = "01" THEN + Dq_temp := Bank1 (Row_index) (Col_index); + IF Dqm = "01" THEN + Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8)); + ELSIF Dqm = "10" THEN + Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0)); + ELSE + Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0)); + END IF; + Bank1 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0)); + ELSIF Bank = "10" THEN + Dq_temp := Bank2 (Row_index) (Col_index); + IF Dqm = "01" THEN + Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8)); + ELSIF Dqm = "10" THEN + Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0)); + ELSE + Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0)); + END IF; + Bank2 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0)); + ELSIF Bank = "11" THEN + Dq_temp := Bank3 (Row_index) (Col_index); + IF Dqm = "01" THEN + Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8)); + ELSIF Dqm = "10" THEN + Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0)); + ELSE + Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0)); + END IF; + Bank3 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0)); + END IF; + WR_chkp(TO_INTEGER(Bank)) := NOW; + WR_counter(TO_INTEGER(Bank)) := 0; + END IF; + Burst_decode; + ELSIF Data_out_enable = '1' THEN + IF Dqm_reg0 /= "11" THEN + Init_mem (Bank, Row_index); + IF Bank = "00" THEN + Dq_temp := Bank0 (Row_index) (Col_index); + IF Dqm_reg0 = "00" THEN + Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC; + ELSIF Dqm_reg0 = "01" THEN + Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + ELSIF Dqm_reg0 = "10" THEN + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC; + END IF; + ELSIF Bank = "01" THEN + Dq_temp := Bank1 (Row_index) (Col_index); + IF Dqm_reg0 = "00" THEN + Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC; + ELSIF Dqm_reg0 = "01" THEN + Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + ELSIF Dqm_reg0 = "10" THEN + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC; + END IF; + ELSIF Bank = "10" THEN + Dq_temp := Bank2 (Row_index) (Col_index); + IF Dqm_reg0 = "00" THEN + Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC; + ELSIF Dqm_reg0 = "01" THEN + Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + ELSIF Dqm_reg0 = "10" THEN + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC; + END IF; + ELSIF Bank = "11" THEN + Dq_temp := Bank3 (Row_index) (Col_index); + IF Dqm_reg0 = "00" THEN + Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC; + ELSIF Dqm_reg0 = "01" THEN + Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + ELSIF Dqm_reg0 = "10" THEN + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC; + END IF; + END IF; + ELSE + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tHZ; + END IF; + Burst_decode; + END IF; + ELSIF Sys_clk'event AND Sys_clk = '1' AND Load = '1' AND Dump = '0' THEN + Operation <= LOAD_FILE; + ASSERT (FALSE) REPORT "Reading memory array from file. This operation may take several minutes. Please wait..." + SEVERITY NOTE; + WHILE NOT endfile(file_load) LOOP + readline(file_load, l); + -- skip the line if it doesn't start with a number + read(l, bank_load, good => good_load); + NEXT WHEN NOT good_load; + read(l, rows_load); + read(l, cols_load); + read(l, data_load); + Init_Mem (Bank_Load, To_Integer(Rows_Load)); + IF Bank_Load = "00" THEN + Bank0 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)) := ('1' & Data_Load); + ELSIF Bank_Load = "01" THEN + Bank1 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)) := ('1' & Data_Load); + ELSIF Bank_Load = "10" THEN + Bank2 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)) := ('1' & Data_Load); + ELSIF Bank_Load = "11" THEN + Bank3 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)) := ('1' & Data_Load); + END IF; + END LOOP; + ELSIF Sys_clk'event AND Sys_clk = '1' AND Load = '0' AND Dump = '1' THEN + Operation <= DUMP_FILE; + ASSERT (FALSE) REPORT "Writing memory array to file. This operation may take several minutes. Please wait..." + SEVERITY NOTE; + WRITE (l, string'("# Micron Technology, Inc. (FILE DUMP / MEMORY DUMP)")); + WRITELINE (file_dump, l); + WRITE (l, string'("# BA ROWS COLS DQ")); + WRITELINE (file_dump, l); + WRITE (l, string'("# -- ------------- --------- ----------------")); + WRITELINE (file_dump, l); + -- Dumping Bank 0 + FOR i IN 0 TO 2**addr_bits -1 LOOP + -- Check if ROW is NULL + IF Bank0 (i) /= NULL THEN + For j IN 0 TO 2**col_bits - 1 LOOP + -- Check if COL is NULL + NEXT WHEN Bank0 (i) (j) (data_bits) = '0'; + WRITE (l, string'("00"), right, 4); + WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1); + WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1); + WRITE (l, Bank0 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1); + WRITELINE (file_dump, l); + END LOOP; + END IF; + END LOOP; + -- Dumping Bank 1 + FOR i IN 0 TO 2**addr_bits -1 LOOP + -- Check if ROW is NULL + IF Bank1 (i) /= NULL THEN + For j IN 0 TO 2**col_bits - 1 LOOP + -- Check if COL is NULL + NEXT WHEN Bank1 (i) (j) (data_bits) = '0'; + WRITE (l, string'("01"), right, 4); + WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1); + WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1); + WRITE (l, Bank1 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1); + WRITELINE (file_dump, l); + END LOOP; + END IF; + END LOOP; + -- Dumping Bank 2 + FOR i IN 0 TO 2**addr_bits -1 LOOP + -- Check if ROW is NULL + IF Bank2 (i) /= NULL THEN + For j IN 0 TO 2**col_bits - 1 LOOP + -- Check if COL is NULL + NEXT WHEN Bank2 (i) (j) (data_bits) = '0'; + WRITE (l, string'("10"), right, 4); + WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1); + WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1); + WRITE (l, Bank2 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1); + WRITELINE (file_dump, l); + END LOOP; + END IF; + END LOOP; + -- Dumping Bank 3 + FOR i IN 0 TO 2**addr_bits -1 LOOP + -- Check if ROW is NULL + IF Bank3 (i) /= NULL THEN + For j IN 0 TO 2**col_bits - 1 LOOP + -- Check if COL is NULL + NEXT WHEN Bank3 (i) (j) (data_bits) = '0'; + WRITE (l, string'("11"), right, 4); + WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1); + WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1); + WRITE (l, Bank3 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1); + WRITELINE (file_dump, l); + END LOOP; + END IF; + END LOOP; + END IF; + + -- Write with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. tWR cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Write_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(0) >= 1 AND NOW - Count_time(0) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2 AND NOW - Count_time(0) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4 AND NOW - Count_time(0) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8 AND NOW - Count_time(0) >= tWRa))) OR + (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 1 AND NOW - WR_time(0) >= tWRa)) THEN + Auto_precharge(0) := '0'; + Write_precharge(0) := '0'; + RW_interrupt_write(0) := '0'; + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + ASSERT FALSE REPORT "Start Internal Precharge Bank 0" SEVERITY NOTE; + END IF; + END IF; + IF ((Auto_precharge(1) = '1') AND (Write_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(1) >= 1 AND NOW - Count_time(1) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2 AND NOW - Count_time(1) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4 AND NOW - Count_time(1) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8 AND NOW - Count_time(1) >= tWRa))) OR + (RW_interrupt_write(1) = '1' AND WR_counter(1) >= 1 AND NOW - WR_time(1) >= tWRa)) THEN + Auto_precharge(1) := '0'; + Write_precharge(1) := '0'; + RW_interrupt_write(1) := '0'; + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + END IF; + END IF; + IF ((Auto_precharge(2) = '1') AND (Write_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(2) >= 1 AND NOW - Count_time(2) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2 AND NOW - Count_time(2) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4 AND NOW - Count_time(2) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8 AND NOW - Count_time(2) >= tWRa))) OR + (RW_interrupt_write(2) = '1' AND WR_counter(2) >= 1 AND NOW - WR_time(2) >= tWRa)) THEN + Auto_precharge(2) := '0'; + Write_precharge(2) := '0'; + RW_interrupt_write(2) := '0'; + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + END IF; + END IF; + IF ((Auto_precharge(3) = '1') AND (Write_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(3) >= 1 AND NOW - Count_time(3) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2 AND NOW - Count_time(3) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4 AND NOW - Count_time(3) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8 AND NOW - Count_time(3) >= tWRa))) OR + (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 1 AND NOW - WR_time(3) >= tWRa)) THEN + Auto_precharge(3) := '0'; + Write_precharge(3) := '0'; + RW_interrupt_write(3) := '0'; + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + END IF; + END IF; + + -- Checking internal wires (Optional for debug purpose) + Pre_chk (0) <= Pc_b0; + Pre_chk (1) <= Pc_b1; + Pre_chk (2) <= Pc_b2; + Pre_chk (3) <= Pc_b3; + Act_chk (0) <= Act_b0; + Act_chk (1) <= Act_b1; + Act_chk (2) <= Act_b2; + Act_chk (3) <= Act_b3; + Dq_in_chk <= Data_in_enable; + Dq_out_chk <= Data_out_enable; + Bank_chk <= Bank; + Row_chk <= Row; + Col_chk <= Col; + END PROCESS; + + + -- Clock timing checks + Clock_check : PROCESS + VARIABLE Clk_low, Clk_high : TIME := 0 ns; + BEGIN + WAIT ON Clk; + IF (Clk = '1' AND NOW >= 10 ns) THEN + ASSERT (NOW - Clk_low >= tCL) + REPORT "tCL violation" + SEVERITY WARNING; + ASSERT (NOW - Clk_high >= tCK) + REPORT "tCK violation" + SEVERITY WARNING; + Clk_high := NOW; + ELSIF (Clk = '0' AND NOW /= 0 ns) THEN + ASSERT (NOW - Clk_high >= tCH) + REPORT "tCH violation" + SEVERITY WARNING; + Clk_low := NOW; + END IF; + END PROCESS; + + -- Setup timing checks + Setup_check : PROCESS + BEGIN + WAIT ON Clk; + IF Clk = '1' THEN + ASSERT(Cke'LAST_EVENT >= tCKS) + REPORT "CKE Setup time violation -- tCKS" + SEVERITY WARNING; + ASSERT(Cs_n'LAST_EVENT >= tCMS) + REPORT "CS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT >= tCMS) + REPORT "CAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT >= tCMS) + REPORT "RAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT >= tCMS) + REPORT "WE# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT >= tCMS) + REPORT "Dqm Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Addr'LAST_EVENT >= tAS) + REPORT "ADDR Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT >= tAS) + REPORT "BA Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Dq'LAST_EVENT >= tDS) + REPORT "Dq Setup time violation -- tDS" + SEVERITY WARNING; + END IF; + END PROCESS; + + -- Hold timing checks + Hold_check : PROCESS + BEGIN + WAIT ON Clk'DELAYED (tCKH), Clk'DELAYED (tCMH), Clk'DELAYED (tAH), Clk'DELAYED (tDH); + IF Clk'DELAYED (tCKH) = '1' THEN + ASSERT(Cke'LAST_EVENT > tCKH) + REPORT "CKE Hold time violation -- tCKH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tCMH) = '1' THEN + ASSERT(Cs_n'LAST_EVENT > tCMH) + REPORT "CS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT > tCMH) + REPORT "CAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT > tCMH) + REPORT "RAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT > tCMH) + REPORT "WE# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT > tCMH) + REPORT "Dqm Hold time violation -- tCMH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tAH) = '1' THEN + ASSERT(Addr'LAST_EVENT > tAH) + REPORT "ADDR Hold time violation -- tAH" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT > tAH) + REPORT "BA Hold time violation -- tAH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tDH) = '1' THEN + ASSERT(Dq'LAST_EVENT > tDH) + REPORT "Dq Hold time violation -- tDH" + SEVERITY WARNING; + END IF; + END PROCESS; + +END behave; diff --git a/lib/models/memory/sdram/mt48lc16m16a2/mti_pkg.vhd b/lib/models/memory/sdram/mt48lc16m16a2/mti_pkg.vhd new file mode 100644 index 0000000..80a9639 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc16m16a2/mti_pkg.vhd @@ -0,0 +1,139 @@ +--***************************************************************************** +-- +-- Micron Semiconductor Products, Inc. +-- +-- Copyright 1997, Micron Semiconductor Products, Inc. +-- All rights reserved. +-- +--***************************************************************************** + +LIBRARY ieee; + USE ieee.std_logic_1164.ALL; + +PACKAGE mti_pkg IS + + FUNCTION To_StdLogic (s : BIT) RETURN STD_LOGIC; + FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER; + FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER; + FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER; + PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR); + +END mti_pkg; + +PACKAGE BODY mti_pkg IS + + -- Convert BIT to STD_LOGIC + FUNCTION To_StdLogic (s : BIT) RETURN STD_LOGIC IS + BEGIN + CASE s IS + WHEN '0' => RETURN ('0'); + WHEN '1' => RETURN ('1'); + WHEN OTHERS => RETURN ('0'); + END CASE; + END; + + -- Convert STD_LOGIC to INTEGER + FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + IF input = '1' THEN + result := weight; + ELSE + result := 0; -- if unknowns, default to logic 0 + END IF; + RETURN result; + END TO_INTEGER; + + -- Convert BIT_VECTOR to INTEGER + FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + FOR i IN input'LOW TO input'HIGH LOOP + IF input(i) = '1' THEN + result := result + weight; + ELSE + result := result + 0; -- if unknowns, default to logic 0 + END IF; + weight := weight * 2; + END LOOP; + RETURN result; + END TO_INTEGER; + + -- Convert STD_LOGIC_VECTOR to INTEGER + FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + FOR i IN input'LOW TO input'HIGH LOOP + IF input(i) = '1' THEN + result := result + weight; + ELSE + result := result + 0; -- if unknowns, default to logic 0 + END IF; + weight := weight * 2; + END LOOP; + RETURN result; + END TO_INTEGER; + + -- Conver INTEGER to BIT_VECTOR + PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR) IS + VARIABLE work,offset,outputlen,j : INTEGER := 0; + BEGIN + --length of vector + IF output'LENGTH > 32 THEN + outputlen := 32; + offset := output'LENGTH - 32; + IF input >= 0 THEN + FOR i IN offset-1 DOWNTO 0 LOOP + output(output'HIGH - i) := '0'; + END LOOP; + ELSE + FOR i IN offset-1 DOWNTO 0 LOOP + output(output'HIGH - i) := '1'; + END LOOP; + END IF; + ELSE + outputlen := output'LENGTH; + END IF; + --positive value + IF (input >= 0) THEN + work := input; + j := outputlen - 1; + FOR i IN 1 to 32 LOOP + IF j >= 0 then + IF (work MOD 2) = 0 THEN + output(output'HIGH-j-offset) := '0'; + ELSE + output(output'HIGH-j-offset) := '1'; + END IF; + END IF; + work := work / 2; + j := j - 1; + END LOOP; + IF outputlen = 32 THEN + output(output'HIGH) := '0'; + END IF; + --negative value + ELSE + work := (-input) - 1; + j := outputlen - 1; + FOR i IN 1 TO 32 LOOP + IF j>= 0 THEN + IF (work MOD 2) = 0 THEN + output(output'HIGH-j-offset) := '1'; + ELSE + output(output'HIGH-j-offset) := '0'; + END IF; + END IF; + work := work / 2; + j := j - 1; + END LOOP; + IF outputlen = 32 THEN + output(output'HIGH) := '1'; + END IF; + END IF; + END TO_BITVECTOR; + +END mti_pkg; diff --git a/lib/models/memory/sdram/mt48lc16m16a2/test.do b/lib/models/memory/sdram/mt48lc16m16a2/test.do new file mode 100644 index 0000000..c7e958c --- /dev/null +++ b/lib/models/memory/sdram/mt48lc16m16a2/test.do @@ -0,0 +1,57 @@ +# Macro for running Micron SDRAM VHDL model +# +# Compile Package Library (Require) +vcom mti_pkg.vhd + +# Compile Micron Test Vector Generator (optional or use your own test) +vcom vec_gen.vhd +vcom ed_comnd.vhd +vsim vector_generate +run -all + +# Compile Micron SDRAM +vcom mt48lc16m16a2.vhd + +# Compile Micron Testbench (optional or use your own test bench) +vcom test.vhd + +# Simulate Test +vsim tb + +# Display waveform +onerror {resume} +add wave -logic /tb/u1/clk +add wave -logic /tb/u1/cke +add wave -logic /tb/u1/cs_n +add wave -logic /tb/u1/ras_n +add wave -logic /tb/u1/cas_n +add wave -logic /tb/u1/we_n +add wave -literal -decimal /tb/u1/addr +add wave -literal -unsigned /tb/u1/ba +add wave -literal -decimal /tb/u1/dq +add wave -literal /tb/u1/dqm +add wave -literal /tb/u1/operation +add wave -literal -decimal /tb/u1/mode_reg +add wave -logic /tb/u1/active_enable +add wave -logic /tb/u1/aref_enable +add wave -logic /tb/u1/burst_term +add wave -logic /tb/u1/mode_reg_enable +add wave -logic /tb/u1/prech_enable +add wave -logic /tb/u1/read_enable +add wave -logic /tb/u1/write_enable +add wave -logic /tb/u1/burst_length_1 +add wave -logic /tb/u1/burst_length_2 +add wave -logic /tb/u1/burst_length_4 +add wave -logic /tb/u1/burst_length_8 +add wave -logic /tb/u1/cas_latency_2 +add wave -logic /tb/u1/cas_latency_3 +add wave -literal /tb/u1/pre_chk +add wave -literal /tb/u1/act_chk +add wave -literal /tb/u1/bank_chk +add wave -literal -decimal /tb/u1/row_chk +add wave -literal -decimal /tb/u1/col_chk +add wave -logic /tb/u1/dq_in_chk +add wave -logic /tb/u1/dq_out_chk + +# Run all test +run -all diff --git a/lib/models/memory/sdram/mt48lc16m16a2/test.txt b/lib/models/memory/sdram/mt48lc16m16a2/test.txt new file mode 100644 index 0000000..37330c0 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc16m16a2/test.txt @@ -0,0 +1,101 @@ +0 ns 1 1 1 1 1 00 00 0 -100 0 0 +22 ns 1 1 1 1 1 00 00 0 -100 0 0 +32 ns 1 0 1 1 1 00 00 0 -100 1 0 +42 ns 1 1 1 1 1 00 00 0 -100 0 0 +52 ns 1 1 1 1 1 00 00 0 -100 0 0 +62 ns 1 1 1 1 1 00 00 0 -100 0 0 +72 ns 1 1 1 1 1 00 00 0 -100 0 0 +82 ns 1 0 0 1 0 00 00 1024 -100 0 0 +92 ns 1 1 1 1 1 00 00 0 -100 0 0 +102 ns 1 1 1 1 1 00 00 0 -100 0 0 +112 ns 1 0 0 0 1 00 00 0 -100 0 0 +122 ns 1 1 1 1 1 00 00 0 -100 0 0 +132 ns 1 1 1 1 1 00 00 0 -100 0 0 +142 ns 1 1 1 1 1 00 00 0 -100 0 0 +152 ns 1 1 1 1 1 00 00 0 -100 0 0 +162 ns 1 1 1 1 1 00 00 0 -100 0 0 +172 ns 1 1 1 1 1 00 00 0 -100 0 0 +182 ns 1 1 1 1 1 00 00 0 -100 0 0 +192 ns 1 1 1 1 1 00 00 0 -100 0 0 +202 ns 1 0 0 0 1 00 00 0 -100 0 0 +212 ns 1 1 1 1 1 00 00 0 -100 0 0 +222 ns 1 1 1 1 1 00 00 0 -100 0 0 +232 ns 1 1 1 1 1 00 00 0 -100 0 0 +242 ns 1 1 1 1 1 00 00 0 -100 0 0 +252 ns 1 1 1 1 1 00 00 0 -100 0 0 +262 ns 1 1 1 1 1 00 00 0 -100 0 0 +272 ns 1 1 1 1 1 00 00 0 -100 0 0 +282 ns 1 1 1 1 1 00 00 0 -100 0 0 +292 ns 1 0 0 0 0 00 00 51 -100 0 0 +302 ns 1 1 1 1 1 00 00 0 -100 0 0 +312 ns 1 0 0 1 1 00 00 0 -100 0 0 +322 ns 1 1 1 1 1 00 00 0 -100 0 0 +332 ns 1 0 1 0 0 00 00 0 100 0 0 +342 ns 1 1 1 1 1 00 00 0 101 0 0 +352 ns 1 0 0 1 1 00 01 0 102 0 0 +362 ns 1 1 1 1 1 00 00 0 103 0 0 +372 ns 1 1 1 1 1 00 00 0 104 0 0 +382 ns 1 1 1 1 1 00 00 0 105 0 0 +392 ns 1 1 1 1 1 00 00 0 106 0 0 +402 ns 1 1 1 1 1 00 00 0 107 0 0 +412 ns 1 0 1 0 0 00 01 0 200 0 0 +422 ns 1 0 0 1 0 00 00 0 201 0 0 +432 ns 1 0 0 1 1 00 10 0 202 0 0 +442 ns 1 1 1 1 1 00 00 0 203 0 0 +452 ns 1 1 1 1 1 00 00 0 204 0 0 +462 ns 1 1 1 1 1 00 00 0 205 0 0 +472 ns 1 1 1 1 1 00 00 0 206 0 0 +482 ns 1 1 1 1 1 00 00 0 207 0 0 +492 ns 1 0 1 0 0 00 10 0 300 0 0 +502 ns 1 0 0 1 0 00 01 0 301 0 0 +512 ns 1 0 0 1 1 00 11 0 302 0 0 +522 ns 1 1 1 1 1 00 00 0 303 0 0 +532 ns 1 1 1 1 1 00 00 0 304 0 0 +542 ns 1 1 1 1 1 00 00 0 305 0 0 +552 ns 1 1 1 1 1 00 00 0 306 0 0 +562 ns 1 1 1 1 1 00 00 0 307 0 0 +572 ns 1 0 1 0 0 00 11 0 400 0 0 +582 ns 1 0 0 1 0 00 10 0 401 0 0 +592 ns 1 0 0 1 1 00 00 0 402 0 0 +602 ns 1 1 1 1 1 00 00 0 403 0 0 +612 ns 1 1 1 1 1 00 00 0 404 0 0 +622 ns 1 1 1 1 1 00 00 0 405 0 0 +632 ns 1 1 1 1 1 00 00 0 406 0 0 +642 ns 1 1 1 1 1 00 00 0 407 0 0 +652 ns 1 0 1 0 1 00 00 0 -100 0 0 +662 ns 1 0 0 1 0 00 11 0 -100 0 0 +672 ns 1 0 0 1 1 00 01 0 -100 0 0 +682 ns 1 1 1 1 1 00 00 0 -100 0 0 +692 ns 1 1 1 1 1 00 00 0 -100 0 0 +702 ns 1 1 1 1 1 00 00 0 -100 0 0 +712 ns 1 1 1 1 1 00 00 0 -100 0 0 +722 ns 1 1 1 1 1 00 00 0 -100 0 0 +732 ns 1 0 1 0 1 00 01 0 -100 0 0 +742 ns 1 0 0 1 0 00 00 0 -100 0 0 +752 ns 1 0 0 1 1 00 10 0 -100 0 0 +762 ns 1 1 1 1 1 00 00 0 -100 0 0 +772 ns 1 1 1 1 1 00 00 0 -100 0 0 +782 ns 1 1 1 1 1 00 00 0 -100 0 0 +792 ns 1 1 1 1 1 00 00 0 -100 0 0 +802 ns 1 1 1 1 1 00 00 0 -100 0 0 +812 ns 1 0 1 0 1 00 10 0 -100 0 0 +822 ns 1 0 0 1 0 00 01 0 -100 0 0 +832 ns 1 0 0 1 1 00 11 0 -100 0 0 +842 ns 1 1 1 1 1 00 00 0 -100 0 0 +852 ns 1 1 1 1 1 00 00 0 -100 0 0 +862 ns 1 1 1 1 1 00 00 0 -100 0 0 +872 ns 1 1 1 1 1 00 00 0 -100 0 0 +882 ns 1 1 1 1 1 00 00 0 -100 0 0 +892 ns 1 0 1 0 1 00 11 0 -100 0 0 +902 ns 1 0 0 1 0 00 10 0 -100 0 0 +912 ns 1 1 1 1 1 00 00 0 -100 0 0 +922 ns 1 1 1 1 1 00 00 0 -100 0 0 +932 ns 1 1 1 1 1 00 00 0 -100 0 0 +942 ns 1 1 1 1 1 00 00 0 -100 0 0 +952 ns 1 1 1 1 1 00 00 0 -100 0 0 +962 ns 1 1 1 1 1 00 00 0 -100 0 0 +972 ns 1 0 0 1 0 00 11 0 -100 0 0 +982 ns 1 1 1 1 1 00 00 0 -100 0 0 +992 ns 1 1 1 1 1 00 00 0 -100 0 0 +1002 ns 1 0 1 1 1 00 00 0 -100 0 1 +1012 ns 1 1 1 1 1 00 00 0 -100 0 0 diff --git a/lib/models/memory/sdram/mt48lc16m16a2/test.vhd b/lib/models/memory/sdram/mt48lc16m16a2/test.vhd new file mode 100644 index 0000000..d5de6f8 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc16m16a2/test.vhd @@ -0,0 +1,164 @@ +LIBRARY ieee; + USE ieee.std_logic_1164.ALL; + USE ieee.std_logic_arith.ALL; +LIBRARY STD; + USE std.textio.ALL; +LIBRARY work; + USE work.mti_pkg.ALL; + +ENTITY tb IS +END tb; + + +ARCHITECTURE test OF tb IS + CONSTANT addr_bits : INTEGER := 13; + CONSTANT data_bits : INTEGER := 16; + CONSTANT clk_start : time := 5 ns; + CONSTANT clk_period : time := 10 ns; + CONSTANT continue_time : time := 10 ns; + + COMPONENT mt48lc16m16a2 + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '1'; + Cs_n : IN STD_LOGIC := '1'; + Cas_n : IN STD_LOGIC := '1'; + Ras_n : IN STD_LOGIC := '1'; + We_n : IN STD_LOGIC := '1'; + Dqm : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := (OTHERS => '0'); + Load : IN STD_LOGIC := '0'; -- FOR LOADING MEMORY ARRAY + Dump : IN STD_LOGIC := '0' -- FOR DUMPING MEMORY ARRAY + ); + END COMPONENT; + + FOR ALL : mt48lc16m16a2 USE ENTITY work.mt48lc16m16a2 (behave); + + SIGNAL pDq : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0); + SIGNAL pAddr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + SIGNAL pBa : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL pClk : STD_LOGIC; + SIGNAL pCke : STD_LOGIC; + SIGNAL pCs : STD_LOGIC; + SIGNAL pCas : STD_LOGIC; + SIGNAL pRas : STD_LOGIC; + SIGNAL pWe : STD_LOGIC; + SIGNAL pDqm : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL pLoad : STD_LOGIC; + SIGNAL pDump : STD_LOGIC; + SIGNAL stim_done : boolean := false; + SIGNAL clk_done : boolean := false; + + +BEGIN + u1: mt48lc16m16a2 + PORT MAP( + Dq => pDq, + Addr => pAddr, + Ba => pBa, + Clk => pClk, + Cke => pCke, + Cs_n => pCs, + Ras_n => pRas, + Cas_n => pCas, + We_n => pWe, + Dqm => pDqm, + Load => pLoad, + Dump => pDump + ); + + stimulator : PROCESS + FILE stim_file:text IS IN "test.txt"; + VARIABLE l : line; + VARIABLE time_var : TIME; + VARIABLE pCke_var : bit; + VARIABLE pCs_var : bit; + VARIABLE pRas_var : bit; + VARIABLE PCas_var : bit; + VARIABLE pWe_var : bit; + VARIABLE pDqm_var : bit_vector (1 DOWNTO 0); + VARIABLE pBa_var : bit_vector (1 DOWNTO 0); + VARIABLE pAddr_var : INTEGER; + VARIABLE pDq_var : INTEGER; -- -100 is converted to hi-Z state + VARIABLE PLoad_var : bit; + VARIABLE pDump_var : bit; + VARIABLE pMa_var_vect : STD_LOGIC_VECTOR(addr_bits - 1 DOWNTO 0); + CONSTANT HiZ : STD_LOGIC_VECTOR(data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + BEGIN + WHILE not ENDFILE(stim_file) LOOP + readline(stim_file,l); + IF l'length > 0 THEN + read(l, time_var); + read(l, pCke_var); + read(l, pCs_var); + read(l, pRas_var); + read(l, pCas_var); + read(l, pWe_var); + read(l, pDqm_var); + read(l, pBa_var); + read(l, pAddr_var); + read(l, pDq_var); + read(l, PLoad_var); + read(l, pDump_var); + IF now > time_var THEN + ASSERT false + REPORT "Detected a time in the stim file that is in the past" + SEVERITY error; + ELSE + WAIT FOR time_var-now; + pCke <= TO_StdLogic(pCke_var); + pCs <= TO_StdLogic(pCs_var); + pRas <= TO_StdLogic(pRas_var); + pCas <= TO_StdLogic(pCas_var); + pWe <= TO_StdLogic(pWe_var); + pDqm <= TO_StdLogicVector(pDqm_var); + pBa <= TO_StdLogicVector(pBa_var); + pMa_var_vect := CONV_STD_LOGIC_VECTOR(pAddr_var, addr_bits); + pAddr <= pMa_var_vect; + IF pDq_var = -100 THEN + pDq <= HiZ; + ELSE + pDq <= CONV_STD_LOGIC_VECTOR(pDq_var, data_bits); + END IF; + pLoad <= TO_StdLogic(PLoad_var); + pDump <= TO_StdLogic(pDump_var); + END IF; + END IF; + END LOOP; + ASSERT false + REPORT "End of Stimulation File Detected!" + SEVERITY note; + stim_done <= true; + WAIT; + END PROCESS; + + clock : PROCESS + VARIABLE done_time : time; + BEGIN + pclk <= '0'; + WAIT for clk_start; + WHILE not stim_done loop + pclk <= '1'; + WAIT for clk_period/2; + pclk <= '0'; + WAIT for clk_period/2; + END LOOP; + done_time := now+continue_time; + WHILE now < done_time LOOP --one last clock to finish last command + pclk <= '1'; + WAIT for clk_period/2; + pclk <= '0'; + WAIT for clk_period/2; + END LOOP; + ASSERT false + REPORT "Suspending clock activity" + SEVERITY note; + clk_done <= true; + WAIT; + END PROCESS; + +END test; + + diff --git a/lib/models/memory/sdram/mt48lc16m16a2/vec_gen.vhd b/lib/models/memory/sdram/mt48lc16m16a2/vec_gen.vhd new file mode 100644 index 0000000..633fb8d --- /dev/null +++ b/lib/models/memory/sdram/mt48lc16m16a2/vec_gen.vhd @@ -0,0 +1,353 @@ +------------------------------------------------------------------------------- +-- -- +-- This is a data generator for the testbench for Micron's Synchronous -- +-- DRAM. This generator reads a text file line-by-line and generates -- +-- a file of test vectors that is then read by the testbench and -- +-- applied to the part. -- +-- -- +-- This VHDL program creates a text file of test vectors that is used by the -- +-- test bench. Place your commands in a file (a copy of VEC_GEN.VHD) and run -- +-- VEC_GEN.VHD in your VHDL simulator (make sure you have compiled this -- +-- package prior to running the program VEC_GEN.VHD). This will produce the -- +-- vectors that are required to run the included testbench. Change the name -- +-- of the vector file to save your vectors in separate files. The default -- +-- file name for the output vectors generated from this pacakage is -- +-- "test.txt." -- +-- -- +-- Now compile and run the testbench program embedtb.vhd. The testbench uses -- +-- the default test.txt as input vectors. -- +-- -- +-- -- +-- Copyright 1997 Micron Technology, Inc. -- +-- -- +------------------------------------------------------------------------------- + +LIBRARY ieee; + USE ieee.std_logic_1164.all; +LIBRARY STD; + USE std.textio.all; + + +PACKAGE generate_vectors IS + + CONSTANT set_up : TIME; + CONSTANT hold : TIME; + CONSTANT cycle_start : TIME; + + SIGNAL cycle : INTEGER := 0; + SIGNAL sim_time : TIME := 0 ns; + FILE output_file:TEXT IS OUT "test.txt"; + PROCEDURE write(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); + first_data : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE read(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE active(row_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE precharge(bank : IN BIT_VECTOR(1 DOWNTO 0); address : IN INTEGER; data_bus: IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE nop(data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT; cs : IN BIT); + PROCEDURE burst_term(data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE auto_refresh; + PROCEDURE next_cycle(SIGNAL clk : IN BIT); + PROCEDURE load_array; + PROCEDURE load_mode_reg(op_code : IN INTEGER; cke : IN BIT); + PROCEDURE unload_array; + +END generate_vectors; + + +PACKAGE BODY generate_vectors IS + + CONSTANT set_up : TIME := 3 ns; + CONSTANT hold : TIME := 1 ns; + CONSTANT cycle_start : TIME := 0 ns; + + +PROCEDURE write(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); first_data : IN INTEGER; + dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 0, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, first_data, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE read(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 0, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, -100, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE active(row_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 0, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, row_address, right, 6); --address +write(l, data_bus, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE precharge(bank : IN BIT_VECTOR(1 DOWNTO 0); address : IN INTEGER; data_bus: IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 0, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, address, right, 6); --address +write(l, data_bus, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE nop(data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT; cs : IN BIT) IS + + +VARIABLE l : LINE; +VARIABLE col_address : INTEGER := 0; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, cke, right, 4); --Cke +write(l, cs, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, data_bus, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +writeline(output_file,l); --write vector to file + +END; + + +PROCEDURE burst_term(data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; +VARIABLE col_address : INTEGER := 0; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, data_bus, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE auto_refresh IS + VARIABLE l : LINE; + VARIABLE dqm : BIT_VECTOR(1 DOWNTO 0) := "00"; + VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; +BEGIN + IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); + ELSE + write(l, now-set_up, left, 4, ns); + END IF; + write(l, 1, right, 4); --Cke + write(l, 0, right, 4); --Cs + write(l, 0, right, 4); --Ras + write(l, 0, right, 4); --Cas + write(l, 1, right, 4); --We + write(l, dqm, right, 4); --Dqm + write(l, bank, right, 4); --Ba + write(l, 0, right, 6); --address + write(l, -100, right, 6); --first data location + write(l, 0, right, 4); --load + write(l, 0, right, 4); --unload + writeline(output_file,l); --write vector to file +END; + + +PROCEDURE next_cycle(SIGNAL clk : IN BIT) IS + +BEGIN + +WAIT UNTIL clk = '1'; + +END; + +PROCEDURE load_array IS + +VARIABLE l : LINE; +VARIABLE dqm : BIT_VECTOR(1 DOWNTO 0) := "00"; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, 1, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, 0, right, 6); --address +write(l, -100, right, 6); --first data location +write(l, 1, right, 4); --load +write(l, 0, right, 4); --unload +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE unload_array IS + +VARIABLE l : LINE; +VARIABLE dqm : BIT_VECTOR(1 DOWNTO 0) := "00"; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, 1, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, 0, right, 6); --address +write(l, -100, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 1, right, 4); --unload +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE load_mode_reg(op_code : IN INTEGER; cke : IN BIT) IS + +VARIABLE l : LINE; +VARIABLE dqm : BIT_VECTOR(1 DOWNTO 0) := "00"; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 0, right, 4); --Ras +write(l, 0, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, op_code, right, 6); --address +write(l, -100, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +writeline(output_file,l); --write vector to file + +END; + +END generate_vectors; + diff --git a/lib/models/memory/sdram/mt48lc16m16a2/wave.do b/lib/models/memory/sdram/mt48lc16m16a2/wave.do new file mode 100644 index 0000000..0e59196 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc16m16a2/wave.do @@ -0,0 +1,33 @@ +onerror {resume} +add wave -logic /tb/u1/clk +add wave -logic /tb/u1/cke +add wave -logic /tb/u1/cs_n +add wave -logic /tb/u1/ras_n +add wave -logic /tb/u1/cas_n +add wave -logic /tb/u1/we_n +add wave -literal -decimal /tb/u1/addr +add wave -literal -unsigned /tb/u1/ba +add wave -literal -decimal /tb/u1/dq +add wave -literal /tb/u1/dqm +add wave -literal /tb/u1/operation +add wave -literal -decimal /tb/u1/mode_reg +add wave -logic /tb/u1/active_enable +add wave -logic /tb/u1/aref_enable +add wave -logic /tb/u1/burst_term +add wave -logic /tb/u1/mode_reg_enable +add wave -logic /tb/u1/prech_enable +add wave -logic /tb/u1/read_enable +add wave -logic /tb/u1/write_enable +add wave -logic /tb/u1/burst_length_1 +add wave -logic /tb/u1/burst_length_2 +add wave -logic /tb/u1/burst_length_4 +add wave -logic /tb/u1/burst_length_8 +add wave -logic /tb/u1/cas_latency_2 +add wave -logic /tb/u1/cas_latency_3 +add wave -literal /tb/u1/pre_chk +add wave -literal /tb/u1/act_chk +add wave -literal /tb/u1/bank_chk +add wave -literal -decimal /tb/u1/row_chk +add wave -literal -decimal /tb/u1/col_chk +add wave -logic /tb/u1/dq_in_chk +add wave -logic /tb/u1/dq_out_chk diff --git a/lib/models/memory/sdram/mt48lc16m8a2/mt48lc16m8a2.vhd b/lib/models/memory/sdram/mt48lc16m8a2/mt48lc16m8a2.vhd new file mode 100644 index 0000000..562a4cc --- /dev/null +++ b/lib/models/memory/sdram/mt48lc16m8a2/mt48lc16m8a2.vhd @@ -0,0 +1,1069 @@ +----------------------------------------------------------------------------------------- +-- +-- File Name: MT48LC16M8A2.VHD +-- Version: 1.0a +-- Date: January 26th, 2000 +-- Model: Behavioral +-- Simulator: Model Technology +-- +-- Dependencies: None +-- +-- Author: Son P. Huynh +-- Email: sphuynh@micron.com +-- Phone: (208) 368-3825 +-- Company: Micron Technology, Inc. +-- Part Number: MT48LC16M8A2 (4Mb x 8 x 4 Banks) +-- +-- Description: Micron 128Mb SDRAM +-- +-- Limitation: - Doesn't check for 4096-cycle refresh +-- +-- Note: - Set simulator resolution to "ps" accuracy +-- +-- Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY +-- WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY +-- IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR +-- A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT. +-- +-- Copyright (c) 1998 Micron Semiconductor Products, Inc. +-- All rights researved +-- +-- Rev Author Phone Date Changes +-- ---- ---------------------------- ---------- ------------------------------------- +-- 1.0a Son P. Huynh 208-368-3825 12/02/1999 Second Release +-- Micron Technology Inc. - Simple testbench included +-- +----------------------------------------------------------------------------------------- + +LIBRARY ieee; + USE ieee.std_logic_1164.ALL; + USE ieee.std_logic_unsigned.conv_integer; + USE ieee.std_logic_arith.conv_std_logic_vector; + +ENTITY mt48lc16m8a2 IS + GENERIC ( + -- Timing Parameters for -75 (133 MHz @ CL2) + tAC : TIME := 6.0 ns; + tHZ : TIME := 6.0 ns; + tOH : TIME := 2.7 ns; + tMRD : TIME := 20.0 ns; -- 2 * tCK + tRAS : TIME := 44.0 ns; + tRC : TIME := 66.0 ns; + tRCD : TIME := 20.0 ns; + tRP : TIME := 20.0 ns; + tRRD : TIME := 15.0 ns; + tWRa : TIME := 17.5 ns; -- Auto precharge = tCK + 7.5 ns + tWRm : TIME := 15.0 ns; -- Manual Precharge = 15 ns + + tAH : TIME := 0.8 ns; + tAS : TIME := 1.5 ns; + tCH : TIME := 2.5 ns; + tCL : TIME := 2.5 ns; + tCK : TIME := 10.0 ns; + tDH : TIME := 0.8 ns; + tDS : TIME := 1.5 ns; + tCKH : TIME := 0.8 ns; + tCKS : TIME := 1.5 ns; + tCMH : TIME := 0.8 ns; + tCMS : TIME := 1.5 ns; + + addr_bits : INTEGER := 12; + data_bits : INTEGER := 8; + col_bits : INTEGER := 10 + ); + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC_VECTOR := "00"; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '0'; + Cs_n : IN STD_LOGIC := '1'; + Ras_n : IN STD_LOGIC := '0'; + Cas_n : IN STD_LOGIC := '0'; + We_n : IN STD_LOGIC := '0'; + Dqm : IN STD_LOGIC := '0' + ); +END mt48lc16m8a2; + +ARCHITECTURE behave OF mt48lc16m8a2 IS + TYPE State IS (ACT, A_REF, BST, LMR, NOP, PRECH, READ, READ_A, WRITE, WRITE_A, FILE_LOAD, FILE_UNLOAD); + TYPE Array4xI IS ARRAY (3 DOWNTO 0) OF INTEGER; + TYPE Array4xT IS ARRAY (3 DOWNTO 0) OF TIME; + TYPE Array4xSL IS ARRAY (3 DOWNTO 0) OF STD_LOGIC; + TYPE Array4x2SLV IS ARRAY (3 DOWNTO 0) OF STD_LOGIC_VECTOR (1 DOWNTO 0); -- For Bank Pipeline + TYPE Array2x4SLV IS ARRAY (1 DOWNTO 0) OF STD_LOGIC_VECTOR (3 DOWNTO 0); -- For Dqm Pipeline + TYPE Array4xCSLV IS ARRAY (4 DOWNTO 0) OF STD_LOGIC_VECTOR (Col_bits - 1 DOWNTO 0); -- For Column Pipeline + TYPE Array_state IS ARRAY (4 DOWNTO 0) OF State; + SIGNAL Operation : State := NOP; + SIGNAL Mode_reg : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL Active_enable, Aref_enable, Burst_term : STD_LOGIC := '0'; + SIGNAL Mode_reg_enable, Prech_enable, Read_enable, Write_enable : STD_LOGIC := '0'; + SIGNAL Burst_length_1, Burst_length_2, Burst_length_4, Burst_length_8 : STD_LOGIC := '0'; + SIGNAL Cas_latency_1, Cas_latency_2, Cas_latency_3 : STD_LOGIC := '0'; + SIGNAL Cs_in, Ras_in, Cas_in, We_in : STD_LOGIC := '0'; + SIGNAL Write_burst_mode : STD_LOGIC := '0'; + SIGNAL RAS_clk, Sys_clk, CkeZ : STD_LOGIC := '0'; + + -- The following signals are for debug purpose only + SIGNAL Act_chk : STD_LOGIC_VECTOR (3 DOWNTO 0) := "0000"; + SIGNAL Din_chk : STD_LOGIC := '0'; + SIGNAL Dout_chk : STD_LOGIC := '0'; + +BEGIN + -- Strip the strength + Cs_in <= To_X01 (Cs_n); + Ras_in <= To_X01 (Ras_n); + Cas_in <= To_X01 (Cas_n); + We_in <= To_X01 (We_n); + + -- Commands Decode + Active_enable <= NOT(Cs_in) AND NOT(Ras_in) AND Cas_in AND We_in; + Aref_enable <= NOT(Cs_in) AND NOT(Ras_in) AND NOT(Cas_in) AND We_in; + Burst_term <= NOT(Cs_in) AND Ras_in AND Cas_in AND NOT(We_in); + Mode_reg_enable <= NOT(Cs_in) AND NOT(Ras_in) AND NOT(Cas_in) AND NOT(We_in); + Prech_enable <= NOT(Cs_in) AND NOT(Ras_in) AND Cas_in AND NOT(We_in); + Read_enable <= NOT(Cs_in) AND Ras_in AND NOT(Cas_in) AND We_in; + Write_enable <= NOT(Cs_in) AND Ras_in AND NOT(Cas_in) AND NOT(We_in); + + -- Burst Length Decode + Burst_length_1 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND NOT(Mode_reg(0)); + Burst_length_2 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND Mode_reg(0); + Burst_length_4 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND NOT(Mode_reg(0)); + Burst_length_8 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND Mode_reg(0); + + -- CAS Latency Decode + Cas_latency_1 <= NOT(Mode_reg(6)) AND NOT(Mode_reg(5)) AND Mode_reg(4); + Cas_latency_2 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND NOT(Mode_reg(4)); + Cas_latency_3 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND Mode_reg(4); + + -- Write Burst Mode + Write_burst_mode <= Mode_reg(9); + + -- RAS Clock for checking tWR and tRP + PROCESS + variable Clk0, Clk1 : integer := 0; + begin + RAS_clk <= '1'; + wait for 0.5 ns; + RAS_clk <= '0'; + wait for 0.5 ns; + END PROCESS; + + -- System Clock + int_clk : PROCESS (Clk) + begin + IF Clk'LAST_VALUE = '0' AND Clk = '1' THEN + CkeZ <= Cke; + END IF; + Sys_clk <= CkeZ AND Clk; + END PROCESS; + + state_register : PROCESS + TYPE ram_type IS ARRAY (2**col_bits - 1 DOWNTO 0) OF STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0); + TYPE ram_pntr IS ACCESS ram_type; + TYPE ram_stor IS ARRAY (2**addr_bits - 1 DOWNTO 0) OF ram_pntr; + VARIABLE Bank0 : ram_stor; + VARIABLE Bank1 : ram_stor; + VARIABLE Bank2 : ram_stor; + VARIABLE Bank3 : ram_stor; + VARIABLE Row_index, Col_index : INTEGER := 0; + VARIABLE Dq_temp : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => '0'); + + VARIABLE Col_addr : Array4xCSLV; + VARIABLE Bank_addr : Array4x2SLV; + VARIABLE Dqm_reg0, Dqm_reg1 : STD_LOGIC := '0'; + + VARIABLE Bank, Previous_bank : STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"; + VARIABLE B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col_brst : STD_LOGIC_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Row : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col : STD_LOGIC_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Burst_counter : INTEGER := 0; + + VARIABLE Command : Array_state; + VARIABLE Bank_pipe_precharge : Array4x2SLV; + VARIABLE A10_pipe_precharge : Array4xSL := ('0' & '0' & '0' & '0'); + VARIABLE Auto_precharge : Array4xSL := ('0' & '0' & '0' & '0'); + VARIABLE Read_precharge : Array4xSL := ('0' & '0' & '0' & '0'); + VARIABLE Write_precharge : Array4xSL := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_write : Array4xSL := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_read : Array4xSL := ('0' & '0' & '0' & '0'); + VARIABLE Bank_precharge : INTEGER := 0; + VARIABLE Count_precharge : Array4xI := (0 & 0 & 0 & 0); + + VARIABLE Data_in_enable, Data_out_enable : STD_LOGIC := '0'; + VARIABLE Pc_b0, Pc_b1, Pc_b2, Pc_b3 : STD_LOGIC := '0'; + VARIABLE Act_b0, Act_b1, Act_b2, Act_b3 : STD_LOGIC := '0'; + + -- Timing Check + VARIABLE MRD_chk : TIME := 0 ns; + VARIABLE WR_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE WR_chka : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE WR_chkm : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE RC_chk, RRD_chk : TIME := 0 ns; + VARIABLE RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3 : TIME := 0 ns; + VARIABLE RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3 : TIME := 0 ns; + VARIABLE RP_chk0, RP_chk1, RP_chk2, RP_chk3 : TIME := 0 ns; + + -- Initialize empty rows + PROCEDURE Init_mem (Bank : STD_LOGIC_VECTOR (1 DOWNTO 0); Row_index : INTEGER) IS + VARIABLE i, j : INTEGER := 0; + BEGIN + IF Bank = "00" THEN + IF Bank0 (Row_index) = NULL THEN -- Check to see if row empty + Bank0 (Row_index) := NEW ram_type; -- Open new row for access + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP -- Filled row with zeros + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank0 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "01" THEN + IF Bank1 (Row_index) = NULL THEN + Bank1 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank1 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "10" THEN + IF Bank2 (Row_index) = NULL THEN + Bank2 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank2 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "11" THEN + IF Bank3 (Row_index) = NULL THEN + Bank3 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank3 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + END IF; + END; + + -- Burst Counter + PROCEDURE Burst_decode IS + VARIABLE Col_int : INTEGER := 0; + VARIABLE Col_vec, Col_temp : STD_LOGIC_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + BEGIN + -- Advance Burst Counter + Burst_counter := Burst_counter + 1; + + -- Burst Type + IF Mode_reg (3) = '0' THEN + Col_int := conv_integer(Col) + 1; + Col_temp := CONV_STD_LOGIC_VECTOR(Col_int, col_bits); + ELSIF Mode_reg (3) = '1' THEN + Col_vec := CONV_STD_LOGIC_VECTOR(Burst_counter, col_bits); + Col_temp (2) := Col_vec (2) XOR Col_brst (2); + Col_temp (1) := Col_vec (1) XOR Col_brst (1); + Col_temp (0) := Col_vec (0) XOR Col_brst (0); + END IF; + + -- Burst Length + IF Burst_length_2 = '1' THEN + Col (0) := Col_temp (0); + ELSIF Burst_length_4 = '1' THEN + Col (1 DOWNTO 0) := Col_temp (1 DOWNTO 0); + ELSIF Burst_length_8 = '1' THEN + Col (2 DOWNTO 0) := Col_temp (2 DOWNTO 0); + ELSE + Col := Col_temp; + END IF; + + -- Burst Read Single Write + IF Write_burst_mode = '1' AND Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Data counter + IF Burst_length_1 = '1' THEN + IF Burst_counter >= 1 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + IF Write_precharge (CONV_INTEGER(Bank)) = '1' THEN + WR_chka (CONV_INTEGER(Bank)) := NOW; + END IF; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_2 = '1' THEN + IF Burst_counter >= 2 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + IF Write_precharge (CONV_INTEGER(Bank)) = '1' THEN + WR_chka (CONV_INTEGER(Bank)) := NOW; + END IF; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_4 = '1' THEN + IF Burst_counter >= 4 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + IF Write_precharge (CONV_INTEGER(Bank)) = '1' THEN + WR_chka (CONV_INTEGER(Bank)) := NOW; + END IF; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_8 = '1' THEN + IF Burst_counter >= 8 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + IF Write_precharge (CONV_INTEGER(Bank)) = '1' THEN + WR_chka (CONV_INTEGER(Bank)) := NOW; + END IF; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + END IF; + END; + + BEGIN + WAIT ON Sys_clk, RAS_clk; + IF Sys_clk'event AND Sys_clk = '1' THEN + -- Internal Command Pipeline + Command(0) := Command(1); + Command(1) := Command(2); + Command(2) := Command(3); + Command(3) := NOP; + + Col_addr(0) := Col_addr(1); + Col_addr(1) := Col_addr(2); + Col_addr(2) := Col_addr(3); + Col_addr(3) := (OTHERS => '0'); + + Bank_addr(0) := Bank_addr(1); + Bank_addr(1) := Bank_addr(2); + Bank_addr(2) := Bank_addr(3); + Bank_addr(3) := "00"; + + -- Internal Precharge Pipeline + Bank_pipe_precharge(0) := Bank_pipe_precharge(1); + Bank_pipe_precharge(1) := Bank_pipe_precharge(2); + Bank_pipe_precharge(2) := Bank_pipe_precharge(3); + Bank_pipe_precharge(3) := "00"; + + A10_pipe_precharge(0) := A10_pipe_precharge(1); + A10_pipe_precharge(1) := A10_pipe_precharge(2); + A10_pipe_precharge(2) := A10_pipe_precharge(3); + A10_pipe_precharge(3) := '0'; + + -- Operation Decode (Optional for showing current command on posedge clock / debug feature) + IF Active_enable = '1' THEN + Operation <= ACT; + ELSIF Aref_enable = '1' THEN + Operation <= A_REF; + ELSIF Burst_term = '1' THEN + Operation <= BST; + ELSIF Mode_reg_enable = '1' THEN + Operation <= LMR; + ELSIF Prech_enable = '1' THEN + Operation <= PRECH; + ELSIF Read_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= READ; + ELSE + Operation <= READ_A; + END IF; + ELSIF Write_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= WRITE; + ELSE + Operation <= WRITE_A; + END IF; + ELSE + Operation <= NOP; + END IF; + + -- Dqm pipeline for Read + Dqm_reg0 := Dqm_reg1; + Dqm_reg1 := Dqm; + + -- Read or Write with Auto Precharge Counter + IF Auto_precharge (0) = '1' THEN + Count_precharge (0) := Count_precharge (0) + 1; + END IF; + IF Auto_precharge (1) = '1' THEN + Count_precharge (1) := Count_precharge (1) + 1; + END IF; + IF Auto_precharge (2) = '1' THEN + Count_precharge (2) := Count_precharge (2) + 1; + END IF; + IF Auto_precharge (3) = '1' THEN + Count_precharge (3) := Count_precharge (3) + 1; + END IF; + + -- Auto Refresh + IF Aref_enable = '1' THEN + -- Auto Refresh to Auto Refresh + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Auto Refresh" + SEVERITY WARNING; + -- Precharge to Auto Refresh + ASSERT (NOW - RP_chk0 >= tRP OR NOW - RP_chk1 >= tRP OR NOW - RP_chk2 >= tRP OR NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Auto Refresh" + SEVERITY WARNING; + -- All banks must be idle before refresh + IF (Pc_b3 = '0' OR Pc_b2 = '0' OR Pc_b1 = '0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All banks must be Precharge before Auto Refresh" + SEVERITY WARNING; + END IF; + -- Record current tRC time + RC_chk := NOW; + END IF; + + -- Load Mode Register + IF Mode_reg_enable = '1' THEN + Mode_reg <= Addr; + IF (Pc_b3 = '0' OR Pc_b2 = '0' OR Pc_b1 = '0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All bank must be Precharge before Load Mode Register" + SEVERITY WARNING; + END IF; + -- REF to LMR + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Load Mode Register" + SEVERITY WARNING; + -- LMR to LMR + ASSERT (NOW - MRD_chk >= tMRD) + REPORT "tMRD violation during Load Mode Register" + SEVERITY WARNING; + -- Record current tMRD time + MRD_chk := NOW; + END IF; + + -- Active Block (latch Bank and Row Address) + IF Active_enable = '1' THEN + IF Ba = "00" AND Pc_b0 = '1' THEN + Act_b0 := '1'; + Pc_b0 := '0'; + B0_row_addr := Addr; + RCD_chk0 := NOW; + RAS_chk0 := NOW; + -- Precharge to Active Bank 0 + ASSERT (NOW - RP_chk0 >= tRP) + REPORT "tRP violation during Activate Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '1' THEN + Act_b1 := '1'; + Pc_b1 := '0'; + B1_row_addr := Addr; + RCD_chk1 := NOW; + RAS_chk1 := NOW; + -- Precharge to Active Bank 1 + ASSERT (NOW - RP_chk1 >= tRP) + REPORT "tRP violation during Activate Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '1' THEN + Act_b2 := '1'; + Pc_b2 := '0'; + B2_row_addr := Addr; + RCD_chk2 := NOW; + RAS_chk2 := NOW; + -- Precharge to Active Bank 2 + ASSERT (NOW - RP_chk2 >= tRP) + REPORT "tRP violation during Activate Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '1' THEN + Act_b3 := '1'; + Pc_b3 := '0'; + B3_row_addr := Addr; + RCD_chk3 := NOW; + RAS_chk3 := NOW; + -- Precharge to Active Bank 3 + ASSERT (NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Activate Bank 3" + SEVERITY WARNING; + ELSIF Ba = "00" AND Pc_b0 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 0 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 1 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 2 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 3 is not Precharged" + SEVERITY WARNING; + END IF; + -- Active Bank A to Active Bank B + IF ((Previous_bank /= Ba) AND (NOW - RRD_chk < tRRD)) THEN + ASSERT (FALSE) + REPORT "tRRD violation during Activate" + SEVERITY WARNING; + END IF; + -- LMR to ACT + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Activate" + SEVERITY WARNING; + -- AutoRefresh to Activate + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Activate" + SEVERITY WARNING; + -- Record variable for checking violation + RRD_chk := NOW; + Previous_bank := Ba; + END IF; + + -- Precharge Block + IF Prech_enable = '1' THEN + IF Addr(10) = '1' THEN + Pc_b0 := '1'; + Pc_b1 := '1'; + Pc_b2 := '1'; + Pc_b3 := '1'; + Act_b0 := '0'; + Act_b1 := '0'; + Act_b2 := '0'; + Act_b3 := '0'; + RP_chk0 := NOW; + RP_chk1 := NOW; + RP_chk2 := NOW; + RP_chk3 := NOW; + -- Activate to Precharge all banks + ASSERT ((NOW - RAS_chk0 >= tRAS) OR (NOW - RAS_chk1 >= tRAS)) + REPORT "tRAS violation during Precharge all banks" + SEVERITY WARNING; + -- tWR violation check for Write + IF ((NOW - WR_chkm(0) < tWRm) OR (NOW - WR_chkm(1) < tWRm) OR + (NOW - WR_chkm(2) < tWRm) OR (NOW - WR_chkm(3) < tWRm)) THEN + ASSERT (FALSE) + REPORT "tWR violation during Precharge ALL banks" + SEVERITY WARNING; + END IF; + ELSIF Addr(10) = '0' THEN + IF Ba = "00" THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + -- Activate to Precharge bank 0 + ASSERT (NOW - RAS_chk0 >= tRAS) + REPORT "tRAS violation during Precharge bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + -- Activate to Precharge bank 1 + ASSERT (NOW - RAS_chk1 >= tRAS) + REPORT "tRAS violation during Precharge bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + -- Activate to Precharge bank 2 + ASSERT (NOW - RAS_chk2 >= tRAS) + REPORT "tRAS violation during Precharge bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + -- Activate to Precharge bank 3 + ASSERT (NOW - RAS_chk3 >= tRAS) + REPORT "tRAS violation during Precharge bank 3" + SEVERITY WARNING; + END IF; + -- tWR violation check for Write + ASSERT (NOW - WR_chkm(CONV_INTEGER(Ba)) >= tWRm) + REPORT "tWR violation during Precharge" + SEVERITY WARNING; + END IF; + -- Terminate a Write Immediately (if same bank or all banks) + IF (Data_in_enable = '1' AND (Bank = Ba OR Addr(10) = '1')) THEN + Data_in_enable := '0'; + END IF; + -- Precharge Command Pipeline for READ + IF CAS_latency_3 = '1' THEN + Command(2) := PRECH; + Bank_pipe_precharge(2) := Ba; + A10_pipe_precharge(2) := Addr(10); + ELSIF CAS_latency_2 = '1' THEN + Command(1) := PRECH; + Bank_pipe_precharge(1) := Ba; + A10_pipe_precharge(1) := Addr(10); + END IF; + END IF; + + -- Burst Terminate + IF Burst_term = '1' THEN + -- Terminate a Write immediately + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + -- Terminate a Read depend on CAS Latency + IF CAS_latency_3 = '1' THEN + Command(2) := BST; + ELSIF CAS_latency_2 = '1' THEN + Command(1) := BST; + END IF; + END IF; + + -- Read, Write, Column Latch + IF Read_enable = '1' OR Write_enable = '1' THEN + -- Check to see if bank is open (ACT) for Read or Write + IF ((Ba = "00" AND Pc_b0 = '1') OR (Ba = "01" AND Pc_b1 = '1') OR + (Ba = "10" AND Pc_b2 = '1') OR (Ba = "11" AND Pc_b3 = '1')) THEN + ASSERT (FALSE) + REPORT "Cannot Read or Write - Bank is not Activated" + SEVERITY WARNING; + END IF; + -- Activate to Read or Write + IF Ba = "00" THEN + ASSERT (NOW - RCD_chk0 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + ASSERT (NOW - RCD_chk1 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + ASSERT (NOW - RCD_chk2 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + ASSERT (NOW - RCD_chk3 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 3" + SEVERITY WARNING; + END IF; + -- Read Command + IF Read_enable = '1' THEN + -- CAS Latency Pipeline + IF Cas_latency_1 = '1' THEN + IF Addr(10) = '1' THEN + Command(0) := READ_A; + ELSE + Command(0) := READ; + END IF; + Col_addr (0) := Addr(col_bits - 1 DOWNTO 0); + Bank_addr (0) := Ba; + ELSIF Cas_latency_2 = '1' THEN + IF Addr(10) = '1' THEN + Command(1) := READ_A; + ELSE + Command(1) := READ; + END IF; + Col_addr (1) := Addr(col_bits - 1 DOWNTO 0); + Bank_addr (1) := Ba; + ELSIF Cas_latency_3 = '1' THEN + IF Addr(10) = '1' THEN + Command(2) := READ_A; + ELSE + Command(2) := READ; + END IF; + Col_addr (2) := Addr(col_bits - 1 DOWNTO 0); + Bank_addr (2) := Ba; + END IF; + + -- Read intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + -- Interrupt a write with autoprecharge + IF (Auto_precharge (Bank_precharge) = '1' AND + Write_precharge (Bank_precharge) = '1') THEN + RW_interrupt_write (Bank_precharge) := '1'; + WR_time (Bank_precharge) := NOW; + END IF; + END IF; + + -- Write Command + ELSIF Write_enable = '1' THEN + IF Addr(10) = '1' THEN + Command(0) := WRITE_A; + ELSE + Command(0) := WRITE; + END IF; + Col_addr (0) := Addr(col_bits - 1 DOWNTO 0); + Bank_addr (0) := Ba; + + -- Write intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + -- Interrupt a Write with Auto Precharge + IF (Auto_precharge(Bank_precharge) = '1' AND + Write_precharge(Bank_precharge) = '1') THEN + RW_interrupt_write(Bank_precharge) := '1'; + WR_time (Bank_precharge) := NOW; + END IF; + END IF; + + -- Write interrupt a Read (terminate Read immediately) + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + -- Interrupt a Read with Auto Precharge + IF Auto_precharge(Bank_precharge) = '1' AND + Read_precharge(Bank_precharge) = '1' THEN + RW_interrupt_read(Bank_precharge) := '1'; + END IF; + END IF; + END IF; + + -- Read or Write with Auto Precharge + IF Addr(10) = '1' THEN + Auto_precharge (CONV_INTEGER(Ba)) := '1'; + Count_precharge (CONV_INTEGER(Ba)) := 0; + Bank_precharge := (CONV_INTEGER(Ba)); + IF Read_enable = '1' THEN + Read_precharge (CONV_INTEGER(Ba)) := '1'; + ELSIF Write_enable = '1' THEN + Write_precharge (CONV_INTEGER(Ba)) := '1'; + END IF; + END IF; + END IF; + + -- Read with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. BL/2 cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Read_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(0) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8))) OR + (RW_interrupt_read(0) = '1')) THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + Auto_precharge(0) := '0'; + Read_precharge(0) := '0'; + RW_interrupt_read(0) := '0'; + END IF; + END IF; + IF ((Auto_precharge(1) = '1') AND (Read_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(1) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8))) OR + (RW_interrupt_read(1) = '1')) THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + Auto_precharge(1) := '0'; + Read_precharge(1) := '0'; + RW_interrupt_read(1) := '0'; + END IF; + END IF; + IF ((Auto_precharge(2) = '1') AND (Read_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(2) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8))) OR + (RW_interrupt_read(2) = '1')) THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + Auto_precharge(2) := '0'; + Read_precharge(2) := '0'; + RW_interrupt_read(2) := '0'; + END IF; + END IF; + IF ((Auto_precharge(3) = '1') AND (Read_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(3) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8))) OR + (RW_interrupt_read(3) = '1')) THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + Auto_precharge(3) := '0'; + Read_precharge(3) := '0'; + RW_interrupt_read(3) := '0'; + END IF; + END IF; + + -- Internal Precharge or Bst + IF Command(0) = PRECH THEN -- PRECH terminate a read if same bank or all banks + IF Bank_pipe_precharge(0) = Bank OR A10_pipe_precharge(0) = '1' THEN + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Command(0) = BST THEN -- BST terminate a read regardless of bank + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + + -- Turn off databus + IF (Data_out_enable = '0') THEN + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tHZ; + END IF; + + -- Detect Read or Write Command + IF Command(0) = READ OR Command(0) = READ_A THEN + Bank := Bank_addr (0); + Col := Col_addr (0); + Col_brst := Col_addr (0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '0'; + Data_out_enable := '1'; + ELSIF Command(0) = WRITE OR Command(0) = WRITE_A THEN + Bank := Bank_addr(0); + Col := Col_addr(0); + Col_brst := Col_addr(0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '1'; + Data_out_enable := '0'; + END IF; + + -- DQ (Driver / Receiver) + Row_index := CONV_INTEGER (Row); + Col_index := CONV_INTEGER (Col); + IF Data_in_enable = '1' THEN + IF Dqm = '0' THEN + -- Initialize memory + Init_mem (Bank, Row_index); + -- Write to memory + IF Bank = "00" THEN + Bank0 (Row_index) (Col_index) := Dq; + ELSIF Bank = "01" THEN + Bank1 (Row_index) (Col_index) := Dq; + ELSIF Bank = "10" THEN + Bank2 (Row_index) (Col_index) := Dq; + ELSIF Bank = "11" THEN + Bank3 (Row_index) (Col_index) := Dq; + END IF; + -- Reset tWR counter + WR_chkm(CONV_INTEGER(Bank)) := NOW; + END IF; + -- Decode next burst address + Burst_decode; + ELSIF Data_out_enable = '1' THEN + IF Dqm_reg0 = '0' THEN + -- Initialize memory + Init_mem (Bank, Row_index); + -- Load memory into buffer + IF Bank = "00" THEN + Dq <= TRANSPORT Bank0 (Row_index) (Col_index) AFTER tAC; + ELSIF Bank = "01" THEN + Dq <= TRANSPORT Bank1 (Row_index) (Col_index) AFTER tAC; + ELSIF Bank = "10" THEN + Dq <= TRANSPORT Bank2 (Row_index) (Col_index) AFTER tAC; + ELSIF Bank = "11" THEN + Dq <= TRANSPORT Bank3 (Row_index) (Col_index) AFTER tAC; + END IF; + ELSE + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tHZ; + END IF; + Burst_decode; + END IF; + END IF; + + -- Write with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. tWR cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Write_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(0) >= 1 AND NOW - WR_chka(0) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2 AND NOW - WR_chka(0) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4 AND NOW - WR_chka(0) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8 AND NOW - WR_chka(0) >= tWRa))) OR + (RW_interrupt_write(0) = '1' AND NOW - WR_time(0) >= tWRa)) THEN + Auto_precharge(0) := '0'; + Write_precharge(0) := '0'; + RW_interrupt_write(0) := '0'; + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + ASSERT FALSE REPORT "WRITE: Start Internal Precharge Bank 0" SEVERITY NOTE; + END IF; + END IF; + IF ((Auto_precharge(1) = '1') AND (Write_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(1) >= 1 AND NOW - WR_chka(1) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2 AND NOW - WR_chka(1) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4 AND NOW - WR_chka(1) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8 AND NOW - WR_chka(1) >= tWRa))) OR + (RW_interrupt_write(1) = '1' AND NOW - WR_time(1) >= tWRa)) THEN + Auto_precharge(1) := '0'; + Write_precharge(1) := '0'; + RW_interrupt_write(1) := '0'; + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + ASSERT FALSE REPORT "WRITE: Start Internal Precharge Bank 1" SEVERITY NOTE; + END IF; + END IF; + IF ((Auto_precharge(2) = '1') AND (Write_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(2) >= 1 AND NOW - WR_chka(2) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2 AND NOW - WR_chka(2) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4 AND NOW - WR_chka(2) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8 AND NOW - WR_chka(2) >= tWRa))) OR + (RW_interrupt_write(2) = '1' AND NOW - WR_time(2) >= tWRa)) THEN + Auto_precharge(2) := '0'; + Write_precharge(2) := '0'; + RW_interrupt_write(2) := '0'; + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + ASSERT FALSE REPORT "WRITE: Start Internal Precharge Bank 2" SEVERITY NOTE; + END IF; + END IF; + IF ((Auto_precharge(3) = '1') AND (Write_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(3) >= 1 AND NOW - WR_chka(3) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2 AND NOW - WR_chka(3) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4 AND NOW - WR_chka(3) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8 AND NOW - WR_chka(3) >= tWRa))) OR + (RW_interrupt_write(0) = '1' AND NOW - WR_time(3) >= tWRa)) THEN + Auto_precharge(3) := '0'; + Write_precharge(3) := '0'; + RW_interrupt_write(3) := '0'; + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + ASSERT FALSE REPORT "WRITE: Start Internal Precharge Bank 3" SEVERITY NOTE; + END IF; + END IF; + + -- DEBUG STUFF + Act_chk <= (Act_b3 & Act_b2 & Act_b1 & Act_b0); + Din_chk <= Data_in_enable; + Dout_chk <= Data_out_enable; + END PROCESS; + + -- Clock timing checks + Clock_check : PROCESS + VARIABLE Clk_low, Clk_high : TIME := 0 ns; + BEGIN + WAIT ON Clk; + IF (Clk = '1' AND NOW >= 10 ns) THEN + ASSERT (NOW - Clk_low >= tCL) + REPORT "tCL violation" + SEVERITY WARNING; + ASSERT (NOW - Clk_high >= tCK) + REPORT "tCK violation" + SEVERITY WARNING; + Clk_high := NOW; + ELSIF (Clk = '0' AND NOW /= 0 ns) THEN + ASSERT (NOW - Clk_high >= tCH) + REPORT "tCH violation" + SEVERITY WARNING; + Clk_low := NOW; + END IF; + END PROCESS; + + -- Setup timing checks + Setup_check : PROCESS + BEGIN + WAIT ON Clk; + IF Clk = '1' THEN + ASSERT(Cke'LAST_EVENT >= tCKS) + REPORT "CKE Setup time violation -- tCKS" + SEVERITY WARNING; + ASSERT(Cs_n'LAST_EVENT >= tCMS) + REPORT "CS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT >= tCMS) + REPORT "CAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT >= tCMS) + REPORT "RAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT >= tCMS) + REPORT "WE# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT >= tCMS) + REPORT "Dqm Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Addr'LAST_EVENT >= tAS) + REPORT "ADDR Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT >= tAS) + REPORT "BA Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Dq'LAST_EVENT >= tDS) + REPORT "Dq Setup time violation -- tDS" + SEVERITY WARNING; + END IF; + END PROCESS; + + -- Hold timing checks + Hold_check : PROCESS + BEGIN + WAIT ON Clk'DELAYED (tCKH), Clk'DELAYED (tCMH), Clk'DELAYED (tAH), Clk'DELAYED (tDH); + IF Clk'DELAYED (tCKH) = '1' THEN + ASSERT(Cke'LAST_EVENT > tCKH) + REPORT "CKE Hold time violation -- tCKH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tCMH) = '1' THEN + ASSERT(Cs_n'LAST_EVENT > tCMH) + REPORT "CS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT > tCMH) + REPORT "CAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT > tCMH) + REPORT "RAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT > tCMH) + REPORT "WE# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT > tCMH) + REPORT "Dqm Hold time violation -- tCMH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tAH) = '1' THEN + ASSERT(Addr'LAST_EVENT > tAH) + REPORT "ADDR Hold time violation -- tAH" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT > tAH) + REPORT "BA Hold time violation -- tAH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tDH) = '1' THEN + ASSERT(Dq'LAST_EVENT > tDH) + REPORT "DQ Hold time violation -- tDH" + SEVERITY WARNING; + END IF; + END PROCESS; + +END behave; diff --git a/lib/models/memory/sdram/mt48lc16m8a2/test.do b/lib/models/memory/sdram/mt48lc16m8a2/test.do new file mode 100644 index 0000000..56933bb --- /dev/null +++ b/lib/models/memory/sdram/mt48lc16m8a2/test.do @@ -0,0 +1,5 @@ +vcom mt48lc16m8a2.vhd +vcom test.vhd +vsim -t ps tb +do wave.do +run 800 ns diff --git a/lib/models/memory/sdram/mt48lc16m8a2/test.vhd b/lib/models/memory/sdram/mt48lc16m8a2/test.vhd new file mode 100644 index 0000000..77b42ce --- /dev/null +++ b/lib/models/memory/sdram/mt48lc16m8a2/test.vhd @@ -0,0 +1,313 @@ +LIBRARY ieee; + USE ieee.std_logic_1164.ALL; + +ENTITY tb IS +END tb; + +ARCHITECTURE test OF tb IS + COMPONENT mt48lc16m8a2 + GENERIC ( + tCK : TIME := 10 ns; + addr_bits : INTEGER := 12; + data_bits : INTEGER := 8 + ); + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '0'; + Cs_n : IN STD_LOGIC := '1'; + Cas_n : IN STD_LOGIC := '0'; + Ras_n : IN STD_LOGIC := '0'; + We_n : IN STD_LOGIC := '0'; + Dqm : IN STD_LOGIC := '0' + ); + END COMPONENT; + + FOR ALL : mt48lc16m8a2 USE ENTITY work.mt48lc16m8a2 (behave); + + CONSTANT tCK : TIME := 10 ns; + CONSTANT addr_bits : INTEGER := 12; + CONSTANT data_bits : INTEGER := 8; + + SIGNAL pDq : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0); + SIGNAL pAddr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + SIGNAL pBa : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL pClk : STD_LOGIC; + SIGNAL pCke : STD_LOGIC; + SIGNAL pCs_n : STD_LOGIC; + SIGNAL pCas_n : STD_LOGIC; + SIGNAL pRas_n : STD_LOGIC; + SIGNAL pWe_n : STD_LOGIC; + SIGNAL pDqm : STD_LOGIC; + SIGNAL stim_done : boolean := false; + SIGNAL clk_done : boolean := false; + + +BEGIN + u1: mt48lc16m8a2 + PORT MAP( + Dq => pDq, + Addr => pAddr, + Ba => pBa, + Clk => pClk, + Cke => pCke, + Cs_n => pCs_n, + Ras_n => pRas_n, + Cas_n => pCas_n, + We_n => pWe_n, + Dqm => pDqm + ); + + stimulator : PROCESS + PROCEDURE ACTIVE (Ba_in : STD_LOGIC_VECTOR (1 DOWNTO 0); + Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + Dq_in : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '0'; + pCas_n <= '1'; + pWe_n <= '1'; + pDqm <= '0'; + pBa <= Ba_in; + pAddr <= Addr_in; + pDq <= Dq_in; + WAIT FOR tCK; + END; + + PROCEDURE AUTO_REFRESH IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '0'; + pCas_n <= '0'; + pWe_n <= '1'; + pDqm <= '0'; + --pBa <= "00"; + --pAddr <= (OTHERS => '0'); + pDq <= (OTHERS => 'Z'); + WAIT FOR tCK; + END; + + PROCEDURE BURST_TERM IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '1'; + pCas_n <= '1'; + pWe_n <= '0'; + pDqm <= '0'; + --pBa <= "00"; + --pAddr <= (OTHERS => '0'); + pDq <= (OTHERS => 'Z'); + WAIT FOR tCK; + END; + + PROCEDURE LOAD_MODE_REG (Ba_in : STD_LOGIC_VECTOR (1 DOWNTO 0); + Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0)) IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '0'; + pCas_n <= '0'; + pWe_n <= '0'; + pDqm <= '0'; + pBa <= Ba_in; + pAddr <= Addr_in; + pDq <= (OTHERS => 'Z'); + WAIT FOR tCK; + END; + + PROCEDURE NOP (Dq_in : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '1'; + pCas_n <= '1'; + pWe_n <= '1'; + pDqm <= '0'; + --pBa <= "00"; + --pAddr <= (OTHERS => '0'); + pDq <= Dq_in; + WAIT FOR tCK; + END; + + PROCEDURE PRECHARGE (Ba_in : STD_LOGIC_VECTOR (1 DOWNTO 0); + Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + Dq_in : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '0'; + pCas_n <= '1'; + pWe_n <= '0'; + pDqm <= '0'; + pBa <= Ba_in; + pAddr <= Addr_in; + pDq <= Dq_in; + WAIT FOR tCK; + END; + + PROCEDURE READ (Ba_in : STD_LOGIC_VECTOR (1 DOWNTO 0); + Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + Dq_in : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '1'; + pCas_n <= '0'; + pWe_n <= '1'; + pDqm <= '0'; + pBa <= Ba_in; + pAddr <= Addr_in; + pDq <= Dq_in; + WAIT FOR tCK; + END; + + -- Write + PROCEDURE WRITE (Ba_in : STD_LOGIC_VECTOR (1 DOWNTO 0); + Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + Dq_in : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '1'; + pCas_n <= '0'; + pWe_n <= '0'; + pDqm <= '0'; + pBa <= Ba_in; + pAddr <= Addr_in; + pDq <= Dq_in; + WAIT FOR tCK; + END; + BEGIN + -- COMMAND BA ADDR DQ + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + -- We need 100 us power up sequence. I use 10 NOPs here as a required example. + PRECHARGE ("00", "010000000000", "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + + AUTO_REFRESH; + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + + AUTO_REFRESH; + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + + LOAD_MODE_REG ("00", "000000100010"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + + ACTIVE ("00", "000000000000", "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + + ACTIVE ("01", "000000000000", "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + + ACTIVE ("10", "000000000000", "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + + ACTIVE ("11", "000000000000", "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + + WRITE ("00", "000000000000", "00000000"); + NOP ( "00000001"); + NOP ( "00000010"); + NOP ( "00000011"); + + WRITE ("01", "000000000000", "00000100"); + NOP ( "00000101"); + NOP ( "00000110"); + NOP ( "00000111"); + + WRITE ("10", "000000000000", "00001000"); + NOP ( "00001001"); + NOP ( "00001010"); + NOP ( "00001011"); + + WRITE ("11", "000000000000", "00001100"); + NOP ( "00001101"); + NOP ( "00001110"); + NOP ( "00001111"); + + READ ("00", "000000000000", "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + + READ ("01", "000000000000", "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + + READ ("10", "000000000000", "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + + READ ("11", "000000000000", "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + + NOP ( "ZZZZZZZZ"); + NOP ( "ZZZZZZZZ"); + + ASSERT false + REPORT "End of Stimulation Detected!" + SEVERITY note; + stim_done <= true; + WAIT; + END PROCESS; + + clock : PROCESS + VARIABLE done_time : time; + BEGIN + pclk <= '0'; + WAIT for tCK/2; + WHILE not stim_done loop + pclk <= '1'; + WAIT for tCK/2; + pclk <= '0'; + WAIT for tCK/2; + END LOOP; + done_time := now + tCK; + WHILE now < done_time LOOP -- one last clock to finish last command + pclk <= '1'; + WAIT for tCK/2; + pclk <= '0'; + WAIT for tCK/2; + END LOOP; + ASSERT false + REPORT "Suspending clock activity" + SEVERITY note; + clk_done <= true; + WAIT; + END PROCESS; +END test; diff --git a/lib/models/memory/sdram/mt48lc16m8a2/wave.do b/lib/models/memory/sdram/mt48lc16m8a2/wave.do new file mode 100644 index 0000000..14a4520 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc16m8a2/wave.do @@ -0,0 +1,39 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +add wave -noupdate -format Logic /tb/u1/clk +add wave -noupdate -format Logic /tb/u1/cke +add wave -noupdate -format Logic /tb/u1/cs_n +add wave -noupdate -format Logic /tb/u1/ras_n +add wave -noupdate -format Logic /tb/u1/cas_n +add wave -noupdate -format Logic /tb/u1/we_n +add wave -noupdate -format Literal -radix decimal /tb/u1/addr +add wave -noupdate -format Literal -radix unsigned /tb/u1/ba +add wave -noupdate -format Literal -radix decimal /tb/u1/dq +add wave -noupdate -format Logic /tb/u1/dqm +add wave -noupdate -format Literal -radix decimal /tb/u1/operation +add wave -noupdate -format Literal -radix decimal /tb/u1/mode_reg +add wave -noupdate -format Logic /tb/u1/active_enable +add wave -noupdate -format Logic /tb/u1/aref_enable +add wave -noupdate -format Logic /tb/u1/burst_term +add wave -noupdate -format Logic /tb/u1/mode_reg_enable +add wave -noupdate -format Logic /tb/u1/prech_enable +add wave -noupdate -format Logic /tb/u1/read_enable +add wave -noupdate -format Logic /tb/u1/write_enable +add wave -noupdate -format Logic /tb/u1/burst_length_1 +add wave -noupdate -format Logic /tb/u1/burst_length_2 +add wave -noupdate -format Logic /tb/u1/burst_length_4 +add wave -noupdate -format Logic /tb/u1/burst_length_8 +add wave -noupdate -format Logic /tb/u1/cas_latency_2 +add wave -noupdate -format Logic /tb/u1/cas_latency_3 +add wave -noupdate -format Literal /tb/u1/act_chk +add wave -noupdate -format Logic /tb/u1/din_chk +add wave -noupdate -format Logic /tb/u1/dout_chk +TreeUpdate [SetDefaultTree] +WaveRestoreCursors {320 ns} +WaveRestoreZoom {139586 ps} {454431 ps} +configure wave -namecolwidth 150 +configure wave -valuecolwidth 100 +configure wave -justifyvalue left +configure wave -signalnamewidth 0 +configure wave -snapdistance 10 +configure wave -datasetprefix 0 diff --git a/lib/models/memory/sdram/mt48lc1m16a1/ed_comnd.vhd b/lib/models/memory/sdram/mt48lc1m16a1/ed_comnd.vhd new file mode 100644 index 0000000..7273327 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc1m16a1/ed_comnd.vhd @@ -0,0 +1,242 @@ +--------------------------------------------------------------------------------- +--COMMAND FORMAT -- +-- -- +-- write(column address(integer), bank(bit), first data(integer), dqm(bit), cke(bit));-- +-- read(column address(integer), bank(bit), dqm(bit), cke(bit)); -- +-- active(row address(integer), bank(bit), data bus (integer), dqm(bit), cke(bit));-- +-- precharge(bank(bit), data bus(integer), dqm(bit), cke(bit)); -- +-- nop(data bus(integer), dqm(bit), cke(bit), cs(bit)); -- +-- burst_term(data bus(integer), dqm(bit_vector), cke(bit)); -- +-- load_array('1'); -- +-- load_mode_reg(register(integer), cke(bit)); -- +-- next_cycle(clk); This is used after every command(incl. nop) to clock -- +-- at the correct clock frequency entered in the clock -- +-- period constant below -- +-- unload_array(row_start(integer), row_end(integer), bank(bit)) -- +-- load_mode_reg(op_code(integer)) -- +-- -- +--------------------------------------------------------------------------------- + +LIBRARY work; +LIBRARY ieee; +USE ieee.std_logic_1164.all; +USE std.textio.all; +USE work.generate_vectors.all; + +ENTITY vector_generate IS +END vector_generate; + +ARCHITECTURE vector_generate OF vector_generate IS + + SIGNAL stim_done : BOOLEAN := FALSE; + SIGNAL clk : BIT := '0'; + CONSTANT clk_start : time := 15 ns; + CONSTANT clk_period : time := 10 ns; + CONSTANT Z : INTEGER := -100; + +BEGIN + +PROCESS + +BEGIN + +WAIT UNTIL clk = '1' AND clk'EVENT; + +--------------------ENTER COMMANDS BELOW THIS LINE----------------------------- +--******************DO NOT USE -100 FOR A DQ VALUE*************************---- +--*******************Z WILL PLACE HI-Z ON THE BUS**************************---- +--*******USE next_cycle(clk) FOR ADVANCING TO NEXT CLOCK CYCLE*************---- + +nop(Z, "00", '1', '1'); -- Always begin with one nop when using Micron's testbench + +FOR i IN 1 to 5 LOOP -- You will need 100 us for powerup. + next_cycle(clk); -- I used 5 here just for an example. + nop(Z, "00", '1', '1'); +END LOOP; + +next_cycle(clk); +precharge('0', 1024, Z, "00", '1'); -- Precharge all banks + +FOR i IN 1 to 2 LOOP + next_cycle(clk); + nop(Z, "00", '1', '1'); +END LOOP; + +next_cycle(clk); +auto_refresh; -- First auto refresh + +FOR i IN 1 TO 8 LOOP + next_cycle(clk); + nop(Z, "00", '1', '1'); +END LOOP; + +next_cycle(clk); +auto_refresh; -- Second auto refresh + +FOR i IN 1 TO 8 LOOP + next_cycle(clk); + nop(Z, "00", '1', '1'); +END LOOP; + +next_cycle(clk); +load_mode_reg(51, '1'); -- Load mode register (lat=3, bl=8, mode=seq) + +FOR i IN 1 TO 2 LOOP + next_cycle(clk); + nop(Z, "00", '1', '1'); +END LOOP; + +-- Alternate bank write access + +next_cycle(clk); +active(0, '0', Z, "00", '1'); -- Activate Bank 0, Row 0 + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +write(1024, '0', 100, "00", '1'); -- Write Bank 0, Col 0, Data 100 (auto precharge) + +next_cycle(clk); +nop (101, "00", '1', '1'); + +next_cycle(clk); +nop (102, "00", '1', '1'); + +next_cycle(clk); +nop (103, "00", '1', '1'); + +next_cycle(clk); +nop (104, "00", '1', '1'); + +next_cycle(clk); +active(0, '1', 105, "00", '1'); -- Activate Bank 1, Row 0 + +next_cycle(clk); +nop (106, "00", '1', '1'); + +next_cycle(clk); +nop (107, "00", '1', '1'); + +next_cycle(clk); +write(1024, '1', 200, "00", '1'); -- Write Bank 1, Col 0, Data 200 (auto precharge) + +next_cycle(clk); +nop (201, "00", '1', '1'); + +next_cycle(clk); +nop (202, "00", '1', '1'); + +next_cycle(clk); +nop (203, "00", '1', '1'); + +next_cycle(clk); +nop (204, "00", '1', '1'); + +next_cycle(clk); +active(0, '0', 205, "00", '1'); -- Activate Bank 0, Row 0 + +next_cycle(clk); +nop (206, "00", '1', '1'); + +next_cycle(clk); +nop (207, "00", '1', '1'); + +-- Alternate bank read access + +next_cycle(clk); +read(1024, '0', "00", '1'); -- Read Bank 0, Col 0 (auto precharge) + +next_cycle(clk); +nop (Z, "00", '1', '1'); + +next_cycle(clk); +nop (Z, "00", '1', '1'); + +next_cycle(clk); +nop (Z, "00", '1', '1'); + +next_cycle(clk); +nop (Z, "00", '1', '1'); + +next_cycle(clk); +active(0, '1', Z, "00", '1'); -- Activate Bank 1, Row 0 + +next_cycle(clk); +nop (Z, "00", '1', '1'); + +next_cycle(clk); +nop (Z, "00", '1', '1'); + +next_cycle(clk); +read(1024, '1', "00", '1'); -- Read Bank 1, Col 0 (auto precharge) + +next_cycle(clk); +nop (Z, "00", '1', '1'); + +next_cycle(clk); +nop (Z, "00", '1', '1'); + +next_cycle(clk); +nop (Z, "00", '1', '1'); + +next_cycle(clk); +nop (Z, "00", '1', '1'); + +next_cycle(clk); +nop (Z, "00", '1', '1'); + +next_cycle(clk); +nop (Z, "00", '1', '1'); + +next_cycle(clk); +nop (Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +stim_done <= TRUE; --always include this line at the end of your stimulus + +------------------------------------------------------------------------------- +--*************************************************************************---- +END PROCESS; + + +clock: + PROCESS + VARIABLE done_time : time; + VARIABLE cycle_var : integer := 0; + BEGIN + cycle <= 0; + clk <= '0'; + WAIT for clk_start; + WHILE not stim_done loop + clk <= '1'; + cycle <= cycle_var; + WAIT for clk_period/2; + cycle_var := cycle_var + 1; + clk <= '0'; + WAIT for clk_period/2; + END LOOP; + + ASSERT (FALSE) + REPORT "Test Vectors Generated" + SEVERITY note; + + WAIT; + END PROCESS; + + +END; diff --git a/lib/models/memory/sdram/mt48lc1m16a1/io_utils.vhd b/lib/models/memory/sdram/mt48lc1m16a1/io_utils.vhd new file mode 100644 index 0000000..dfcb84a --- /dev/null +++ b/lib/models/memory/sdram/mt48lc1m16a1/io_utils.vhd @@ -0,0 +1,266 @@ +LIBRARY ieee; +USE std.textio.ALL; +USE ieee.std_logic_1164.ALL; + +PACKAGE io_utils IS + + PROCEDURE write_string(l : INOUT line; + value : IN string; + justified : IN side := right; + field : IN width := 0); + + TYPE radix IS (binary, octal, decimal, hex); + + -- read a number from the line + -- use this if you have hex numbers that are not in VHDL pound-sign format + PROCEDURE read(l : INOUT line; value : OUT integer; radix : IN positive); + + -- read a number that might be in VHDL pound-sign format + PROCEDURE read_based(l : INOUT line; value : OUT integer); + + PROCEDURE write(l : INOUT line; + value : IN std_logic_vector; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false); + + PROCEDURE write(l : INOUT line; + value : IN integer; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false); +END io_utils; + +PACKAGE BODY io_utils IS + + PROCEDURE write_string(l : INOUT line; + value : IN string; + justified : IN side := right; + field : IN width := 0) + IS + BEGIN + write(l, value, justified, field); + END; + + PROCEDURE shrink_line(l : INOUT line; pos : integer) IS + VARIABLE tmpl : line; + BEGIN + tmpl := l; + l := NEW string'(tmpl(pos TO tmpl'high)); + deallocate(tmpl); + END; + + PROCEDURE read(l : INOUT line; + value : OUT integer; + radix : IN positive) + IS + CONSTANT not_digit : integer := -999; + + -- convert a character to a value from 0 to 15 + FUNCTION digit_value(c : character) RETURN integer IS + BEGIN + IF (c >= '0') AND (c <= '9') THEN + RETURN (character'pos(c) - character'pos('0')); + ELSIF (c >= 'a') AND (c <= 'f') THEN + RETURN (character'pos(c) - character'pos('a') + 10); + ELSIF (c >= 'A') AND (c <= 'F') THEN + RETURN (character'pos(c) - character'pos('A') + 10); + ELSE + RETURN not_digit; + END IF; + END; + + -- skip leading white space in the line + PROCEDURE skip_white(VARIABLE l : IN line; pos : OUT integer) IS + BEGIN + pos := l'low; + FOR i IN l'low TO l'high LOOP + CASE l(i) IS + WHEN ' ' | ht => + pos := i + 1; + WHEN OTHERS => + EXIT; + END CASE; + END LOOP; + END; + + VARIABLE digit : integer; + VARIABLE result : integer := 0; + VARIABLE pos : integer; + BEGIN + -- skip white space + skip_white(l, pos); + + -- calculate the value + FOR i IN pos TO l'right LOOP + digit := digit_value(l(i)); + EXIT WHEN (digit = not_digit) OR (digit >= radix); + result := result * radix + digit; + pos := i + 1; + END LOOP; + value := result; + + -- remove the "used" characters from the line + shrink_line(l, pos); + END; + + PROCEDURE read_based(l : INOUT line; value : OUT integer) IS + VARIABLE digit : integer; + VARIABLE num : integer; + VARIABLE base : integer; + BEGIN + read(l, num, 10); + IF (l'length > 1) AND (l(l'left) = '#') THEN + shrink_line(l, l'left+1); + base := num; + read(l, num, base); + IF (l'length >= 1) AND (l(l'left) = '#') THEN + shrink_line(l, l'left+1); + END IF; + END IF; + value := num; + END; + + PROCEDURE write(l : INOUT line; + value : IN std_logic_vector; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false) + IS + FUNCTION to_int(bv : std_logic_vector) RETURN integer + IS + VARIABLE result : integer := 0; + BEGIN + FOR i IN bv'RANGE LOOP + result := result * 2; + IF (bv(i) = '1') THEN + result := result + 1; + END IF; + END LOOP; + RETURN result; + END; + + TYPE array_of_widths IS ARRAY(radix) OF natural; + CONSTANT nibble_widths : array_of_widths := ( + binary => 1, + octal => 3, + hex => 4, + decimal=> 32); + CONSTANT hex_digit : string(1 TO 16) := "0123456789ABCDEF"; + + ALIAS input_val : std_logic_vector(value'length DOWNTO 1) IS value; + CONSTANT nibble_width : natural := nibble_widths(base); + CONSTANT result_width : natural := (value'length + nibble_width - 1)/nibble_width; + + VARIABLE result : string(1 TO result_width); -- longest possible value + VARIABLE result_pos : positive := 1; + VARIABLE nibble_val : integer; + VARIABLE bitcnt : integer; + BEGIN + IF base = decimal THEN + write(l, to_int(value), justified, field, base, use_pound); + RETURN; + END IF; + + bitcnt := value'length MOD nibble_width; + IF (bitcnt = 0) THEN + bitcnt := nibble_width; + END IF; + FOR i IN input_val'RANGE LOOP + nibble_val := nibble_val * 2; + IF (input_val(i) = '1') THEN + nibble_val := nibble_val + 1; + END IF; + bitcnt := bitcnt - 1; + IF (bitcnt = 0) THEN + result(result_pos) := hex_digit(nibble_val + 1); + result_pos := result_pos + 1; + nibble_val := 0; + bitcnt := nibble_width; + END IF; + END LOOP; + write(l, result, justified, field); + END; + + PROCEDURE write(l : INOUT line; + value : IN integer; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false) + IS + FUNCTION to_bv(int : integer) RETURN std_logic_vector + IS + VARIABLE bv : std_logic_vector(32 DOWNTO 1) := (OTHERS => '0'); + VARIABLE pos : integer := 0; + VARIABLE tmpval : integer := int; + BEGIN + FOR i IN 1 TO 32 LOOP + pos := pos + 1; + IF (tmpval MOD 2) = 1 THEN + bv(i) := '1'; + END IF; + tmpval := tmpval / 2; + EXIT WHEN tmpval = 0; + END LOOP; + RETURN bv(pos DOWNTO 1); + END; + + VARIABLE tmp : line; + BEGIN + IF (base = decimal) THEN + IF (use_pound) THEN + write_string(tmp, "10#"); + END IF; + write(tmp, value); + IF (use_pound) THEN + write_string(tmp, "#"); + END IF; + write(l, tmp.ALL, justified, field); + deallocate(tmp); + ELSE + write(l, to_bv(value), justified, field, base, use_pound); + END IF; + END; + +END io_utils; + + + +-- test the hex number reader +--ENTITY test IS END; + +--USE std.textio.ALL; +--USE work.io_utils.ALL; +--ARCHITECTURE hex_test OF test IS +--BEGIN +-- PROCESS +-- VARIABLE val : integer; +-- FILE myfile : text IS IN "values"; +-- VARIABLE inline : line; +-- VARIABLE outline : line; +-- BEGIN +-- WHILE NOT endfile(myfile) LOOP +-- readline(myfile, inline); + +-- write(outline, inline.ALL); +-- +-- read_based(inline, val); + -- write_string(outline, " binary: "); + -- write(outline, val, base => binary); + -- write_string(outline, " octal: "); + -- write(outline, val, base => octal); + -- write_string(outline, " decimal: "); + -- write(outline, val, base => decimal); +-- write_string(outline, " hex: "); +-- write(outline, val, base => hex); +-- writeline(output, outline); +-- END LOOP; +-- WAIT; +-- END PROCESS; +--END; + + diff --git a/lib/models/memory/sdram/mt48lc1m16a1/mt48lc1m16a1.vhd b/lib/models/memory/sdram/mt48lc1m16a1/mt48lc1m16a1.vhd new file mode 100644 index 0000000..6b7b1f1 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc1m16a1/mt48lc1m16a1.vhd @@ -0,0 +1,907 @@ +----------------------------------------------------------------------------------------- +-- +-- File Name: MT48LC1M18A1.VHD +-- Version: 0.0c +-- Date: April 20th, 1999 +-- Model: Behavioral +-- Simulator: Model Technology VLOG (PC version 5.2e PE) +-- +-- Dependencies: None +-- +-- Author: Son P. Huynh +-- Email: sphuynh@micron.com +-- Phone: (208) 368-3825 +-- Company: Micron Technology, Inc. +-- Part Number: MT48LC1M16A1 (512k x 16 x 2 Banks) +-- +-- Description: Micron 16Mb SDRAM +-- +-- Limitation: - Doesn't check for 4096-cycle refresh +-- +-- Note: - Set simulator resolution to "ps" accuracy +-- +-- Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY +-- WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY +-- IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR +-- A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT. +-- +-- Copyright (c) 1998 Micron Semiconductor Products, Inc. +-- All rights researved +-- +-- Rev Author Phone Date Changes +-- ---- ---------------------------- ---------- ------------------------------------- +-- 0.0c Son P. Huynh 208-368-3825 04/20/1999 Fix precharge to different bank +-- Micron Technology Inc. terminate current bank +-- +-- 0.0b Son P. Huynh 208-368-3825 12/09/1998 Fix some timing check problem +-- Micron Technology Inc. - Improve model functionality +-- +-- 0.0a Son P. Huynh 208-368-3825 08/10/1998 First Release +-- Micron Technology Inc. - Simple testbench included +----------------------------------------------------------------------------------------- + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE WORK.mti_pkg.ALL; + +ENTITY mt48lc1m16a1 IS + GENERIC ( + tAC : TIME := 6.0 ns; -- Timing parameter for -10 device + tAH : TIME := 1.0 ns; + tAS : TIME := 3.0 ns; + tCH : TIME := 3.5 ns; + tCL : TIME := 3.5 ns; + tCK : TIME := 10.0 ns; + tDH : TIME := 1.0 ns; + tDS : TIME := 3.0 ns; + tCKH : TIME := 1.0 ns; + tCKS : TIME := 3.0 ns; + tCMH : TIME := 1.0 ns; + tCMS : TIME := 3.0 ns; + tOH : TIME := 2.5 ns; + tHZ : TIME := 6.0 ns; + tMRD : INTEGER := 2; + tRAS : TIME := 60.0 ns; + tRC : TIME := 90.0 ns; + tRCD : TIME := 30.0 ns; + tRP : TIME := 30.0 ns; + tRRD : TIME := 20.0 ns; + tWR : INTEGER := 1; + addr_bits : INTEGER := 11; + data_bits : INTEGER := 16; + col_bits : INTEGER := 8 + ); + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC := '0'; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '0'; + Cs_n : IN STD_LOGIC := '1'; + Ras_n : IN STD_LOGIC := '0'; + Cas_n : IN STD_LOGIC := '0'; + We_n : IN STD_LOGIC := '0'; + Dqm : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := "00" + ); +END mt48lc1m16a1; + +ARCHITECTURE behave OF mt48lc1m16a1 IS + TYPE State IS (ACT, A_REF, BST, LMR, NOP, PRECH, READ, READ_A, WRITE, WRITE_A); + TYPE Array2xI IS ARRAY (1 DOWNTO 0) OF INTEGER; + TYPE Array2xB IS ARRAY (1 DOWNTO 0) OF BIT; + TYPE Array4xB IS ARRAY (3 DOWNTO 0) OF BIT; + TYPE Array2x2BV IS ARRAY (1 DOWNTO 0) OF BIT_VECTOR (1 DOWNTO 0); + TYPE Array4xCBV IS ARRAY (3 DOWNTO 0) OF BIT_VECTOR (Col_bits - 1 DOWNTO 0); + TYPE Array_state IS ARRAY (3 DOWNTO 0) OF State; + SIGNAL Operation : State := NOP; + SIGNAL Mode_reg : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL Active_enable, Aref_enable, Burst_term : BIT := '0'; + SIGNAL Mode_reg_enable, Prech_enable, Read_enable, Write_enable : BIT := '0'; + SIGNAL Burst_length_1, Burst_length_2, Burst_length_4, Burst_length_8 : BIT := '0'; + SIGNAL Cas_latency_1, Cas_latency_2, Cas_latency_3 : BIT := '0'; + SIGNAL Ras_in, Cas_in, We_in : BIT := '0'; + SIGNAL Write_burst_mode : BIT := '0'; + SIGNAL Sys_clk, CkeZ : BIT := '0'; + + -- Checking internal wires + SIGNAL Pre_chk : BIT_VECTOR (1 DOWNTO 0) := "00"; + SIGNAL Act_chk : BIT_VECTOR (1 DOWNTO 0) := "00"; + SIGNAL Dq_in_chk, Dq_out_chk : BIT := '0'; + SIGNAL Bank_chk : BIT := '0'; + SIGNAL Row_chk : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL Col_chk : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + + BEGIN + -- CS# Decode + WITH Cs_n SELECT + Cas_in <= TO_BIT (Cas_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + WITH Cs_n SELECT + Ras_in <= TO_BIT (Ras_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + WITH Cs_n SELECT + We_in <= TO_BIT (We_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + + -- Commands Decode + Active_enable <= NOT(Ras_in) AND Cas_in AND We_in; + Aref_enable <= NOT(Ras_in) AND NOT(Cas_in) AND We_in; + Burst_term <= Ras_in AND Cas_in AND NOT(We_in); + Mode_reg_enable <= NOT(Ras_in) AND NOT(Cas_in) AND NOT(We_in); + Prech_enable <= NOT(Ras_in) AND Cas_in AND NOT(We_in); + Read_enable <= Ras_in AND NOT(Cas_in) AND We_in; + Write_enable <= Ras_in AND NOT(Cas_in) AND NOT(We_in); + + -- Burst Length Decode + Burst_length_1 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND NOT(Mode_reg(0)); + Burst_length_2 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND Mode_reg(0); + Burst_length_4 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND NOT(Mode_reg(0)); + Burst_length_8 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND Mode_reg(0); + + -- CAS Latency Decode + Cas_latency_1 <= NOT(Mode_reg(6)) AND NOT(Mode_reg(5)) AND Mode_reg(4); + Cas_latency_2 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND NOT(Mode_reg(4)); + Cas_latency_3 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND Mode_reg(4); + + -- Write Burst Mode + Write_burst_mode <= Mode_reg(9); + + -- System Clock + int_clk : PROCESS (Clk) + begin + IF Clk'LAST_VALUE = '0' AND Clk = '1' THEN + CkeZ <= TO_BIT(Cke, '1'); + END IF; + Sys_clk <= CkeZ AND TO_BIT(Clk, '0'); + END PROCESS; + + state_register : PROCESS + TYPE ram_type IS ARRAY (2**col_bits - 1 DOWNTO 0) OF BIT_VECTOR (data_bits - 1 DOWNTO 0); + TYPE ram_pntr IS ACCESS ram_type; + TYPE ram_stor IS ARRAY (2**addr_bits - 1 DOWNTO 0) OF ram_pntr; + VARIABLE Bank0 : ram_stor; + VARIABLE Bank1 : ram_stor; + VARIABLE Row_index, Col_index : INTEGER := 0; + VARIABLE Dq_temp : BIT_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => '0'); + + VARIABLE Col_addr : Array4xCBV; + VARIABLE Bank_addr : Array4xB; + VARIABLE Dqm_reg : Array2x2BV; + + VARIABLE Bank, Previous_bank : BIT := '0'; + VARIABLE B0_row_addr, B1_row_addr : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col_brst : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Row : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Burst_counter : INTEGER := 0; + + VARIABLE Command : Array_state; + VARIABLE A10_precharge, Bank_precharge : Array4xB; + VARIABLE Auto_precharge, Read_precharge, Write_precharge : Array2xB; + VARIABLE Count_precharge : Array2xI; + VARIABLE RW_interrupt_write : BIT := '0'; + + VARIABLE Data_in_enable, Data_out_enable : BIT := '0'; + VARIABLE Pc_b0, Pc_b1 : BIT := '0'; + VARIABLE Act_b0, Act_b1 : BIT := '0'; + + -- Timing Check + VARIABLE MRD_chk : INTEGER := 0; + VARIABLE RC_chk, RRD_chk : TIME := 0 ns; + VARIABLE RAS_chk0, RAS_chk1 : TIME := 0 ns; + VARIABLE RCD_chk0, RCD_chk1 : TIME := 0 ns; + VARIABLE RP_chk, RP_chk0, RP_chk1 : TIME := 0 ns; + VARIABLE WR_chk : Array2xI := (0 & 0); + + -- Initialize empty rows + PROCEDURE Init_mem (Bank : BIT; Row_index : INTEGER) IS + VARIABLE i, j : INTEGER := 0; + BEGIN + IF Bank = '0' THEN + IF Bank0 (Row_index) = NULL THEN -- Check to see if row empty + Bank0 (Row_index) := NEW ram_type; -- Open new row for access + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP -- Filled row with zeros + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank0 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = '1' THEN + IF Bank1 (Row_index) = NULL THEN + Bank1 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank1 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + END IF; + END; + + -- Burst Counter + PROCEDURE Burst_decode IS + VARIABLE Col_int : INTEGER := 0; + VARIABLE Col_vec, Col_temp : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + BEGIN + -- Advance Burst Counter + Burst_counter := Burst_counter + 1; + + -- Burst Type + IF Mode_reg (3) = '0' THEN + Col_int := TO_INTEGER(Col); + Col_int := Col_int + 1; + TO_BITVECTOR (Col_int, Col_temp); + ELSIF Mode_reg (3) = '1' THEN + TO_BITVECTOR (Burst_counter, Col_vec); + Col_temp (2) := Col_vec (2) XOR Col_brst (2); + Col_temp (1) := Col_vec (1) XOR Col_brst (1); + Col_temp (0) := Col_vec (0) XOR Col_brst (0); + END IF; + + -- Burst Length + IF Burst_length_2 = '1' THEN + Col (0) := Col_temp (0); + ELSIF Burst_length_4 = '1' THEN + Col (1 DOWNTO 0) := Col_temp (1 DOWNTO 0); + ELSIF Burst_length_8 = '1' THEN + Col (2 DOWNTO 0) := Col_temp (2 DOWNTO 0); + ELSE + Col := Col_temp; + END IF; + + -- Burst Read Single Write + IF Write_burst_mode = '1' AND Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Data counter + IF Burst_length_1 = '1' THEN + IF Burst_counter >= 1 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_2 = '1' THEN + IF Burst_counter >= 2 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_4 = '1' THEN + IF Burst_counter >= 4 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_8 = '1' THEN + IF Burst_counter >= 8 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + END IF; + END; + + BEGIN + WAIT ON Sys_clk; + IF Sys_clk = '1' THEN + -- Internal Command Pipeline + Command(0) := Command(1); + Command(1) := Command(2); + Command(2) := Command(3); + Command(3) := NOP; + + Col_addr(0) := Col_addr(1); + Col_addr(1) := Col_addr(2); + Col_addr(2) := Col_addr(3); + Col_addr(3) := (OTHERS => '0'); + + Bank_addr(0) := Bank_addr(1); + Bank_addr(1) := Bank_addr(2); + Bank_addr(2) := Bank_addr(3); + Bank_addr(3) := '0'; + + Bank_precharge(0) := Bank_precharge(1); + Bank_precharge(1) := Bank_precharge(2); + Bank_precharge(2) := Bank_precharge(3); + Bank_precharge(3) := '0'; + + A10_precharge(0) := A10_precharge(1); + A10_precharge(1) := A10_precharge(2); + A10_precharge(2) := A10_precharge(3); + A10_precharge(3) := '0'; + + -- Operation Decode + IF Active_enable = '1' THEN + Operation <= ACT; + ELSIF Aref_enable = '1' THEN + Operation <= A_REF; + ELSIF Burst_term = '1' THEN + Operation <= BST; + ELSIF Mode_reg_enable = '1' THEN + Operation <= LMR; + ELSIF Prech_enable = '1' THEN + Operation <= PRECH; + ELSIF Read_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= READ; + ELSE + Operation <= READ_A; + END IF; + ELSIF Write_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= WRITE; + ELSE + Operation <= WRITE_A; + END IF; + ELSE + Operation <= NOP; + END IF; + + -- Dqm pipeline for Read + Dqm_reg(0) := Dqm_reg(1); + Dqm_reg(1) := TO_BITVECTOR(Dqm); + + -- Read or Write with Auto Precharge Counter + IF Auto_precharge (0) = '1' THEN + Count_precharge (0) := Count_precharge (0) + 1; + END IF; + IF Auto_precharge (1) = '1' THEN + Count_precharge (1) := Count_precharge (1) + 1; + END IF; + + -- tMRD Counter + MRD_chk := MRD_chk + 1; + + -- tWR Counter + WR_chk(0) := WR_chk(0) + 1; + WR_chk(1) := WR_chk(1) + 1; + + -- Auto Refresh + IF Aref_enable = '1' THEN + -- Auto Refresh to Auto Refresh + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Auto Refresh" + SEVERITY WARNING; + -- Precharge to Auto Refresh + ASSERT (NOW - RP_chk >= tRP) + REPORT "tRP violation during Auto Refresh" + SEVERITY WARNING; + -- Banks must be idle before Refresh + IF Pc_b1 = '0' OR Pc_b0 = '0' THEN + ASSERT (FALSE) + REPORT "All banks must be Precharge before Auto Refresh" + SEVERITY WARNING; + END IF; + -- Record current tRC time + RC_chk := NOW; + END IF; + + -- Load Mode Register + IF Mode_reg_enable = '1' THEN + Mode_reg <= TO_BITVECTOR (Addr); + IF (Pc_b0 /= '1' OR Pc_b1 /= '1') THEN + ASSERT (FALSE) + REPORT "All bank must be Precharge before Load Mode Register" + SEVERITY WARNING; + END IF; + -- REF to LMR + ASSERT (RC_chk >= tRC) + REPORT "tRC violation during Load Mode Register" + SEVERITY WARNING; + -- LMR to LMR + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Load Mode Register" + SEVERITY WARNING; + -- Record current tMRD time + MRD_chk := 0; + END IF; + + -- Active Block (latch Bank and Row Address) + IF Active_enable = '1' THEN + IF Ba = '0' AND Pc_b0 = '1' THEN + Act_b0 := '1'; + Pc_b0 := '0'; + B0_row_addr := TO_BITVECTOR (Addr); + RCD_chk0 := NOW; + RAS_chk0 := NOW; + -- Precharge to Active Bank 0 + ASSERT (NOW - RP_chk0 >= tRP) + REPORT "tRP violation during Activate Bank 0" + SEVERITY WARNING; + ELSIF Ba = '1' AND Pc_b1 = '1' THEN + Act_b1 := '1'; + Pc_b1 := '0'; + B1_row_addr := TO_BITVECTOR (Addr); + RCD_chk1 := NOW; + RAS_chk1 := NOW; + -- Precharge to Active Bank 1 + ASSERT (NOW - RP_chk1 >= tRP) + REPORT "tRP violation during Activate Bank 1" + SEVERITY WARNING; + ELSIF Ba = '0' AND Pc_b0 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 0 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = '1' AND Pc_b1 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 1 is not Precharged" + SEVERITY WARNING; + END IF; + -- Active Bank A to Active Bank B + IF (Previous_bank /= TO_BIT(Ba)) AND (NOW - RRD_chk < tRRD) THEN + ASSERT (FALSE) + REPORT "tRRD violation during activate" + SEVERITY WARNING; + END IF; + -- LMR to ACT + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Activate" + SEVERITY WARNING; + -- AutoRefresh to Activate + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Activate" + SEVERITY WARNING; + -- Record current Bank and RRD_chk + Previous_bank := TO_BIT(Ba); + RRD_chk := NOW; + END IF; + + -- Precharge Block + IF Prech_enable = '1' THEN + IF Addr(10) = '1' THEN + Pc_b0 := '1'; + Pc_b1 := '1'; + Act_b0 := '0'; + Act_b1 := '0'; + RP_chk0 := NOW; + RP_chk1 := NOW; + -- Activate to Precharge all banks + ASSERT ((NOW - RAS_chk0 >= tRAS) OR (NOW - RAS_chk1 >= tRAS)) + REPORT "tRAS violation during Precharge all banks" + SEVERITY WARNING; + -- tWR violation check for Write + IF ((WR_chk(0) < tWR) AND (WR_chk(1) < tWR)) THEN + ASSERT (FALSE) + REPORT "tWR violation during Precharge all banks" + SEVERITY WARNING; + END IF; + ELSIF Addr(10) = '0' THEN + IF Ba = '0' THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + -- Activate to Precharge bank 0 + ASSERT (NOW - RAS_chk0 >= tRAS) + REPORT "tRAS violation during Precharge bank 0" + SEVERITY WARNING; + ELSIF Ba = '1' THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + -- Activate to Precharge bank 1 + ASSERT (NOW - RAS_chk1 >= tRAS) + REPORT "tRAS violation during Precharge bank 1" + SEVERITY WARNING; + END IF; + -- tWR violation check for Write + IF (WR_chk(TO_INTEGER(Ba)) < tWR) THEN + ASSERT (FALSE) + REPORT "tWR violation during Precharge" + SEVERITY WARNING; + END IF; + END IF; + + -- Terminate a Write Immediately (if same bank or all banks) + IF (Data_in_enable = '1' AND (Bank = TO_BIT(Ba) OR Addr(10) = '1')) THEN + Data_in_enable := '0'; + END IF; + + -- Precharge Command Pipeline for READ + IF CAS_latency_3 = '1' THEN + Command(2) := PRECH; + Bank_precharge(2) := TO_BIT (Ba); + A10_precharge(2) := TO_BIT (Addr(10)); + ELSIF CAS_latency_2 = '1' THEN + Command(1) := PRECH; + Bank_precharge(1) := TO_BIT (Ba); + A10_precharge(1) := TO_BIT (Addr(10)); + ELSIF CAS_latency_1 = '1' THEN + Command(0) := PRECH; + Bank_precharge(0) := TO_BIT (Ba); + A10_precharge(0) := TO_BIT (Addr(10)); + END IF; + -- Record Precharge Bank and Current tRP time + RP_chk := NOW; + END IF; + + -- Burst Terminate + IF Burst_term = '1' THEN + IF CAS_latency_3 = '1' THEN + Command(2) := BST; + ELSIF CAS_latency_2 = '1' THEN + Command(1) := BST; + ELSIF CAS_latency_1 = '1' THEN + Command(0) := BST; + END IF; + END IF; + + -- Read, Write, Column Latch + IF Read_enable = '1' OR Write_enable = '1' THEN + -- Check to see if bank is open (ACT) for Read or Write + IF ((Ba = '0' AND Pc_b0 = '1') OR (Ba = '1' AND Pc_b1 = '1')) THEN + ASSERT (FALSE) + REPORT "Cannot Read or Write - Bank is not Activated" + SEVERITY WARNING; + END IF; + -- Activate to Read or Write + IF Ba = '0' THEN + ASSERT (NOW - RCD_chk0 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 0" + SEVERITY WARNING; + ELSIF Ba = '1' THEN + ASSERT (NOW - RCD_chk1 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 1" + SEVERITY WARNING; + END IF; + -- Read Command + IF Read_enable = '1' THEN + -- Read Terminate a Write Immediately + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + RW_interrupt_write := '1'; + END IF; + -- CAS Latency Pipeline + IF Cas_latency_3 = '1' THEN + IF Addr(10) = '1' THEN + Command(2) := READ_A; + ELSE + Command(2) := READ; + END IF; + Col_addr (2) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0)); + Bank_addr (2) := TO_BIT (Ba); + ELSIF Cas_latency_2 = '1' THEN + IF Addr(10) = '1' THEN + Command(1) := READ_A; + ELSE + Command(1) := READ; + END IF; + Col_addr (1) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0)); + Bank_addr (1) := TO_BIT (Ba); + ELSIF Cas_latency_1 = '1' THEN + IF Addr(10) = '1' THEN + Command(0) := READ_A; + ELSE + Command(0) := READ; + END IF; + Col_addr (0) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0)); + Bank_addr (0) := TO_BIT (Ba); + END IF; + -- Write Command + ELSIF Write_enable = '1' THEN + IF Addr(10) = '1' THEN + Command(0) := WRITE_A; + ELSE + Command(0) := WRITE; + END IF; + Col_addr (0) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0)); + Bank_addr (0) := TO_BIT (Ba); + IF Data_in_enable = '1' THEN + RW_interrupt_write := '1'; + END IF; + END IF; + -- Read or Write with Auto Precharge + IF Addr(10) = '1' THEN + Auto_precharge (TO_INTEGER(Ba)) := '1'; + Count_precharge (TO_INTEGER(Ba)) := 0; + IF Read_enable = '1' THEN + Read_precharge (TO_INTEGER(Ba)) := '1'; + ELSIF Write_enable = '1' THEN + Write_precharge (TO_INTEGER(Ba)) := '1'; + END IF; + END IF; + END IF; + + -- Read with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. BL/2 cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Read_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(0) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8))) OR + ((Read_enable = '1' OR Write_enable = '1') AND Count_precharge(0) >= 1)) THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + Auto_precharge(0) := '0'; + Read_precharge(0) := '0'; + Write_precharge(0) := '0'; + END IF; + END IF; + IF ((Auto_precharge(1) = '1') AND (Read_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(1) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8))) OR + ((Read_enable = '1' OR Write_enable = '1') AND Count_precharge(1) >= 1)) THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + Auto_precharge(1) := '0'; + Read_precharge(1) := '0'; + Write_precharge(1) := '0'; + END IF; + END IF; + + -- Write with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. tWR cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Write_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(0) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8))) OR + (RW_interrupt_write = '1' AND WR_chk(0) >= 1)) THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + Auto_precharge(0) := '0'; + Read_precharge(0) := '0'; + Write_precharge(0) := '0'; + RW_interrupt_write := '0'; + END IF; + END IF; + IF ((Auto_precharge(1) = '1') AND (Write_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(1) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8))) OR + (RW_interrupt_write = '1' AND WR_chk(1) >= 1)) THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + Auto_precharge(1) := '0'; + Read_precharge(1) := '0'; + Write_precharge(1) := '0'; + RW_interrupt_write := '0'; + END IF; + END IF; + + -- Internal Precharge or Bst + IF Command(0) = PRECH THEN + IF Bank_precharge(0) = Bank OR A10_precharge(0) = '1' THEN + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Command(0) = BST THEN + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + + IF Data_out_enable = '0' THEN + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tOH; + END IF; + + -- Detect Read or Write Command + IF Command(0) = READ OR Command(0) = READ_A THEN + Bank := Bank_addr (0); + Col := Col_addr (0); + Col_brst := Col_addr (0); + IF Bank_addr (0) = '0' THEN + Row := B0_row_addr; + ELSE + Row := B1_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '0'; + Data_out_enable := '1'; + ELSIF Command(0) = WRITE OR Command(0) = WRITE_A THEN + Bank := Bank_addr(0); + Col := Col_addr(0); + Col_brst := Col_addr(0); + IF Bank_addr (0) = '0' THEN + Row := B0_row_addr; + ELSE + Row := B1_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '1'; + Data_out_enable := '0'; + END IF; + + -- DQ (Driver / Receiver) + Row_index := TO_INTEGER (Row); + Col_index := TO_INTEGER (Col); + IF Data_in_enable = '1' THEN + IF Dqm /= "11" THEN + Init_mem (Bank, Row_index); + IF Bank = '0' THEN + Dq_temp := Bank0 (Row_index) (Col_index); + IF Dqm = "01" THEN + Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8)); + ELSIF Dqm = "10" THEN + Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0)); + ELSE + Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0)); + END IF; + Bank0 (Row_index) (Col_index) := Dq_temp; + ELSIF Bank = '1' THEN + Dq_temp := Bank1 (Row_index) (Col_index); + IF Dqm = "01" THEN + Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8)); + ELSIF Dqm = "10" THEN + Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0)); + ELSE + Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0)); + END IF; + Bank1 (Row_index) (Col_index) := Dq_temp; + END IF; + WR_chk(TO_INTEGER(Bank)) := 0; + END IF; + Burst_decode; + ELSIF Data_out_enable = '1' THEN + Init_mem (Bank, Row_index); + IF Bank = '0' THEN + Dq_temp (15 DOWNTO 0) := Bank0 (Row_index) (Col_index); + IF Dqm_reg(0) = "00" THEN + Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC; + ELSIF Dqm_reg(0) = "01" THEN + Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + ELSIF Dqm_reg(0) = "10" THEN + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC; + ELSE + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + END IF; + ELSIF Bank = '1' THEN + Dq_temp (15 DOWNTO 0) := Bank1 (Row_index) (Col_index); + IF Dqm_reg(0) = "00" THEN + Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC; + ELSIF Dqm_reg(0) = "01" THEN + Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + ELSIF Dqm_reg(0) = "10" THEN + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC; + ELSE + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + END IF; + END IF; + Burst_decode; + END IF; + + -- Checking internal wires + Pre_chk (0) <= Pc_b0; + Pre_chk (1) <= Pc_b1; + Act_chk (0) <= Act_b0; + Act_chk (1) <= Act_b1; + Dq_in_chk <= Data_in_enable; + Dq_out_chk <= Data_out_enable; + Bank_chk <= Bank; + Row_chk <= Row; + Col_chk <= Col; + END IF; + END PROCESS; + + + -- Clock timing checks + Clock_check : PROCESS + VARIABLE Clk_low, Clk_high : TIME := 0 ns; + BEGIN + WAIT ON Clk; + IF (Clk = '1' AND NOW >= 10 ns) THEN + ASSERT (NOW - Clk_low >= tCL) + REPORT "tCL violation" + SEVERITY WARNING; + ASSERT (NOW - Clk_high >= tCK) + REPORT "tCK violation" + SEVERITY WARNING; + Clk_high := NOW; + ELSIF (Clk = '0' AND NOW /= 0 ns) THEN + ASSERT (NOW - Clk_high >= tCH) + REPORT "tCH violation" + SEVERITY WARNING; + Clk_low := NOW; + END IF; + END PROCESS; + + -- Setup timing checks + Setup_check : PROCESS + BEGIN + WAIT ON Clk; + IF Clk = '1' THEN + ASSERT(Cke'LAST_EVENT >= tCKS) + REPORT "CKE Setup time violation -- tCKS" + SEVERITY WARNING; + ASSERT(Cs_n'LAST_EVENT >= tCMS) + REPORT "CS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT >= tCMS) + REPORT "CAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT >= tCMS) + REPORT "RAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT >= tCMS) + REPORT "WE# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT >= tCMS) + REPORT "Dqm Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Addr'LAST_EVENT >= tAS) + REPORT "ADDR Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT >= tAS) + REPORT "BA Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Dq'LAST_EVENT >= tDS) + REPORT "Dq Setup time violation -- tDS" + SEVERITY WARNING; + END IF; + END PROCESS; + + -- Hold timing checks + Hold_check : PROCESS + BEGIN + WAIT ON Clk'DELAYED (tCKH), Clk'DELAYED (tCMH), Clk'DELAYED (tAH), Clk'DELAYED (tDH); + IF Clk'DELAYED (tCKH) = '1' THEN + ASSERT(Cke'LAST_EVENT > tCKH) + REPORT "CKE Hold time violation -- tCKH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tCMH) = '1' THEN + ASSERT(Cs_n'LAST_EVENT > tCMH) + REPORT "CS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT > tCMH) + REPORT "CAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT > tCMH) + REPORT "RAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT > tCMH) + REPORT "WE# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT > tCMH) + REPORT "Dqm Hold time violation -- tCMH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tAH) = '1' THEN + ASSERT(Addr'LAST_EVENT > tAH) + REPORT "ADDR Hold time violation -- tAH" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT > tAH) + REPORT "BA Hold time violation -- tAH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tDH) = '1' THEN + ASSERT(Dq'LAST_EVENT > tDH) + REPORT "DQ Hold time violation -- tDH" + SEVERITY WARNING; + END IF; + END PROCESS; + +END behave; diff --git a/lib/models/memory/sdram/mt48lc1m16a1/mti_pkg.vhd b/lib/models/memory/sdram/mt48lc1m16a1/mti_pkg.vhd new file mode 100644 index 0000000..58cbbcd --- /dev/null +++ b/lib/models/memory/sdram/mt48lc1m16a1/mti_pkg.vhd @@ -0,0 +1,143 @@ +--***************************************************************************** +-- +-- Micron Semiconductor Products, Inc. +-- +-- Copyright 1997, Micron Semiconductor Products, Inc. +-- All rights reserved. +-- +--***************************************************************************** + +LIBRARY work; +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +PACKAGE mti_pkg IS + + FUNCTION TO_INTEGER (input : BIT) RETURN INTEGER; + FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER; + FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER; + FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER; + PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR); + +END mti_pkg; + +PACKAGE BODY mti_pkg IS + + -- Convert BIT to INTEGER + FUNCTION TO_INTEGER (input : BIT) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + IF input = '1' THEN + result := weight; + ELSE + result := 0; -- if unknowns, default to logic 0 + END IF; + RETURN result; + END TO_INTEGER; + + -- Convert BIT_VECTOR to INTEGER + FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + FOR i IN input'LOW TO input'HIGH LOOP + IF input(i) = '1' THEN + result := result + weight; + ELSE + result := result + 0; -- if unknowns, default to logic 0 + END IF; + weight := weight * 2; + END LOOP; + RETURN result; + END TO_INTEGER; + + -- Convert STD_LOGIC to INTEGER + FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + IF input = '1' THEN + result := weight; + ELSE + result := 0; -- if unknowns, default to logic 0 + END IF; + RETURN result; + END TO_INTEGER; + + -- Convert STD_LOGIC_VECTOR to INTEGER + FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + FOR i IN input'LOW TO input'HIGH LOOP + IF input(i) = '1' THEN + result := result + weight; + ELSE + result := result + 0; -- if unknowns, default to logic 0 + END IF; + weight := weight * 2; + END LOOP; + RETURN result; + END TO_INTEGER; + + -- Conver integer to bit_vector + PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR) IS + VARIABLE work,offset,outputlen,j : INTEGER := 0; + BEGIN + --length of vector + IF output'LENGTH > 32 THEN + outputlen := 32; + offset := output'LENGTH - 32; + IF input >= 0 THEN + FOR i IN offset-1 DOWNTO 0 LOOP + output(output'HIGH - i) := '0'; + END LOOP; + ELSE + FOR i IN offset-1 DOWNTO 0 LOOP + output(output'HIGH - i) := '1'; + END LOOP; + END IF; + ELSE + outputlen := output'LENGTH; + END IF; + --positive value + IF (input >= 0) THEN + work := input; + j := outputlen - 1; + FOR i IN 1 to 32 LOOP + IF j >= 0 then + IF (work MOD 2) = 0 THEN + output(output'HIGH-j-offset) := '0'; + ELSE + output(output'HIGH-j-offset) := '1'; + END IF; + END IF; + work := work / 2; + j := j - 1; + END LOOP; + IF outputlen = 32 THEN + output(output'HIGH) := '0'; + END IF; + --negative value + ELSE + work := (-input) - 1; + j := outputlen - 1; + FOR i IN 1 TO 32 LOOP + IF j>= 0 THEN + IF (work MOD 2) = 0 THEN + output(output'HIGH-j-offset) := '1'; + ELSE + output(output'HIGH-j-offset) := '0'; + END IF; + END IF; + work := work / 2; + j := j - 1; + END LOOP; + IF outputlen = 32 THEN + output(output'HIGH) := '1'; + END IF; + END IF; + END TO_BITVECTOR; + +END mti_pkg; diff --git a/lib/models/memory/sdram/mt48lc1m16a1/readme.txt b/lib/models/memory/sdram/mt48lc1m16a1/readme.txt new file mode 100644 index 0000000..141be5c --- /dev/null +++ b/lib/models/memory/sdram/mt48lc1m16a1/readme.txt @@ -0,0 +1,14 @@ +To operate the test bench for the Micron SDRAM VHDL model, follow the directions +given below: + +1. Be sure all supporting files for the SDRAM are compiled into your library: + + util1164.vhd + stdlogar.vhd + io_utils.vhd + mti_pkg.vhd + +2. Next, compile the mt48lc1m16a1.vhd file and the test.vhd file. + +3. Simulate the "tb" architecture. This is the testbench for the SDRAM. + diff --git a/lib/models/memory/sdram/mt48lc1m16a1/stdlogar.vhd b/lib/models/memory/sdram/mt48lc1m16a1/stdlogar.vhd new file mode 100644 index 0000000..e435ea2 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc1m16a1/stdlogar.vhd @@ -0,0 +1,2247 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990,1991,1992 by Synopsys, Inc. All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_ARITH -- +-- -- +-- Purpose: -- +-- A set of arithemtic, conversion, and comparison functions -- +-- for SIGNED, UNSIGNED, SMALL_INT, INTEGER, -- +-- STD_ULOGIC, STD_LOGIC, and STD_LOGIC_VECTOR. -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +package std_logic_arith is + + type UNSIGNED is array (NATURAL range <>) of STD_LOGIC; + type SIGNED is array (NATURAL range <>) of STD_LOGIC; + subtype SMALL_INT is INTEGER range 0 to 1; + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: INTEGER) return SIGNED; + function "+"(L: INTEGER; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: INTEGER) return SIGNED; + function "-"(L: INTEGER; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "+"(L: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED) return SIGNED; + function "-"(L: SIGNED) return SIGNED; + function "ABS"(L: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED) return STD_LOGIC_VECTOR; + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "*"(L: SIGNED; R: SIGNED) return SIGNED; + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + + function CONV_INTEGER(ARG: INTEGER) return INTEGER; + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER; + function CONV_INTEGER(ARG: SIGNED) return INTEGER; + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT; + + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED; + + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED; + + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + -- zero extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- returns STD_LOGIC_VECTOR(SIZE-1 downto 0) + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + + -- sign extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- return STD_LOGIC_VECTOR(SIZE-1 downto 0) + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end Std_logic_arith; + + + +library IEEE; +use IEEE.std_logic_1164.all; + +package body std_logic_arith is + + function max(L, R: INTEGER) return INTEGER is + begin + if L > R then + return L; + else + return R; + end if; + end; + + + function min(L, R: INTEGER) return INTEGER is + begin + if L < R then + return L; + else + return R; + end if; + end; + + -- synopsys synthesis_off + type tbl_type is array (STD_ULOGIC) of STD_ULOGIC; + constant tbl_BINARY : tbl_type := + ('X', 'X', '0', '1', 'X', 'X', '0', '1', 'X'); + -- synopsys synthesis_on + + -- synopsys synthesis_off + type tbl_mvl9_boolean is array (STD_ULOGIC) of boolean; + constant IS_X : tbl_mvl9_boolean := + (true, true, false, false, true, true, false, false, true); + -- synopsys synthesis_on + + + + function MAKE_BINARY(A : STD_ULOGIC) return STD_ULOGIC is + -- synopsys built_in SYN_FEED_THRU + begin + -- synopsys synthesis_off + if (IS_X(A)) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + return ('X'); + end if; + return tbl_BINARY(A); + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return UNSIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : UNSIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return SIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : SIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return UNSIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : UNSIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return SIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : SIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + + + -- Type propagation function which returns a signed type with the + -- size of the left arg. + function LEFT_SIGNED_ARG(A,B: SIGNED) return SIGNED is + variable Z: SIGNED (A'left downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns an unsigned type with the + -- size of the left arg. + function LEFT_UNSIGNED_ARG(A,B: UNSIGNED) return UNSIGNED is + variable Z: UNSIGNED (A'left downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns a signed type with the + -- size of the result of a signed multiplication + function MULT_SIGNED_ARG(A,B: SIGNED) return SIGNED is + variable Z: SIGNED ((A'length+B'length-1) downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns an unsigned type with the + -- size of the result of a unsigned multiplication + function MULT_UNSIGNED_ARG(A,B: UNSIGNED) return UNSIGNED is + variable Z: UNSIGNED ((A'length+B'length-1) downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + + + function mult(A,B: SIGNED) return SIGNED is + + variable BA: SIGNED((A'length+B'length-1) downto 0); + variable PA: SIGNED((A'length+B'length-1) downto 0); + variable AA: SIGNED(A'length downto 0); + variable neg: STD_ULOGIC; + constant one : UNSIGNED(1 downto 0) := "01"; + + -- pragma map_to_operator MULT_TC_OP + -- pragma type_function MULT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + PA := (others => 'X'); + return(PA); + end if; + PA := (others => '0'); + neg := B(B'left) xor A(A'left); + BA := CONV_SIGNED(('0' & ABS(B)),(A'length+B'length)); + AA := '0' & ABS(A); + for i in 0 to A'length-1 loop + if AA(i) = '1' then + PA := PA+BA; + end if; + BA := SHL(BA,one); + end loop; + if (neg= '1') then + return(-PA); + else + return(PA); + end if; + end; + + function mult(A,B: UNSIGNED) return UNSIGNED is + + variable BA: UNSIGNED((A'length+B'length-1) downto 0); + variable PA: UNSIGNED((A'length+B'length-1) downto 0); + constant one : UNSIGNED(1 downto 0) := "01"; + + -- pragma map_to_operator MULT_UNS_OP + -- pragma type_function MULT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + PA := (others => 'X'); + return(PA); + end if; + PA := (others => '0'); + BA := CONV_UNSIGNED(B,(A'length+B'length)); + for i in 0 to A'length-1 loop + if A(i) = '1' then + PA := PA+BA; + end if; + BA := SHL(BA,one); + end loop; + return(PA); + end; + + -- subtract two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function minus(A, B: SIGNED) return SIGNED is + variable carry: STD_ULOGIC; + variable BV: STD_ULOGIC_VECTOR (A'left downto 0); + variable sum: SIGNED (A'left downto 0); + + -- pragma map_to_operator SUB_TC_OP + + -- pragma type_function LEFT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '1'; + BV := not STD_ULOGIC_VECTOR(B); + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + -- add two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function plus(A, B: SIGNED) return SIGNED is + variable carry: STD_ULOGIC; + variable BV, sum: SIGNED (A'left downto 0); + + -- pragma map_to_operator ADD_TC_OP + -- pragma type_function LEFT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '0'; + BV := B; + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + + -- subtract two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_minus(A, B: UNSIGNED) return UNSIGNED is + variable carry: STD_ULOGIC; + variable BV: STD_ULOGIC_VECTOR (A'left downto 0); + variable sum: UNSIGNED (A'left downto 0); + + -- pragma map_to_operator SUB_UNS_OP + -- pragma type_function LEFT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '1'; + BV := not STD_ULOGIC_VECTOR(B); + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + -- add two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_plus(A, B: UNSIGNED) return UNSIGNED is + variable carry: STD_ULOGIC; + variable BV, sum: UNSIGNED (A'left downto 0); + + -- pragma map_to_operator ADD_UNS_OP + -- pragma type_function LEFT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '0'; + BV := B; + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + + + function "*"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to mult + begin + return mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to mult + begin + return mult(CONV_UNSIGNED(L, L'length), + CONV_UNSIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + begin + return mult(CONV_SIGNED(L, L'length+1), + CONV_SIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to plus + begin + return mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length+1)); -- pragma label mult + end; + + + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + begin + return STD_LOGIC_VECTOR (mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length))); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + begin + return STD_LOGIC_VECTOR (mult(CONV_UNSIGNED(L, L'length), + CONV_UNSIGNED(R, R'length))); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + begin + return STD_LOGIC_VECTOR (mult(CONV_SIGNED(L, L'length+1), + CONV_SIGNED(R, R'length))); -- pragma label mult + end; + + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + begin + return STD_LOGIC_VECTOR (mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length+1))); -- pragma label mult + end; + + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "+"(L: SIGNED; R: INTEGER) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: INTEGER; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)) ; -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))) ; -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_minus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: SIGNED; R: INTEGER) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: INTEGER; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (unsigned_minus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + + + function "+"(L: UNSIGNED) return UNSIGNED is + begin + return L; + end; + + + function "+"(L: SIGNED) return SIGNED is + begin + return L; + end; + + + function "-"(L: SIGNED) return SIGNED is + -- pragma label_applies_to minus + begin + return 0 - L; -- pragma label minus + end; + + + function "ABS"(L: SIGNED) return SIGNED is + begin + if (L(L'left) = '0' or L(L'left) = 'L') then + return L; + else + return 0 - L; + end if; + end; + + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L); + end; + + + function "+"(L: SIGNED) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L); + end; + + + function "-"(L: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable tmp: SIGNED(L'length-1 downto 0); + begin + tmp := 0 - L; -- pragma label minus + return STD_LOGIC_VECTOR (tmp); + end; + + + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR is + variable tmp: SIGNED(L'length-1 downto 0); + begin + if (L(L'left) = '0' or L(L'left) = 'L') then + return STD_LOGIC_VECTOR (L); + else + tmp := 0 - L; + return STD_LOGIC_VECTOR (tmp); + end if; + end; + + + -- Type propagation function which returns the type BOOLEAN + function UNSIGNED_RETURN_BOOLEAN(A,B: UNSIGNED) return BOOLEAN is + variable Z: BOOLEAN; + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns the type BOOLEAN + function SIGNED_RETURN_BOOLEAN(A,B: SIGNED) return BOOLEAN is + variable Z: BOOLEAN; + -- pragma return_port_name Z + begin + return(Z); + end; + + + -- compare two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function is_less(A, B: SIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LT_TC_OP + -- pragma type_function SIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + if A(sign) /= B(sign) then + result := A(sign) = '1'; + else + result := FALSE; + for i in 0 to sign-1 loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + end if; + return result; + end; + + + -- compare two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function is_less_or_equal(A, B: SIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LEQ_TC_OP + -- pragma type_function SIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + if A(sign) /= B(sign) then + result := A(sign) = '1'; + else + result := TRUE; + for i in 0 to sign-1 loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + end if; + return result; + end; + + + + -- compare two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_is_less(A, B: UNSIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LT_UNS_OP + -- pragma type_function UNSIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + result := FALSE; + for i in 0 to sign loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + return result; + end; + + + -- compare two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_is_less_or_equal(A, B: UNSIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LEQ_UNS_OP + -- pragma type_function UNSIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + result := TRUE; + for i in 0 to sign loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + return result; + end; + + + + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length, R'length); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := L'length + 1; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := R'length + 1; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := L'length; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := R'length; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less_or_equal(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length, R'length); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := L'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := R'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := L'length; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := R'length; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less(CONV_UNSIGNED(R, length), + CONV_UNSIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length, R'length); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := L'length + 1; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := R'length + 1; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := L'length; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := R'length; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less_or_equal(CONV_UNSIGNED(R, length), + CONV_UNSIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length, R'length); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := L'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := R'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := L'length; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := R'length; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + + + -- for internal use only. Assumes SIGNED arguments of equal length. + function bitwise_eql(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) + return BOOLEAN is + -- pragma built_in SYN_EQL + begin + for i in L'range loop + if L(i) /= R(i) then + return FALSE; + end if; + end loop; + return TRUE; + end; + + -- for internal use only. Assumes SIGNED arguments of equal length. + function bitwise_neq(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) + return BOOLEAN is + -- pragma built_in SYN_NEQ + begin + for i in L'range loop + if L(i) /= R(i) then + return TRUE; + end if; + end loop; + return FALSE; + end; + + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_UNSIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_UNSIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length + 1, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length + 1); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length + 1; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := R'length + 1; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: INTEGER; R: SIGNED) return BOOLEAN is + constant length: INTEGER := R'length; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_UNSIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_UNSIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length + 1, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length + 1); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length + 1; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := R'length + 1; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN is + constant length: INTEGER := R'length; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is UNSIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb downto 2**i) := + result(result_msb - 2**i downto 0); + end if; + result := temp; + end if; + end loop; + return result; + end; + + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is SIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb downto 2**i) := + result(result_msb - 2**i downto 0); + end if; + result := temp; + end if; + end loop; + return result; + end; + + + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is UNSIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb - 2**i downto 0) := + result(result_msb downto 2**i); + end if; + result := temp; + end if; + end loop; + return result; + end; + + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is SIGNED (result_msb downto 0); + variable result, temp: rtype; + variable sign_bit: STD_ULOGIC; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + sign_bit := ARG(ARG'left); + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => sign_bit); + if 2**i <= result_msb then + temp(result_msb - 2**i downto 0) := + result(result_msb downto 2**i); + end if; + result := temp; + end if; + end loop; + return result; + end; + + + + + function CONV_INTEGER(ARG: INTEGER) return INTEGER is + begin + return ARG; + end; + + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER is + variable result: INTEGER; + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_UNSIGNED_TO_INTEGER + begin + -- synopsys synthesis_off + assert ARG'length <= 31 + report "ARG is too large in CONV_INTEGER" + severity FAILURE; + result := 0; + for i in ARG'range loop + result := result * 2; + tmp := tbl_BINARY(ARG(i)); + if tmp = '1' then + result := result + 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_INTEGER(ARG: SIGNED) return INTEGER is + variable result: INTEGER; + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_SIGNED_TO_INTEGER + begin + -- synopsys synthesis_off + assert ARG'length <= 32 + report "ARG is too large in CONV_INTEGER" + severity FAILURE; + result := 0; + for i in ARG'range loop + if i /= ARG'left then + result := result * 2; + tmp := tbl_BINARY(ARG(i)); + if tmp = '1' then + result := result + 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + end if; + end if; + end loop; + tmp := MAKE_BINARY(ARG(ARG'left)); + if tmp = '1' then + if ARG'length = 32 then + result := (result - 2**30) - 2**30; + else + result := result - (2 ** (ARG'length-1)); + end if; + end if; + return result; + -- synopsys synthesis_on + end; + + + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT is + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_FEED_THRU + begin + -- synopsys synthesis_off + tmp := tbl_BINARY(ARG); + if tmp = '1' then + return 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + return 0; + else + return 0; + end if; + -- synopsys synthesis_on + end; + + + -- convert an integer to a unsigned STD_ULOGIC_VECTOR + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED is + variable result: UNSIGNED(SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_UNSIGNED + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable new_bounds: UNSIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable new_bounds: UNSIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED is + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + + -- convert an integer to a 2's complement STD_ULOGIC_VECTOR + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED is + variable result: SIGNED (SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_SIGNED + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is SIGNED (SIZE-1 downto 0); + variable new_bounds : SIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is SIGNED (SIZE-1 downto 0); + variable new_bounds : SIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED is + subtype rtype is SIGNED (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + + -- convert an integer to an STD_LOGIC_VECTOR + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR is + variable result: STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_SIGNED + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) return STD_LOGIC_VECTOR is + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) + return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds: STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + +end std_logic_arith; diff --git a/lib/models/memory/sdram/mt48lc1m16a1/test.txt b/lib/models/memory/sdram/mt48lc1m16a1/test.txt new file mode 100644 index 0000000..75ed4c6 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc1m16a1/test.txt @@ -0,0 +1,69 @@ +0 ns 1 1 1 1 1 00 0 0 -100 +22 ns 1 1 1 1 1 00 0 0 -100 +32 ns 1 1 1 1 1 00 0 0 -100 +42 ns 1 1 1 1 1 00 0 0 -100 +52 ns 1 1 1 1 1 00 0 0 -100 +62 ns 1 1 1 1 1 00 0 0 -100 +72 ns 1 0 0 1 0 00 0 1024 -100 +82 ns 1 1 1 1 1 00 0 0 -100 +92 ns 1 1 1 1 1 00 0 0 -100 +102 ns 1 0 0 0 1 00 0 0 -100 +112 ns 1 1 1 1 1 00 0 0 -100 +122 ns 1 1 1 1 1 00 0 0 -100 +132 ns 1 1 1 1 1 00 0 0 -100 +142 ns 1 1 1 1 1 00 0 0 -100 +152 ns 1 1 1 1 1 00 0 0 -100 +162 ns 1 1 1 1 1 00 0 0 -100 +172 ns 1 1 1 1 1 00 0 0 -100 +182 ns 1 1 1 1 1 00 0 0 -100 +192 ns 1 0 0 0 1 00 0 0 -100 +202 ns 1 1 1 1 1 00 0 0 -100 +212 ns 1 1 1 1 1 00 0 0 -100 +222 ns 1 1 1 1 1 00 0 0 -100 +232 ns 1 1 1 1 1 00 0 0 -100 +242 ns 1 1 1 1 1 00 0 0 -100 +252 ns 1 1 1 1 1 00 0 0 -100 +262 ns 1 1 1 1 1 00 0 0 -100 +272 ns 1 1 1 1 1 00 0 0 -100 +282 ns 1 0 0 0 0 00 0 51 -100 +292 ns 1 1 1 1 1 00 0 0 -100 +302 ns 1 1 1 1 1 00 0 0 -100 +312 ns 1 0 0 1 1 00 0 0 -100 +322 ns 1 1 1 1 1 00 0 0 -100 +332 ns 1 1 1 1 1 00 0 0 -100 +342 ns 1 0 1 0 0 00 0 1024 100 +352 ns 1 1 1 1 1 00 0 0 101 +362 ns 1 1 1 1 1 00 0 0 102 +372 ns 1 1 1 1 1 00 0 0 103 +382 ns 1 1 1 1 1 00 0 0 104 +392 ns 1 0 0 1 1 00 1 0 105 +402 ns 1 1 1 1 1 00 0 0 106 +412 ns 1 1 1 1 1 00 0 0 107 +422 ns 1 0 1 0 0 00 1 1024 200 +432 ns 1 1 1 1 1 00 0 0 201 +442 ns 1 1 1 1 1 00 0 0 202 +452 ns 1 1 1 1 1 00 0 0 203 +462 ns 1 1 1 1 1 00 0 0 204 +472 ns 1 0 0 1 1 00 0 0 205 +482 ns 1 1 1 1 1 00 0 0 206 +492 ns 1 1 1 1 1 00 0 0 207 +502 ns 1 0 1 0 1 00 0 1024 -100 +512 ns 1 1 1 1 1 00 0 0 -100 +522 ns 1 1 1 1 1 00 0 0 -100 +532 ns 1 1 1 1 1 00 0 0 -100 +542 ns 1 1 1 1 1 00 0 0 -100 +552 ns 1 0 0 1 1 00 1 0 -100 +562 ns 1 1 1 1 1 00 0 0 -100 +572 ns 1 1 1 1 1 00 0 0 -100 +582 ns 1 0 1 0 1 00 1 1024 -100 +592 ns 1 1 1 1 1 00 0 0 -100 +602 ns 1 1 1 1 1 00 0 0 -100 +612 ns 1 1 1 1 1 00 0 0 -100 +622 ns 1 1 1 1 1 00 0 0 -100 +632 ns 1 1 1 1 1 00 0 0 -100 +642 ns 1 1 1 1 1 00 0 0 -100 +652 ns 1 1 1 1 1 00 0 0 -100 +662 ns 1 1 1 1 1 00 0 0 -100 +672 ns 1 1 1 1 1 00 0 0 -100 +682 ns 1 1 1 1 1 00 0 0 -100 +692 ns 1 1 1 1 1 00 0 0 -100 diff --git a/lib/models/memory/sdram/mt48lc1m16a1/test.vhd b/lib/models/memory/sdram/mt48lc1m16a1/test.vhd new file mode 100644 index 0000000..53a8a7a --- /dev/null +++ b/lib/models/memory/sdram/mt48lc1m16a1/test.vhd @@ -0,0 +1,168 @@ +LIBRARY ieee; +LIBRARY work; +USE ieee.std_logic_1164.ALL; +USE work.std_logic_arith.ALL; +USE work.util_1164.ALL; +USE std.textio.ALL; +USE work.mti_pkg.ALL; + +ENTITY tb IS +END tb; + + +ARCHITECTURE test OF tb IS + CONSTANT addr_bits : INTEGER := 11; + CONSTANT clk_start : time := 5 ns; + CONSTANT clk_period : time := 10 ns; + CONSTANT continue_time : time := 10 ns; + CONSTANT data_bits : INTEGER := 16; + + COMPONENT mt48lc1m16a1 + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC := '0'; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '0'; + Cs_n : IN STD_LOGIC := '1'; + Cas_n : IN STD_LOGIC := '0'; + Ras_n : IN STD_LOGIC := '0'; + We_n : IN STD_LOGIC := '0'; + Dqm : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := "00" + ); + END COMPONENT; + + FOR ALL : mt48lc1m16a1 USE ENTITY work.mt48lc1m16a1 (behave); + + SIGNAL pDq : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0); + SIGNAL pAddr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + SIGNAL pBa : STD_LOGIC; + SIGNAL pClk : STD_LOGIC; + SIGNAL pCke : STD_LOGIC; + SIGNAL pCs : STD_LOGIC; + SIGNAL pCas : STD_LOGIC; + SIGNAL pRas : STD_LOGIC; + SIGNAL pWe : STD_LOGIC; + SIGNAL pDqm : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL stim_done : boolean := false; + SIGNAL clk_done : boolean := false; + +BEGIN + u1: mt48lc1m16a1 + PORT MAP( + Dq => pDq, + Addr => pAddr, + Ba => pBa, + Clk => pClk, + Cke => pCke, + Cs_n => pCs, + Ras_n => pRas, + Cas_n => pCas, + We_n => pWe, + Dqm => pDqm + ); + + stimulator : PROCESS + FILE stim_file:text IS IN "test.txt"; + VARIABLE l : line; + VARIABLE time_var : TIME; + VARIABLE pCke_var : STD_LOGIC; + VARIABLE pCs_var : STD_LOGIC; + VARIABLE pRas_var : STD_LOGIC; + VARIABLE PCas_var : STD_LOGIC; + VARIABLE pWe_var : STD_LOGIC; + VARIABLE pDqm_var : STD_LOGIC_VECTOR (1 DOWNTO 0); + VARIABLE pBa_var : STD_LOGIC; + VARIABLE pAddr_var : INTEGER; + VARIABLE pDq_var : INTEGER; -- -100 is converted to hi-Z state + VARIABLE pMa_var_vect : STD_LOGIC_VECTOR(addr_bits - 1 DOWNTO 0); + CONSTANT HiZ : STD_LOGIC_VECTOR(data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + BEGIN + WHILE not ENDFILE(stim_file) LOOP + readline(stim_file,l); + IF l'length > 0 THEN + read(l, time_var); + read(l, pCke_var); + read(l, pCs_var); + read(l, pRas_var); + read(l, pCas_var); + read(l, pWe_var); + read(l, pDqm_var); + read(l, pBa_var); + read(l, pAddr_var); + read(l, pDq_var); + IF now > time_var THEN + ASSERT false + REPORT "Detected a time in the stim file that is in the past" + SEVERITY error; + ELSE + WAIT FOR time_var-now; + IF pWe_var='1' THEN + pCke <= pCke_var; + pCs <= pCs_var; + pRas <= pRas_var; + pCas <= pCas_var; + pWe <= pWe_var; + pDqm <= pDqm_var; + pBa <= pBa_var; + pMa_var_vect := CONV_STD_LOGIC_VECTOR(pAddr_var, addr_bits); + pAddr <= pMa_var_vect; + IF pDq_var = -100 THEN + pDq <= HiZ; + ELSE + pDq <= CONV_STD_LOGIC_VECTOR(pDq_var, data_bits); + END IF; + ELSE + pCke <= pCke_var; + pCs <= pCs_var; + pRas <= pRas_var; + pCas <= pCas_var; + pWe <= pWe_var; + pDqm <= pDqm_var; + pBa <= pBa_var; + pMa_var_vect := CONV_STD_LOGIC_VECTOR(pAddr_var, addr_bits); + pAddr <= pMa_var_vect; + IF pDq_var = -100 THEN + pDq <= HiZ; + ELSE + pDq <= CONV_STD_LOGIC_VECTOR(pDq_var, data_bits); + END IF; + END IF; + END IF; + END IF; + END LOOP; + ASSERT false + REPORT "End of Stimulation File Detected!" + SEVERITY note; + stim_done <= true; + WAIT; + END PROCESS; + + clock : PROCESS + VARIABLE done_time : time; + BEGIN + pclk <= '0'; + WAIT for clk_start; + WHILE not stim_done loop + pclk <= '1'; + WAIT for clk_period/2; + pclk <= '0'; + WAIT for clk_period/2; + END LOOP; + done_time := now+continue_time; + WHILE now < done_time LOOP --one last clock to finish last command + pclk <= '1'; + WAIT for clk_period/2; + pclk <= '0'; + WAIT for clk_period/2; + END LOOP; + ASSERT false + REPORT "Suspending clock activity" + SEVERITY note; + clk_done <= true; + WAIT; + END PROCESS; + +END test; + + diff --git a/lib/models/memory/sdram/mt48lc1m16a1/util1164.vhd b/lib/models/memory/sdram/mt48lc1m16a1/util1164.vhd new file mode 100644 index 0000000..bb4b5dd --- /dev/null +++ b/lib/models/memory/sdram/mt48lc1m16a1/util1164.vhd @@ -0,0 +1,124 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE STD.textio.ALL; + +PACKAGE util_1164 IS + PROCEDURE read(l: INOUT line; value: OUT std_logic); + PROCEDURE read(l: INOUT line; value: OUT std_logic_vector); + PROCEDURE write(l: INOUT line; value: IN std_logic_vector; + JUSTIFIED: IN SIDE := right; + FIELD: IN WIDTH := 0); + PROCEDURE Grow_line(L : inout LINE; incr : in integer); +END util_1164; + + + +PACKAGE BODY util_1164 IS + + FUNCTION white_space(value:character) RETURN boolean IS + VARIABLE result:boolean; + BEGIN + IF (value = ' ') OR (value = HT) THEN + RETURN true; + ELSE + RETURN false; + END IF; + END white_space; + + PROCEDURE read(l: INOUT line; value: OUT std_logic) IS + VARIABLE char_var: character:= ' '; + BEGIN + WHILE l'LENGTH > 0 LOOP + read(l,char_var); + IF NOT white_space(char_var) THEN + EXIT; + END IF; + END LOOP; + IF white_space(char_var) THEN + ASSERT false REPORT "No std_logic value found in file" + SEVERITY error; + value := 'X'; + RETURN; + END IF; + + CASE char_var IS + WHEN 'U'|'u' => value := 'U'; + WHEN '0' => value := '0'; + WHEN '1' => value := '1'; + WHEN 'X'|'x' => value := 'X'; + WHEN 'L'|'l' => value := 'L'; + WHEN 'H'|'h' => value := 'H'; + WHEN 'W'|'w' => value := 'W'; + WHEN 'Z'|'z' => value := 'Z'; + WHEN '-' => value := '-'; + WHEN OTHERS => + ASSERT false REPORT "Unrecognized value read for std_logic" + SEVERITY error; + value := 'X'; + END CASE; + END read; + + PROCEDURE read(l: INOUT line; value: OUT std_logic_vector) IS + BEGIN + FOR i IN value'HIGH DOWNTO value'LOW LOOP + IF l'LENGTH > 0 THEN + read(l,value(i)); + ELSE + ASSERT false REPORT "Not enough values for std_logic_vector in file" + SEVERITY error; + RETURN; + END IF; + END LOOP; + END read; + + procedure Grow_line(L : inout LINE; incr : in integer) + is + variable old_L : LINE := L; + variable bfp: integer; -- Blank fill pointer. + begin + assert incr > 0 + report "Textio: Grow_line called with zero increment." + severity error; + + if L = null then + bfp := 0; + L := new string(1 to incr); + else + bfp := old_L'high; + L := new string(old_L'low to old_L'high + incr); + L(old_L'low to old_L'high) := old_L.all; + Deallocate(old_L); + end if; + for i in 1 to incr loop + L(bfp + i) := ' '; + end loop; + end; + + + PROCEDURE write(l: INOUT line; value: IN std_logic_vector; + JUSTIFIED: IN SIDE := right; + FIELD: IN WIDTH := 0) IS + variable fw: integer := VALUE'length; + variable bp: integer; + variable offset: integer := 0; + alias normal : std_logic_vector(0 to value'length - 1) is value; + begin + if L /= null then + bp := L'high + 1; + else bp := 1; + end if; + if FIELD > VALUE'length then + fw := FIELD; + if JUSTIFIED = right then + offset := fw - VALUE'length; + end if; + end if; + Grow_line(L, fw); + for i in normal'range loop + L(bp + i + offset) := character'val( + std_logic'pos(normal(i)) + character'pos('0')); + end loop; + end; + + +END util_1164; diff --git a/lib/models/memory/sdram/mt48lc1m16a1/vec_gen.vhd b/lib/models/memory/sdram/mt48lc1m16a1/vec_gen.vhd new file mode 100644 index 0000000..784fe26 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc1m16a1/vec_gen.vhd @@ -0,0 +1,369 @@ +------------------------------------------------------------------------------- +-- -- +-- This is a data generator for the testbench for Micron's Synchronous -- +-- DRAM. This generator reads a text file line-by-line and generates -- +-- a file of test vectors that is then read by the testbench and -- +-- applied to the part. -- +-- -- +-- This VHDL program creates a text file of test vectors that is used by the -- +-- test bench. Place your commands in a file (a copy of VEC_GEN.VHD) and run -- +-- VEC_GEN.VHD in your VHDL simulator (make sure you have compiled this -- +-- package prior to running the program VEC_GEN.VHD). This will produce the -- +-- vectors that are required to run the included testbench. Change the name -- +-- of the vector file to save your vectors in separate files. The default -- +-- file name for the output vectors generated from this pacakage is -- +-- "test.txt." -- +-- -- +-- Now compile and run the testbench program embedtb.vhd. The testbench uses -- +-- the default test.txt as input vectors. -- +-- -- +-- -- +-- Copyright 1997 Micron Technology, Inc. -- +-- -- +------------------------------------------------------------------------------- + +LIBRARY work; +LIBRARY ieee; +USE ieee.std_logic_1164.all; +USE std.textio.all; +USE work.io_utils.all; + + +PACKAGE generate_vectors IS + + CONSTANT set_up : TIME; + CONSTANT hold : TIME; + CONSTANT cycle_start : TIME; + + SIGNAL cycle : INTEGER := 0; + SIGNAL sim_time : TIME := 0 ns; + FILE output_file:TEXT IS OUT "test.txt"; + PROCEDURE write(col_address : IN INTEGER; bank : IN BIT; + first_data : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE read(col_address : IN INTEGER; bank : IN BIT; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE active(row_address : IN INTEGER; bank : IN BIT; data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE precharge(bank : IN BIT; address : IN INTEGER; data_bus: IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE nop(data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT; cs : IN BIT); + PROCEDURE burst_term(data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE auto_refresh; + PROCEDURE next_cycle(SIGNAL clk : IN BIT); + PROCEDURE load_array(load : IN BIT); + PROCEDURE load_mode_reg(op_code : IN INTEGER; cke : IN BIT); + PROCEDURE unload_array(row_start : IN INTEGER; row_end : IN INTEGER; bank : IN BIT); + +END generate_vectors; + + +PACKAGE BODY generate_vectors IS + + CONSTANT set_up : TIME := 3 ns; + CONSTANT hold : TIME := 1 ns; + CONSTANT cycle_start : TIME := 0 ns; + + +PROCEDURE write(col_address : IN INTEGER; bank : IN BIT; first_data : IN INTEGER; + dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 0, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, first_data, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE read(col_address : IN INTEGER; bank : IN BIT; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 0, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, -100, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE active(row_address : IN INTEGER; bank : IN BIT; data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 0, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, row_address, right, 6); --address +write(l, data_bus, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE precharge(bank : IN BIT; address : IN INTEGER; data_bus: IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 0, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, address, right, 6); --address +write(l, data_bus, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE nop(data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT; cs : IN BIT) IS + + +VARIABLE l : LINE; +VARIABLE col_address : INTEGER := 0; +VARIABLE bank : BIT := '0'; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, cke, right, 4); --Cke +write(l, cs, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, data_bus, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + + +PROCEDURE burst_term(data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; +VARIABLE col_address : INTEGER := 0; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, 0, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, data_bus, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE auto_refresh IS + VARIABLE l : LINE; + VARIABLE dqm : BIT_VECTOR(1 DOWNTO 0) := "00"; +BEGIN + IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); + ELSE + write(l, now-set_up, left, 4, ns); + END IF; + write(l, 1, right, 4); --Cke + write(l, 0, right, 4); --Cs + write(l, 0, right, 4); --Ras + write(l, 0, right, 4); --Cas + write(l, 1, right, 4); --We + write(l, dqm, right, 4); --Dqm + write(l, 0, right, 4); --Ba + write(l, 0, right, 6); --address + write(l, -100, right, 6); --first data location + --write(l, 0, right, 4); --load + --write(l, 0, right, 4); --unload + --write(l, 0, right, 6); --row_address_start + --write(l, 0, right, 6); --row_address_end + writeline(output_file,l); --write vector to file +END; + + +PROCEDURE next_cycle(SIGNAL clk : IN BIT) IS + +BEGIN + +WAIT UNTIL clk = '1'; + +END; + +PROCEDURE load_array(load : IN BIT) IS + +VARIABLE l : LINE; +VARIABLE dqm : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, 1, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, 0, right, 4); --Ba +write(l, 0, right, 6); --address +write(l, -100, right, 6); --first data location +--write(l, 1, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE unload_array(row_start : IN INTEGER; row_end : IN INTEGER; bank : IN BIT) IS + +VARIABLE l : LINE; +VARIABLE dqm : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, 1, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, 0, right, 6); --address +write(l, -100, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 1, right, 4); --unload +--write(l, row_start, right, 6); --row_address_start +--write(l, row_end, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE load_mode_reg(op_code : IN INTEGER; cke : IN BIT) IS + +VARIABLE l : LINE; +VARIABLE dqm : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 0, right, 4); --Ras +write(l, 0, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, 0, right, 4); --Ba +write(l, op_code, right, 6); --address +write(l, -100, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +END generate_vectors; + diff --git a/lib/models/memory/sdram/mt48lc32m4a2/base.do b/lib/models/memory/sdram/mt48lc32m4a2/base.do new file mode 100644 index 0000000..d2afbcb --- /dev/null +++ b/lib/models/memory/sdram/mt48lc32m4a2/base.do @@ -0,0 +1,5 @@ +vcom util1164.vhd +vcom stdlogar.vhd +vcom io_utils.vhd +vcom mti_pkg.vhd + diff --git a/lib/models/memory/sdram/mt48lc32m4a2/ed_comnd.vhd b/lib/models/memory/sdram/mt48lc32m4a2/ed_comnd.vhd new file mode 100644 index 0000000..bd59d3c --- /dev/null +++ b/lib/models/memory/sdram/mt48lc32m4a2/ed_comnd.vhd @@ -0,0 +1,345 @@ +--------------------------------------------------------------------------------- +--COMMAND FORMAT -- +-- -- +-- write(column address(integer), bank(bit_vector), first data(integer), dqm(bit), cke(bit));-- +-- read(column address(integer), bank(bit_vector), dqm(bit), cke(bit)); -- +-- active(row address(integer), bank(bit_vector), data bus (integer), dqm(bit), cke(bit));-- +-- precharge(bank(bit_vector), address (integer), data bus(integer), dqm(bit), cke(bit)); -- +-- nop(data bus(integer), dqm(bit), cke(bit), cs(bit)); -- +-- burst_term(data bus(integer), dqm(bit), cke(bit)); -- +-- load_array('1'); -- +-- load_mode_reg(register(integer), cke(bit)); -- +-- next_cycle(clk); This is used after every command(incl. nop) to clock -- +-- at the correct clock frequency entered in the clock -- +-- period constant below -- +-- unload_array(row_start(integer), row_end(integer), bank(bit_vector)) -- +-- load_mode_reg(op_code(integer)) -- +-- -- +--------------------------------------------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.all; +USE std.textio.all; +USE work.generate_vectors.all; + +ENTITY vector_generate IS +END vector_generate; + +ARCHITECTURE vector_generate OF vector_generate IS + + SIGNAL stim_done : BOOLEAN := FALSE; + SIGNAL clk : BIT := '0'; + CONSTANT clk_start : time := 15 ns; + CONSTANT clk_period : time := 10 ns; + CONSTANT Z : INTEGER := -100; + +BEGIN + +PROCESS + +BEGIN + +WAIT UNTIL clk = '1' AND clk'EVENT; + +--------------------ENTER COMMANDS BELOW THIS LINE----------------------------- +--******************DO NOT USE -100 FOR A DQ VALUE*************************---- +--*******************Z WILL PLACE HI-Z ON THE BUS**************************---- +--*******USE next_cycle(clk) FOR ADVANCING TO NEXT CLOCK CYCLE*************---- + +nop(Z, '0', '1', '1'); --Always begin with one nop when using Micron's testbench + +--next_cycle(clk); +--load_array('1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +precharge("00", 1024, Z, '0', '1'); + +FOR i IN 1 to 2 LOOP + next_cycle(clk); + nop(Z, '0', '1', '1'); +END LOOP; + +next_cycle(clk); +auto_refresh; + +FOR i IN 1 TO 8 LOOP + next_cycle(clk); + nop(Z, '0', '1', '1'); +END LOOP; + +next_cycle(clk); +auto_refresh; + +FOR i IN 1 TO 8 LOOP + next_cycle(clk); + nop(Z, '0', '1', '1'); +END LOOP; + +next_cycle(clk); +load_mode_reg(51, '1'); -- 19 / 35 / 51 -> lat=3,bl=8,mode=seq + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +-- Write Section + +next_cycle(clk); +active(0, "00", Z, '0', '1'); -- Activate Bank 0 + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); -- Write Bank 0 +write(10, "00", 0, '0', '1'); + +next_cycle(clk); +nop(1, '0', '1', '1'); + +next_cycle(clk); +active(0, "01", 2, '0', '1'); -- Activate Bank 1 + +next_cycle(clk); +nop(3, '0', '1', '1'); + +next_cycle(clk); +nop(4, '0', '1', '1'); + +next_cycle(clk); +nop(5, '0', '1', '1'); + +next_cycle(clk); +nop(6, '0', '1', '1'); + +next_cycle(clk); +nop(7, '0', '1', '1'); + +next_cycle(clk); +write(20, "01", 8, '0', '1'); -- Write Bank 1 + +next_cycle(clk); +precharge("00", 0, 9, '0', '1'); -- Precharge Bank 0 + +next_cycle(clk); +active(0, "10", 10, '0', '1'); -- Activate Bank 2 + +next_cycle(clk); +nop(11, '0', '1', '1'); + +next_cycle(clk); +nop(12, '0', '1', '1'); + +next_cycle(clk); +nop(13, '0', '1', '1'); + +next_cycle(clk); +nop(14, '0', '1', '1'); + +next_cycle(clk); +nop(15, '0', '1', '1'); + +next_cycle(clk); +write(30, "10", 0, '0', '1'); -- Write Bank 2 + +next_cycle(clk); +precharge("01", 0, 1, '0', '1'); -- Precharge Bank 1 + +next_cycle(clk); +active(0, "11", 2, '0', '1'); -- Activate Bank 3 + +next_cycle(clk); +nop(3, '0', '1', '1'); + +next_cycle(clk); +nop(4, '0', '1', '1'); + +next_cycle(clk); +nop(5, '0', '1', '1'); + +next_cycle(clk); +nop(6, '0', '1', '1'); + +next_cycle(clk); +nop(7, '0', '1', '1'); + +next_cycle(clk); +write(40, "11", 8, '0', '1'); -- Write Bank 3 + +next_cycle(clk); +precharge("10", 0, 9, '0', '1'); -- Precharge Bank 2 + +next_cycle(clk); +active(0, "00", 10, '0', '1'); -- Activate Bank 0 + +next_cycle(clk); +nop(11, '0', '1', '1'); + +next_cycle(clk); +nop(12, '0', '1', '1'); + +next_cycle(clk); +nop(13, '0', '1', '1'); + +next_cycle(clk); +nop(14, '0', '1', '1'); + +next_cycle(clk); +nop(15, '0', '1', '1'); + +-- Read Section + +next_cycle(clk); +read(10, "00", '0', '1'); -- Read Bank 0 + +next_cycle(clk); +precharge("11", 0, Z, '0', '1'); -- Precharge Bank 3 + +next_cycle(clk); +active(0, "01", Z, '0', '1'); -- Activate Bank 1 + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +read(20, "01", '0', '1'); -- Read Bank 1 + +next_cycle(clk); +precharge("00", 0, Z, '0', '1'); -- Precharge Bank 0 + +next_cycle(clk); +active(0, "10", Z, '0', '1'); -- Activate Bank 2 + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +read(30, "10", '0', '1'); -- Read Bank 2 + +next_cycle(clk); +precharge("01", 0, Z, '0', '1'); -- Precharge Bank 1 + +next_cycle(clk); +active(0, "11", Z, '0', '1'); -- Activate Bank 3 + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +read(40, "11", '0', '1'); -- Read Bank 3 + +next_cycle(clk); +precharge("10", 0, Z, '0', '1'); -- Precharge Bank 2 + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +precharge("11", 0, Z, '0', '1'); -- Precharge Bank 3 + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +--next_cycle(clk); +--unload_array(0, 0, '0'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +stim_done <= TRUE; --always include this line at the end of your stimulus + +------------------------------------------------------------------------------- +--*************************************************************************---- +END PROCESS; + + +clock: + PROCESS + VARIABLE done_time : time; + VARIABLE cycle_var : integer := 0; + BEGIN + cycle <= 0; + clk <= '0'; + WAIT for clk_start; + WHILE not stim_done loop + clk <= '1'; + cycle <= cycle_var; + WAIT for clk_period/2; + cycle_var := cycle_var + 1; + clk <= '0'; + WAIT for clk_period/2; + END LOOP; + + ASSERT (FALSE) + REPORT "Test Vectors Generated" + SEVERITY note; + + WAIT; + END PROCESS; + + +END; diff --git a/lib/models/memory/sdram/mt48lc32m4a2/io_utils.vhd b/lib/models/memory/sdram/mt48lc32m4a2/io_utils.vhd new file mode 100644 index 0000000..dfcb84a --- /dev/null +++ b/lib/models/memory/sdram/mt48lc32m4a2/io_utils.vhd @@ -0,0 +1,266 @@ +LIBRARY ieee; +USE std.textio.ALL; +USE ieee.std_logic_1164.ALL; + +PACKAGE io_utils IS + + PROCEDURE write_string(l : INOUT line; + value : IN string; + justified : IN side := right; + field : IN width := 0); + + TYPE radix IS (binary, octal, decimal, hex); + + -- read a number from the line + -- use this if you have hex numbers that are not in VHDL pound-sign format + PROCEDURE read(l : INOUT line; value : OUT integer; radix : IN positive); + + -- read a number that might be in VHDL pound-sign format + PROCEDURE read_based(l : INOUT line; value : OUT integer); + + PROCEDURE write(l : INOUT line; + value : IN std_logic_vector; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false); + + PROCEDURE write(l : INOUT line; + value : IN integer; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false); +END io_utils; + +PACKAGE BODY io_utils IS + + PROCEDURE write_string(l : INOUT line; + value : IN string; + justified : IN side := right; + field : IN width := 0) + IS + BEGIN + write(l, value, justified, field); + END; + + PROCEDURE shrink_line(l : INOUT line; pos : integer) IS + VARIABLE tmpl : line; + BEGIN + tmpl := l; + l := NEW string'(tmpl(pos TO tmpl'high)); + deallocate(tmpl); + END; + + PROCEDURE read(l : INOUT line; + value : OUT integer; + radix : IN positive) + IS + CONSTANT not_digit : integer := -999; + + -- convert a character to a value from 0 to 15 + FUNCTION digit_value(c : character) RETURN integer IS + BEGIN + IF (c >= '0') AND (c <= '9') THEN + RETURN (character'pos(c) - character'pos('0')); + ELSIF (c >= 'a') AND (c <= 'f') THEN + RETURN (character'pos(c) - character'pos('a') + 10); + ELSIF (c >= 'A') AND (c <= 'F') THEN + RETURN (character'pos(c) - character'pos('A') + 10); + ELSE + RETURN not_digit; + END IF; + END; + + -- skip leading white space in the line + PROCEDURE skip_white(VARIABLE l : IN line; pos : OUT integer) IS + BEGIN + pos := l'low; + FOR i IN l'low TO l'high LOOP + CASE l(i) IS + WHEN ' ' | ht => + pos := i + 1; + WHEN OTHERS => + EXIT; + END CASE; + END LOOP; + END; + + VARIABLE digit : integer; + VARIABLE result : integer := 0; + VARIABLE pos : integer; + BEGIN + -- skip white space + skip_white(l, pos); + + -- calculate the value + FOR i IN pos TO l'right LOOP + digit := digit_value(l(i)); + EXIT WHEN (digit = not_digit) OR (digit >= radix); + result := result * radix + digit; + pos := i + 1; + END LOOP; + value := result; + + -- remove the "used" characters from the line + shrink_line(l, pos); + END; + + PROCEDURE read_based(l : INOUT line; value : OUT integer) IS + VARIABLE digit : integer; + VARIABLE num : integer; + VARIABLE base : integer; + BEGIN + read(l, num, 10); + IF (l'length > 1) AND (l(l'left) = '#') THEN + shrink_line(l, l'left+1); + base := num; + read(l, num, base); + IF (l'length >= 1) AND (l(l'left) = '#') THEN + shrink_line(l, l'left+1); + END IF; + END IF; + value := num; + END; + + PROCEDURE write(l : INOUT line; + value : IN std_logic_vector; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false) + IS + FUNCTION to_int(bv : std_logic_vector) RETURN integer + IS + VARIABLE result : integer := 0; + BEGIN + FOR i IN bv'RANGE LOOP + result := result * 2; + IF (bv(i) = '1') THEN + result := result + 1; + END IF; + END LOOP; + RETURN result; + END; + + TYPE array_of_widths IS ARRAY(radix) OF natural; + CONSTANT nibble_widths : array_of_widths := ( + binary => 1, + octal => 3, + hex => 4, + decimal=> 32); + CONSTANT hex_digit : string(1 TO 16) := "0123456789ABCDEF"; + + ALIAS input_val : std_logic_vector(value'length DOWNTO 1) IS value; + CONSTANT nibble_width : natural := nibble_widths(base); + CONSTANT result_width : natural := (value'length + nibble_width - 1)/nibble_width; + + VARIABLE result : string(1 TO result_width); -- longest possible value + VARIABLE result_pos : positive := 1; + VARIABLE nibble_val : integer; + VARIABLE bitcnt : integer; + BEGIN + IF base = decimal THEN + write(l, to_int(value), justified, field, base, use_pound); + RETURN; + END IF; + + bitcnt := value'length MOD nibble_width; + IF (bitcnt = 0) THEN + bitcnt := nibble_width; + END IF; + FOR i IN input_val'RANGE LOOP + nibble_val := nibble_val * 2; + IF (input_val(i) = '1') THEN + nibble_val := nibble_val + 1; + END IF; + bitcnt := bitcnt - 1; + IF (bitcnt = 0) THEN + result(result_pos) := hex_digit(nibble_val + 1); + result_pos := result_pos + 1; + nibble_val := 0; + bitcnt := nibble_width; + END IF; + END LOOP; + write(l, result, justified, field); + END; + + PROCEDURE write(l : INOUT line; + value : IN integer; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false) + IS + FUNCTION to_bv(int : integer) RETURN std_logic_vector + IS + VARIABLE bv : std_logic_vector(32 DOWNTO 1) := (OTHERS => '0'); + VARIABLE pos : integer := 0; + VARIABLE tmpval : integer := int; + BEGIN + FOR i IN 1 TO 32 LOOP + pos := pos + 1; + IF (tmpval MOD 2) = 1 THEN + bv(i) := '1'; + END IF; + tmpval := tmpval / 2; + EXIT WHEN tmpval = 0; + END LOOP; + RETURN bv(pos DOWNTO 1); + END; + + VARIABLE tmp : line; + BEGIN + IF (base = decimal) THEN + IF (use_pound) THEN + write_string(tmp, "10#"); + END IF; + write(tmp, value); + IF (use_pound) THEN + write_string(tmp, "#"); + END IF; + write(l, tmp.ALL, justified, field); + deallocate(tmp); + ELSE + write(l, to_bv(value), justified, field, base, use_pound); + END IF; + END; + +END io_utils; + + + +-- test the hex number reader +--ENTITY test IS END; + +--USE std.textio.ALL; +--USE work.io_utils.ALL; +--ARCHITECTURE hex_test OF test IS +--BEGIN +-- PROCESS +-- VARIABLE val : integer; +-- FILE myfile : text IS IN "values"; +-- VARIABLE inline : line; +-- VARIABLE outline : line; +-- BEGIN +-- WHILE NOT endfile(myfile) LOOP +-- readline(myfile, inline); + +-- write(outline, inline.ALL); +-- +-- read_based(inline, val); + -- write_string(outline, " binary: "); + -- write(outline, val, base => binary); + -- write_string(outline, " octal: "); + -- write(outline, val, base => octal); + -- write_string(outline, " decimal: "); + -- write(outline, val, base => decimal); +-- write_string(outline, " hex: "); +-- write(outline, val, base => hex); +-- writeline(output, outline); +-- END LOOP; +-- WAIT; +-- END PROCESS; +--END; + + diff --git a/lib/models/memory/sdram/mt48lc32m4a2/mt48lc32m4a2.vhd b/lib/models/memory/sdram/mt48lc32m4a2/mt48lc32m4a2.vhd new file mode 100644 index 0000000..fc22f7f --- /dev/null +++ b/lib/models/memory/sdram/mt48lc32m4a2/mt48lc32m4a2.vhd @@ -0,0 +1,1140 @@ +----------------------------------------------------------------------------------------- +-- +-- File Name: MT48LC32M4A2.VHD +-- Version: 0.0g +-- Date: May 15th, 1999 +-- Model: Behavioral +-- Simulator: Model Technology (PC version 5.3 PE) +-- +-- Dependencies: None +-- +-- Author: Son P. Huynh +-- Email: sphuynh@micron.com +-- Phone: (208) 368-3825 +-- Company: Micron Technology, Inc. +-- Part Number: MT48LC32M4A2 (8Mb x 4 x 4 Banks) +-- +-- Description: Micron 128Mb SDRAM +-- +-- Limitation: - Doesn't check for 4096-cycle refresh +-- +-- Note: - Set simulator resolution to "ps" accuracy +-- +-- Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY +-- WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY +-- IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR +-- A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT. +-- +-- Copyright (c) 1998 Micron Semiconductor Products, Inc. +-- All rights researved +-- +-- Rev Author Phone Date Changes +-- ---- ---------------------------- ---------- ------------------------------------- +-- 0.0g Son Huynh 208-368-3825 05/15/2000 Fix tWR + tRP timing +-- Micron Technology Inc. +-- +-- 0.0f Son Huynh 208-368-3825 07/08/1999 Fix tWR = 1 Clk + 7.5 ns (Auto) +-- Micron Technology Inc. Fix tWR = 15 ns (Manual) +-- Fix tRP (Autoprecharge to AutoRefresh) +-- +-- 0.0c Son P. Huynh 208-368-3825 04/08/1999 Fix tWR + tRP in Write with AP +-- Micron Technology Inc. Fix tRC check in Load Mode Register +-- +-- 0.0b Son P. Huynh 208-368-3825 12/29/1998 Derive from 64Mb SDRAM model +-- Micron Technology Inc. +-- +----------------------------------------------------------------------------------------- + +LIBRARY ieee; + USE ieee.std_logic_1164.ALL; +LIBRARY work; + USE work.mti_pkg.ALL; + +ENTITY mt48lc32m4a2 IS + GENERIC ( + -- Timing Parameters for -7E and CAS Latency = 2 + tAC : TIME := 5.4 ns; + tHZ : TIME := 4.5 ns; + tOH : TIME := 2.7 ns; + tMRD : INTEGER := 2; -- 2 Clk Cycles + tRAS : TIME := 37.0 ns; + tRC : TIME := 60.0 ns; + tRCD : TIME := 15.0 ns; + tRP : TIME := 15.0 ns; + tRRD : TIME := 14.0 ns; + tWRa : TIME := 7.0 ns; -- A2 Version - Auto precharge mode only (1 Clk + 7 ns) + tWRp : TIME := 14.0 ns; -- A2 Version - Precharge mode only (14 ns) + + tAH : TIME := 0.8 ns; + tAS : TIME := 1.5 ns; + tCH : TIME := 2.5 ns; + tCL : TIME := 2.5 ns; + tCK : TIME := 7.5 ns; + tDH : TIME := 0.8 ns; + tDS : TIME := 1.5 ns; + tCKH : TIME := 0.8 ns; + tCKS : TIME := 1.5 ns; + tCMH : TIME := 0.8 ns; + tCMS : TIME := 1.5 ns; + + addr_bits : INTEGER := 12; + data_bits : INTEGER := 4; + col_bits : INTEGER := 11 + ); + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC_VECTOR := "00"; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '0'; + Cs_n : IN STD_LOGIC := '1'; + Ras_n : IN STD_LOGIC := '0'; + Cas_n : IN STD_LOGIC := '0'; + We_n : IN STD_LOGIC := '0'; + Dqm : IN STD_LOGIC := '0' + ); +END mt48lc32m4a2; + +ARCHITECTURE behave OF mt48lc32m4a2 IS + TYPE State IS (ACT, A_REF, BST, LMR, NOP, PRECH, READ, READ_A, WRITE, WRITE_A); + TYPE Array4xI IS ARRAY (3 DOWNTO 0) OF INTEGER; + TYPE Array4xT IS ARRAY (3 DOWNTO 0) OF TIME; + TYPE Array4xB IS ARRAY (3 DOWNTO 0) OF BIT; + TYPE Array4x2BV IS ARRAY (3 DOWNTO 0) OF BIT_VECTOR (1 DOWNTO 0); + TYPE Array2xB IS ARRAY (1 DOWNTO 0) OF BIT; + TYPE Array4xCBV IS ARRAY (4 DOWNTO 0) OF BIT_VECTOR (Col_bits - 1 DOWNTO 0); + TYPE Array_state IS ARRAY (4 DOWNTO 0) OF State; + SIGNAL Operation : State := NOP; + SIGNAL Mode_reg : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL Active_enable, Aref_enable, Burst_term : BIT := '0'; + SIGNAL Mode_reg_enable, Prech_enable, Read_enable, Write_enable : BIT := '0'; + SIGNAL Burst_length_1, Burst_length_2, Burst_length_4, Burst_length_8 : BIT := '0'; + SIGNAL Cas_latency_2, Cas_latency_3 : BIT := '0'; + SIGNAL Ras_in, Cas_in, We_in : BIT := '0'; + SIGNAL Write_burst_mode : BIT := '0'; + SIGNAL RAS_clk, Sys_clk, CkeZ : BIT := '0'; + + -- Checking internal wires + SIGNAL Pre_chk : BIT_VECTOR (3 DOWNTO 0) := "0000"; + SIGNAL Act_chk : BIT_VECTOR (3 DOWNTO 0) := "0000"; + SIGNAL Dq_in_chk, Dq_out_chk : BIT := '0'; + SIGNAL Bank_chk : BIT_VECTOR (1 DOWNTO 0) := "00"; + SIGNAL Row_chk : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL Col_chk : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + + BEGIN + -- CS# Decode + WITH Cs_n SELECT + Cas_in <= TO_BIT (Cas_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + WITH Cs_n SELECT + Ras_in <= TO_BIT (Ras_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + WITH Cs_n SELECT + We_in <= TO_BIT (We_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + + -- Commands Decode + Active_enable <= NOT(Ras_in) AND Cas_in AND We_in; + Aref_enable <= NOT(Ras_in) AND NOT(Cas_in) AND We_in; + Burst_term <= Ras_in AND Cas_in AND NOT(We_in); + Mode_reg_enable <= NOT(Ras_in) AND NOT(Cas_in) AND NOT(We_in); + Prech_enable <= NOT(Ras_in) AND Cas_in AND NOT(We_in); + Read_enable <= Ras_in AND NOT(Cas_in) AND We_in; + Write_enable <= Ras_in AND NOT(Cas_in) AND NOT(We_in); + + -- Burst Length Decode + Burst_length_1 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND NOT(Mode_reg(0)); + Burst_length_2 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND Mode_reg(0); + Burst_length_4 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND NOT(Mode_reg(0)); + Burst_length_8 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND Mode_reg(0); + + -- CAS Latency Decode + Cas_latency_2 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND NOT(Mode_reg(4)); + Cas_latency_3 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND Mode_reg(4); + + -- Write Burst Mode + Write_burst_mode <= Mode_reg(9); + + -- RAS Clock for checking tWR and tRP + PROCESS + variable Clk0, Clk1 : integer := 0; + begin + RAS_clk <= '1'; + wait for 0.5 ns; + RAS_clk <= '0'; + wait for 0.5 ns; + if Clk0 > 100 or Clk1 > 100 then + wait; + else + if Clk = '1' then + Clk0 := 0; + Clk1 := Clk1 + 1; + else + Clk0 := Clk0 + 1; + Clk1 := 0; + end if; + end if; + END PROCESS; + + -- System Clock + int_clk : PROCESS (Clk) + begin + IF Clk'LAST_VALUE = '0' AND Clk = '1' THEN + CkeZ <= TO_BIT(Cke, '1'); + END IF; + Sys_clk <= CkeZ AND TO_BIT(Clk, '0'); + END PROCESS; + + state_register : PROCESS + TYPE ram_type IS ARRAY (2**col_bits - 1 DOWNTO 0) OF BIT_VECTOR (data_bits - 1 DOWNTO 0); + TYPE ram_pntr IS ACCESS ram_type; + TYPE ram_stor IS ARRAY (2**addr_bits - 1 DOWNTO 0) OF ram_pntr; + VARIABLE Bank0 : ram_stor; + VARIABLE Bank1 : ram_stor; + VARIABLE Bank2 : ram_stor; + VARIABLE Bank3 : ram_stor; + VARIABLE Row_index, Col_index : INTEGER := 0; + VARIABLE Dq_temp : BIT_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => '0'); + + VARIABLE Col_addr : Array4xCBV; + VARIABLE Bank_addr : Array4x2BV; + VARIABLE Dqm_reg : Array2xB; + + VARIABLE Bank, Previous_bank : BIT_VECTOR (1 DOWNTO 0) := "00"; + VARIABLE B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col_brst : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Row : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Burst_counter : INTEGER := 0; + + VARIABLE Command : Array_state; + VARIABLE Bank_precharge : Array4x2BV; + VARIABLE A10_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Auto_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Read_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Write_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_write : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_read : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_bank : BIT_VECTOR (1 DOWNTO 0) := "00"; + VARIABLE Count_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE Count_precharge : Array4xI := (0 & 0 & 0 & 0); + + VARIABLE Data_in_enable, Data_out_enable : BIT := '0'; + VARIABLE Pc_b0, Pc_b1, Pc_b2, Pc_b3 : BIT := '0'; + VARIABLE Act_b0, Act_b1, Act_b2, Act_b3 : BIT := '0'; + + -- Timing Check + VARIABLE MRD_chk : INTEGER := 0; + VARIABLE WR_counter : Array4xI := (0 & 0 & 0 & 0); + VARIABLE WR_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE WR_chkp : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE RC_chk, RRD_chk : TIME := 0 ns; + VARIABLE RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3 : TIME := 0 ns; + VARIABLE RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3 : TIME := 0 ns; + VARIABLE RP_chk0, RP_chk1, RP_chk2, RP_chk3 : TIME := 0 ns; + + -- Initialize empty rows + PROCEDURE Init_mem (Bank : BIT_VECTOR (1 DOWNTO 0); Row_index : INTEGER) IS + VARIABLE i, j : INTEGER := 0; + BEGIN + IF Bank = "00" THEN + IF Bank0 (Row_index) = NULL THEN -- Check to see if row empty + Bank0 (Row_index) := NEW ram_type; -- Open new row for access + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP -- Filled row with zeros + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank0 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "01" THEN + IF Bank1 (Row_index) = NULL THEN + Bank1 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank1 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "10" THEN + IF Bank2 (Row_index) = NULL THEN + Bank2 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank2 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "11" THEN + IF Bank3 (Row_index) = NULL THEN + Bank3 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank3 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + END IF; + END; + + -- Burst Counter + PROCEDURE Burst_decode IS + VARIABLE Col_int : INTEGER := 0; + VARIABLE Col_vec, Col_temp : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + BEGIN + -- Advance Burst Counter + Burst_counter := Burst_counter + 1; + + -- Burst Type + IF Mode_reg (3) = '0' THEN + Col_int := TO_INTEGER(Col); + Col_int := Col_int + 1; + TO_BITVECTOR (Col_int, Col_temp); + ELSIF Mode_reg (3) = '1' THEN + TO_BITVECTOR (Burst_counter, Col_vec); + Col_temp (2) := Col_vec (2) XOR Col_brst (2); + Col_temp (1) := Col_vec (1) XOR Col_brst (1); + Col_temp (0) := Col_vec (0) XOR Col_brst (0); + END IF; + + -- Burst Length + IF Burst_length_2 = '1' THEN + Col (0) := Col_temp (0); + ELSIF Burst_length_4 = '1' THEN + Col (1 DOWNTO 0) := Col_temp (1 DOWNTO 0); + ELSIF Burst_length_8 = '1' THEN + Col (2 DOWNTO 0) := Col_temp (2 DOWNTO 0); + ELSE + Col := Col_temp; + END IF; + + -- Burst Read Single Write + IF Write_burst_mode = '1' AND Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Data counter + IF Burst_length_1 = '1' THEN + IF Burst_counter >= 1 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_2 = '1' THEN + IF Burst_counter >= 2 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_4 = '1' THEN + IF Burst_counter >= 4 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_8 = '1' THEN + IF Burst_counter >= 8 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + END IF; + END; + + BEGIN + WAIT ON Sys_clk, RAS_clk; + IF Sys_clk'event and Sys_clk = '1' THEN + -- Internal Command Pipeline + Command(0) := Command(1); + Command(1) := Command(2); + Command(2) := Command(3); + Command(3) := NOP; + + Col_addr(0) := Col_addr(1); + Col_addr(1) := Col_addr(2); + Col_addr(2) := Col_addr(3); + Col_addr(3) := (OTHERS => '0'); + + Bank_addr(0) := Bank_addr(1); + Bank_addr(1) := Bank_addr(2); + Bank_addr(2) := Bank_addr(3); + Bank_addr(3) := "00"; + + Bank_precharge(0) := Bank_precharge(1); + Bank_precharge(1) := Bank_precharge(2); + Bank_precharge(2) := Bank_precharge(3); + Bank_precharge(3) := "00"; + + A10_precharge(0) := A10_precharge(1); + A10_precharge(1) := A10_precharge(2); + A10_precharge(2) := A10_precharge(3); + A10_precharge(3) := '0'; + + -- Operation Decode (Optional for showing current command on posedge clock / debug feature) + IF Active_enable = '1' THEN + Operation <= ACT; + ELSIF Aref_enable = '1' THEN + Operation <= A_REF; + ELSIF Burst_term = '1' THEN + Operation <= BST; + ELSIF Mode_reg_enable = '1' THEN + Operation <= LMR; + ELSIF Prech_enable = '1' THEN + Operation <= PRECH; + ELSIF Read_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= READ; + ELSE + Operation <= READ_A; + END IF; + ELSIF Write_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= WRITE; + ELSE + Operation <= WRITE_A; + END IF; + ELSE + Operation <= NOP; + END IF; + + -- Dqm pipeline for Read + Dqm_reg(0) := Dqm_reg(1); + Dqm_reg(1) := TO_BIT(Dqm); + + -- Read or Write with Auto Precharge Counter + IF Auto_precharge (0) = '1' THEN + Count_precharge (0) := Count_precharge (0) + 1; + END IF; + IF Auto_precharge (1) = '1' THEN + Count_precharge (1) := Count_precharge (1) + 1; + END IF; + IF Auto_precharge (2) = '1' THEN + Count_precharge (2) := Count_precharge (2) + 1; + END IF; + IF Auto_precharge (3) = '1' THEN + Count_precharge (3) := Count_precharge (3) + 1; + END IF; + + -- Auto Precharge Timer for tWR + if (Burst_length_1 = '1' OR Write_burst_mode = '1') then + if (Count_precharge(0) = 1) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 1) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 1) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 1) then + Count_time(3) := NOW; + end if; + elsif (Burst_length_2 = '1') then + if (Count_precharge(0) = 2) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 2) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 2) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 2) then + Count_time(3) := NOW; + end if; + elsif (Burst_length_4 = '1') then + if (Count_precharge(0) = 4) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 4) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 4) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 4) then + Count_time(3) := NOW; + end if; + elsif (Burst_length_8 = '1') then + if (Count_precharge(0) = 8) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 8) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 8) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 8) then + Count_time(3) := NOW; + end if; + end if; + + -- tMRD Counter + MRD_chk := MRD_chk + 1; + + -- tWR Counter + WR_counter(0) := WR_counter(0) + 1; + WR_counter(1) := WR_counter(1) + 1; + WR_counter(2) := WR_counter(2) + 1; + WR_counter(3) := WR_counter(3) + 1; + + -- Auto Refresh + IF Aref_enable = '1' THEN + -- Auto Refresh to Auto Refresh + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Auto Refresh" + SEVERITY WARNING; + -- Precharge to Auto Refresh + ASSERT (NOW - RP_chk0 >= tRP OR NOW - RP_chk1 >= tRP OR NOW - RP_chk2 >= tRP OR NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Auto Refresh" + SEVERITY WARNING; + -- All banks must be idle before refresh + IF (Pc_b3 = '0' OR Pc_b2 = '0' OR Pc_b1 = '0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All banks must be Precharge before Auto Refresh" + SEVERITY WARNING; + END IF; + -- Record current tRC time + RC_chk := NOW; + END IF; + + -- Load Mode Register + IF Mode_reg_enable = '1' THEN + Mode_reg <= TO_BITVECTOR (Addr); + IF (Pc_b3 = '0' OR Pc_b2 = '0' OR Pc_b1 = '0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All bank must be Precharge before Load Mode Register" + SEVERITY WARNING; + END IF; + -- REF to LMR + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Load Mode Register" + SEVERITY WARNING; + -- LMR to LMR + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Load Mode Register" + SEVERITY WARNING; + -- Record current tMRD time + MRD_chk := 0; + END IF; + + -- Active Block (latch Bank and Row Address) + IF Active_enable = '1' THEN + IF Ba = "00" AND Pc_b0 = '1' THEN + Act_b0 := '1'; + Pc_b0 := '0'; + B0_row_addr := TO_BITVECTOR (Addr); + RCD_chk0 := NOW; + RAS_chk0 := NOW; + -- Precharge to Active Bank 0 + ASSERT (NOW - RP_chk0 >= tRP) + REPORT "tRP violation during Activate Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '1' THEN + Act_b1 := '1'; + Pc_b1 := '0'; + B1_row_addr := TO_BITVECTOR (Addr); + RCD_chk1 := NOW; + RAS_chk1 := NOW; + -- Precharge to Active Bank 1 + ASSERT (NOW - RP_chk1 >= tRP) + REPORT "tRP violation during Activate Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '1' THEN + Act_b2 := '1'; + Pc_b2 := '0'; + B2_row_addr := TO_BITVECTOR (Addr); + RCD_chk2 := NOW; + RAS_chk2 := NOW; + -- Precharge to Active Bank 2 + ASSERT (NOW - RP_chk2 >= tRP) + REPORT "tRP violation during Activate Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '1' THEN + Act_b3 := '1'; + Pc_b3 := '0'; + B3_row_addr := TO_BITVECTOR (Addr); + RCD_chk3 := NOW; + RAS_chk3 := NOW; + -- Precharge to Active Bank 3 + ASSERT (NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Activate Bank 3" + SEVERITY WARNING; + ELSIF Ba = "00" AND Pc_b0 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 0 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 1 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 2 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 3 is not Precharged" + SEVERITY WARNING; + END IF; + -- Active Bank A to Active Bank B + IF ((Previous_bank /= TO_BITVECTOR (Ba)) AND (NOW - RRD_chk < tRRD)) THEN + ASSERT (FALSE) + REPORT "tRRD violation during Activate" + SEVERITY WARNING; + END IF; + -- LMR to ACT + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Activate" + SEVERITY WARNING; + -- AutoRefresh to Activate + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Activate" + SEVERITY WARNING; + -- Record variable for checking violation + RRD_chk := NOW; + Previous_bank := TO_BITVECTOR (Ba); + END IF; + + -- Precharge Block + IF Prech_enable = '1' THEN + IF Addr(10) = '1' THEN + Pc_b0 := '1'; + Pc_b1 := '1'; + Pc_b2 := '1'; + Pc_b3 := '1'; + Act_b0 := '0'; + Act_b1 := '0'; + Act_b2 := '0'; + Act_b3 := '0'; + RP_chk0 := NOW; + RP_chk1 := NOW; + RP_chk2 := NOW; + RP_chk3 := NOW; + -- Activate to Precharge all banks + ASSERT ((NOW - RAS_chk0 >= tRAS) OR (NOW - RAS_chk1 >= tRAS)) + REPORT "tRAS violation during Precharge all banks" + SEVERITY WARNING; + -- tWR violation check for Write + IF ((NOW - WR_chkp(0) < tWRp) OR (NOW - WR_chkp(1) < tWRp) OR + (NOW - WR_chkp(2) < tWRp) OR (NOW - WR_chkp(3) < tWRp)) THEN + ASSERT (FALSE) + REPORT "tWR violation during Precharge ALL banks" + SEVERITY WARNING; + END IF; + ELSIF Addr(10) = '0' THEN + IF Ba = "00" THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + -- Activate to Precharge bank 0 + ASSERT (NOW - RAS_chk0 >= tRAS) + REPORT "tRAS violation during Precharge bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + -- Activate to Precharge bank 1 + ASSERT (NOW - RAS_chk1 >= tRAS) + REPORT "tRAS violation during Precharge bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + -- Activate to Precharge bank 2 + ASSERT (NOW - RAS_chk2 >= tRAS) + REPORT "tRAS violation during Precharge bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + -- Activate to Precharge bank 3 + ASSERT (NOW - RAS_chk3 >= tRAS) + REPORT "tRAS violation during Precharge bank 3" + SEVERITY WARNING; + END IF; + -- tWR violation check for Write + ASSERT (NOW - WR_chkp(TO_INTEGER(Ba)) >= tWRp) + REPORT "tWR violation during Precharge" + SEVERITY WARNING; + END IF; + -- Terminate a Write Immediately (if same bank or all banks) + IF (Data_in_enable = '1' AND (Bank = TO_BITVECTOR(Ba) OR Addr(10) = '1')) THEN + Data_in_enable := '0'; + END IF; + -- Precharge Command Pipeline for READ + IF CAS_latency_3 = '1' THEN + Command(2) := PRECH; + Bank_precharge(2) := TO_BITVECTOR (Ba); + A10_precharge(2) := TO_BIT(Addr(10)); + ELSIF CAS_latency_2 = '1' THEN + Command(1) := PRECH; + Bank_precharge(1) := TO_BITVECTOR (Ba); + A10_precharge(1) := TO_BIT(Addr(10)); + END IF; + END IF; + + -- Burst Terminate + IF Burst_term = '1' THEN + -- Terminate a Write immediately + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + -- Terminate a Read depend on CAS Latency + IF CAS_latency_3 = '1' THEN + Command(2) := BST; + ELSIF CAS_latency_2 = '1' THEN + Command(1) := BST; + END IF; + END IF; + + -- Read, Write, Column Latch + IF Read_enable = '1' OR Write_enable = '1' THEN + -- Check to see if bank is open (ACT) for Read or Write + IF ((Ba = "00" AND Pc_b0 = '1') OR (Ba = "01" AND Pc_b1 = '1') OR (Ba = "10" AND Pc_b2 = '1') OR (Ba = "11" AND Pc_b3 = '1')) THEN + ASSERT (FALSE) + REPORT "Cannot Read or Write - Bank is not Activated" + SEVERITY WARNING; + END IF; + -- Activate to Read or Write + IF Ba = "00" THEN + ASSERT (NOW - RCD_chk0 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + ASSERT (NOW - RCD_chk1 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + ASSERT (NOW - RCD_chk2 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + ASSERT (NOW - RCD_chk3 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 3" + SEVERITY WARNING; + END IF; + -- Read Command + IF Read_enable = '1' THEN + -- CAS Latency Pipeline + IF Cas_latency_3 = '1' THEN + IF Addr(10) = '1' THEN + Command(2) := READ_A; + ELSE + Command(2) := READ; + END IF; + Col_addr (2) := TO_BITVECTOR (Addr(11) & Addr(9 DOWNTO 0)); + Bank_addr (2) := TO_BITVECTOR (Ba); + ELSIF Cas_latency_2 = '1' THEN + IF Addr(10) = '1' THEN + Command(1) := READ_A; + ELSE + Command(1) := READ; + END IF; + Col_addr (1) := TO_BITVECTOR (Addr(11) & Addr(9 DOWNTO 0)); + Bank_addr (1) := TO_BITVECTOR (Ba); + END IF; + + -- Read intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Write Command + ELSIF Write_enable = '1' THEN + IF Addr(10) = '1' THEN + Command(0) := WRITE_A; + ELSE + Command(0) := WRITE; + END IF; + Col_addr (0) := TO_BITVECTOR (Addr(11) & Addr(9 DOWNTO 0)); + Bank_addr (0) := TO_BITVECTOR (Ba); + + -- Write intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Write interrupt a Read (terminate Read immediately) + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + + -- Interrupt a Write with Auto Precharge + IF Auto_precharge(TO_INTEGER(RW_interrupt_bank)) = '1' AND Write_precharge(TO_INTEGER(RW_interrupt_bank)) = '1' THEN + RW_interrupt_write(TO_INTEGER(RW_interrupt_bank)) := '1'; + END IF; + + -- Interrupt a Read with Auto Precharge + IF Auto_precharge(TO_INTEGER(RW_interrupt_bank)) = '1' AND Read_precharge(TO_INTEGER(RW_interrupt_bank)) = '1' THEN + RW_interrupt_read(TO_INTEGER(RW_interrupt_bank)) := '1'; + END IF; + + -- Read or Write with Auto Precharge + IF Addr(10) = '1' THEN + Auto_precharge (TO_INTEGER(Ba)) := '1'; + Count_precharge (TO_INTEGER(Ba)) := 0; + RW_interrupt_bank := TO_BITVECTOR (Ba); + IF Read_enable = '1' THEN + Read_precharge (TO_INTEGER(Ba)) := '1'; + ELSIF Write_enable = '1' THEN + Write_precharge (TO_INTEGER(Ba)) := '1'; + END IF; + END IF; + END IF; + + -- Read with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. BL/2 cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Read_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(0) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8))) OR + (RW_interrupt_read(0) = '1')) THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + Auto_precharge(0) := '0'; + Read_precharge(0) := '0'; + RW_interrupt_read(0) := '0'; + END IF; + END IF; + IF ((Auto_precharge(1) = '1') AND (Read_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(1) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8))) OR + (RW_interrupt_read(1) = '1')) THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + Auto_precharge(1) := '0'; + Read_precharge(1) := '0'; + RW_interrupt_read(1) := '0'; + END IF; + END IF; + IF ((Auto_precharge(2) = '1') AND (Read_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(2) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8))) OR + (RW_interrupt_read(2) = '1')) THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + Auto_precharge(2) := '0'; + Read_precharge(2) := '0'; + RW_interrupt_read(2) := '0'; + END IF; + END IF; + IF ((Auto_precharge(3) = '1') AND (Read_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(3) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8))) OR + (RW_interrupt_read(3) = '1')) THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + Auto_precharge(3) := '0'; + Read_precharge(3) := '0'; + RW_interrupt_read(3) := '0'; + END IF; + END IF; + + -- Internal Precharge or Bst + IF Command(0) = PRECH THEN -- PRECH terminate a read if same bank or all banks + IF Bank_precharge(0) = Bank OR A10_precharge(0) = '1' THEN + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Command(0) = BST THEN -- BST terminate a read regardless of bank + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + + IF Data_out_enable = '0' THEN + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tOH; + END IF; + + -- Detect Read or Write Command + IF Command(0) = READ OR Command(0) = READ_A THEN + Bank := Bank_addr (0); + Col := Col_addr (0); + Col_brst := Col_addr (0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '0'; + Data_out_enable := '1'; + ELSIF Command(0) = WRITE OR Command(0) = WRITE_A THEN + Bank := Bank_addr(0); + Col := Col_addr(0); + Col_brst := Col_addr(0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '1'; + Data_out_enable := '0'; + END IF; + + -- DQ (Driver / Receiver) + Row_index := TO_INTEGER (Row); + Col_index := TO_INTEGER (Col); + IF Data_in_enable = '1' THEN + IF Dqm = '0' THEN + Init_mem (Bank, Row_index); + IF Bank = "00" THEN + Bank0 (Row_index) (Col_index) := TO_BITVECTOR(Dq); + ELSIF Bank = "01" THEN + Bank1 (Row_index) (Col_index) := TO_BITVECTOR(Dq); + ELSIF Bank = "10" THEN + Bank2 (Row_index) (Col_index) := TO_BITVECTOR(Dq); + ELSIF Bank = "11" THEN + Bank3 (Row_index) (Col_index) := TO_BITVECTOR(Dq); + END IF; + WR_chkp(TO_INTEGER(Bank)) := NOW; + WR_counter(TO_INTEGER(Bank)) := 0; + END IF; + Burst_decode; + ELSIF Data_out_enable = '1' THEN + IF Dqm_reg(0) = '0' THEN + Init_mem (Bank, Row_index); + IF Bank = "00" THEN + Dq <= TRANSPORT TO_STDLOGICVECTOR(Bank0 (Row_index) (Col_index)) AFTER tAC; + ELSIF Bank = "01" THEN + Dq <= TRANSPORT TO_STDLOGICVECTOR(Bank1 (Row_index) (Col_index)) AFTER tAC; + ELSIF Bank = "10" THEN + Dq <= TRANSPORT TO_STDLOGICVECTOR(Bank2 (Row_index) (Col_index)) AFTER tAC; + ELSIF Bank = "11" THEN + Dq <= TRANSPORT TO_STDLOGICVECTOR(Bank3 (Row_index) (Col_index)) AFTER tAC; + END IF; + ELSE + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tHZ; + END IF; + Burst_decode; + END IF; + + END IF; + + -- Write with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. tWR cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Write_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(0) >= 1 AND NOW - Count_time(0) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2 AND NOW - Count_time(0) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4 AND NOW - Count_time(0) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8 AND NOW - Count_time(0) >= tWRa))) OR + (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 1 AND NOW - WR_time(0) >= tWRa)) THEN + Auto_precharge(0) := '0'; + Write_precharge(0) := '0'; + RW_interrupt_write(0) := '0'; + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + ASSERT FALSE REPORT "Start Internal Precharge Bank 0" SEVERITY NOTE; + END IF; + END IF; + IF ((Auto_precharge(1) = '1') AND (Write_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(1) >= 1 AND NOW - Count_time(1) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2 AND NOW - Count_time(1) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4 AND NOW - Count_time(1) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8 AND NOW - Count_time(1) >= tWRa))) OR + (RW_interrupt_write(1) = '1' AND WR_counter(1) >= 1 AND NOW - WR_time(1) >= tWRa)) THEN + Auto_precharge(1) := '0'; + Write_precharge(1) := '0'; + RW_interrupt_write(1) := '0'; + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + END IF; + END IF; + IF ((Auto_precharge(2) = '1') AND (Write_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(2) >= 1 AND NOW - Count_time(2) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2 AND NOW - Count_time(2) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4 AND NOW - Count_time(2) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8 AND NOW - Count_time(2) >= tWRa))) OR + (RW_interrupt_write(2) = '1' AND WR_counter(2) >= 1 AND NOW - WR_time(2) >= tWRa)) THEN + Auto_precharge(2) := '0'; + Write_precharge(2) := '0'; + RW_interrupt_write(2) := '0'; + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + END IF; + END IF; + IF ((Auto_precharge(3) = '1') AND (Write_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(3) >= 1 AND NOW - Count_time(3) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2 AND NOW - Count_time(3) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4 AND NOW - Count_time(3) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8 AND NOW - Count_time(3) >= tWRa))) OR + (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 1 AND NOW - WR_time(3) >= tWRa)) THEN + Auto_precharge(3) := '0'; + Write_precharge(3) := '0'; + RW_interrupt_write(3) := '0'; + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + END IF; + END IF; + + -- Checking internal variables (Optional for debug purpose) + Pre_chk (0) <= Pc_b0; + Pre_chk (1) <= Pc_b1; + Pre_chk (2) <= Pc_b2; + Pre_chk (3) <= Pc_b3; + Act_chk (0) <= Act_b0; + Act_chk (1) <= Act_b1; + Act_chk (2) <= Act_b2; + Act_chk (3) <= Act_b3; + Dq_in_chk <= Data_in_enable; + Dq_out_chk <= Data_out_enable; + Bank_chk <= Bank; + Row_chk <= Row; + Col_chk <= Col; + END PROCESS; + + + -- Clock timing checks + Clock_check : PROCESS + VARIABLE Clk_low, Clk_high : TIME := 0 ns; + BEGIN + WAIT ON Clk; + IF (Clk = '1' AND NOW >= 10 ns) THEN + ASSERT (NOW - Clk_low >= tCL) + REPORT "tCL violation" + SEVERITY WARNING; + ASSERT (NOW - Clk_high >= tCK) + REPORT "tCK violation" + SEVERITY WARNING; + Clk_high := NOW; + ELSIF (Clk = '0' AND NOW /= 0 ns) THEN + ASSERT (NOW - Clk_high >= tCH) + REPORT "tCH violation" + SEVERITY WARNING; + Clk_low := NOW; + END IF; + END PROCESS; + + -- Setup timing checks + Setup_check : PROCESS + BEGIN + WAIT ON Clk; + IF Clk = '1' THEN + ASSERT(Cke'LAST_EVENT >= tCKS) + REPORT "CKE Setup time violation -- tCKS" + SEVERITY WARNING; + ASSERT(Cs_n'LAST_EVENT >= tCMS) + REPORT "CS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT >= tCMS) + REPORT "CAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT >= tCMS) + REPORT "RAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT >= tCMS) + REPORT "WE# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT >= tCMS) + REPORT "Dqm Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Addr'LAST_EVENT >= tAS) + REPORT "ADDR Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT >= tAS) + REPORT "BA Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Dq'LAST_EVENT >= tDS) + REPORT "Dq Setup time violation -- tDS" + SEVERITY WARNING; + END IF; + END PROCESS; + + -- Hold timing checks + Hold_check : PROCESS + BEGIN + WAIT ON Clk'DELAYED (tCKH), Clk'DELAYED (tCMH), Clk'DELAYED (tAH), Clk'DELAYED (tDH); + IF Clk'DELAYED (tCKH) = '1' THEN + ASSERT(Cke'LAST_EVENT > tCKH) + REPORT "CKE Hold time violation -- tCKH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tCMH) = '1' THEN + ASSERT(Cs_n'LAST_EVENT > tCMH) + REPORT "CS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT > tCMH) + REPORT "CAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT > tCMH) + REPORT "RAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT > tCMH) + REPORT "WE# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT > tCMH) + REPORT "Dqm Hold time violation -- tCMH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tAH) = '1' THEN + ASSERT(Addr'LAST_EVENT > tAH) + REPORT "ADDR Hold time violation -- tAH" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT > tAH) + REPORT "BA Hold time violation -- tAH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tDH) = '1' THEN + ASSERT(Dq'LAST_EVENT > tDH) + REPORT "Dq Hold time violation -- tDH" + SEVERITY WARNING; + END IF; + END PROCESS; + +END behave; diff --git a/lib/models/memory/sdram/mt48lc32m4a2/mti_pkg.vhd b/lib/models/memory/sdram/mt48lc32m4a2/mti_pkg.vhd new file mode 100644 index 0000000..9e4f824 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc32m4a2/mti_pkg.vhd @@ -0,0 +1,129 @@ +--***************************************************************************** +-- +-- Micron Semiconductor Products, Inc. +-- +-- Copyright 1997, Micron Semiconductor Products, Inc. +-- All rights reserved. +-- +--***************************************************************************** + +LIBRARY work; +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +PACKAGE mti_pkg IS + + FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER; + FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER; + FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER; + PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR); + +END mti_pkg; + +PACKAGE BODY mti_pkg IS + + -- Convert BIT to INTEGER + FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + IF input = '1' THEN + result := weight; + ELSE + result := 0; -- if unknowns, default to logic 0 + END IF; + RETURN result; + END TO_INTEGER; + + -- Convert BIT_VECTOR to INTEGER + FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + FOR i IN input'LOW TO input'HIGH LOOP + IF input(i) = '1' THEN + result := result + weight; + ELSE + result := result + 0; -- if unknowns, default to logic 0 + END IF; + weight := weight * 2; + END LOOP; + RETURN result; + END TO_INTEGER; + + -- Convert STD_LOGIC_VECTOR to INTEGER + FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + FOR i IN input'LOW TO input'HIGH LOOP + IF input(i) = '1' THEN + result := result + weight; + ELSE + result := result + 0; -- if unknowns, default to logic 0 + END IF; + weight := weight * 2; + END LOOP; + RETURN result; + END TO_INTEGER; + + -- Conver integer to bit_vector + PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR) IS + VARIABLE work,offset,outputlen,j : INTEGER := 0; + BEGIN + --length of vector + IF output'LENGTH > 32 THEN + outputlen := 32; + offset := output'LENGTH - 32; + IF input >= 0 THEN + FOR i IN offset-1 DOWNTO 0 LOOP + output(output'HIGH - i) := '0'; + END LOOP; + ELSE + FOR i IN offset-1 DOWNTO 0 LOOP + output(output'HIGH - i) := '1'; + END LOOP; + END IF; + ELSE + outputlen := output'LENGTH; + END IF; + --positive value + IF (input >= 0) THEN + work := input; + j := outputlen - 1; + FOR i IN 1 to 32 LOOP + IF j >= 0 then + IF (work MOD 2) = 0 THEN + output(output'HIGH-j-offset) := '0'; + ELSE + output(output'HIGH-j-offset) := '1'; + END IF; + END IF; + work := work / 2; + j := j - 1; + END LOOP; + IF outputlen = 32 THEN + output(output'HIGH) := '0'; + END IF; + --negative value + ELSE + work := (-input) - 1; + j := outputlen - 1; + FOR i IN 1 TO 32 LOOP + IF j>= 0 THEN + IF (work MOD 2) = 0 THEN + output(output'HIGH-j-offset) := '1'; + ELSE + output(output'HIGH-j-offset) := '0'; + END IF; + END IF; + work := work / 2; + j := j - 1; + END LOOP; + IF outputlen = 32 THEN + output(output'HIGH) := '1'; + END IF; + END IF; + END TO_BITVECTOR; + +END mti_pkg; diff --git a/lib/models/memory/sdram/mt48lc32m4a2/readme.txt b/lib/models/memory/sdram/mt48lc32m4a2/readme.txt new file mode 100644 index 0000000..5728ae8 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc32m4a2/readme.txt @@ -0,0 +1,14 @@ +To operate the test bench for the Micron SDRAM VHDL model, follow the directions +given below: + +1. Be sure all supporting files for the SDRAM are compiled into your library: + + util1164.vhd + stdlogar.vhd + io_utils.vhd + mti_pkg.vhd + +2. Next, compile the mt48lc32m4a2.vhd file and the test.vhd file. + +3. Simulate the "tb" architecture. This is the testbench for the 128Mb SDRAM. + diff --git a/lib/models/memory/sdram/mt48lc32m4a2/stdlogar.vhd b/lib/models/memory/sdram/mt48lc32m4a2/stdlogar.vhd new file mode 100644 index 0000000..e435ea2 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc32m4a2/stdlogar.vhd @@ -0,0 +1,2247 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990,1991,1992 by Synopsys, Inc. All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_ARITH -- +-- -- +-- Purpose: -- +-- A set of arithemtic, conversion, and comparison functions -- +-- for SIGNED, UNSIGNED, SMALL_INT, INTEGER, -- +-- STD_ULOGIC, STD_LOGIC, and STD_LOGIC_VECTOR. -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +package std_logic_arith is + + type UNSIGNED is array (NATURAL range <>) of STD_LOGIC; + type SIGNED is array (NATURAL range <>) of STD_LOGIC; + subtype SMALL_INT is INTEGER range 0 to 1; + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: INTEGER) return SIGNED; + function "+"(L: INTEGER; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: INTEGER) return SIGNED; + function "-"(L: INTEGER; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "+"(L: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED) return SIGNED; + function "-"(L: SIGNED) return SIGNED; + function "ABS"(L: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED) return STD_LOGIC_VECTOR; + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "*"(L: SIGNED; R: SIGNED) return SIGNED; + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + + function CONV_INTEGER(ARG: INTEGER) return INTEGER; + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER; + function CONV_INTEGER(ARG: SIGNED) return INTEGER; + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT; + + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED; + + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED; + + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + -- zero extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- returns STD_LOGIC_VECTOR(SIZE-1 downto 0) + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + + -- sign extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- return STD_LOGIC_VECTOR(SIZE-1 downto 0) + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end Std_logic_arith; + + + +library IEEE; +use IEEE.std_logic_1164.all; + +package body std_logic_arith is + + function max(L, R: INTEGER) return INTEGER is + begin + if L > R then + return L; + else + return R; + end if; + end; + + + function min(L, R: INTEGER) return INTEGER is + begin + if L < R then + return L; + else + return R; + end if; + end; + + -- synopsys synthesis_off + type tbl_type is array (STD_ULOGIC) of STD_ULOGIC; + constant tbl_BINARY : tbl_type := + ('X', 'X', '0', '1', 'X', 'X', '0', '1', 'X'); + -- synopsys synthesis_on + + -- synopsys synthesis_off + type tbl_mvl9_boolean is array (STD_ULOGIC) of boolean; + constant IS_X : tbl_mvl9_boolean := + (true, true, false, false, true, true, false, false, true); + -- synopsys synthesis_on + + + + function MAKE_BINARY(A : STD_ULOGIC) return STD_ULOGIC is + -- synopsys built_in SYN_FEED_THRU + begin + -- synopsys synthesis_off + if (IS_X(A)) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + return ('X'); + end if; + return tbl_BINARY(A); + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return UNSIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : UNSIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return SIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : SIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return UNSIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : UNSIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return SIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : SIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + + + -- Type propagation function which returns a signed type with the + -- size of the left arg. + function LEFT_SIGNED_ARG(A,B: SIGNED) return SIGNED is + variable Z: SIGNED (A'left downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns an unsigned type with the + -- size of the left arg. + function LEFT_UNSIGNED_ARG(A,B: UNSIGNED) return UNSIGNED is + variable Z: UNSIGNED (A'left downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns a signed type with the + -- size of the result of a signed multiplication + function MULT_SIGNED_ARG(A,B: SIGNED) return SIGNED is + variable Z: SIGNED ((A'length+B'length-1) downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns an unsigned type with the + -- size of the result of a unsigned multiplication + function MULT_UNSIGNED_ARG(A,B: UNSIGNED) return UNSIGNED is + variable Z: UNSIGNED ((A'length+B'length-1) downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + + + function mult(A,B: SIGNED) return SIGNED is + + variable BA: SIGNED((A'length+B'length-1) downto 0); + variable PA: SIGNED((A'length+B'length-1) downto 0); + variable AA: SIGNED(A'length downto 0); + variable neg: STD_ULOGIC; + constant one : UNSIGNED(1 downto 0) := "01"; + + -- pragma map_to_operator MULT_TC_OP + -- pragma type_function MULT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + PA := (others => 'X'); + return(PA); + end if; + PA := (others => '0'); + neg := B(B'left) xor A(A'left); + BA := CONV_SIGNED(('0' & ABS(B)),(A'length+B'length)); + AA := '0' & ABS(A); + for i in 0 to A'length-1 loop + if AA(i) = '1' then + PA := PA+BA; + end if; + BA := SHL(BA,one); + end loop; + if (neg= '1') then + return(-PA); + else + return(PA); + end if; + end; + + function mult(A,B: UNSIGNED) return UNSIGNED is + + variable BA: UNSIGNED((A'length+B'length-1) downto 0); + variable PA: UNSIGNED((A'length+B'length-1) downto 0); + constant one : UNSIGNED(1 downto 0) := "01"; + + -- pragma map_to_operator MULT_UNS_OP + -- pragma type_function MULT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + PA := (others => 'X'); + return(PA); + end if; + PA := (others => '0'); + BA := CONV_UNSIGNED(B,(A'length+B'length)); + for i in 0 to A'length-1 loop + if A(i) = '1' then + PA := PA+BA; + end if; + BA := SHL(BA,one); + end loop; + return(PA); + end; + + -- subtract two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function minus(A, B: SIGNED) return SIGNED is + variable carry: STD_ULOGIC; + variable BV: STD_ULOGIC_VECTOR (A'left downto 0); + variable sum: SIGNED (A'left downto 0); + + -- pragma map_to_operator SUB_TC_OP + + -- pragma type_function LEFT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '1'; + BV := not STD_ULOGIC_VECTOR(B); + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + -- add two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function plus(A, B: SIGNED) return SIGNED is + variable carry: STD_ULOGIC; + variable BV, sum: SIGNED (A'left downto 0); + + -- pragma map_to_operator ADD_TC_OP + -- pragma type_function LEFT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '0'; + BV := B; + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + + -- subtract two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_minus(A, B: UNSIGNED) return UNSIGNED is + variable carry: STD_ULOGIC; + variable BV: STD_ULOGIC_VECTOR (A'left downto 0); + variable sum: UNSIGNED (A'left downto 0); + + -- pragma map_to_operator SUB_UNS_OP + -- pragma type_function LEFT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '1'; + BV := not STD_ULOGIC_VECTOR(B); + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + -- add two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_plus(A, B: UNSIGNED) return UNSIGNED is + variable carry: STD_ULOGIC; + variable BV, sum: UNSIGNED (A'left downto 0); + + -- pragma map_to_operator ADD_UNS_OP + -- pragma type_function LEFT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '0'; + BV := B; + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + + + function "*"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to mult + begin + return mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to mult + begin + return mult(CONV_UNSIGNED(L, L'length), + CONV_UNSIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + begin + return mult(CONV_SIGNED(L, L'length+1), + CONV_SIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to plus + begin + return mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length+1)); -- pragma label mult + end; + + + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + begin + return STD_LOGIC_VECTOR (mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length))); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + begin + return STD_LOGIC_VECTOR (mult(CONV_UNSIGNED(L, L'length), + CONV_UNSIGNED(R, R'length))); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + begin + return STD_LOGIC_VECTOR (mult(CONV_SIGNED(L, L'length+1), + CONV_SIGNED(R, R'length))); -- pragma label mult + end; + + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + begin + return STD_LOGIC_VECTOR (mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length+1))); -- pragma label mult + end; + + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "+"(L: SIGNED; R: INTEGER) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: INTEGER; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)) ; -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))) ; -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_minus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: SIGNED; R: INTEGER) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: INTEGER; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (unsigned_minus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + + + function "+"(L: UNSIGNED) return UNSIGNED is + begin + return L; + end; + + + function "+"(L: SIGNED) return SIGNED is + begin + return L; + end; + + + function "-"(L: SIGNED) return SIGNED is + -- pragma label_applies_to minus + begin + return 0 - L; -- pragma label minus + end; + + + function "ABS"(L: SIGNED) return SIGNED is + begin + if (L(L'left) = '0' or L(L'left) = 'L') then + return L; + else + return 0 - L; + end if; + end; + + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L); + end; + + + function "+"(L: SIGNED) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L); + end; + + + function "-"(L: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable tmp: SIGNED(L'length-1 downto 0); + begin + tmp := 0 - L; -- pragma label minus + return STD_LOGIC_VECTOR (tmp); + end; + + + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR is + variable tmp: SIGNED(L'length-1 downto 0); + begin + if (L(L'left) = '0' or L(L'left) = 'L') then + return STD_LOGIC_VECTOR (L); + else + tmp := 0 - L; + return STD_LOGIC_VECTOR (tmp); + end if; + end; + + + -- Type propagation function which returns the type BOOLEAN + function UNSIGNED_RETURN_BOOLEAN(A,B: UNSIGNED) return BOOLEAN is + variable Z: BOOLEAN; + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns the type BOOLEAN + function SIGNED_RETURN_BOOLEAN(A,B: SIGNED) return BOOLEAN is + variable Z: BOOLEAN; + -- pragma return_port_name Z + begin + return(Z); + end; + + + -- compare two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function is_less(A, B: SIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LT_TC_OP + -- pragma type_function SIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + if A(sign) /= B(sign) then + result := A(sign) = '1'; + else + result := FALSE; + for i in 0 to sign-1 loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + end if; + return result; + end; + + + -- compare two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function is_less_or_equal(A, B: SIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LEQ_TC_OP + -- pragma type_function SIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + if A(sign) /= B(sign) then + result := A(sign) = '1'; + else + result := TRUE; + for i in 0 to sign-1 loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + end if; + return result; + end; + + + + -- compare two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_is_less(A, B: UNSIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LT_UNS_OP + -- pragma type_function UNSIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + result := FALSE; + for i in 0 to sign loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + return result; + end; + + + -- compare two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_is_less_or_equal(A, B: UNSIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LEQ_UNS_OP + -- pragma type_function UNSIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + result := TRUE; + for i in 0 to sign loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + return result; + end; + + + + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length, R'length); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := L'length + 1; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := R'length + 1; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := L'length; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := R'length; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less_or_equal(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length, R'length); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := L'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := R'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := L'length; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := R'length; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less(CONV_UNSIGNED(R, length), + CONV_UNSIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length, R'length); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := L'length + 1; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := R'length + 1; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := L'length; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := R'length; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less_or_equal(CONV_UNSIGNED(R, length), + CONV_UNSIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length, R'length); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := L'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := R'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := L'length; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := R'length; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + + + -- for internal use only. Assumes SIGNED arguments of equal length. + function bitwise_eql(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) + return BOOLEAN is + -- pragma built_in SYN_EQL + begin + for i in L'range loop + if L(i) /= R(i) then + return FALSE; + end if; + end loop; + return TRUE; + end; + + -- for internal use only. Assumes SIGNED arguments of equal length. + function bitwise_neq(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) + return BOOLEAN is + -- pragma built_in SYN_NEQ + begin + for i in L'range loop + if L(i) /= R(i) then + return TRUE; + end if; + end loop; + return FALSE; + end; + + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_UNSIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_UNSIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length + 1, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length + 1); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length + 1; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := R'length + 1; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: INTEGER; R: SIGNED) return BOOLEAN is + constant length: INTEGER := R'length; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_UNSIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_UNSIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length + 1, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length + 1); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length + 1; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := R'length + 1; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN is + constant length: INTEGER := R'length; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is UNSIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb downto 2**i) := + result(result_msb - 2**i downto 0); + end if; + result := temp; + end if; + end loop; + return result; + end; + + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is SIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb downto 2**i) := + result(result_msb - 2**i downto 0); + end if; + result := temp; + end if; + end loop; + return result; + end; + + + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is UNSIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb - 2**i downto 0) := + result(result_msb downto 2**i); + end if; + result := temp; + end if; + end loop; + return result; + end; + + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is SIGNED (result_msb downto 0); + variable result, temp: rtype; + variable sign_bit: STD_ULOGIC; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + sign_bit := ARG(ARG'left); + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => sign_bit); + if 2**i <= result_msb then + temp(result_msb - 2**i downto 0) := + result(result_msb downto 2**i); + end if; + result := temp; + end if; + end loop; + return result; + end; + + + + + function CONV_INTEGER(ARG: INTEGER) return INTEGER is + begin + return ARG; + end; + + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER is + variable result: INTEGER; + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_UNSIGNED_TO_INTEGER + begin + -- synopsys synthesis_off + assert ARG'length <= 31 + report "ARG is too large in CONV_INTEGER" + severity FAILURE; + result := 0; + for i in ARG'range loop + result := result * 2; + tmp := tbl_BINARY(ARG(i)); + if tmp = '1' then + result := result + 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_INTEGER(ARG: SIGNED) return INTEGER is + variable result: INTEGER; + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_SIGNED_TO_INTEGER + begin + -- synopsys synthesis_off + assert ARG'length <= 32 + report "ARG is too large in CONV_INTEGER" + severity FAILURE; + result := 0; + for i in ARG'range loop + if i /= ARG'left then + result := result * 2; + tmp := tbl_BINARY(ARG(i)); + if tmp = '1' then + result := result + 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + end if; + end if; + end loop; + tmp := MAKE_BINARY(ARG(ARG'left)); + if tmp = '1' then + if ARG'length = 32 then + result := (result - 2**30) - 2**30; + else + result := result - (2 ** (ARG'length-1)); + end if; + end if; + return result; + -- synopsys synthesis_on + end; + + + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT is + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_FEED_THRU + begin + -- synopsys synthesis_off + tmp := tbl_BINARY(ARG); + if tmp = '1' then + return 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + return 0; + else + return 0; + end if; + -- synopsys synthesis_on + end; + + + -- convert an integer to a unsigned STD_ULOGIC_VECTOR + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED is + variable result: UNSIGNED(SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_UNSIGNED + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable new_bounds: UNSIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable new_bounds: UNSIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED is + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + + -- convert an integer to a 2's complement STD_ULOGIC_VECTOR + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED is + variable result: SIGNED (SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_SIGNED + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is SIGNED (SIZE-1 downto 0); + variable new_bounds : SIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is SIGNED (SIZE-1 downto 0); + variable new_bounds : SIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED is + subtype rtype is SIGNED (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + + -- convert an integer to an STD_LOGIC_VECTOR + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR is + variable result: STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_SIGNED + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) return STD_LOGIC_VECTOR is + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) + return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds: STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + +end std_logic_arith; diff --git a/lib/models/memory/sdram/mt48lc32m4a2/test.do b/lib/models/memory/sdram/mt48lc32m4a2/test.do new file mode 100644 index 0000000..83a6f3b --- /dev/null +++ b/lib/models/memory/sdram/mt48lc32m4a2/test.do @@ -0,0 +1,5 @@ +vcom mt48lc32m4a2.vhd +vcom test.vhd +vsim tb +do wave.do +run -all diff --git a/lib/models/memory/sdram/mt48lc32m4a2/test.txt b/lib/models/memory/sdram/mt48lc32m4a2/test.txt new file mode 100644 index 0000000..ad4a459 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc32m4a2/test.txt @@ -0,0 +1,98 @@ +0 ns 1 1 1 1 1 0 00 0 -100 +22 ns 1 1 1 1 1 0 00 0 -100 +32 ns 1 1 1 1 1 0 00 0 -100 +42 ns 1 1 1 1 1 0 00 0 -100 +52 ns 1 1 1 1 1 0 00 0 -100 +62 ns 1 0 0 1 0 0 00 1024 -100 +72 ns 1 1 1 1 1 0 00 0 -100 +82 ns 1 1 1 1 1 0 00 0 -100 +92 ns 1 0 0 0 1 0 00 0 -100 +102 ns 1 1 1 1 1 0 00 0 -100 +112 ns 1 1 1 1 1 0 00 0 -100 +122 ns 1 1 1 1 1 0 00 0 -100 +132 ns 1 1 1 1 1 0 00 0 -100 +142 ns 1 1 1 1 1 0 00 0 -100 +152 ns 1 1 1 1 1 0 00 0 -100 +162 ns 1 1 1 1 1 0 00 0 -100 +172 ns 1 1 1 1 1 0 00 0 -100 +182 ns 1 0 0 0 1 0 00 0 -100 +192 ns 1 1 1 1 1 0 00 0 -100 +202 ns 1 1 1 1 1 0 00 0 -100 +212 ns 1 1 1 1 1 0 00 0 -100 +222 ns 1 1 1 1 1 0 00 0 -100 +232 ns 1 1 1 1 1 0 00 0 -100 +242 ns 1 1 1 1 1 0 00 0 -100 +252 ns 1 1 1 1 1 0 00 0 -100 +262 ns 1 1 1 1 1 0 00 0 -100 +272 ns 1 0 0 0 0 0 00 51 -100 +282 ns 1 1 1 1 1 0 00 0 -100 +292 ns 1 0 0 1 1 0 00 0 -100 +302 ns 1 1 1 1 1 0 00 0 -100 +312 ns 1 0 1 0 0 0 00 10 0 +322 ns 1 1 1 1 1 0 00 0 1 +332 ns 1 0 0 1 1 0 01 0 2 +342 ns 1 1 1 1 1 0 00 0 3 +352 ns 1 1 1 1 1 0 00 0 4 +362 ns 1 1 1 1 1 0 00 0 5 +372 ns 1 1 1 1 1 0 00 0 6 +382 ns 1 1 1 1 1 0 00 0 7 +392 ns 1 0 1 0 0 0 01 20 8 +402 ns 1 0 0 1 0 0 00 0 9 +412 ns 1 0 0 1 1 0 10 0 10 +422 ns 1 1 1 1 1 0 00 0 11 +432 ns 1 1 1 1 1 0 00 0 12 +442 ns 1 1 1 1 1 0 00 0 13 +452 ns 1 1 1 1 1 0 00 0 14 +462 ns 1 1 1 1 1 0 00 0 15 +472 ns 1 0 1 0 0 0 10 30 0 +482 ns 1 0 0 1 0 0 01 0 1 +492 ns 1 0 0 1 1 0 11 0 2 +502 ns 1 1 1 1 1 0 00 0 3 +512 ns 1 1 1 1 1 0 00 0 4 +522 ns 1 1 1 1 1 0 00 0 5 +532 ns 1 1 1 1 1 0 00 0 6 +542 ns 1 1 1 1 1 0 00 0 7 +552 ns 1 0 1 0 0 0 11 40 8 +562 ns 1 0 0 1 0 0 10 0 9 +572 ns 1 0 0 1 1 0 00 0 10 +582 ns 1 1 1 1 1 0 00 0 11 +592 ns 1 1 1 1 1 0 00 0 12 +602 ns 1 1 1 1 1 0 00 0 13 +612 ns 1 1 1 1 1 0 00 0 14 +622 ns 1 1 1 1 1 0 00 0 15 +632 ns 1 0 1 0 1 0 00 10 -100 +642 ns 1 0 0 1 0 0 11 0 -100 +652 ns 1 0 0 1 1 0 01 0 -100 +662 ns 1 1 1 1 1 0 00 0 -100 +672 ns 1 1 1 1 1 0 00 0 -100 +682 ns 1 1 1 1 1 0 00 0 -100 +692 ns 1 1 1 1 1 0 00 0 -100 +702 ns 1 1 1 1 1 0 00 0 -100 +712 ns 1 0 1 0 1 0 01 20 -100 +722 ns 1 0 0 1 0 0 00 0 -100 +732 ns 1 0 0 1 1 0 10 0 -100 +742 ns 1 1 1 1 1 0 00 0 -100 +752 ns 1 1 1 1 1 0 00 0 -100 +762 ns 1 1 1 1 1 0 00 0 -100 +772 ns 1 1 1 1 1 0 00 0 -100 +782 ns 1 1 1 1 1 0 00 0 -100 +792 ns 1 0 1 0 1 0 10 30 -100 +802 ns 1 0 0 1 0 0 01 0 -100 +812 ns 1 0 0 1 1 0 11 0 -100 +822 ns 1 1 1 1 1 0 00 0 -100 +832 ns 1 1 1 1 1 0 00 0 -100 +842 ns 1 1 1 1 1 0 00 0 -100 +852 ns 1 1 1 1 1 0 00 0 -100 +862 ns 1 1 1 1 1 0 00 0 -100 +872 ns 1 0 1 0 1 0 11 40 -100 +882 ns 1 0 0 1 0 0 10 0 -100 +892 ns 1 1 1 1 1 0 00 0 -100 +902 ns 1 1 1 1 1 0 00 0 -100 +912 ns 1 1 1 1 1 0 00 0 -100 +922 ns 1 1 1 1 1 0 00 0 -100 +932 ns 1 1 1 1 1 0 00 0 -100 +942 ns 1 1 1 1 1 0 00 0 -100 +952 ns 1 0 0 1 0 0 11 0 -100 +962 ns 1 1 1 1 1 0 00 0 -100 +972 ns 1 1 1 1 1 0 00 0 -100 +982 ns 1 1 1 1 1 0 00 0 -100 diff --git a/lib/models/memory/sdram/mt48lc32m4a2/test.vhd b/lib/models/memory/sdram/mt48lc32m4a2/test.vhd new file mode 100644 index 0000000..0d173f3 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc32m4a2/test.vhd @@ -0,0 +1,169 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE std.textio.ALL; +USE work.std_logic_arith.ALL; +USE work.util_1164.ALL; +USE work.mti_pkg.ALL; + +ENTITY tb IS +END tb; + + +ARCHITECTURE test OF tb IS + CONSTANT addr_bits : INTEGER := 12; + CONSTANT data_bits : INTEGER := 4; + CONSTANT clk_start : time := 5 ns; + CONSTANT clk_period : time := 10 ns; + CONSTANT continue_time : time := 10 ns; + + COMPONENT mt48lc32m4a2 + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '1'; + Cs_n : IN STD_LOGIC := '1'; + Cas_n : IN STD_LOGIC := '1'; + Ras_n : IN STD_LOGIC := '1'; + We_n : IN STD_LOGIC := '1'; + Dqm : IN STD_LOGIC := '0' + ); + END COMPONENT; + + FOR ALL : mt48lc32m4a2 USE ENTITY work.mt48lc32m4a2 (behave); + + SIGNAL pDq : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0); + SIGNAL pAddr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + SIGNAL pBa : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL pClk : STD_LOGIC; + SIGNAL pCke : STD_LOGIC; + SIGNAL pCs : STD_LOGIC; + SIGNAL pCas : STD_LOGIC; + SIGNAL pRas : STD_LOGIC; + SIGNAL pWe : STD_LOGIC; + SIGNAL pDqm : STD_LOGIC; + SIGNAL stim_done : boolean := false; + SIGNAL clk_done : boolean := false; + + +BEGIN + u1: mt48lc32m4a2 + PORT MAP( + Dq => pDq, + Addr => pAddr, + Ba => pBa, + Clk => pClk, + Cke => pCke, + Cs_n => pCs, + Ras_n => pRas, + Cas_n => pCas, + We_n => pWe, + Dqm => pDqm + ); + + stimulator : PROCESS + FILE stim_file:text IS IN "test.txt"; + --FILE stim_file:text IS IN "test1.txt"; + VARIABLE l : line; + VARIABLE time_var : TIME; + VARIABLE pCke_var : STD_LOGIC; + VARIABLE pCs_var : STD_LOGIC; + VARIABLE pRas_var : STD_LOGIC; + VARIABLE PCas_var : STD_LOGIC; + VARIABLE pWe_var : STD_LOGIC; + VARIABLE pDqm_var : STD_LOGIC; + VARIABLE pBa_var : STD_LOGIC_VECTOR (1 DOWNTO 0); + VARIABLE pAddr_var : INTEGER; + VARIABLE pDq_var : INTEGER; -- -100 is converted to hi-Z state + VARIABLE pMa_var_vect : STD_LOGIC_VECTOR(addr_bits - 1 DOWNTO 0); + CONSTANT HiZ : STD_LOGIC_VECTOR(data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + BEGIN + WHILE not ENDFILE(stim_file) LOOP + readline(stim_file,l); + IF l'length > 0 THEN + read(l, time_var); + read(l, pCke_var); + read(l, pCs_var); + read(l, pRas_var); + read(l, pCas_var); + read(l, pWe_var); + read(l, pDqm_var); + read(l, pBa_var); + read(l, pAddr_var); + read(l, pDq_var); + IF now > time_var THEN + ASSERT false + REPORT "Detected a time in the stim file that is in the past" + SEVERITY error; + ELSE + WAIT FOR time_var-now; + IF pWe_var='1' THEN + pCke <= pCke_var; + pCs <= pCs_var; + pRas <= pRas_var; + pCas <= pCas_var; + pWe <= pWe_var; + pDqm <= pDqm_var; + pBa <= pBa_var; + pMa_var_vect := CONV_STD_LOGIC_VECTOR(pAddr_var, addr_bits); + pAddr <= pMa_var_vect; + IF pDq_var = -100 THEN + pDq <= HiZ; + ELSE + pDq <= CONV_STD_LOGIC_VECTOR(pDq_var, data_bits); + END IF; + ELSE + pCke <= pCke_var; + pCs <= pCs_var; + pRas <= pRas_var; + pCas <= pCas_var; + pWe <= pWe_var; + pDqm <= pDqm_var; + pBa <= pBa_var; + pMa_var_vect := CONV_STD_LOGIC_VECTOR(pAddr_var, addr_bits); + pAddr <= pMa_var_vect; + IF pDq_var = -100 THEN + pDq <= HiZ; + ELSE + pDq <= CONV_STD_LOGIC_VECTOR(pDq_var, data_bits); + END IF; + END IF; + END IF; + END IF; + END LOOP; + ASSERT false + REPORT "End of Stimulation File Detected!" + SEVERITY note; + stim_done <= true; + WAIT; + END PROCESS; + + clock : PROCESS + VARIABLE done_time : time; + BEGIN + pclk <= '0'; + WAIT for clk_start; + WHILE not stim_done loop + pclk <= '1'; + WAIT for clk_period/2; + pclk <= '0'; + WAIT for clk_period/2; + END LOOP; + done_time := now+continue_time; + WHILE now < done_time LOOP --one last clock to finish last command + pclk <= '1'; + WAIT for clk_period/2; + pclk <= '0'; + WAIT for clk_period/2; + END LOOP; + ASSERT false + REPORT "Suspending clock activity" + SEVERITY note; + clk_done <= true; + WAIT; + END PROCESS; + +END test; + + diff --git a/lib/models/memory/sdram/mt48lc32m4a2/util1164.vhd b/lib/models/memory/sdram/mt48lc32m4a2/util1164.vhd new file mode 100644 index 0000000..bb4b5dd --- /dev/null +++ b/lib/models/memory/sdram/mt48lc32m4a2/util1164.vhd @@ -0,0 +1,124 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE STD.textio.ALL; + +PACKAGE util_1164 IS + PROCEDURE read(l: INOUT line; value: OUT std_logic); + PROCEDURE read(l: INOUT line; value: OUT std_logic_vector); + PROCEDURE write(l: INOUT line; value: IN std_logic_vector; + JUSTIFIED: IN SIDE := right; + FIELD: IN WIDTH := 0); + PROCEDURE Grow_line(L : inout LINE; incr : in integer); +END util_1164; + + + +PACKAGE BODY util_1164 IS + + FUNCTION white_space(value:character) RETURN boolean IS + VARIABLE result:boolean; + BEGIN + IF (value = ' ') OR (value = HT) THEN + RETURN true; + ELSE + RETURN false; + END IF; + END white_space; + + PROCEDURE read(l: INOUT line; value: OUT std_logic) IS + VARIABLE char_var: character:= ' '; + BEGIN + WHILE l'LENGTH > 0 LOOP + read(l,char_var); + IF NOT white_space(char_var) THEN + EXIT; + END IF; + END LOOP; + IF white_space(char_var) THEN + ASSERT false REPORT "No std_logic value found in file" + SEVERITY error; + value := 'X'; + RETURN; + END IF; + + CASE char_var IS + WHEN 'U'|'u' => value := 'U'; + WHEN '0' => value := '0'; + WHEN '1' => value := '1'; + WHEN 'X'|'x' => value := 'X'; + WHEN 'L'|'l' => value := 'L'; + WHEN 'H'|'h' => value := 'H'; + WHEN 'W'|'w' => value := 'W'; + WHEN 'Z'|'z' => value := 'Z'; + WHEN '-' => value := '-'; + WHEN OTHERS => + ASSERT false REPORT "Unrecognized value read for std_logic" + SEVERITY error; + value := 'X'; + END CASE; + END read; + + PROCEDURE read(l: INOUT line; value: OUT std_logic_vector) IS + BEGIN + FOR i IN value'HIGH DOWNTO value'LOW LOOP + IF l'LENGTH > 0 THEN + read(l,value(i)); + ELSE + ASSERT false REPORT "Not enough values for std_logic_vector in file" + SEVERITY error; + RETURN; + END IF; + END LOOP; + END read; + + procedure Grow_line(L : inout LINE; incr : in integer) + is + variable old_L : LINE := L; + variable bfp: integer; -- Blank fill pointer. + begin + assert incr > 0 + report "Textio: Grow_line called with zero increment." + severity error; + + if L = null then + bfp := 0; + L := new string(1 to incr); + else + bfp := old_L'high; + L := new string(old_L'low to old_L'high + incr); + L(old_L'low to old_L'high) := old_L.all; + Deallocate(old_L); + end if; + for i in 1 to incr loop + L(bfp + i) := ' '; + end loop; + end; + + + PROCEDURE write(l: INOUT line; value: IN std_logic_vector; + JUSTIFIED: IN SIDE := right; + FIELD: IN WIDTH := 0) IS + variable fw: integer := VALUE'length; + variable bp: integer; + variable offset: integer := 0; + alias normal : std_logic_vector(0 to value'length - 1) is value; + begin + if L /= null then + bp := L'high + 1; + else bp := 1; + end if; + if FIELD > VALUE'length then + fw := FIELD; + if JUSTIFIED = right then + offset := fw - VALUE'length; + end if; + end if; + Grow_line(L, fw); + for i in normal'range loop + L(bp + i + offset) := character'val( + std_logic'pos(normal(i)) + character'pos('0')); + end loop; + end; + + +END util_1164; diff --git a/lib/models/memory/sdram/mt48lc32m4a2/vec_gen.vhd b/lib/models/memory/sdram/mt48lc32m4a2/vec_gen.vhd new file mode 100644 index 0000000..821d321 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc32m4a2/vec_gen.vhd @@ -0,0 +1,372 @@ +------------------------------------------------------------------------------- +-- -- +-- This is a data generator for the testbench for Micron's Synchronous -- +-- DRAM. This generator reads a text file line-by-line and generates -- +-- a file of test vectors that is then read by the testbench and -- +-- applied to the part. -- +-- -- +-- This VHDL program creates a text file of test vectors that is used by the -- +-- test bench. Place your commands in a file (a copy of VEC_GEN.VHD) and run -- +-- VEC_GEN.VHD in your VHDL simulator (make sure you have compiled this -- +-- package prior to running the program VEC_GEN.VHD). This will produce the -- +-- vectors that are required to run the included testbench. Change the name -- +-- of the vector file to save your vectors in separate files. The default -- +-- file name for the output vectors generated from this pacakage is -- +-- "test.txt." -- +-- -- +-- Now compile and run the testbench program embedtb.vhd. The testbench uses -- +-- the default test.txt as input vectors. -- +-- -- +-- -- +-- Copyright 1997 Micron Technology, Inc. -- +-- -- +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.all; +USE std.textio.all; +USE work.io_utils.all; + + +PACKAGE generate_vectors IS + + CONSTANT set_up : TIME; + CONSTANT hold : TIME; + CONSTANT cycle_start : TIME; + + SIGNAL cycle : INTEGER := 0; + SIGNAL sim_time : TIME := 0 ns; + FILE output_file:TEXT IS OUT "test.txt"; + PROCEDURE write(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); + first_data : IN INTEGER; dqm : IN BIT; cke : IN BIT); + PROCEDURE read(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); dqm : IN BIT; cke : IN BIT); + PROCEDURE active(row_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); data_bus : IN INTEGER; dqm : IN BIT; cke : IN BIT); + PROCEDURE precharge(bank : IN BIT_VECTOR(1 DOWNTO 0); address : IN INTEGER; data_bus: IN INTEGER; dqm : IN BIT; cke : IN BIT); + PROCEDURE nop(data_bus : IN INTEGER; dqm : IN BIT; cke : IN BIT; cs : IN BIT); + PROCEDURE burst_term(data_bus : IN INTEGER; dqm : IN BIT; cke : IN BIT); + PROCEDURE auto_refresh; + PROCEDURE next_cycle(SIGNAL clk : IN BIT); + PROCEDURE load_array(load : IN BIT); + PROCEDURE load_mode_reg(op_code : IN INTEGER; cke : IN BIT); + PROCEDURE unload_array(row_start : IN INTEGER; row_end : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0)); + +END generate_vectors; + + +PACKAGE BODY generate_vectors IS + + CONSTANT set_up : TIME := 3 ns; + CONSTANT hold : TIME := 1 ns; + CONSTANT cycle_start : TIME := 0 ns; + + +PROCEDURE write(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); first_data : IN INTEGER; + dqm : IN BIT; cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 0, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, first_data, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE read(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); dqm : IN BIT; cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 0, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, -100, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE active(row_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); data_bus : IN INTEGER; dqm : IN BIT; cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 0, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, row_address, right, 6); --address +write(l, data_bus, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE precharge(bank : IN BIT_VECTOR(1 DOWNTO 0); address : IN INTEGER; data_bus: IN INTEGER; dqm : IN BIT; cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 0, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, address, right, 6); --address +write(l, data_bus, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE nop(data_bus : IN INTEGER; dqm : IN BIT; cke : IN BIT; cs : IN BIT) IS + + +VARIABLE l : LINE; +VARIABLE col_address : INTEGER := 0; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, cke, right, 4); --Cke +write(l, cs, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, data_bus, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + + +PROCEDURE burst_term(data_bus : IN INTEGER; dqm : IN BIT; cke : IN BIT) IS + +VARIABLE l : LINE; +VARIABLE col_address : INTEGER := 0; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, data_bus, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE auto_refresh IS + VARIABLE l : LINE; + VARIABLE dqm : BIT := '0'; + VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; +BEGIN + IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); + ELSE + write(l, now-set_up, left, 4, ns); + END IF; + write(l, 1, right, 4); --Cke + write(l, 0, right, 4); --Cs + write(l, 0, right, 4); --Ras + write(l, 0, right, 4); --Cas + write(l, 1, right, 4); --We + write(l, dqm, right, 4); --Dqm + write(l, bank, right, 4); --Ba + write(l, 0, right, 6); --address + write(l, -100, right, 6); --first data location + --write(l, 0, right, 4); --load + --write(l, 0, right, 4); --unload + --write(l, 0, right, 6); --row_address_start + --write(l, 0, right, 6); --row_address_end + writeline(output_file,l); --write vector to file +END; + + +PROCEDURE next_cycle(SIGNAL clk : IN BIT) IS + +BEGIN + +WAIT UNTIL clk = '1'; + +END; + +PROCEDURE load_array(load : IN BIT) IS + +VARIABLE l : LINE; +VARIABLE dqm : BIT := '0'; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, 1, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, 0, right, 6); --address +write(l, -100, right, 6); --first data location +--write(l, 1, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE unload_array(row_start : IN INTEGER; row_end : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0)) IS + +VARIABLE l : LINE; +VARIABLE dqm : BIT := '0'; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, 1, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, 0, right, 6); --address +write(l, -100, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 1, right, 4); --unload +--write(l, row_start, right, 6); --row_address_start +--write(l, row_end, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE load_mode_reg(op_code : IN INTEGER; cke : IN BIT) IS + +VARIABLE l : LINE; +VARIABLE dqm : BIT := '0'; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 0, right, 4); --Ras +write(l, 0, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, op_code, right, 6); --address +write(l, -100, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +END generate_vectors; + diff --git a/lib/models/memory/sdram/mt48lc32m4a2/vector.do b/lib/models/memory/sdram/mt48lc32m4a2/vector.do new file mode 100644 index 0000000..7480359 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc32m4a2/vector.do @@ -0,0 +1,4 @@ +vcom vec_gen.vhd +vcom ed_comnd.vhd +vsim vector_generate +run -all diff --git a/lib/models/memory/sdram/mt48lc32m4a2/wave.do b/lib/models/memory/sdram/mt48lc32m4a2/wave.do new file mode 100644 index 0000000..168e846 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc32m4a2/wave.do @@ -0,0 +1,31 @@ +onerror {resume} +add wave -logic -height 20 /tb/u1/clk +add wave -logic -height 20 /tb/u1/cke +add wave -logic -height 20 /tb/u1/cs_n +add wave -logic -height 20 /tb/u1/ras_n +add wave -logic -height 20 /tb/u1/cas_n +add wave -logic -height 20 /tb/u1/we_n +add wave -logic -unsigned -height 20 /tb/u1/addr +add wave -logic -height 20 /tb/u1/ba +add wave -logic -unsigned -height 20 /tb/u1/dq +add wave -logic -height 20 /tb/u1/dqm +add wave -literal -ascii -height 20 /tb/u1/operation +add wave -logic -unsigned -height 20 /tb/u1/mode_reg +add wave -logic -height 20 /tb/u1/active_enable +add wave -logic -height 20 /tb/u1/aref_enable +add wave -logic -height 20 /tb/u1/burst_term +add wave -logic -height 20 /tb/u1/mode_reg_enable +add wave -logic -height 20 /tb/u1/prech_enable +add wave -logic -height 20 /tb/u1/read_enable +add wave -logic -height 20 /tb/u1/write_enable +add wave -logic -height 20 /tb/u1/burst_length_1 +add wave -logic -height 20 /tb/u1/burst_length_2 +add wave -logic -height 20 /tb/u1/burst_length_4 +add wave -logic -height 20 /tb/u1/burst_length_8 +add wave -logic -height 20 /tb/u1/cas_latency_2 +add wave -logic -height 20 /tb/u1/cas_latency_3 +add wave -logic -height 20 /tb/u1/pre_chk +add wave -logic -height 20 /tb/u1/act_chk +add wave -logic -height 20 /tb/u1/bank_chk +add wave -logic -unsigned -height 20 /tb/u1/row_chk +add wave -logic -unsigned -height 20 /tb/u1/col_chk diff --git a/lib/models/memory/sdram/mt48lc4m16a2/base.do b/lib/models/memory/sdram/mt48lc4m16a2/base.do new file mode 100644 index 0000000..d2afbcb --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m16a2/base.do @@ -0,0 +1,5 @@ +vcom util1164.vhd +vcom stdlogar.vhd +vcom io_utils.vhd +vcom mti_pkg.vhd + diff --git a/lib/models/memory/sdram/mt48lc4m16a2/ed_comnd.vhd b/lib/models/memory/sdram/mt48lc4m16a2/ed_comnd.vhd new file mode 100644 index 0000000..489311e --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m16a2/ed_comnd.vhd @@ -0,0 +1,357 @@ +--------------------------------------------------------------------------------- +--COMMAND FORMAT -- +-- -- +-- write(column address(integer), bank(bit_vector), first data(integer), dqm(bit), cke(bit));-- +-- read(column address(integer), bank(bit_vector), dqm(bit), cke(bit)); -- +-- active(row address(integer), bank(bit_vector), data bus (integer), dqm(bit), cke(bit));-- +-- precharge(bank(bit_vector), address (integer), data bus(integer), dqm(bit), cke(bit)); -- +-- nop(data bus(integer), dqm(bit), cke(bit)); -- +-- burst_term(data bus(integer), dqm(bit_vector), cke(bit)); -- +-- load_array('1'); -- +-- load_mode_reg(register(integer), cke(bit)); -- +-- next_cycle(clk); This is used after every command(incl. nop) to clock -- +-- at the correct clock frequency entered in the clock -- +-- period constant below -- +-- unload_array(row_start(integer), row_end(integer), bank(bit_vector)) -- +-- load_mode_reg(op_code(integer)) -- +-- -- +--------------------------------------------------------------------------------- + +LIBRARY work; +LIBRARY ieee; +USE ieee.std_logic_1164.all; +USE std.textio.all; +USE work.generate_vectors.all; + +ENTITY vector_generate IS +END vector_generate; + +ARCHITECTURE vector_generate OF vector_generate IS + + SIGNAL stim_done : BOOLEAN := FALSE; + SIGNAL clk : BIT := '0'; + CONSTANT clk_start : time := 15 ns; + CONSTANT clk_period : time := 10 ns; + CONSTANT Z : INTEGER := -100; + +BEGIN + +PROCESS + +BEGIN + +WAIT UNTIL clk = '1' AND clk'EVENT; + +--------------------ENTER COMMANDS BELOW THIS LINE----------------------------- +--******************DO NOT USE -100 FOR A DQ VALUE*************************---- +--*******************Z WILL PLACE HI-Z ON THE BUS**************************---- +--*******USE next_cycle(clk) FOR ADVANCING TO NEXT CLOCK CYCLE*************---- + +nop(Z, "00", '1'); -- Always begin with one nop when using Micron's testbench + +next_cycle(clk); -- Load Memory Array +load_array('1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); -- Precharge All Banks +precharge("00", 1024, Z, "00", '1'); + +FOR i IN 1 to 2 LOOP + next_cycle(clk); + nop(Z, "00", '1'); +END LOOP; + +next_cycle(clk); -- First Auto Refresh +auto_refresh; + +FOR i IN 1 TO 8 LOOP + next_cycle(clk); + nop(Z, "00", '1'); +END LOOP; + +next_cycle(clk); -- Second Auto Refresh +auto_refresh; + +FOR i IN 1 TO 8 LOOP + next_cycle(clk); + nop(Z, "00", '1'); +END LOOP; + +next_cycle(clk); -- Load Mode Register (CAS Latency = 3, Burst Length = 8) +load_mode_reg(51, '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +-- Write Section + +next_cycle(clk); +active(0, "00", Z, "00", '1'); -- Activate Bank 0 + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); -- Write Bank 0 +write(0, "00", 10, "00", '1'); + +next_cycle(clk); +nop(11, "00", '1'); + +next_cycle(clk); +active(0, "01", 12, "00", '1'); -- Activate Bank 1 + +next_cycle(clk); +nop(13, "00", '1'); + +next_cycle(clk); +nop(14, "00", '1'); + +next_cycle(clk); +nop(15, "00", '1'); + +next_cycle(clk); +nop(16, "00", '1'); + +next_cycle(clk); +nop(17, "00", '1'); + +next_cycle(clk); +write(0, "01", 20, "00", '1'); -- Write Bank 1 + +next_cycle(clk); +precharge("00", 0, 21, "00", '1'); -- Precharge Bank 0 + +next_cycle(clk); +active(0, "10", 22, "00", '1'); -- Activate Bank 2 + +next_cycle(clk); +nop(23, "00", '1'); + +next_cycle(clk); +nop(24, "00", '1'); + +next_cycle(clk); +nop(25, "00", '1'); + +next_cycle(clk); +nop(26, "00", '1'); + +next_cycle(clk); +nop(27, "00", '1'); + +next_cycle(clk); +write(0, "10", 30, "00", '1'); -- Write Bank 2 + +next_cycle(clk); +precharge("01", 0, 31, "00", '1'); -- Precharge Bank 1 + +next_cycle(clk); +active(0, "11", 32, "00", '1'); -- Activate Bank 3 + +next_cycle(clk); +nop(33, "00", '1'); + +next_cycle(clk); +nop(34, "00", '1'); + +next_cycle(clk); +nop(35, "00", '1'); + +next_cycle(clk); +nop(36, "00", '1'); + +next_cycle(clk); +nop(37, "00", '1'); + +next_cycle(clk); +write(0, "11", 40, "00", '1'); -- Write Bank 3 + +next_cycle(clk); +precharge("10", 0, 41, "00", '1'); -- Precharge Bank 2 + +next_cycle(clk); +active(0, "00", 42, "00", '1'); -- Activate Bank 0 + +next_cycle(clk); +nop(43, "00", '1'); + +next_cycle(clk); +nop(44, "00", '1'); + +next_cycle(clk); +nop(45, "00", '1'); + +next_cycle(clk); +nop(46, "00", '1'); + +next_cycle(clk); +nop(47, "00", '1'); + +-- Read Section + +next_cycle(clk); +read(0, "00", "00", '1'); -- Read Bank 0 + +next_cycle(clk); +precharge("11", 0, Z, "00", '1'); -- Precharge Bank 3 + +next_cycle(clk); +active(0, "01", Z, "00", '1'); -- Activate Bank 1 + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +read(0, "01", "00", '1'); -- Read Bank 1 + +next_cycle(clk); +precharge("00", 0, Z, "00", '1'); -- Precharge Bank 0 + +next_cycle(clk); +active(0, "10", Z, "00", '1'); -- Activate Bank 2 + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +read(0, "10", "00", '1'); -- Read Bank 2 + +next_cycle(clk); +precharge("01", 0, Z, "00", '1'); -- Precharge Bank 1 + +next_cycle(clk); +active(0, "11", Z, "00", '1'); -- Activate Bank 3 + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +read(0, "11", "00", '1'); -- Read Bank 3 + +next_cycle(clk); +precharge("10", 0, Z, "00", '1'); -- Precharge Bank 2 + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +precharge("11", 0, Z, "00", '1'); -- Precharge Bank 3 + +next_cycle(clk); +nop(Z, "00", '1'); + +next_cycle(clk); +nop(Z, "00", '1'); + +--next_cycle(clk); -- Unload Bank 0 Memory Array +--unload_array(0, 3, "00"); + +--next_cycle(clk); -- Unload Bank 1 Memory Array +--unload_array(0, 3, "01"); + +--next_cycle(clk); -- Unload Bank 2 Memory Array +--unload_array(0, 3, "10"); + +--next_cycle(clk); -- Unload Bank 3 Memory Array +--unload_array(0, 3, "11"); + +next_cycle(clk); +nop(Z, "00", '1'); + +stim_done <= TRUE; --always include this line at the end of your stimulus + + + +------------------------------------------------------------------------------- +--*************************************************************************---- +END PROCESS; + + +clock: + PROCESS + VARIABLE done_time : time; + VARIABLE cycle_var : integer := 0; + BEGIN + cycle <= 0; + clk <= '0'; + WAIT for clk_start; + WHILE not stim_done loop + clk <= '1'; + cycle <= cycle_var; + WAIT for clk_period/2; + cycle_var := cycle_var + 1; + clk <= '0'; + WAIT for clk_period/2; + END LOOP; + + ASSERT (FALSE) + REPORT "Test Vectors Generated" + SEVERITY note; + + WAIT; + END PROCESS; + + +END; diff --git a/lib/models/memory/sdram/mt48lc4m16a2/io_utils.vhd b/lib/models/memory/sdram/mt48lc4m16a2/io_utils.vhd new file mode 100644 index 0000000..dfcb84a --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m16a2/io_utils.vhd @@ -0,0 +1,266 @@ +LIBRARY ieee; +USE std.textio.ALL; +USE ieee.std_logic_1164.ALL; + +PACKAGE io_utils IS + + PROCEDURE write_string(l : INOUT line; + value : IN string; + justified : IN side := right; + field : IN width := 0); + + TYPE radix IS (binary, octal, decimal, hex); + + -- read a number from the line + -- use this if you have hex numbers that are not in VHDL pound-sign format + PROCEDURE read(l : INOUT line; value : OUT integer; radix : IN positive); + + -- read a number that might be in VHDL pound-sign format + PROCEDURE read_based(l : INOUT line; value : OUT integer); + + PROCEDURE write(l : INOUT line; + value : IN std_logic_vector; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false); + + PROCEDURE write(l : INOUT line; + value : IN integer; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false); +END io_utils; + +PACKAGE BODY io_utils IS + + PROCEDURE write_string(l : INOUT line; + value : IN string; + justified : IN side := right; + field : IN width := 0) + IS + BEGIN + write(l, value, justified, field); + END; + + PROCEDURE shrink_line(l : INOUT line; pos : integer) IS + VARIABLE tmpl : line; + BEGIN + tmpl := l; + l := NEW string'(tmpl(pos TO tmpl'high)); + deallocate(tmpl); + END; + + PROCEDURE read(l : INOUT line; + value : OUT integer; + radix : IN positive) + IS + CONSTANT not_digit : integer := -999; + + -- convert a character to a value from 0 to 15 + FUNCTION digit_value(c : character) RETURN integer IS + BEGIN + IF (c >= '0') AND (c <= '9') THEN + RETURN (character'pos(c) - character'pos('0')); + ELSIF (c >= 'a') AND (c <= 'f') THEN + RETURN (character'pos(c) - character'pos('a') + 10); + ELSIF (c >= 'A') AND (c <= 'F') THEN + RETURN (character'pos(c) - character'pos('A') + 10); + ELSE + RETURN not_digit; + END IF; + END; + + -- skip leading white space in the line + PROCEDURE skip_white(VARIABLE l : IN line; pos : OUT integer) IS + BEGIN + pos := l'low; + FOR i IN l'low TO l'high LOOP + CASE l(i) IS + WHEN ' ' | ht => + pos := i + 1; + WHEN OTHERS => + EXIT; + END CASE; + END LOOP; + END; + + VARIABLE digit : integer; + VARIABLE result : integer := 0; + VARIABLE pos : integer; + BEGIN + -- skip white space + skip_white(l, pos); + + -- calculate the value + FOR i IN pos TO l'right LOOP + digit := digit_value(l(i)); + EXIT WHEN (digit = not_digit) OR (digit >= radix); + result := result * radix + digit; + pos := i + 1; + END LOOP; + value := result; + + -- remove the "used" characters from the line + shrink_line(l, pos); + END; + + PROCEDURE read_based(l : INOUT line; value : OUT integer) IS + VARIABLE digit : integer; + VARIABLE num : integer; + VARIABLE base : integer; + BEGIN + read(l, num, 10); + IF (l'length > 1) AND (l(l'left) = '#') THEN + shrink_line(l, l'left+1); + base := num; + read(l, num, base); + IF (l'length >= 1) AND (l(l'left) = '#') THEN + shrink_line(l, l'left+1); + END IF; + END IF; + value := num; + END; + + PROCEDURE write(l : INOUT line; + value : IN std_logic_vector; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false) + IS + FUNCTION to_int(bv : std_logic_vector) RETURN integer + IS + VARIABLE result : integer := 0; + BEGIN + FOR i IN bv'RANGE LOOP + result := result * 2; + IF (bv(i) = '1') THEN + result := result + 1; + END IF; + END LOOP; + RETURN result; + END; + + TYPE array_of_widths IS ARRAY(radix) OF natural; + CONSTANT nibble_widths : array_of_widths := ( + binary => 1, + octal => 3, + hex => 4, + decimal=> 32); + CONSTANT hex_digit : string(1 TO 16) := "0123456789ABCDEF"; + + ALIAS input_val : std_logic_vector(value'length DOWNTO 1) IS value; + CONSTANT nibble_width : natural := nibble_widths(base); + CONSTANT result_width : natural := (value'length + nibble_width - 1)/nibble_width; + + VARIABLE result : string(1 TO result_width); -- longest possible value + VARIABLE result_pos : positive := 1; + VARIABLE nibble_val : integer; + VARIABLE bitcnt : integer; + BEGIN + IF base = decimal THEN + write(l, to_int(value), justified, field, base, use_pound); + RETURN; + END IF; + + bitcnt := value'length MOD nibble_width; + IF (bitcnt = 0) THEN + bitcnt := nibble_width; + END IF; + FOR i IN input_val'RANGE LOOP + nibble_val := nibble_val * 2; + IF (input_val(i) = '1') THEN + nibble_val := nibble_val + 1; + END IF; + bitcnt := bitcnt - 1; + IF (bitcnt = 0) THEN + result(result_pos) := hex_digit(nibble_val + 1); + result_pos := result_pos + 1; + nibble_val := 0; + bitcnt := nibble_width; + END IF; + END LOOP; + write(l, result, justified, field); + END; + + PROCEDURE write(l : INOUT line; + value : IN integer; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false) + IS + FUNCTION to_bv(int : integer) RETURN std_logic_vector + IS + VARIABLE bv : std_logic_vector(32 DOWNTO 1) := (OTHERS => '0'); + VARIABLE pos : integer := 0; + VARIABLE tmpval : integer := int; + BEGIN + FOR i IN 1 TO 32 LOOP + pos := pos + 1; + IF (tmpval MOD 2) = 1 THEN + bv(i) := '1'; + END IF; + tmpval := tmpval / 2; + EXIT WHEN tmpval = 0; + END LOOP; + RETURN bv(pos DOWNTO 1); + END; + + VARIABLE tmp : line; + BEGIN + IF (base = decimal) THEN + IF (use_pound) THEN + write_string(tmp, "10#"); + END IF; + write(tmp, value); + IF (use_pound) THEN + write_string(tmp, "#"); + END IF; + write(l, tmp.ALL, justified, field); + deallocate(tmp); + ELSE + write(l, to_bv(value), justified, field, base, use_pound); + END IF; + END; + +END io_utils; + + + +-- test the hex number reader +--ENTITY test IS END; + +--USE std.textio.ALL; +--USE work.io_utils.ALL; +--ARCHITECTURE hex_test OF test IS +--BEGIN +-- PROCESS +-- VARIABLE val : integer; +-- FILE myfile : text IS IN "values"; +-- VARIABLE inline : line; +-- VARIABLE outline : line; +-- BEGIN +-- WHILE NOT endfile(myfile) LOOP +-- readline(myfile, inline); + +-- write(outline, inline.ALL); +-- +-- read_based(inline, val); + -- write_string(outline, " binary: "); + -- write(outline, val, base => binary); + -- write_string(outline, " octal: "); + -- write(outline, val, base => octal); + -- write_string(outline, " decimal: "); + -- write(outline, val, base => decimal); +-- write_string(outline, " hex: "); +-- write(outline, val, base => hex); +-- writeline(output, outline); +-- END LOOP; +-- WAIT; +-- END PROCESS; +--END; + + diff --git a/lib/models/memory/sdram/mt48lc4m16a2/loaddata.txt b/lib/models/memory/sdram/mt48lc4m16a2/loaddata.txt new file mode 100644 index 0000000..c7599a9 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m16a2/loaddata.txt @@ -0,0 +1,40 @@ +0 0 00 0 -- ROW (HEX), COL (HEX), BANK (BIN), DATA (HEX) +0 1 00 1 +0 2 00 2 +0 3 00 3 +0 4 00 4 +0 5 00 5 +0 6 00 6 +0 7 00 7 +0 8 00 8 +0 9 00 9 +0 0 01 10 +0 1 01 11 +0 2 01 12 +0 3 01 13 +0 4 01 14 +0 5 01 15 +0 6 01 16 +0 7 01 17 +0 8 01 18 +0 9 01 19 +0 0 10 20 +0 1 10 21 +0 2 10 22 +0 3 10 23 +0 4 10 24 +0 5 10 25 +0 6 10 26 +0 7 10 27 +0 8 10 28 +0 9 10 29 +0 0 11 30 +0 1 11 31 +0 2 11 32 +0 3 11 33 +0 4 11 34 +0 5 11 35 +0 6 11 36 +0 7 11 37 +0 8 11 38 +0 9 11 39 diff --git a/lib/models/memory/sdram/mt48lc4m16a2/mt48lc4m16a2.vhd b/lib/models/memory/sdram/mt48lc4m16a2/mt48lc4m16a2.vhd new file mode 100644 index 0000000..45df8d2 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m16a2/mt48lc4m16a2.vhd @@ -0,0 +1,1356 @@ +----------------------------------------------------------------------------------------- +-- +-- File Name: MT48LC4M16A2.VHD +-- Version: 0.0f +-- Date: July 8th, 1999 +-- Model: Behavioral +-- Simulator: Model Technology (PC version 5.2e PE) +-- +-- Dependencies: None +-- +-- Author: Son P. Huynh +-- Email: sphuynh@micron.com +-- Phone: (208) 368-3825 +-- Company: Micron Technology, Inc. +-- Part Number: MT48LC4M16A2 (1Mb x 16 x 4 Banks) +-- +-- Description: Micron 64Mb SDRAM +-- +-- Limitation: - Doesn't check for 4096-cycle refresh +-- +-- Note: - Set simulator resolution to "ps" accuracy +-- +-- Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY +-- WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY +-- IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR +-- A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT. +-- +-- Copyright (c) 1998 Micron Semiconductor Products, Inc. +-- All rights researved +-- +-- Rev Author Phone Date Changes +-- ---- ---------------------------- ---------- ------------------------------------- +-- 0.0f Son Huynh 208-368-3825 07/08/1999 Fix tWR = 1 Clk + 7.5 ns (Auto) +-- Micron Technology Inc. Fix tWR = 15 ns (Manual) +-- Fix tRP (Autoprecharge to AutoRefresh) +-- +-- 0.0e Son P. Huynh 208-368-3825 05/25/1999 Fix R/W Interrupting R/W with AP +-- Micron Technology Inc. +-- +-- 0.0d Son P. Huynh 208-368-3825 04/08/1999 Fix tWR + tRP in Write with AP +-- Micron Technology Inc. +-- +-- 0.0c Son P. Huynh 208-368-3825 01/14/1998 Add Load / Unload memory array +-- Micron Technology Inc. +-- +-- 0.0b Son P. Huynh 208-368-3825 12/09/1998 Fix some timing check problem +-- Micron Technology Inc. - Improve model functionality +-- +-- 0.0a Son P. Huynh 208-368-3825 08/10/1998 First Release +-- Micron Technology Inc. - Simple testbench included +----------------------------------------------------------------------------------------- + +LIBRARY std; + USE std.textio.ALL; +LIBRARY ieee; + USE ieee.std_logic_1164.ALL; +LIBRARY work; + USE work.io_utils.ALL; + USE work.mti_pkg.ALL; + +ENTITY mt48lc4m16a2 IS + GENERIC ( + -- Timing Parameters for -75 (PC133) and CAS Latency = 2 + tAC : TIME := 6.0 ns; + tHZ : TIME := 7.0 ns; + tOH : TIME := 2.7 ns; + tMRD : INTEGER := 2; -- 2 Clk Cycles + tRAS : TIME := 44.0 ns; + tRC : TIME := 66.0 ns; + tRCD : TIME := 20.0 ns; + tRP : TIME := 20.0 ns; + tRRD : TIME := 15.0 ns; + tWRa : TIME := 7.5 ns; -- A2 Version - Auto precharge mode only (1 Clk + 7.5 ns) + tWRp : TIME := 15.0 ns; -- A2 Version - Precharge mode only (15 ns) + + tAH : TIME := 0.8 ns; + tAS : TIME := 1.5 ns; + tCH : TIME := 2.5 ns; + tCL : TIME := 2.5 ns; + tCK : TIME := 10.0 ns; + tDH : TIME := 0.8 ns; + tDS : TIME := 1.5 ns; + tCKH : TIME := 0.8 ns; + tCKS : TIME := 1.5 ns; + tCMH : TIME := 0.8 ns; + tCMS : TIME := 1.5 ns; + + addr_bits : INTEGER := 12; + data_bits : INTEGER := 16; + col_bits : INTEGER := 8 + ); + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC_VECTOR := "00"; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '1'; + Cs_n : IN STD_LOGIC := '1'; + Ras_n : IN STD_LOGIC := '1'; + Cas_n : IN STD_LOGIC := '1'; + We_n : IN STD_LOGIC := '1'; + Dqm : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"; + Load : IN STD_LOGIC := '0'; + Unload : IN STD_LOGIC := '0'; + Row_start : IN INTEGER := 0; + Row_end : IN INTEGER := 0 + ); +END mt48lc4m16a2; + +ARCHITECTURE behave OF mt48lc4m16a2 IS + TYPE State IS (ACT, A_REF, BST, LMR, NOP, PRECH, READ, READ_A, WRITE, WRITE_A, FILE_LOAD, FILE_UNLOAD); + TYPE Array4xI IS ARRAY (3 DOWNTO 0) OF INTEGER; + TYPE Array4xT IS ARRAY (3 DOWNTO 0) OF TIME; + TYPE Array4xB IS ARRAY (3 DOWNTO 0) OF BIT; + TYPE Array4x2BV IS ARRAY (3 DOWNTO 0) OF BIT_VECTOR (1 DOWNTO 0); + TYPE Array4xCBV IS ARRAY (4 DOWNTO 0) OF BIT_VECTOR (Col_bits - 1 DOWNTO 0); + TYPE Array_state IS ARRAY (4 DOWNTO 0) OF State; + SIGNAL Operation : State := NOP; + SIGNAL Mode_reg : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL Active_enable, Aref_enable, Burst_term : BIT := '0'; + SIGNAL Mode_reg_enable, Prech_enable, Read_enable, Write_enable : BIT := '0'; + SIGNAL Burst_length_1, Burst_length_2, Burst_length_4, Burst_length_8 : BIT := '0'; + SIGNAL Cas_latency_2, Cas_latency_3 : BIT := '0'; + SIGNAL Ras_in, Cas_in, We_in : BIT := '0'; + SIGNAL Write_burst_mode : BIT := '0'; + SIGNAL Sys_clk, CkeZ : BIT := '0'; + SIGNAL WR_counter : Array4xI := (0 & 0 & 0 & 0); + + -- Checking internal wires + SIGNAL Pre_chk : BIT_VECTOR (3 DOWNTO 0) := "0000"; + SIGNAL Act_chk : BIT_VECTOR (3 DOWNTO 0) := "0000"; + SIGNAL Dq_in_chk, Dq_out_chk : BIT := '0'; + SIGNAL Bank_chk : BIT_VECTOR (1 DOWNTO 0) := "00"; + SIGNAL Row_chk : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL Col_chk : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + + BEGIN + -- CS# Decode + WITH Cs_n SELECT + Cas_in <= TO_BIT (Cas_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + WITH Cs_n SELECT + Ras_in <= TO_BIT (Ras_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + WITH Cs_n SELECT + We_in <= TO_BIT (We_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + + -- Commands Decode + Active_enable <= NOT(Ras_in) AND Cas_in AND We_in; + Aref_enable <= NOT(Ras_in) AND NOT(Cas_in) AND We_in; + Burst_term <= Ras_in AND Cas_in AND NOT(We_in); + Mode_reg_enable <= NOT(Ras_in) AND NOT(Cas_in) AND NOT(We_in); + Prech_enable <= NOT(Ras_in) AND Cas_in AND NOT(We_in); + Read_enable <= Ras_in AND NOT(Cas_in) AND We_in; + Write_enable <= Ras_in AND NOT(Cas_in) AND NOT(We_in); + + -- Burst Length Decode + Burst_length_1 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND NOT(Mode_reg(0)); + Burst_length_2 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND Mode_reg(0); + Burst_length_4 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND NOT(Mode_reg(0)); + Burst_length_8 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND Mode_reg(0); + + -- CAS Latency Decode + Cas_latency_2 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND NOT(Mode_reg(4)); + Cas_latency_3 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND Mode_reg(4); + + -- Write Burst Mode + Write_burst_mode <= Mode_reg(9); + + -- System Clock + int_clk : PROCESS (Clk) + begin + IF Clk'LAST_VALUE = '0' AND Clk = '1' THEN + CkeZ <= TO_BIT(Cke, '1'); + END IF; + Sys_clk <= CkeZ AND TO_BIT(Clk, '0'); + END PROCESS; + + state_register : PROCESS + TYPE ram_type IS ARRAY (2**col_bits - 1 DOWNTO 0) OF BIT_VECTOR (data_bits - 1 DOWNTO 0); + TYPE ram_pntr IS ACCESS ram_type; + TYPE ram_stor IS ARRAY (2**addr_bits - 1 DOWNTO 0) OF ram_pntr; + VARIABLE Bank0 : ram_stor; + VARIABLE Bank1 : ram_stor; + VARIABLE Bank2 : ram_stor; + VARIABLE Bank3 : ram_stor; + VARIABLE Row_index, Col_index : INTEGER := 0; + VARIABLE Dq_temp : BIT_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => '0'); + + VARIABLE Col_addr : Array4xCBV; + VARIABLE Bank_addr : Array4x2BV; + VARIABLE Dqm_reg0, Dqm_reg1 : BIT_VECTOR (1 DOWNTO 0) := "00"; + + VARIABLE Bank, Previous_bank : BIT_VECTOR (1 DOWNTO 0) := "00"; + VARIABLE B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col_brst : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Row : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Burst_counter : INTEGER := 0; + + VARIABLE Command : Array_state; + VARIABLE Bank_precharge : Array4x2BV; + VARIABLE A10_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Auto_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Read_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Write_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Count_precharge : Array4xI := (0 & 0 & 0 & 0); + VARIABLE RW_interrupt_write : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_read : Array4xB := ('0' & '0' & '0' & '0'); + + VARIABLE Data_in_enable, Data_out_enable : BIT := '0'; + VARIABLE Pc_b0, Pc_b1, Pc_b2, Pc_b3 : BIT := '0'; + VARIABLE Act_b0, Act_b1, Act_b2, Act_b3 : BIT := '0'; + + -- Timing Check + VARIABLE MRD_chk : INTEGER := 0; + VARIABLE RC_chk, RRD_chk : TIME := 0 ns; + VARIABLE RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3 : TIME := 0 ns; + VARIABLE RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3 : TIME := 0 ns; + VARIABLE RP_chk0, RP_chk1, RP_chk2, RP_chk3 : TIME := 0 ns; + VARIABLE WR_chk : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + + -- Load and Unload variables + FILE load_file : TEXT IS IN "loaddata.txt"; -- Data load + FILE out_file0 : TEXT IS OUT "outdata0.txt"; -- Data dump for bank 0 + FILE out_file1 : TEXT IS OUT "outdata1.txt"; -- Data dump for bank 1 + FILE out_file2 : TEXT IS OUT "outdata2.txt"; -- Data dump for bank 2 + FILE out_file3 : TEXT IS OUT "outdata3.txt"; -- Data dump for bank 3 + VARIABLE l_in, l_out0, l_out1, l_out2, l_out3 : LINE; + VARIABLE array_buffer : BIT_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE write_data_var : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE row_load, col_load, dq_load : INTEGER; + VARIABLE ba_load : BIT_VECTOR (1 DOWNTO 0); + VARIABLE dq_vec : BIT_VECTOR (data_bits - 1 DOWNTO 0); + VARIABLE i, j, k : INTEGER; + + -- Initialize empty rows + PROCEDURE Init_mem (Bank : BIT_VECTOR (1 DOWNTO 0); Row_index : INTEGER) IS + VARIABLE i, j : INTEGER := 0; + BEGIN + IF Bank = "00" THEN + IF Bank0 (Row_index) = NULL THEN -- Check to see if row empty + Bank0 (Row_index) := NEW ram_type; -- Open new row for access + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP -- Filled row with zeros + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank0 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "01" THEN + IF Bank1 (Row_index) = NULL THEN + Bank1 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank1 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "10" THEN + IF Bank2 (Row_index) = NULL THEN + Bank2 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank2 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "11" THEN + IF Bank3 (Row_index) = NULL THEN + Bank3 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank3 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + END IF; + END; + + -- Burst Counter + PROCEDURE Burst_decode IS + VARIABLE Col_int : INTEGER := 0; + VARIABLE Col_vec, Col_temp : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + BEGIN + -- Advance Burst Counter + Burst_counter := Burst_counter + 1; + + -- Burst Type + IF Mode_reg (3) = '0' THEN + Col_int := TO_INTEGER(Col); + Col_int := Col_int + 1; + TO_BITVECTOR (Col_int, Col_temp); + ELSIF Mode_reg (3) = '1' THEN + TO_BITVECTOR (Burst_counter, Col_vec); + Col_temp (2) := Col_vec (2) XOR Col_brst (2); + Col_temp (1) := Col_vec (1) XOR Col_brst (1); + Col_temp (0) := Col_vec (0) XOR Col_brst (0); + END IF; + + -- Burst Length + IF Burst_length_2 = '1' THEN + Col (0) := Col_temp (0); + ELSIF Burst_length_4 = '1' THEN + Col (1 DOWNTO 0) := Col_temp (1 DOWNTO 0); + ELSIF Burst_length_8 = '1' THEN + Col (2 DOWNTO 0) := Col_temp (2 DOWNTO 0); + ELSE + Col := Col_temp; + END IF; + + -- Burst Read Single Write + IF Write_burst_mode = '1' AND Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Data counter + IF Burst_length_1 = '1' THEN + IF Burst_counter >= 1 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_2 = '1' THEN + IF Burst_counter >= 2 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_4 = '1' THEN + IF Burst_counter >= 4 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_8 = '1' THEN + IF Burst_counter >= 8 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + END IF; + END; + + BEGIN + WAIT ON Sys_clk, WR_counter(0), WR_counter(1), WR_counter(2), WR_counter(3); + IF Sys_clk'event and Sys_clk = '1' AND Load = '0' AND Unload = '0' THEN + -- Internal Command Pipeline + Command(0) := Command(1); + Command(1) := Command(2); + Command(2) := Command(3); + Command(3) := NOP; + + Col_addr(0) := Col_addr(1); + Col_addr(1) := Col_addr(2); + Col_addr(2) := Col_addr(3); + Col_addr(3) := (OTHERS => '0'); + + Bank_addr(0) := Bank_addr(1); + Bank_addr(1) := Bank_addr(2); + Bank_addr(2) := Bank_addr(3); + Bank_addr(3) := "00"; + + Bank_precharge(0) := Bank_precharge(1); + Bank_precharge(1) := Bank_precharge(2); + Bank_precharge(2) := Bank_precharge(3); + Bank_precharge(3) := "00"; + + A10_precharge(0) := A10_precharge(1); + A10_precharge(1) := A10_precharge(2); + A10_precharge(2) := A10_precharge(3); + A10_precharge(3) := '0'; + + -- Operation Decode (Optional for showing current command on posedge clock / debug feature) + IF Active_enable = '1' THEN + Operation <= ACT; + ELSIF Aref_enable = '1' THEN + Operation <= A_REF; + ELSIF Burst_term = '1' THEN + Operation <= BST; + ELSIF Mode_reg_enable = '1' THEN + Operation <= LMR; + ELSIF Prech_enable = '1' THEN + Operation <= PRECH; + ELSIF Read_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= READ; + ELSE + Operation <= READ_A; + END IF; + ELSIF Write_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= WRITE; + ELSE + Operation <= WRITE_A; + END IF; + ELSE + Operation <= NOP; + END IF; + + -- Dqm pipeline for Read + Dqm_reg0 := Dqm_reg1; + Dqm_reg1 := TO_BITVECTOR(Dqm); + + -- Read or Write with Auto Precharge Counter + IF Auto_precharge (0) = '1' THEN + Count_precharge (0) := Count_precharge (0) + 1; + END IF; + IF Auto_precharge (1) = '1' THEN + Count_precharge (1) := Count_precharge (1) + 1; + END IF; + IF Auto_precharge (2) = '1' THEN + Count_precharge (2) := Count_precharge (2) + 1; + END IF; + IF Auto_precharge (3) = '1' THEN + Count_precharge (3) := Count_precharge (3) + 1; + END IF; + + -- tMRD Counter + MRD_chk := MRD_chk + 1; + + -- tWR Counter + WR_counter(0) <= WR_counter(0) + 1; + WR_counter(1) <= WR_counter(1) + 1; + WR_counter(2) <= WR_counter(2) + 1; + WR_counter(3) <= WR_counter(3) + 1; + + -- Auto Refresh + IF Aref_enable = '1' THEN + -- Auto Refresh to Auto Refresh + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Auto Refresh" + SEVERITY WARNING; + -- Precharge to Auto Refresh + ASSERT (NOW - RP_chk0 >= tRP OR NOW - RP_chk1 >= tRP OR NOW - RP_chk2 >= tRP OR NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Auto Refresh" + SEVERITY WARNING; + -- All banks must be idle before refresh + IF (Pc_b3 ='0' OR Pc_b2 = '0' OR Pc_b1 ='0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All banks must be Precharge before Auto Refresh" + SEVERITY WARNING; + END IF; + -- Record current tRC time + RC_chk := NOW; + END IF; + + -- Load Mode Register + IF Mode_reg_enable = '1' THEN + Mode_reg <= TO_BITVECTOR (Addr); + IF (Pc_b3 ='0' OR Pc_b2 = '0' OR Pc_b1 ='0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All bank must be Precharge before Load Mode Register" + SEVERITY WARNING; + END IF; + -- REF to LMR + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Load Mode Register" + SEVERITY WARNING; + -- LMR to LMR + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Load Mode Register" + SEVERITY WARNING; + -- Record current tMRD time + MRD_chk := 0; + END IF; + + -- Active Block (latch Bank and Row Address) + IF Active_enable = '1' THEN + IF Ba = "00" AND Pc_b0 = '1' THEN + Act_b0 := '1'; + Pc_b0 := '0'; + B0_row_addr := TO_BITVECTOR (Addr); + RCD_chk0 := NOW; + RAS_chk0 := NOW; + -- Precharge to Active Bank 0 + ASSERT (NOW - RP_chk0 >= tRP) + REPORT "tRP violation during Activate Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '1' THEN + Act_b1 := '1'; + Pc_b1 := '0'; + B1_row_addr := TO_BITVECTOR (Addr); + RCD_chk1 := NOW; + RAS_chk1 := NOW; + -- Precharge to Active Bank 1 + ASSERT (NOW - RP_chk1 >= tRP) + REPORT "tRP violation during Activate Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '1' THEN + Act_b2 := '1'; + Pc_b2 := '0'; + B2_row_addr := TO_BITVECTOR (Addr); + RCD_chk2 := NOW; + RAS_chk2 := NOW; + -- Precharge to Active Bank 2 + ASSERT (NOW - RP_chk2 >= tRP) + REPORT "tRP violation during Activate Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '1' THEN + Act_b3 := '1'; + Pc_b3 := '0'; + B3_row_addr := TO_BITVECTOR (Addr); + RCD_chk3 := NOW; + RAS_chk3 := NOW; + -- Precharge to Active Bank 3 + ASSERT (NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Activate Bank 3" + SEVERITY WARNING; + ELSIF Ba = "00" AND Pc_b0 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 0 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 1 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 2 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 3 is not Precharged" + SEVERITY WARNING; + END IF; + -- Active Bank A to Active Bank B + IF ((Previous_bank /= TO_BITVECTOR (Ba)) AND (NOW - RRD_chk < tRRD)) THEN + ASSERT (FALSE) + REPORT "tRRD violation during Activate" + SEVERITY WARNING; + END IF; + -- LMR to ACT + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Activate" + SEVERITY WARNING; + -- AutoRefresh to Activate + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Activate" + SEVERITY WARNING; + -- Record variable for checking violation + RRD_chk := NOW; + Previous_bank := TO_BITVECTOR (Ba); + END IF; + + -- Precharge Block + IF Prech_enable = '1' THEN + IF Addr(10) = '1' THEN + Pc_b0 := '1'; + Pc_b1 := '1'; + Pc_b2 := '1'; + Pc_b3 := '1'; + Act_b0 := '0'; + Act_b1 := '0'; + Act_b2 := '0'; + Act_b3 := '0'; + RP_chk0 := NOW; + RP_chk1 := NOW; + RP_chk2 := NOW; + RP_chk3 := NOW; + -- Activate to Precharge all banks + ASSERT ((NOW - RAS_chk0 >= tRAS) OR (NOW - RAS_chk1 >= tRAS)) + REPORT "tRAS violation during Precharge all banks" + SEVERITY WARNING; + -- tWR violation check for Write + IF ((NOW - WR_chk(0) < tWRp) OR (NOW - WR_chk(1) < tWRp) OR + (NOW - WR_chk(2) < tWRp) OR (NOW - WR_chk(3) < tWRp)) THEN + ASSERT (FALSE) + REPORT "tWR violation during Precharge ALL banks" + SEVERITY WARNING; + END IF; + ELSIF Addr(10) = '0' THEN + IF Ba = "00" THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + -- Activate to Precharge bank 0 + ASSERT (NOW - RAS_chk0 >= tRAS) + REPORT "tRAS violation during Precharge bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + -- Activate to Precharge bank 1 + ASSERT (NOW - RAS_chk1 >= tRAS) + REPORT "tRAS violation during Precharge bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + -- Activate to Precharge bank 2 + ASSERT (NOW - RAS_chk2 >= tRAS) + REPORT "tRAS violation during Precharge bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + -- Activate to Precharge bank 3 + ASSERT (NOW - RAS_chk3 >= tRAS) + REPORT "tRAS violation during Precharge bank 3" + SEVERITY WARNING; + END IF; + -- tWR violation check for Write + ASSERT (NOW - WR_chk(TO_INTEGER(Ba)) >= tWRp) + REPORT "tWR violation during Precharge" + SEVERITY WARNING; + END IF; + -- Terminate a Write Immediately (if same bank or all banks) + IF (Data_in_enable = '1' AND (Bank = TO_BITVECTOR(Ba) OR Addr(10) = '1')) THEN + Data_in_enable := '0'; + END IF; + -- Precharge Command Pipeline for READ + IF CAS_latency_3 = '1' THEN + Command(2) := PRECH; + Bank_precharge(2) := TO_BITVECTOR (Ba); + A10_precharge(2) := TO_BIT(Addr(10)); + ELSIF CAS_latency_2 = '1' THEN + Command(1) := PRECH; + Bank_precharge(1) := TO_BITVECTOR (Ba); + A10_precharge(1) := TO_BIT(Addr(10)); + END IF; + END IF; + + -- Burst Terminate + IF Burst_term = '1' THEN + -- Terminate a Write immediately + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + -- Terminate a Read depend on CAS Latency + IF CAS_latency_3 = '1' THEN + Command(2) := BST; + ELSIF CAS_latency_2 = '1' THEN + Command(1) := BST; + END IF; + END IF; + + -- Read, Write, Column Latch + IF Read_enable = '1' OR Write_enable = '1' THEN + -- Check to see if bank is open (ACT) for Read or Write + IF ((Ba = "00" AND Pc_b0 = '1') OR (Ba = "01" AND Pc_b1 = '1') OR (Ba = "10" AND Pc_b2 = '1') OR (Ba = "11" AND Pc_b3 = '1')) THEN + ASSERT (FALSE) + REPORT "Cannot Read or Write - Bank is not Activated" + SEVERITY WARNING; + END IF; + -- Activate to Read or Write + IF Ba = "00" THEN + ASSERT (NOW - RCD_chk0 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + ASSERT (NOW - RCD_chk1 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + ASSERT (NOW - RCD_chk2 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + ASSERT (NOW - RCD_chk3 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 3" + SEVERITY WARNING; + END IF; + -- Read Command + IF Read_enable = '1' THEN + -- CAS Latency Pipeline + IF Cas_latency_3 = '1' THEN + IF Addr(10) = '1' THEN + Command(2) := READ_A; + ELSE + Command(2) := READ; + END IF; + Col_addr (2) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0)); + Bank_addr (2) := TO_BITVECTOR (Ba); + ELSIF Cas_latency_2 = '1' THEN + IF Addr(10) = '1' THEN + Command(1) := READ_A; + ELSE + Command(1) := READ; + END IF; + Col_addr (1) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0)); + Bank_addr (1) := TO_BITVECTOR (Ba); + END IF; + + -- Read intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Write Command + ELSIF Write_enable = '1' THEN + IF Addr(10) = '1' THEN + Command(0) := WRITE_A; + ELSE + Command(0) := WRITE; + END IF; + Col_addr (0) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0)); + Bank_addr (0) := TO_BITVECTOR (Ba); + + -- Write intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Write interrupt a Read (terminate Read immediately) + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + + -- Interrupt a Write with Auto Precharge + IF Auto_precharge(TO_INTEGER(Bank)) = '1' AND Write_precharge(TO_INTEGER(Bank)) = '1' THEN + RW_interrupt_write(TO_INTEGER(Bank)) := '1'; + END IF; + + -- Interrupt a Read with Auto Precharge + IF Auto_precharge(TO_INTEGER(Bank)) = '1' AND Read_precharge(TO_INTEGER(Bank)) = '1' THEN + RW_interrupt_read(TO_INTEGER(Bank)) := '1'; + END IF; + + -- Read or Write with Auto Precharge + IF Addr(10) = '1' THEN + Auto_precharge (TO_INTEGER(Ba)) := '1'; + Count_precharge (TO_INTEGER(Ba)) := 0; + IF Read_enable = '1' THEN + Read_precharge (TO_INTEGER(Ba)) := '1'; + ELSIF Write_enable = '1' THEN + Write_precharge (TO_INTEGER(Ba)) := '1'; + END IF; + END IF; + END IF; + + -- Read with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. BL/2 cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Read_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(0) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8))) OR + (RW_interrupt_read(0) = '1')) THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + Auto_precharge(0) := '0'; + Read_precharge(0) := '0'; + RW_interrupt_read(0) := '0'; + END IF; + END IF; + IF ((Auto_precharge(1) = '1') AND (Read_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(1) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8))) OR + (RW_interrupt_read(1) = '1')) THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + Auto_precharge(1) := '0'; + Read_precharge(1) := '0'; + RW_interrupt_read(1) := '0'; + END IF; + END IF; + IF ((Auto_precharge(2) = '1') AND (Read_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(2) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8))) OR + (RW_interrupt_read(2) = '1')) THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + Auto_precharge(2) := '0'; + Read_precharge(2) := '0'; + RW_interrupt_read(2) := '0'; + END IF; + END IF; + IF ((Auto_precharge(3) = '1') AND (Read_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(3) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8))) OR + (RW_interrupt_read(3) = '1')) THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + Auto_precharge(3) := '0'; + Read_precharge(3) := '0'; + RW_interrupt_read(3) := '0'; + END IF; + END IF; + + -- Internal Precharge or Bst + IF Command(0) = PRECH THEN -- PRECH terminate a read if same bank or all banks + IF Bank_precharge(0) = Bank OR A10_precharge(0) = '1' THEN + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Command(0) = BST THEN -- BST terminate a read regardless of bank + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + + IF Data_out_enable = '0' THEN + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tOH; + END IF; + + -- Detect Read or Write Command + IF Command(0) = READ OR Command(0) = READ_A THEN + Bank := Bank_addr (0); + Col := Col_addr (0); + Col_brst := Col_addr (0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '0'; + Data_out_enable := '1'; + ELSIF Command(0) = WRITE OR Command(0) = WRITE_A THEN + Bank := Bank_addr(0); + Col := Col_addr(0); + Col_brst := Col_addr(0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '1'; + Data_out_enable := '0'; + END IF; + + -- DQ (Driver / Receiver) + Row_index := TO_INTEGER (Row); + Col_index := TO_INTEGER (Col); + IF Data_in_enable = '1' THEN + IF Dqm /= "11" THEN + Init_mem (Bank, Row_index); + IF Bank = "00" THEN + Dq_temp := Bank0 (Row_index) (Col_index); + IF Dqm = "01" THEN + Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8)); + ELSIF Dqm = "10" THEN + Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0)); + ELSE + Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0)); + END IF; + Bank0 (Row_index) (Col_index) := Dq_temp; + ELSIF Bank = "01" THEN + Dq_temp := Bank1 (Row_index) (Col_index); + IF Dqm = "01" THEN + Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8)); + ELSIF Dqm = "10" THEN + Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0)); + ELSE + Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0)); + END IF; + Bank1 (Row_index) (Col_index) := Dq_temp; + ELSIF Bank = "10" THEN + Dq_temp := Bank2 (Row_index) (Col_index); + IF Dqm = "01" THEN + Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8)); + ELSIF Dqm = "10" THEN + Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0)); + ELSE + Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0)); + END IF; + Bank2 (Row_index) (Col_index) := Dq_temp; + ELSIF Bank = "11" THEN + Dq_temp := Bank3 (Row_index) (Col_index); + IF Dqm = "01" THEN + Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8)); + ELSIF Dqm = "10" THEN + Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0)); + ELSE + Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0)); + END IF; + Bank3 (Row_index) (Col_index) := Dq_temp; + END IF; + WR_chk(TO_INTEGER(Bank)) := NOW; + WR_counter(TO_INTEGER(Bank)) <= 0; + END IF; + Burst_decode; + ELSIF Data_out_enable = '1' THEN + IF Dqm_reg0 /= "11" THEN + Init_mem (Bank, Row_index); + IF Bank = "00" THEN + Dq_temp (15 DOWNTO 0) := Bank0 (Row_index) (Col_index); + IF Dqm_reg0 = "00" THEN + Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC; + ELSIF Dqm_reg0 = "01" THEN + Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + ELSIF Dqm_reg0 = "10" THEN + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC; + END IF; + ELSIF Bank = "01" THEN + Dq_temp (15 DOWNTO 0) := Bank1 (Row_index) (Col_index); + IF Dqm_reg0 = "00" THEN + Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC; + ELSIF Dqm_reg0 = "01" THEN + Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + ELSIF Dqm_reg0 = "10" THEN + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC; + END IF; + ELSIF Bank = "10" THEN + Dq_temp (15 DOWNTO 0) := Bank2 (Row_index) (Col_index); + IF Dqm_reg0 = "00" THEN + Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC; + ELSIF Dqm_reg0 = "01" THEN + Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + ELSIF Dqm_reg0 = "10" THEN + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC; + END IF; + ELSIF Bank = "11" THEN + Dq_temp (15 DOWNTO 0) := Bank3 (Row_index) (Col_index); + IF Dqm_reg0 = "00" THEN + Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC; + ELSIF Dqm_reg0 = "01" THEN + Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + ELSIF Dqm_reg0 = "10" THEN + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC; + END IF; + END IF; + ELSE + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tHZ; + END IF; + Burst_decode; + END IF; + + ELSIF Sys_clk'event and Sys_clk = '1' AND Load = '1' AND Unload = '0' THEN + Operation <= FILE_LOAD; + WHILE NOT ENDFILE (load_file) LOOP + READLINE (load_file, l_in); + IF l_in'LENGTH > 0 THEN + read (l_in, row_load, 16); -- Load from HEX to INTEGER + read (l_in, col_load, 16); -- Load from HEX to INTEGER + read (l_in, ba_load); + read (l_in, dq_load, 16); -- Load from HEX to INTEGER + + TO_BITVECTOR (dq_load, dq_vec); + + IF ba_load = "00" THEN + IF Bank0(row_load) = NULL THEN --initialize new memory block + Bank0(row_load) := new ram_type; + FOR i IN (2**(col_bits))-1 DOWNTO 0 LOOP + FOR k IN data_bits - 1 DOWNTO 0 LOOP + Bank0(row_load) (i) (k) := '0'; + END LOOP; + END LOOP; + END IF; + Bank0(row_load)(col_load) := dq_vec; + ELSIF ba_load = "01" THEN + IF Bank1(row_load) = NULL THEN --initialize new memory block + Bank1(row_load) := new ram_type; + FOR i IN (2**(col_bits))-1 DOWNTO 0 LOOP + FOR k IN data_bits - 1 DOWNTO 0 LOOP + Bank1(row_load) (i) (k) := '0'; + END LOOP; + END LOOP; + END IF; + Bank1(row_load)(col_load) := dq_vec; + ELSIF ba_load = "10" THEN + IF Bank2(row_load) = NULL THEN --initialize new memory block + Bank2(row_load) := new ram_type; + FOR i IN (2**(col_bits))-1 DOWNTO 0 LOOP + FOR k IN data_bits - 1 DOWNTO 0 LOOP + Bank2(row_load) (i) (k) := '0'; + END LOOP; + END LOOP; + END IF; + Bank2(row_load)(col_load) := dq_vec; + ELSIF ba_load = "11" THEN + IF Bank3(row_load) = NULL THEN --initialize new memory block + Bank3(row_load) := new ram_type; + FOR i IN (2**(col_bits))-1 DOWNTO 0 LOOP + FOR k IN data_bits - 1 DOWNTO 0 LOOP + Bank3(row_load) (i) (k) := '0'; + END LOOP; + END LOOP; + END IF; + Bank3(row_load)(col_load) := dq_vec; + END IF; + END IF; + END LOOP; + ELSIF Sys_clk'event and Sys_clk = '1' AND Load = '0' AND Unload = '1' THEN + Operation <= FILE_UNLOAD; + ASSERT (Row_start < 2**(Addr'HIGH + 1)) + REPORT "Row_start is out of range for device" + SEVERITY ERROR; + ASSERT (Row_end < 2**(Addr'HIGH + 1)) + REPORT "Row_end is out of range for device" + SEVERITY ERROR; + ASSERT ((Row_end - Row_start) >= 0) + REPORT "The Row ranges for Unload is invalid!" + SEVERITY ERROR; + IF ((Row_end - Row_start) >= 0) THEN + FOR i IN Row_start TO Row_end LOOP + j := 1; + IF (Ba = "00") THEN -- Unload Bank 0 + WRITE (l_out0, STRING'("Micron Technology Inc. - Unload Data Array - Bank 0 Row ")); + WRITE (l_out0, i, RIGHT, 3, HEX, FALSE); + WRITELINE (out_file0, l_out0); + FOR k IN 0 TO ((2**Col_bits) - 1) LOOP -- Display Row and Column + IF (j = 1) THEN + WRITE (l_out0, i, RIGHT, 3, HEX, FALSE); + WRITE (l_out0, STRING'(" : ")); + WRITE (l_out0, k, RIGHT, 3, HEX, FALSE); + WRITE (l_out0, STRING'(" : ")); + END IF; + + IF (Bank0 (i) = NULL) THEN -- Row is empty, write message and exit + WRITE (l_out0, STRING'(" Row ")); + WRITE (l_out0, i); + WRITE (l_out0, STRING'(" is empty.")); + WRITELINE (out_file0, l_out0); + EXIT; + ELSE -- Buffering + array_buffer := Bank0 (i) (k); + END IF; + + write_data_var := TO_STDLOGICVECTOR(array_buffer); -- Convert to STD_LOGIC_VECTOR + WRITE (l_out0, write_data_var, RIGHT, 6, HEX, FALSE); -- Write message + IF (j = 16) then + WRITELINE (out_file0, l_out0); + j := 1; + ELSE + j := j + 1; + END IF; + END LOOP; + ELSIF (Ba = "01") THEN + WRITE (l_out1, STRING'("Micron Technology Inc. - Unload Data Array - Bank 1 Row ")); + WRITE (l_out1, i, RIGHT, 3, HEX, FALSE); + WRITELINE (out_file1, l_out1); + FOR k IN 0 TO ((2**Col_bits) - 1) LOOP + IF (j = 1) THEN + WRITE (l_out1, i, RIGHT, 3, HEX, FALSE); + WRITE (l_out1, STRING'(" : ")); + WRITE (l_out1, k, RIGHT, 3, HEX, FALSE); + WRITE (l_out1, STRING'(" : ")); + END IF; + + IF (Bank1 (i) = NULL) THEN + WRITE (l_out1, STRING'(" Row ")); + WRITE (l_out1, i); + WRITE (l_out1, STRING'(" is empty.")); + WRITELINE (out_file1, l_out1); + EXIT; + ELSE + array_buffer := Bank1 (i) (k); + END IF; + + write_data_var := TO_STDLOGICVECTOR(array_buffer); + WRITE (l_out1, write_data_var, RIGHT, 6, HEX, FALSE); + IF (j = 16) then + WRITELINE (out_file1, l_out1); + j := 1; + ELSE + j := j + 1; + END IF; + END LOOP; + ELSIF (Ba = "10") THEN + WRITE (l_out2, STRING'("Micron Technology Inc. - Unload Data Array - Bank 2 Row ")); + WRITE (l_out2, i, RIGHT, 3, HEX, FALSE); + WRITELINE (out_file2, l_out2); + FOR k IN 0 TO ((2**Col_bits) - 1) LOOP + IF (j = 1) THEN + WRITE (l_out2, i, RIGHT, 3, HEX, FALSE); + WRITE (l_out2, STRING'(" : ")); + WRITE (l_out2, k, RIGHT, 3, HEX, FALSE); + WRITE (l_out2, STRING'(" : ")); + END IF; + + IF (Bank2 (i) = NULL) THEN + WRITE (l_out2, STRING'(" Row ")); + WRITE (l_out2, i); + WRITE (l_out2, STRING'(" is empty.")); + WRITELINE (out_file2, l_out2); + EXIT; + ELSE + array_buffer := Bank2 (i) (k); + END IF; + + write_data_var := TO_STDLOGICVECTOR(array_buffer); + WRITE (l_out2, write_data_var, RIGHT, 6, HEX, FALSE); + IF (j = 16) then + WRITELINE (out_file2, l_out2); + j := 1; + ELSE + j := j + 1; + END IF; + END LOOP; + ELSIF (Ba = "11") THEN + WRITE (l_out3, STRING'("Micron Technology Inc. - Unload Data Array - Bank 3 Row ")); + WRITE (l_out3, i, RIGHT, 3, HEX, FALSE); + WRITELINE (out_file3, l_out3); + FOR k IN 0 TO ((2**Col_bits) - 1) LOOP + IF (j = 1) THEN + WRITE (l_out3, i, RIGHT, 3, HEX, FALSE); + WRITE (l_out3, STRING'(" : ")); + WRITE (l_out3, k, RIGHT, 3, HEX, FALSE); + WRITE (l_out3, STRING'(" : ")); + END IF; + + IF (Bank3 (i) = NULL) THEN + WRITE (l_out3, STRING'(" Row ")); + WRITE (l_out3, i); + WRITE (l_out3, STRING'(" is empty.")); + WRITELINE (out_file3, l_out3); + EXIT; + ELSE + array_buffer := Bank3 (i) (k); + END IF; + + write_data_var := TO_STDLOGICVECTOR(array_buffer); + WRITE (l_out3, write_data_var, RIGHT, 6, HEX, FALSE); + IF (j = 16) then + WRITELINE (out_file3, l_out3); + j := 1; + ELSE + j := j + 1; + END IF; + END LOOP; + END IF; + END LOOP; + END IF; + + END IF; + + -- Write with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. tWR cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Write_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(0) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8))) OR + (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 2)) THEN + Auto_precharge(0) := '0'; + Write_precharge(0) := '0'; + RW_interrupt_write(0) := '0'; + WAIT FOR tWRa; + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + END IF; + END IF; + + IF ((Auto_precharge(1) = '1') AND (Write_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(1) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8))) OR + (RW_interrupt_write(1) = '1' AND WR_counter(1) >= 2)) THEN + Auto_precharge(1) := '0'; + Write_precharge(1) := '0'; + RW_interrupt_write(1) := '0'; + WAIT FOR tWRa; + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + END IF; + END IF; + + IF ((Auto_precharge(2) = '1') AND (Write_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(2) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8))) OR + (RW_interrupt_write(2) = '1' AND WR_counter(2) >= 2)) THEN + Auto_precharge(2) := '0'; + Write_precharge(2) := '0'; + RW_interrupt_write(2) := '0'; + WAIT FOR tWRa; + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + END IF; + END IF; + + IF ((Auto_precharge(3) = '1') AND (Write_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(3) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8))) OR + (RW_interrupt_write(3) = '1' AND WR_counter(3) >= 2)) THEN + Auto_precharge(3) := '0'; + Write_precharge(3) := '0'; + RW_interrupt_write(3) := '0'; + WAIT FOR tWRa; + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + END IF; + END IF; + + -- Checking internal wires (Optional for debug purpose) + Pre_chk (0) <= Pc_b0; + Pre_chk (1) <= Pc_b1; + Pre_chk (2) <= Pc_b2; + Pre_chk (3) <= Pc_b3; + Act_chk (0) <= Act_b0; + Act_chk (1) <= Act_b1; + Act_chk (2) <= Act_b2; + Act_chk (3) <= Act_b3; + Dq_in_chk <= Data_in_enable; + Dq_out_chk <= Data_out_enable; + Bank_chk <= Bank; + Row_chk <= Row; + Col_chk <= Col; + END PROCESS; + + + -- Clock timing checks + Clock_check : PROCESS + VARIABLE Clk_low, Clk_high : TIME := 0 ns; + BEGIN + WAIT ON Clk; + IF (Clk = '1' AND NOW >= 10 ns) THEN + ASSERT (NOW - Clk_low >= tCL) + REPORT "tCL violation" + SEVERITY WARNING; + ASSERT (NOW - Clk_high >= tCK) + REPORT "tCK violation" + SEVERITY WARNING; + Clk_high := NOW; + ELSIF (Clk = '0' AND NOW /= 0 ns) THEN + ASSERT (NOW - Clk_high >= tCH) + REPORT "tCH violation" + SEVERITY WARNING; + Clk_low := NOW; + END IF; + END PROCESS; + + -- Setup timing checks + Setup_check : PROCESS + BEGIN + WAIT ON Clk; + IF Clk = '1' THEN + ASSERT(Cke'LAST_EVENT >= tCKS) + REPORT "CKE Setup time violation -- tCKS" + SEVERITY WARNING; + ASSERT(Cs_n'LAST_EVENT >= tCMS) + REPORT "CS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT >= tCMS) + REPORT "CAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT >= tCMS) + REPORT "RAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT >= tCMS) + REPORT "WE# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT >= tCMS) + REPORT "Dqm Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Addr'LAST_EVENT >= tAS) + REPORT "ADDR Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT >= tAS) + REPORT "BA Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Dq'LAST_EVENT >= tDS) + REPORT "Dq Setup time violation -- tDS" + SEVERITY WARNING; + END IF; + END PROCESS; + + -- Hold timing checks + Hold_check : PROCESS + BEGIN + WAIT ON Clk'DELAYED (tCKH), Clk'DELAYED (tCMH), Clk'DELAYED (tAH), Clk'DELAYED (tDH); + IF Clk'DELAYED (tCKH) = '1' THEN + ASSERT(Cke'LAST_EVENT > tCKH) + REPORT "CKE Hold time violation -- tCKH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tCMH) = '1' THEN + ASSERT(Cs_n'LAST_EVENT > tCMH) + REPORT "CS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT > tCMH) + REPORT "CAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT > tCMH) + REPORT "RAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT > tCMH) + REPORT "WE# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT > tCMH) + REPORT "Dqm Hold time violation -- tCMH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tAH) = '1' THEN + ASSERT(Addr'LAST_EVENT > tAH) + REPORT "ADDR Hold time violation -- tAH" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT > tAH) + REPORT "BA Hold time violation -- tAH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tDH) = '1' THEN + ASSERT(Dq'LAST_EVENT > tDH) + REPORT "Dq Hold time violation -- tDH" + SEVERITY WARNING; + END IF; + END PROCESS; + +END behave; diff --git a/lib/models/memory/sdram/mt48lc4m16a2/mti_pkg.vhd b/lib/models/memory/sdram/mt48lc4m16a2/mti_pkg.vhd new file mode 100644 index 0000000..7ab90da --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m16a2/mti_pkg.vhd @@ -0,0 +1,128 @@ +-- ---------------------------------------------------------------------------- +-- +-- Micron Semiconductor Products, Inc. +-- +-- Copyright 1997, Micron Semiconductor Products, Inc. +-- All rights reserved. +-- +-- ---------------------------------------------------------------------------- + +LIBRARY work; +LIBRARY ieee; + USE ieee.std_logic_1164.ALL; + +PACKAGE mti_pkg IS + + FUNCTION TO_INTEGER (input : BIT) RETURN INTEGER; + FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER; + FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER; + FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER; + PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR); + +END mti_pkg; + +PACKAGE BODY mti_pkg IS + + FUNCTION TO_INTEGER (input : BIT) RETURN INTEGER IS + BEGIN + CASE input IS + WHEN '0' => RETURN 0; + WHEN '1' => RETURN 1; + WHEN OTHERS => RETURN 0; + END CASE; + END TO_INTEGER; + + FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER IS + BEGIN + CASE input IS + WHEN '0' | 'L' => RETURN 0; + WHEN '1' | 'H' => RETURN 1; + WHEN OTHERS => RETURN 0; + END CASE; + END TO_INTEGER; + + FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + FOR i IN input'LOW TO input'HIGH LOOP + IF input(i) = '1' THEN + result := result + weight; + END IF; + weight := weight * 2; + END LOOP; + RETURN result; + END TO_INTEGER; + + FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + FOR i IN input'LOW TO input'HIGH LOOP + IF input(i) = '1' OR input(i) = 'H' THEN + result := result + weight; + END IF; + weight := weight * 2; + END LOOP; + RETURN result; + END TO_INTEGER; + + PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR) IS + VARIABLE work,offset,outputlen,j : INTEGER := 0; + BEGIN + --length of vector + IF output'LENGTH > 32 THEN + outputlen := 32; + offset := output'LENGTH - 32; + IF input >= 0 THEN + FOR i IN offset-1 DOWNTO 0 LOOP + output(output'HIGH - i) := '0'; + END LOOP; + ELSE + FOR i IN offset-1 DOWNTO 0 LOOP + output(output'HIGH - i) := '1'; + END LOOP; + END IF; + ELSE + outputlen := output'LENGTH; + END IF; + --positive value + IF (input >= 0) THEN + work := input; + j := outputlen - 1; + FOR i IN 1 to 32 LOOP + IF j >= 0 then + IF (work MOD 2) = 0 THEN + output(output'HIGH-j-offset) := '0'; + ELSE + output(output'HIGH-j-offset) := '1'; + END IF; + END IF; + work := work / 2; + j := j - 1; + END LOOP; + IF outputlen = 32 THEN + output(output'HIGH) := '0'; + END IF; + --negative value + ELSE + work := (-input) - 1; + j := outputlen - 1; + FOR i IN 1 TO 32 LOOP + IF j>= 0 THEN + IF (work MOD 2) = 0 THEN + output(output'HIGH-j-offset) := '1'; + ELSE + output(output'HIGH-j-offset) := '0'; + END IF; + END IF; + work := work / 2; + j := j - 1; + END LOOP; + IF outputlen = 32 THEN + output(output'HIGH) := '1'; + END IF; + END IF; + END TO_BITVECTOR; + +END mti_pkg; diff --git a/lib/models/memory/sdram/mt48lc4m16a2/outdata0.txt b/lib/models/memory/sdram/mt48lc4m16a2/outdata0.txt new file mode 100644 index 0000000..e69de29 diff --git a/lib/models/memory/sdram/mt48lc4m16a2/outdata1.txt b/lib/models/memory/sdram/mt48lc4m16a2/outdata1.txt new file mode 100644 index 0000000..e69de29 diff --git a/lib/models/memory/sdram/mt48lc4m16a2/outdata2.txt b/lib/models/memory/sdram/mt48lc4m16a2/outdata2.txt new file mode 100644 index 0000000..e69de29 diff --git a/lib/models/memory/sdram/mt48lc4m16a2/outdata3.txt b/lib/models/memory/sdram/mt48lc4m16a2/outdata3.txt new file mode 100644 index 0000000..e69de29 diff --git a/lib/models/memory/sdram/mt48lc4m16a2/readme.txt b/lib/models/memory/sdram/mt48lc4m16a2/readme.txt new file mode 100644 index 0000000..df7ad5c --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m16a2/readme.txt @@ -0,0 +1,14 @@ +To operate the test bench for the Micron SDRAM VHDL model, follow the directions +given below: + +1. Be sure all supporting files for the SDRAM are compiled into your library: + + util1164.vhd + stdlogar.vhd + io_utils.vhd + mti_pkg.vhd + +2. Next, compile the mt48lc4m16a2.vhd file and the test.vhd file. + +3. Simulate the "tb" architecture. This is the testbench for the 64Mb SDRAM. + diff --git a/lib/models/memory/sdram/mt48lc4m16a2/runall.do b/lib/models/memory/sdram/mt48lc4m16a2/runall.do new file mode 100644 index 0000000..0cde4e3 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m16a2/runall.do @@ -0,0 +1,42 @@ +vcom util1164.vhd +vcom stdlogar.vhd +vcom io_utils.vhd +vcom mti_pkg.vhd +vcom vec_gen.vhd +vcom ed_comnd.vhd +vsim vector_generate +run -all +vcom mt48lc4m16a2.vhd +vcom test.vhd +vsim tb +add wave -logic /u1/clk +add wave -logic /u1/cke +add wave -logic /u1/cs_n +add wave -logic /u1/ras_n +add wave -logic /u1/cas_n +add wave -logic /u1/we_n +add wave -literal -dec /u1/addr +add wave -literal -dec /u1/ba +add wave -literal -dec /u1/dq +add wave -literal /u1/dqm +add wave -literal /u1/operation +add wave -literal -dec /u1/mode_reg +add wave -logic /u1/active_enable +add wave -logic /u1/aref_enable +add wave -logic /u1/burst_term +add wave -logic /u1/mode_reg_enable +add wave -logic /u1/prech_enable +add wave -logic /u1/read_enable +add wave -logic /u1/write_enable +add wave -logic /u1/burst_length_1 +add wave -logic /u1/burst_length_2 +add wave -logic /u1/burst_length_4 +add wave -logic /u1/burst_length_8 +add wave -logic /u1/cas_latency_2 +add wave -logic /u1/cas_latency_3 +add wave -literal /u1/pre_chk +add wave -literal /u1/act_chk +add wave -literal /u1/bank_chk +add wave -literal -dec /u1/row_chk +add wave -literal -dec /u1/col_chk +run -all diff --git a/lib/models/memory/sdram/mt48lc4m16a2/stdlogar.vhd b/lib/models/memory/sdram/mt48lc4m16a2/stdlogar.vhd new file mode 100644 index 0000000..e435ea2 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m16a2/stdlogar.vhd @@ -0,0 +1,2247 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990,1991,1992 by Synopsys, Inc. All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_ARITH -- +-- -- +-- Purpose: -- +-- A set of arithemtic, conversion, and comparison functions -- +-- for SIGNED, UNSIGNED, SMALL_INT, INTEGER, -- +-- STD_ULOGIC, STD_LOGIC, and STD_LOGIC_VECTOR. -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +package std_logic_arith is + + type UNSIGNED is array (NATURAL range <>) of STD_LOGIC; + type SIGNED is array (NATURAL range <>) of STD_LOGIC; + subtype SMALL_INT is INTEGER range 0 to 1; + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: INTEGER) return SIGNED; + function "+"(L: INTEGER; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: INTEGER) return SIGNED; + function "-"(L: INTEGER; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "+"(L: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED) return SIGNED; + function "-"(L: SIGNED) return SIGNED; + function "ABS"(L: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED) return STD_LOGIC_VECTOR; + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "*"(L: SIGNED; R: SIGNED) return SIGNED; + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + + function CONV_INTEGER(ARG: INTEGER) return INTEGER; + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER; + function CONV_INTEGER(ARG: SIGNED) return INTEGER; + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT; + + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED; + + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED; + + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + -- zero extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- returns STD_LOGIC_VECTOR(SIZE-1 downto 0) + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + + -- sign extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- return STD_LOGIC_VECTOR(SIZE-1 downto 0) + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end Std_logic_arith; + + + +library IEEE; +use IEEE.std_logic_1164.all; + +package body std_logic_arith is + + function max(L, R: INTEGER) return INTEGER is + begin + if L > R then + return L; + else + return R; + end if; + end; + + + function min(L, R: INTEGER) return INTEGER is + begin + if L < R then + return L; + else + return R; + end if; + end; + + -- synopsys synthesis_off + type tbl_type is array (STD_ULOGIC) of STD_ULOGIC; + constant tbl_BINARY : tbl_type := + ('X', 'X', '0', '1', 'X', 'X', '0', '1', 'X'); + -- synopsys synthesis_on + + -- synopsys synthesis_off + type tbl_mvl9_boolean is array (STD_ULOGIC) of boolean; + constant IS_X : tbl_mvl9_boolean := + (true, true, false, false, true, true, false, false, true); + -- synopsys synthesis_on + + + + function MAKE_BINARY(A : STD_ULOGIC) return STD_ULOGIC is + -- synopsys built_in SYN_FEED_THRU + begin + -- synopsys synthesis_off + if (IS_X(A)) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + return ('X'); + end if; + return tbl_BINARY(A); + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return UNSIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : UNSIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return SIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : SIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return UNSIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : UNSIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return SIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : SIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + + + -- Type propagation function which returns a signed type with the + -- size of the left arg. + function LEFT_SIGNED_ARG(A,B: SIGNED) return SIGNED is + variable Z: SIGNED (A'left downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns an unsigned type with the + -- size of the left arg. + function LEFT_UNSIGNED_ARG(A,B: UNSIGNED) return UNSIGNED is + variable Z: UNSIGNED (A'left downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns a signed type with the + -- size of the result of a signed multiplication + function MULT_SIGNED_ARG(A,B: SIGNED) return SIGNED is + variable Z: SIGNED ((A'length+B'length-1) downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns an unsigned type with the + -- size of the result of a unsigned multiplication + function MULT_UNSIGNED_ARG(A,B: UNSIGNED) return UNSIGNED is + variable Z: UNSIGNED ((A'length+B'length-1) downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + + + function mult(A,B: SIGNED) return SIGNED is + + variable BA: SIGNED((A'length+B'length-1) downto 0); + variable PA: SIGNED((A'length+B'length-1) downto 0); + variable AA: SIGNED(A'length downto 0); + variable neg: STD_ULOGIC; + constant one : UNSIGNED(1 downto 0) := "01"; + + -- pragma map_to_operator MULT_TC_OP + -- pragma type_function MULT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + PA := (others => 'X'); + return(PA); + end if; + PA := (others => '0'); + neg := B(B'left) xor A(A'left); + BA := CONV_SIGNED(('0' & ABS(B)),(A'length+B'length)); + AA := '0' & ABS(A); + for i in 0 to A'length-1 loop + if AA(i) = '1' then + PA := PA+BA; + end if; + BA := SHL(BA,one); + end loop; + if (neg= '1') then + return(-PA); + else + return(PA); + end if; + end; + + function mult(A,B: UNSIGNED) return UNSIGNED is + + variable BA: UNSIGNED((A'length+B'length-1) downto 0); + variable PA: UNSIGNED((A'length+B'length-1) downto 0); + constant one : UNSIGNED(1 downto 0) := "01"; + + -- pragma map_to_operator MULT_UNS_OP + -- pragma type_function MULT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + PA := (others => 'X'); + return(PA); + end if; + PA := (others => '0'); + BA := CONV_UNSIGNED(B,(A'length+B'length)); + for i in 0 to A'length-1 loop + if A(i) = '1' then + PA := PA+BA; + end if; + BA := SHL(BA,one); + end loop; + return(PA); + end; + + -- subtract two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function minus(A, B: SIGNED) return SIGNED is + variable carry: STD_ULOGIC; + variable BV: STD_ULOGIC_VECTOR (A'left downto 0); + variable sum: SIGNED (A'left downto 0); + + -- pragma map_to_operator SUB_TC_OP + + -- pragma type_function LEFT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '1'; + BV := not STD_ULOGIC_VECTOR(B); + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + -- add two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function plus(A, B: SIGNED) return SIGNED is + variable carry: STD_ULOGIC; + variable BV, sum: SIGNED (A'left downto 0); + + -- pragma map_to_operator ADD_TC_OP + -- pragma type_function LEFT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '0'; + BV := B; + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + + -- subtract two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_minus(A, B: UNSIGNED) return UNSIGNED is + variable carry: STD_ULOGIC; + variable BV: STD_ULOGIC_VECTOR (A'left downto 0); + variable sum: UNSIGNED (A'left downto 0); + + -- pragma map_to_operator SUB_UNS_OP + -- pragma type_function LEFT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '1'; + BV := not STD_ULOGIC_VECTOR(B); + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + -- add two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_plus(A, B: UNSIGNED) return UNSIGNED is + variable carry: STD_ULOGIC; + variable BV, sum: UNSIGNED (A'left downto 0); + + -- pragma map_to_operator ADD_UNS_OP + -- pragma type_function LEFT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '0'; + BV := B; + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + + + function "*"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to mult + begin + return mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to mult + begin + return mult(CONV_UNSIGNED(L, L'length), + CONV_UNSIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + begin + return mult(CONV_SIGNED(L, L'length+1), + CONV_SIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to plus + begin + return mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length+1)); -- pragma label mult + end; + + + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + begin + return STD_LOGIC_VECTOR (mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length))); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + begin + return STD_LOGIC_VECTOR (mult(CONV_UNSIGNED(L, L'length), + CONV_UNSIGNED(R, R'length))); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + begin + return STD_LOGIC_VECTOR (mult(CONV_SIGNED(L, L'length+1), + CONV_SIGNED(R, R'length))); -- pragma label mult + end; + + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + begin + return STD_LOGIC_VECTOR (mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length+1))); -- pragma label mult + end; + + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "+"(L: SIGNED; R: INTEGER) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: INTEGER; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)) ; -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))) ; -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_minus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: SIGNED; R: INTEGER) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: INTEGER; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (unsigned_minus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + + + function "+"(L: UNSIGNED) return UNSIGNED is + begin + return L; + end; + + + function "+"(L: SIGNED) return SIGNED is + begin + return L; + end; + + + function "-"(L: SIGNED) return SIGNED is + -- pragma label_applies_to minus + begin + return 0 - L; -- pragma label minus + end; + + + function "ABS"(L: SIGNED) return SIGNED is + begin + if (L(L'left) = '0' or L(L'left) = 'L') then + return L; + else + return 0 - L; + end if; + end; + + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L); + end; + + + function "+"(L: SIGNED) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L); + end; + + + function "-"(L: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable tmp: SIGNED(L'length-1 downto 0); + begin + tmp := 0 - L; -- pragma label minus + return STD_LOGIC_VECTOR (tmp); + end; + + + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR is + variable tmp: SIGNED(L'length-1 downto 0); + begin + if (L(L'left) = '0' or L(L'left) = 'L') then + return STD_LOGIC_VECTOR (L); + else + tmp := 0 - L; + return STD_LOGIC_VECTOR (tmp); + end if; + end; + + + -- Type propagation function which returns the type BOOLEAN + function UNSIGNED_RETURN_BOOLEAN(A,B: UNSIGNED) return BOOLEAN is + variable Z: BOOLEAN; + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns the type BOOLEAN + function SIGNED_RETURN_BOOLEAN(A,B: SIGNED) return BOOLEAN is + variable Z: BOOLEAN; + -- pragma return_port_name Z + begin + return(Z); + end; + + + -- compare two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function is_less(A, B: SIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LT_TC_OP + -- pragma type_function SIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + if A(sign) /= B(sign) then + result := A(sign) = '1'; + else + result := FALSE; + for i in 0 to sign-1 loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + end if; + return result; + end; + + + -- compare two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function is_less_or_equal(A, B: SIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LEQ_TC_OP + -- pragma type_function SIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + if A(sign) /= B(sign) then + result := A(sign) = '1'; + else + result := TRUE; + for i in 0 to sign-1 loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + end if; + return result; + end; + + + + -- compare two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_is_less(A, B: UNSIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LT_UNS_OP + -- pragma type_function UNSIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + result := FALSE; + for i in 0 to sign loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + return result; + end; + + + -- compare two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_is_less_or_equal(A, B: UNSIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LEQ_UNS_OP + -- pragma type_function UNSIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + result := TRUE; + for i in 0 to sign loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + return result; + end; + + + + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length, R'length); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := L'length + 1; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := R'length + 1; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := L'length; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := R'length; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less_or_equal(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length, R'length); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := L'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := R'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := L'length; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := R'length; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less(CONV_UNSIGNED(R, length), + CONV_UNSIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length, R'length); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := L'length + 1; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := R'length + 1; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := L'length; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := R'length; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less_or_equal(CONV_UNSIGNED(R, length), + CONV_UNSIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length, R'length); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := L'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := R'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := L'length; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := R'length; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + + + -- for internal use only. Assumes SIGNED arguments of equal length. + function bitwise_eql(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) + return BOOLEAN is + -- pragma built_in SYN_EQL + begin + for i in L'range loop + if L(i) /= R(i) then + return FALSE; + end if; + end loop; + return TRUE; + end; + + -- for internal use only. Assumes SIGNED arguments of equal length. + function bitwise_neq(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) + return BOOLEAN is + -- pragma built_in SYN_NEQ + begin + for i in L'range loop + if L(i) /= R(i) then + return TRUE; + end if; + end loop; + return FALSE; + end; + + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_UNSIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_UNSIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length + 1, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length + 1); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length + 1; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := R'length + 1; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: INTEGER; R: SIGNED) return BOOLEAN is + constant length: INTEGER := R'length; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_UNSIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_UNSIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length + 1, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length + 1); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length + 1; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := R'length + 1; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN is + constant length: INTEGER := R'length; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is UNSIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb downto 2**i) := + result(result_msb - 2**i downto 0); + end if; + result := temp; + end if; + end loop; + return result; + end; + + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is SIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb downto 2**i) := + result(result_msb - 2**i downto 0); + end if; + result := temp; + end if; + end loop; + return result; + end; + + + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is UNSIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb - 2**i downto 0) := + result(result_msb downto 2**i); + end if; + result := temp; + end if; + end loop; + return result; + end; + + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is SIGNED (result_msb downto 0); + variable result, temp: rtype; + variable sign_bit: STD_ULOGIC; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + sign_bit := ARG(ARG'left); + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => sign_bit); + if 2**i <= result_msb then + temp(result_msb - 2**i downto 0) := + result(result_msb downto 2**i); + end if; + result := temp; + end if; + end loop; + return result; + end; + + + + + function CONV_INTEGER(ARG: INTEGER) return INTEGER is + begin + return ARG; + end; + + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER is + variable result: INTEGER; + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_UNSIGNED_TO_INTEGER + begin + -- synopsys synthesis_off + assert ARG'length <= 31 + report "ARG is too large in CONV_INTEGER" + severity FAILURE; + result := 0; + for i in ARG'range loop + result := result * 2; + tmp := tbl_BINARY(ARG(i)); + if tmp = '1' then + result := result + 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_INTEGER(ARG: SIGNED) return INTEGER is + variable result: INTEGER; + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_SIGNED_TO_INTEGER + begin + -- synopsys synthesis_off + assert ARG'length <= 32 + report "ARG is too large in CONV_INTEGER" + severity FAILURE; + result := 0; + for i in ARG'range loop + if i /= ARG'left then + result := result * 2; + tmp := tbl_BINARY(ARG(i)); + if tmp = '1' then + result := result + 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + end if; + end if; + end loop; + tmp := MAKE_BINARY(ARG(ARG'left)); + if tmp = '1' then + if ARG'length = 32 then + result := (result - 2**30) - 2**30; + else + result := result - (2 ** (ARG'length-1)); + end if; + end if; + return result; + -- synopsys synthesis_on + end; + + + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT is + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_FEED_THRU + begin + -- synopsys synthesis_off + tmp := tbl_BINARY(ARG); + if tmp = '1' then + return 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + return 0; + else + return 0; + end if; + -- synopsys synthesis_on + end; + + + -- convert an integer to a unsigned STD_ULOGIC_VECTOR + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED is + variable result: UNSIGNED(SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_UNSIGNED + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable new_bounds: UNSIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable new_bounds: UNSIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED is + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + + -- convert an integer to a 2's complement STD_ULOGIC_VECTOR + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED is + variable result: SIGNED (SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_SIGNED + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is SIGNED (SIZE-1 downto 0); + variable new_bounds : SIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is SIGNED (SIZE-1 downto 0); + variable new_bounds : SIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED is + subtype rtype is SIGNED (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + + -- convert an integer to an STD_LOGIC_VECTOR + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR is + variable result: STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_SIGNED + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) return STD_LOGIC_VECTOR is + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) + return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds: STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + +end std_logic_arith; diff --git a/lib/models/memory/sdram/mt48lc4m16a2/test.do b/lib/models/memory/sdram/mt48lc4m16a2/test.do new file mode 100644 index 0000000..80696c2 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m16a2/test.do @@ -0,0 +1,5 @@ +vcom mt48lc4m16a2.vhd +vcom test.vhd +vsim tb +do wave.do +run -all diff --git a/lib/models/memory/sdram/mt48lc4m16a2/test.txt b/lib/models/memory/sdram/mt48lc4m16a2/test.txt new file mode 100644 index 0000000..78207b0 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m16a2/test.txt @@ -0,0 +1,99 @@ +0 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +22 ns 1 1 1 1 1 00 00 0 -100 1 0 0 0 +32 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +42 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +52 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +62 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +72 ns 1 0 0 1 0 00 00 1024 -100 0 0 0 0 +82 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +92 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +102 ns 1 0 0 0 1 00 00 0 -100 0 0 0 0 +112 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +122 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +132 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +142 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +152 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +162 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +172 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +182 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +192 ns 1 0 0 0 1 00 00 0 -100 0 0 0 0 +202 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +212 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +222 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +232 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +242 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +252 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +262 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +272 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +282 ns 1 0 0 0 0 00 00 51 -100 0 0 0 0 +292 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +302 ns 1 0 0 1 1 00 00 0 -100 0 0 0 0 +312 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +322 ns 1 0 1 0 0 00 00 0 10 0 0 0 0 +332 ns 1 1 1 1 1 00 00 0 11 0 0 0 0 +342 ns 1 0 0 1 1 00 01 0 12 0 0 0 0 +352 ns 1 1 1 1 1 00 00 0 13 0 0 0 0 +362 ns 1 1 1 1 1 00 00 0 14 0 0 0 0 +372 ns 1 1 1 1 1 00 00 0 15 0 0 0 0 +382 ns 1 1 1 1 1 00 00 0 16 0 0 0 0 +392 ns 1 1 1 1 1 00 00 0 17 0 0 0 0 +402 ns 1 0 1 0 0 00 01 0 20 0 0 0 0 +412 ns 1 0 0 1 0 00 00 0 21 0 0 0 0 +422 ns 1 0 0 1 1 00 10 0 22 0 0 0 0 +432 ns 1 1 1 1 1 00 00 0 23 0 0 0 0 +442 ns 1 1 1 1 1 00 00 0 24 0 0 0 0 +452 ns 1 1 1 1 1 00 00 0 25 0 0 0 0 +462 ns 1 1 1 1 1 00 00 0 26 0 0 0 0 +472 ns 1 1 1 1 1 00 00 0 27 0 0 0 0 +482 ns 1 0 1 0 0 00 10 0 30 0 0 0 0 +492 ns 1 0 0 1 0 00 01 0 31 0 0 0 0 +502 ns 1 0 0 1 1 00 11 0 32 0 0 0 0 +512 ns 1 1 1 1 1 00 00 0 33 0 0 0 0 +522 ns 1 1 1 1 1 00 00 0 34 0 0 0 0 +532 ns 1 1 1 1 1 00 00 0 35 0 0 0 0 +542 ns 1 1 1 1 1 00 00 0 36 0 0 0 0 +552 ns 1 1 1 1 1 00 00 0 37 0 0 0 0 +562 ns 1 0 1 0 0 00 11 0 40 0 0 0 0 +572 ns 1 0 0 1 0 00 10 0 41 0 0 0 0 +582 ns 1 0 0 1 1 00 00 0 42 0 0 0 0 +592 ns 1 1 1 1 1 00 00 0 43 0 0 0 0 +602 ns 1 1 1 1 1 00 00 0 44 0 0 0 0 +612 ns 1 1 1 1 1 00 00 0 45 0 0 0 0 +622 ns 1 1 1 1 1 00 00 0 46 0 0 0 0 +632 ns 1 1 1 1 1 00 00 0 47 0 0 0 0 +642 ns 1 0 1 0 1 00 00 0 -100 0 0 0 0 +652 ns 1 0 0 1 0 00 11 0 -100 0 0 0 0 +662 ns 1 0 0 1 1 00 01 0 -100 0 0 0 0 +672 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +682 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +692 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +702 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +712 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +722 ns 1 0 1 0 1 00 01 0 -100 0 0 0 0 +732 ns 1 0 0 1 0 00 00 0 -100 0 0 0 0 +742 ns 1 0 0 1 1 00 10 0 -100 0 0 0 0 +752 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +762 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +772 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +782 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +792 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +802 ns 1 0 1 0 1 00 10 0 -100 0 0 0 0 +812 ns 1 0 0 1 0 00 01 0 -100 0 0 0 0 +822 ns 1 0 0 1 1 00 11 0 -100 0 0 0 0 +832 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +842 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +852 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +862 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +872 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +882 ns 1 0 1 0 1 00 11 0 -100 0 0 0 0 +892 ns 1 0 0 1 0 00 10 0 -100 0 0 0 0 +902 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +912 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +922 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +932 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +942 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +952 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +962 ns 1 0 0 1 0 00 11 0 -100 0 0 0 0 +972 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +982 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +992 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 diff --git a/lib/models/memory/sdram/mt48lc4m16a2/test.vhd b/lib/models/memory/sdram/mt48lc4m16a2/test.vhd new file mode 100644 index 0000000..8c24d28 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m16a2/test.vhd @@ -0,0 +1,196 @@ +LIBRARY ieee; +LIBRARY work; +USE ieee.std_logic_1164.ALL; +USE work.std_logic_arith.ALL; +USE work.util_1164.ALL; +USE std.textio.ALL; +USE work.mti_pkg.ALL; + +ENTITY tb IS +END tb; + + +ARCHITECTURE test OF tb IS + CONSTANT addr_bits : INTEGER := 12; + CONSTANT data_bits : INTEGER := 16; + CONSTANT clk_start : time := 5 ns; + CONSTANT clk_period : time := 10 ns; + CONSTANT continue_time : time := 10 ns; + + COMPONENT mt48lc4m16a2 + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '1'; + Cs_n : IN STD_LOGIC := '1'; + Cas_n : IN STD_LOGIC := '1'; + Ras_n : IN STD_LOGIC := '1'; + We_n : IN STD_LOGIC := '1'; + Dqm : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := (OTHERS => '0'); + Load : IN STD_LOGIC := '0'; + Unload : IN STD_LOGIC := '0'; + Row_start : IN INTEGER := 0; + Row_end : IN INTEGER := 0 + ); + END COMPONENT; + + FOR ALL : mt48lc4m16a2 USE ENTITY work.mt48lc4m16a2 (behave); + + SIGNAL pDq : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0); + SIGNAL pAddr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + SIGNAL pBa : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL pClk : STD_LOGIC; + SIGNAL pCke : STD_LOGIC; + SIGNAL pCs : STD_LOGIC; + SIGNAL pCas : STD_LOGIC; + SIGNAL pRas : STD_LOGIC; + SIGNAL pWe : STD_LOGIC; + SIGNAL pDqm : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL PLoad : STD_LOGIC; + SIGNAL PUnload : STD_LOGIC; + SIGNAL PRow_start : INTEGER; + SIGNAL PRow_end : INTEGER; + SIGNAL stim_done : boolean := false; + SIGNAL clk_done : boolean := false; + +BEGIN + u1: mt48lc4m16a2 + PORT MAP( + Dq => pDq, + Addr => pAddr, + Ba => pBa, + Clk => pClk, + Cke => pCke, + Cs_n => pCs, + Ras_n => pRas, + Cas_n => pCas, + We_n => pWe, + Dqm => pDqm, + Load => pLoad, + Unload => pUnload, + Row_start => PRow_start, + Row_end => PRow_end + ); + + stimulator : PROCESS + FILE stim_file:text IS IN "test.txt"; + VARIABLE l : line; + VARIABLE time_var : TIME; + VARIABLE pCke_var : STD_LOGIC; + VARIABLE pCs_var : STD_LOGIC; + VARIABLE pRas_var : STD_LOGIC; + VARIABLE PCas_var : STD_LOGIC; + VARIABLE pWe_var : STD_LOGIC; + VARIABLE pDqm_var : STD_LOGIC_VECTOR (1 DOWNTO 0); + VARIABLE pBa_var : STD_LOGIC_VECTOR (1 DOWNTO 0); + VARIABLE pAddr_var : INTEGER; + VARIABLE pDq_var : INTEGER; -- -100 is converted to hi-Z state + VARIABLE pLoad_var : STD_LOGIC; + VARIABLE pUnload_var : STD_LOGIC; + VARIABLE pRow_start_var : INTEGER; + VARIABLE pRow_end_var : INTEGER; + VARIABLE pMa_var_vect : STD_LOGIC_VECTOR(addr_bits - 1 DOWNTO 0); + CONSTANT HiZ : STD_LOGIC_VECTOR(data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + BEGIN + WHILE not ENDFILE(stim_file) LOOP + readline(stim_file,l); + IF l'length > 0 THEN + read (l, time_var); + read (l, pCke_var); + read (l, pCs_var); + read (l, pRas_var); + read (l, pCas_var); + read (l, pWe_var); + read (l, pDqm_var); + read (l, pBa_var); + read (l, pAddr_var); + read (l, pDq_var); + read (l, pLoad_var); + read (l, pUnload_var); + read (l, pRow_start_var); + read (l, pRow_end_var); + IF now > time_var THEN + ASSERT false + REPORT "Detected a time in the stim file that is in the past" + SEVERITY error; + ELSE + WAIT FOR time_var-now; + IF pWe_var='1' THEN + pCke <= pCke_var; + pCs <= pCs_var; + pRas <= pRas_var; + pCas <= pCas_var; + pWe <= pWe_var; + pDqm <= pDqm_var; + pBa <= pBa_var; + pMa_var_vect := CONV_STD_LOGIC_VECTOR(pAddr_var, addr_bits); + pAddr <= pMa_var_vect; + IF pDq_var = -100 THEN + pDq <= HiZ; + ELSE + pDq <= CONV_STD_LOGIC_VECTOR(pDq_var, data_bits); + END IF; + pLoad <= pLoad_var; + pUnload <= pUnload_var; + pRow_start <= pRow_start_var; + pRow_end <= pRow_end_var; + ELSE + pCke <= pCke_var; + pCs <= pCs_var; + pRas <= pRas_var; + pCas <= pCas_var; + pWe <= pWe_var; + pDqm <= pDqm_var; + pBa <= pBa_var; + pMa_var_vect := CONV_STD_LOGIC_VECTOR(pAddr_var, addr_bits); + pAddr <= pMa_var_vect; + IF pDq_var = -100 THEN + pDq <= HiZ; + ELSE + pDq <= CONV_STD_LOGIC_VECTOR(pDq_var, data_bits); + END IF; + pLoad <= pLoad_var; + pUnload <= pUnload_var; + pRow_start <= pRow_start_var; + pRow_end <= pRow_end_var; + END IF; + END IF; + END IF; + END LOOP; + ASSERT false + REPORT "End of Stimulation File Detected!" + SEVERITY note; + stim_done <= true; + WAIT; + END PROCESS; + + clock : PROCESS + VARIABLE done_time : time; + BEGIN + pclk <= '0'; + WAIT for clk_start; + WHILE not stim_done loop + pclk <= '1'; + WAIT for clk_period/2; + pclk <= '0'; + WAIT for clk_period/2; + END LOOP; + done_time := now+continue_time; + WHILE now < done_time LOOP --one last clock to finish last command + pclk <= '1'; + WAIT for clk_period/2; + pclk <= '0'; + WAIT for clk_period/2; + END LOOP; + ASSERT false + REPORT "Suspending clock activity" + SEVERITY note; + clk_done <= true; + WAIT; + END PROCESS; + +END test; + + diff --git a/lib/models/memory/sdram/mt48lc4m16a2/util1164.vhd b/lib/models/memory/sdram/mt48lc4m16a2/util1164.vhd new file mode 100644 index 0000000..bb4b5dd --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m16a2/util1164.vhd @@ -0,0 +1,124 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE STD.textio.ALL; + +PACKAGE util_1164 IS + PROCEDURE read(l: INOUT line; value: OUT std_logic); + PROCEDURE read(l: INOUT line; value: OUT std_logic_vector); + PROCEDURE write(l: INOUT line; value: IN std_logic_vector; + JUSTIFIED: IN SIDE := right; + FIELD: IN WIDTH := 0); + PROCEDURE Grow_line(L : inout LINE; incr : in integer); +END util_1164; + + + +PACKAGE BODY util_1164 IS + + FUNCTION white_space(value:character) RETURN boolean IS + VARIABLE result:boolean; + BEGIN + IF (value = ' ') OR (value = HT) THEN + RETURN true; + ELSE + RETURN false; + END IF; + END white_space; + + PROCEDURE read(l: INOUT line; value: OUT std_logic) IS + VARIABLE char_var: character:= ' '; + BEGIN + WHILE l'LENGTH > 0 LOOP + read(l,char_var); + IF NOT white_space(char_var) THEN + EXIT; + END IF; + END LOOP; + IF white_space(char_var) THEN + ASSERT false REPORT "No std_logic value found in file" + SEVERITY error; + value := 'X'; + RETURN; + END IF; + + CASE char_var IS + WHEN 'U'|'u' => value := 'U'; + WHEN '0' => value := '0'; + WHEN '1' => value := '1'; + WHEN 'X'|'x' => value := 'X'; + WHEN 'L'|'l' => value := 'L'; + WHEN 'H'|'h' => value := 'H'; + WHEN 'W'|'w' => value := 'W'; + WHEN 'Z'|'z' => value := 'Z'; + WHEN '-' => value := '-'; + WHEN OTHERS => + ASSERT false REPORT "Unrecognized value read for std_logic" + SEVERITY error; + value := 'X'; + END CASE; + END read; + + PROCEDURE read(l: INOUT line; value: OUT std_logic_vector) IS + BEGIN + FOR i IN value'HIGH DOWNTO value'LOW LOOP + IF l'LENGTH > 0 THEN + read(l,value(i)); + ELSE + ASSERT false REPORT "Not enough values for std_logic_vector in file" + SEVERITY error; + RETURN; + END IF; + END LOOP; + END read; + + procedure Grow_line(L : inout LINE; incr : in integer) + is + variable old_L : LINE := L; + variable bfp: integer; -- Blank fill pointer. + begin + assert incr > 0 + report "Textio: Grow_line called with zero increment." + severity error; + + if L = null then + bfp := 0; + L := new string(1 to incr); + else + bfp := old_L'high; + L := new string(old_L'low to old_L'high + incr); + L(old_L'low to old_L'high) := old_L.all; + Deallocate(old_L); + end if; + for i in 1 to incr loop + L(bfp + i) := ' '; + end loop; + end; + + + PROCEDURE write(l: INOUT line; value: IN std_logic_vector; + JUSTIFIED: IN SIDE := right; + FIELD: IN WIDTH := 0) IS + variable fw: integer := VALUE'length; + variable bp: integer; + variable offset: integer := 0; + alias normal : std_logic_vector(0 to value'length - 1) is value; + begin + if L /= null then + bp := L'high + 1; + else bp := 1; + end if; + if FIELD > VALUE'length then + fw := FIELD; + if JUSTIFIED = right then + offset := fw - VALUE'length; + end if; + end if; + Grow_line(L, fw); + for i in normal'range loop + L(bp + i + offset) := character'val( + std_logic'pos(normal(i)) + character'pos('0')); + end loop; + end; + + +END util_1164; diff --git a/lib/models/memory/sdram/mt48lc4m16a2/vec_gen.vhd b/lib/models/memory/sdram/mt48lc4m16a2/vec_gen.vhd new file mode 100644 index 0000000..e036644 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m16a2/vec_gen.vhd @@ -0,0 +1,373 @@ +------------------------------------------------------------------------------- +-- -- +-- This is a data generator for the testbench for Micron's Synchronous -- +-- DRAM. This generator reads a text file line-by-line and generates -- +-- a file of test vectors that is then read by the testbench and -- +-- applied to the part. -- +-- -- +-- This VHDL program creates a text file of test vectors that is used by the -- +-- test bench. Place your commands in a file (a copy of VEC_GEN.VHD) and run -- +-- VEC_GEN.VHD in your VHDL simulator (make sure you have compiled this -- +-- package prior to running the program VEC_GEN.VHD). This will produce the -- +-- vectors that are required to run the included testbench. Change the name -- +-- of the vector file to save your vectors in separate files. The default -- +-- file name for the output vectors generated from this pacakage is -- +-- "test.txt." -- +-- -- +-- Now compile and run the testbench program embedtb.vhd. The testbench uses -- +-- the default test.txt as input vectors. -- +-- -- +-- -- +-- Copyright 1997 Micron Technology, Inc. -- +-- -- +------------------------------------------------------------------------------- + +LIBRARY work; +LIBRARY ieee; +USE ieee.std_logic_1164.all; +USE std.textio.all; +USE work.io_utils.all; + + +PACKAGE generate_vectors IS + + CONSTANT set_up : TIME; + CONSTANT hold : TIME; + CONSTANT cycle_start : TIME; + + SIGNAL cycle : INTEGER := 0; + SIGNAL sim_time : TIME := 0 ns; + FILE output_file:TEXT IS OUT "test.txt"; + PROCEDURE write(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); + first_data : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE read(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE active(row_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE precharge(bank : IN BIT_VECTOR(1 DOWNTO 0); address : IN INTEGER; data_bus: IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE nop(data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE burst_term(data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE auto_refresh; + PROCEDURE next_cycle(SIGNAL clk : IN BIT); + PROCEDURE load_array(load : IN BIT); + PROCEDURE load_mode_reg(op_code : IN INTEGER; cke : IN BIT); + PROCEDURE unload_array(row_start : IN INTEGER; row_end : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0)); + +END generate_vectors; + + +PACKAGE BODY generate_vectors IS + + CONSTANT set_up : TIME := 3 ns; + CONSTANT hold : TIME := 1 ns; + CONSTANT cycle_start : TIME := 0 ns; + + +PROCEDURE write(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); first_data : IN INTEGER; + dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 0, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, first_data, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +write(l, 0, right, 6); --row_address_start +write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE read(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 0, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, -100, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +write(l, 0, right, 6); --row_address_start +write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE active(row_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 0, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, row_address, right, 6); --address +write(l, data_bus, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +write(l, 0, right, 6); --row_address_start +write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE precharge(bank : IN BIT_VECTOR(1 DOWNTO 0); address : IN INTEGER; data_bus: IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 0, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, address, right, 6); --address +write(l, data_bus, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +write(l, 0, right, 6); --row_address_start +write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE nop(data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + + +VARIABLE l : LINE; +VARIABLE col_address : INTEGER := 0; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, cke, right, 4); --Cke +write(l, 1, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, data_bus, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +write(l, 0, right, 6); --row_address_start +write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + + +PROCEDURE burst_term(data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; +VARIABLE col_address : INTEGER := 0; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, data_bus, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +write(l, 0, right, 6); --row_address_start +write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE auto_refresh IS + VARIABLE l : LINE; + VARIABLE dqm : BIT_VECTOR(1 DOWNTO 0) := "00"; + VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; +BEGIN + IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); + ELSE + write(l, now-set_up, left, 4, ns); + END IF; + write(l, 1, right, 4); --Cke + write(l, 0, right, 4); --Cs + write(l, 0, right, 4); --Ras + write(l, 0, right, 4); --Cas + write(l, 1, right, 4); --We + write(l, dqm, right, 4); --Dqm + write(l, bank, right, 4); --Ba + write(l, 0, right, 6); --address + write(l, -100, right, 6); --first data location + write(l, 0, right, 4); --load + write(l, 0, right, 4); --unload + write(l, 0, right, 6); --row_address_start + write(l, 0, right, 6); --row_address_end + writeline(output_file,l); --write vector to file +END; + + +PROCEDURE next_cycle(SIGNAL clk : IN BIT) IS + +BEGIN + +WAIT UNTIL clk = '1'; + +END; + +PROCEDURE load_array(load : IN BIT) IS + +VARIABLE l : LINE; +VARIABLE dqm : BIT_VECTOR(1 DOWNTO 0) := "00"; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, 1, right, 4); --Cke +write(l, 1, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, 0, right, 6); --address +write(l, -100, right, 6); --first data location +write(l, 1, right, 4); --load +write(l, 0, right, 4); --unload +write(l, 0, right, 6); --row_address_start +write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE unload_array(row_start : IN INTEGER; row_end : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0)) IS + +VARIABLE l : LINE; +VARIABLE dqm : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, 1, right, 4); --Cke +write(l, 1, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, 0, right, 6); --address +write(l, -100, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 1, right, 4); --unload +write(l, row_start, right, 6); --row_address_start +write(l, row_end, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE load_mode_reg(op_code : IN INTEGER; cke : IN BIT) IS + +VARIABLE l : LINE; +VARIABLE dqm : BIT_VECTOR(1 DOWNTO 0) := "00"; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 0, right, 4); --Ras +write(l, 0, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, op_code, right, 6); --address +write(l, -100, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +write(l, 0, right, 6); --row_address_start +write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +END generate_vectors; + diff --git a/lib/models/memory/sdram/mt48lc4m16a2/vector.do b/lib/models/memory/sdram/mt48lc4m16a2/vector.do new file mode 100644 index 0000000..7480359 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m16a2/vector.do @@ -0,0 +1,4 @@ +vcom vec_gen.vhd +vcom ed_comnd.vhd +vsim vector_generate +run -all diff --git a/lib/models/memory/sdram/mt48lc4m16a2/wave.do b/lib/models/memory/sdram/mt48lc4m16a2/wave.do new file mode 100644 index 0000000..ea73676 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m16a2/wave.do @@ -0,0 +1,34 @@ +onerror {resume} +add wave -logic /tb/u1/clk +add wave -logic /tb/u1/cke +add wave -logic /tb/u1/cs_n +add wave -logic /tb/u1/ras_n +add wave -logic /tb/u1/cas_n +add wave -logic /tb/u1/we_n +add wave -literal -decimal /tb/u1/addr +add wave -literal -binary /tb/u1/ba +add wave -literal -hexadecimal /tb/u1/dq +add wave -literal /tb/u1/dqm +add wave -literal /tb/u1/operation +add wave -literal -decimal /tb/u1/mode_reg +add wave -logic /tb/u1/active_enable +add wave -logic /tb/u1/aref_enable +add wave -logic /tb/u1/burst_term +add wave -logic /tb/u1/mode_reg_enable +add wave -logic /tb/u1/prech_enable +add wave -logic /tb/u1/read_enable +add wave -logic /tb/u1/write_enable +add wave -logic /tb/u1/burst_length_1 +add wave -logic /tb/u1/burst_length_2 +add wave -logic /tb/u1/burst_length_4 +add wave -logic /tb/u1/burst_length_8 +add wave -logic /tb/u1/cas_latency_2 +add wave -logic /tb/u1/cas_latency_3 +add wave -literal /tb/u1/pre_chk +add wave -literal /tb/u1/act_chk +add wave -literal /tb/u1/bank_chk +add wave -literal -decimal /tb/u1/row_chk +add wave -literal -decimal /tb/u1/col_chk +add wave -logic /tb/u1/dq_in_chk +add wave -logic /tb/u1/dq_out_chk +add wave -literal -decimal /tb/u1/rw_bank_chk diff --git a/lib/models/memory/sdram/mt48lc4m32b2/mt48lc4m32b2.vhd b/lib/models/memory/sdram/mt48lc4m32b2/mt48lc4m32b2.vhd new file mode 100644 index 0000000..ddb8820 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m32b2/mt48lc4m32b2.vhd @@ -0,0 +1,1148 @@ +----------------------------------------------------------------------------------------- +-- +-- File Name: MT48LC4M32B2.VHD +-- Version: 0.0g +-- Date: May 19th, 2000 +-- Model: Behavioral +-- Simulator: Model Technology VLOG (PC version 5.3 PE) +-- +-- Dependencies: None +-- +-- Author: Son P. Huynh +-- Email: sphuynh@micron.com +-- Phone: (208) 368-3825 +-- Company: Micron Technology, Inc. +-- Part Number: MT48LC4M32B2 (1Mb x 32 x 4 Banks) +-- +-- Description: Micron 64Mb SDRAM +-- +-- Limitation: - Doesn't check for 4096-cycle refresh +-- +-- Note: - Set simulator resolution to "ps" accuracy +-- +-- Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY +-- WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY +-- IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR +-- A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT. +-- +-- Copyright (c) 1998 Micron Semiconductor Products, Inc. +-- All rights researved +-- +-- Rev Author Phone Date Changes +-- ---- ---------------------------- ---------- ------------------------------------- +-- 0.0g Son Huynh 208-368-3825 05/19/2000 Fix tWR + tRP timing +-- Micron Technology Inc. +-- +-- 0.0a Son P. Huynh 208-368-3825 12/02/1999 First Release +-- Micron Technology Inc. - Simple testbench included +----------------------------------------------------------------------------------------- + +LIBRARY ieee; + USE ieee.std_logic_1164.ALL; + USE ieee.std_logic_unsigned.conv_integer; + USE ieee.std_logic_arith.conv_std_logic_vector; + +ENTITY mt48lc4m32b2 IS + GENERIC ( + -- Timing Parameters for -6 and CAS Latency = 2 + tAC : TIME := 7.5 ns; + tHZ : TIME := 7.5 ns; + tOH : TIME := 2.0 ns; + tMRD : INTEGER := 2; -- 2 Clk Cycles + tRAS : TIME := 42.0 ns; + tRC : TIME := 60.0 ns; + tRCD : TIME := 18.0 ns; + tRP : TIME := 18.0 ns; + tRRD : TIME := 12.0 ns; + tWRa : TIME := 6.0 ns; -- A2 Version - Auto precharge mode only (1 Clk + 6 ns) + tWRp : TIME := 12.0 ns; -- A2 Version - Precharge mode only (12 ns) + + tAH : TIME := 1.0 ns; + tAS : TIME := 1.5 ns; + tCH : TIME := 2.5 ns; + tCL : TIME := 2.5 ns; + tCK : TIME := 7.5 ns; + tDH : TIME := 1.0 ns; + tDS : TIME := 1.5 ns; + tCKH : TIME := 1.0 ns; + tCKS : TIME := 1.5 ns; + tCMH : TIME := 1.0 ns; + tCMS : TIME := 1.5 ns; + + addr_bits : INTEGER := 12; + data_bits : INTEGER := 32; + col_bits : INTEGER := 8 + ); + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC_VECTOR := "00"; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '0'; + Cs_n : IN STD_LOGIC := '1'; + Ras_n : IN STD_LOGIC := '0'; + Cas_n : IN STD_LOGIC := '0'; + We_n : IN STD_LOGIC := '0'; + Dqm : IN STD_LOGIC_VECTOR (3 DOWNTO 0) := (OTHERS => '0') + ); +END mt48lc4m32b2; + +ARCHITECTURE behave OF mt48lc4m32b2 IS + TYPE State IS (ACT, A_REF, BST, LMR, NOP, PRECH, READ, READ_A, WRITE, WRITE_A, FILE_LOAD, FILE_UNLOAD); + TYPE Array4xI IS ARRAY (3 DOWNTO 0) OF INTEGER; + TYPE Array4xT IS ARRAY (3 DOWNTO 0) OF TIME; + TYPE Array4xB IS ARRAY (3 DOWNTO 0) OF STD_LOGIC; + TYPE Array4x2BV IS ARRAY (3 DOWNTO 0) OF STD_LOGIC_VECTOR (1 DOWNTO 0); -- For Bank Pipeline + TYPE Array2x4BV IS ARRAY (1 DOWNTO 0) OF STD_LOGIC_VECTOR (3 DOWNTO 0); -- For Dqm Pipeline + TYPE Array4xCBV IS ARRAY (4 DOWNTO 0) OF STD_LOGIC_VECTOR (Col_bits - 1 DOWNTO 0); -- For Column Pipeline + TYPE Array_state IS ARRAY (4 DOWNTO 0) OF State; + SIGNAL Operation : State := NOP; + SIGNAL Mode_reg : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL Active_enable, Aref_enable, Burst_term : STD_LOGIC := '0'; + SIGNAL Mode_reg_enable, Prech_enable, Read_enable, Write_enable : STD_LOGIC := '0'; + SIGNAL Burst_length_1, Burst_length_2, Burst_length_4, Burst_length_8 : STD_LOGIC := '0'; + SIGNAL Cas_latency_2, Cas_latency_3 : STD_LOGIC := '0'; + SIGNAL Cs_in, Ras_in, Cas_in, We_in : STD_LOGIC := '0'; + SIGNAL Write_burst_mode : STD_LOGIC := '0'; + SIGNAL RAS_clk, Sys_clk, CkeZ : STD_LOGIC := '0'; + +BEGIN + -- Strip the strength + Cs_in <= To_X01 (Cs_n); + Ras_in <= To_X01 (Ras_n); + Cas_in <= To_X01 (Cas_n); + We_in <= To_X01 (We_n); + + -- Commands Decode + Active_enable <= NOT(Cs_in) AND NOT(Ras_in) AND Cas_in AND We_in; + Aref_enable <= NOT(Cs_in) AND NOT(Ras_in) AND NOT(Cas_in) AND We_in; + Burst_term <= NOT(Cs_in) AND Ras_in AND Cas_in AND NOT(We_in); + Mode_reg_enable <= NOT(Cs_in) AND NOT(Ras_in) AND NOT(Cas_in) AND NOT(We_in); + Prech_enable <= NOT(Cs_in) AND NOT(Ras_in) AND Cas_in AND NOT(We_in); + Read_enable <= NOT(Cs_in) AND Ras_in AND NOT(Cas_in) AND We_in; + Write_enable <= NOT(Cs_in) AND Ras_in AND NOT(Cas_in) AND NOT(We_in); + + -- Burst Length Decode + Burst_length_1 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND NOT(Mode_reg(0)); + Burst_length_2 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND Mode_reg(0); + Burst_length_4 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND NOT(Mode_reg(0)); + Burst_length_8 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND Mode_reg(0); + + -- CAS Latency Decode + Cas_latency_2 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND NOT(Mode_reg(4)); + Cas_latency_3 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND Mode_reg(4); + + -- Write Burst Mode + Write_burst_mode <= Mode_reg(9); + + -- RAS Clock for checking tWR and tRP + PROCESS + variable Clk0, Clk1 : integer := 0; + begin + RAS_clk <= '1'; + wait for 0.5 ns; + RAS_clk <= '0'; + wait for 0.5 ns; + if Clk0 > 100 or Clk1 > 100 then + wait; + else + if Clk = '1' then + Clk0 := 0; + Clk1 := Clk1 + 1; + else + Clk0 := Clk0 + 1; + Clk1 := 0; + end if; + end if; + END PROCESS; + + -- System Clock + int_clk : PROCESS (Clk) + begin + IF Clk'LAST_VALUE = '0' AND Clk = '1' THEN + CkeZ <= Cke; + END IF; + Sys_clk <= CkeZ AND Clk; + END PROCESS; + + state_register : PROCESS + TYPE ram_type IS ARRAY (2**col_bits - 1 DOWNTO 0) OF STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0); + TYPE ram_pntr IS ACCESS ram_type; + TYPE ram_stor IS ARRAY (2**addr_bits - 1 DOWNTO 0) OF ram_pntr; + VARIABLE Bank0 : ram_stor; + VARIABLE Bank1 : ram_stor; + VARIABLE Bank2 : ram_stor; + VARIABLE Bank3 : ram_stor; + VARIABLE Row_index, Col_index : INTEGER := 0; + VARIABLE Dq_temp : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => '0'); + + VARIABLE Col_addr : Array4xCBV; + VARIABLE Bank_addr : Array4x2BV; + VARIABLE Dqm_reg0, Dqm_reg1 : STD_LOGIC_VECTOR (3 DOWNTO 0) := "0000"; + + VARIABLE Bank, Previous_bank : STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"; + VARIABLE B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col_brst : STD_LOGIC_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Row : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col : STD_LOGIC_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Burst_counter : INTEGER := 0; + + VARIABLE Command : Array_state; + VARIABLE Bank_precharge : Array4x2BV; + VARIABLE A10_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Auto_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Read_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Write_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_write : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_read : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_bank : STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"; + VARIABLE Count_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE Count_precharge : Array4xI := (0 & 0 & 0 & 0); + + VARIABLE Data_in_enable, Data_out_enable : STD_LOGIC := '0'; + VARIABLE Pc_b0, Pc_b1, Pc_b2, Pc_b3 : STD_LOGIC := '0'; + VARIABLE Act_b0, Act_b1, Act_b2, Act_b3 : STD_LOGIC := '0'; + + -- Timing Check + VARIABLE MRD_chk : INTEGER := 0; + VARIABLE WR_counter : Array4xI := (0 & 0 & 0 & 0); + VARIABLE WR_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE WR_chkp : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE RC_chk, RRD_chk : TIME := 0 ns; + VARIABLE RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3 : TIME := 0 ns; + VARIABLE RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3 : TIME := 0 ns; + VARIABLE RP_chk0, RP_chk1, RP_chk2, RP_chk3 : TIME := 0 ns; + + -- Initialize empty rows + PROCEDURE Init_mem (Bank : STD_LOGIC_VECTOR (1 DOWNTO 0); Row_index : INTEGER) IS + VARIABLE i, j : INTEGER := 0; + BEGIN + IF Bank = "00" THEN + IF Bank0 (Row_index) = NULL THEN -- Check to see if row empty + Bank0 (Row_index) := NEW ram_type; -- Open new row for access + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP -- Filled row with zeros + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank0 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "01" THEN + IF Bank1 (Row_index) = NULL THEN + Bank1 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank1 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "10" THEN + IF Bank2 (Row_index) = NULL THEN + Bank2 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank2 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "11" THEN + IF Bank3 (Row_index) = NULL THEN + Bank3 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank3 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + END IF; + END; + + -- Burst Counter + PROCEDURE Burst_decode IS + VARIABLE Col_int : INTEGER := 0; + VARIABLE Col_vec, Col_temp : STD_LOGIC_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + BEGIN + -- Advance Burst Counter + Burst_counter := Burst_counter + 1; + + -- Burst Type + IF Mode_reg (3) = '0' THEN + Col_int := conv_integer(Col) + 1; + Col_temp := CONV_STD_LOGIC_VECTOR(Col_int, col_bits); + ELSIF Mode_reg (3) = '1' THEN + Col_vec := CONV_STD_LOGIC_VECTOR(Burst_counter, col_bits); + Col_temp (2) := Col_vec (2) XOR Col_brst (2); + Col_temp (1) := Col_vec (1) XOR Col_brst (1); + Col_temp (0) := Col_vec (0) XOR Col_brst (0); + END IF; + + -- Burst Length + IF Burst_length_2 = '1' THEN + Col (0) := Col_temp (0); + ELSIF Burst_length_4 = '1' THEN + Col (1 DOWNTO 0) := Col_temp (1 DOWNTO 0); + ELSIF Burst_length_8 = '1' THEN + Col (2 DOWNTO 0) := Col_temp (2 DOWNTO 0); + ELSE + Col := Col_temp; + END IF; + + -- Burst Read Single Write + IF Write_burst_mode = '1' AND Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Data counter + IF Burst_length_1 = '1' THEN + IF Burst_counter >= 1 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_2 = '1' THEN + IF Burst_counter >= 2 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_4 = '1' THEN + IF Burst_counter >= 4 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_8 = '1' THEN + IF Burst_counter >= 8 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + END IF; + END; + + BEGIN + WAIT ON Sys_clk, RAS_clk; + IF Sys_clk'event AND Sys_clk = '1' THEN + -- Internal Command Pipeline + Command(0) := Command(1); + Command(1) := Command(2); + Command(2) := Command(3); + Command(3) := NOP; + + Col_addr(0) := Col_addr(1); + Col_addr(1) := Col_addr(2); + Col_addr(2) := Col_addr(3); + Col_addr(3) := (OTHERS => '0'); + + Bank_addr(0) := Bank_addr(1); + Bank_addr(1) := Bank_addr(2); + Bank_addr(2) := Bank_addr(3); + Bank_addr(3) := "00"; + + Bank_precharge(0) := Bank_precharge(1); + Bank_precharge(1) := Bank_precharge(2); + Bank_precharge(2) := Bank_precharge(3); + Bank_precharge(3) := "00"; + + A10_precharge(0) := A10_precharge(1); + A10_precharge(1) := A10_precharge(2); + A10_precharge(2) := A10_precharge(3); + A10_precharge(3) := '0'; + + -- Operation Decode (Optional for showing current command on posedge clock / debug feature) + IF Active_enable = '1' THEN + Operation <= ACT; + ELSIF Aref_enable = '1' THEN + Operation <= A_REF; + ELSIF Burst_term = '1' THEN + Operation <= BST; + ELSIF Mode_reg_enable = '1' THEN + Operation <= LMR; + ELSIF Prech_enable = '1' THEN + Operation <= PRECH; + ELSIF Read_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= READ; + ELSE + Operation <= READ_A; + END IF; + ELSIF Write_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= WRITE; + ELSE + Operation <= WRITE_A; + END IF; + ELSE + Operation <= NOP; + END IF; + + -- Dqm pipeline for Read + Dqm_reg0 := Dqm_reg1; + Dqm_reg1 := Dqm; + + -- Read or Write with Auto Precharge Counter + IF Auto_precharge (0) = '1' THEN + Count_precharge (0) := Count_precharge (0) + 1; + END IF; + IF Auto_precharge (1) = '1' THEN + Count_precharge (1) := Count_precharge (1) + 1; + END IF; + IF Auto_precharge (2) = '1' THEN + Count_precharge (2) := Count_precharge (2) + 1; + END IF; + IF Auto_precharge (3) = '1' THEN + Count_precharge (3) := Count_precharge (3) + 1; + END IF; + + -- Auto Precharge Timer for tWR + if (Burst_length_1 = '1' OR Write_burst_mode = '1') then + if (Count_precharge(0) = 1) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 1) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 1) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 1) then + Count_time(3) := NOW; + end if; + elsif (Burst_length_2 = '1') then + if (Count_precharge(0) = 2) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 2) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 2) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 2) then + Count_time(3) := NOW; + end if; + elsif (Burst_length_4 = '1') then + if (Count_precharge(0) = 4) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 4) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 4) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 4) then + Count_time(3) := NOW; + end if; + elsif (Burst_length_8 = '1') then + if (Count_precharge(0) = 8) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 8) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 8) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 8) then + Count_time(3) := NOW; + end if; + end if; + + -- tMRD Counter + MRD_chk := MRD_chk + 1; + + -- tWR Counter + WR_counter(0) := WR_counter(0) + 1; + WR_counter(1) := WR_counter(1) + 1; + WR_counter(2) := WR_counter(2) + 1; + WR_counter(3) := WR_counter(3) + 1; + + -- Auto Refresh + IF Aref_enable = '1' THEN + -- Auto Refresh to Auto Refresh + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Auto Refresh" + SEVERITY WARNING; + -- Precharge to Auto Refresh + ASSERT (NOW - RP_chk0 >= tRP OR NOW - RP_chk1 >= tRP OR NOW - RP_chk2 >= tRP OR NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Auto Refresh" + SEVERITY WARNING; + -- All banks must be idle before refresh + IF (Pc_b3 = '0' OR Pc_b2 = '0' OR Pc_b1 = '0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All banks must be Precharge before Auto Refresh" + SEVERITY WARNING; + END IF; + -- Record current tRC time + RC_chk := NOW; + END IF; + + -- Load Mode Register + IF Mode_reg_enable = '1' THEN + Mode_reg <= Addr; + IF (Pc_b3 = '0' OR Pc_b2 = '0' OR Pc_b1 = '0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All bank must be Precharge before Load Mode Register" + SEVERITY WARNING; + END IF; + -- REF to LMR + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Load Mode Register" + SEVERITY WARNING; + -- LMR to LMR + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Load Mode Register" + SEVERITY WARNING; + -- Record current tMRD time + MRD_chk := 0; + END IF; + + -- Active Block (latch Bank and Row Address) + IF Active_enable = '1' THEN + IF Ba = "00" AND Pc_b0 = '1' THEN + Act_b0 := '1'; + Pc_b0 := '0'; + B0_row_addr := Addr; + RCD_chk0 := NOW; + RAS_chk0 := NOW; + -- Precharge to Active Bank 0 + ASSERT (NOW - RP_chk0 >= tRP) + REPORT "tRP violation during Activate Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '1' THEN + Act_b1 := '1'; + Pc_b1 := '0'; + B1_row_addr := Addr; + RCD_chk1 := NOW; + RAS_chk1 := NOW; + -- Precharge to Active Bank 1 + ASSERT (NOW - RP_chk1 >= tRP) + REPORT "tRP violation during Activate Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '1' THEN + Act_b2 := '1'; + Pc_b2 := '0'; + B2_row_addr := Addr; + RCD_chk2 := NOW; + RAS_chk2 := NOW; + -- Precharge to Active Bank 2 + ASSERT (NOW - RP_chk2 >= tRP) + REPORT "tRP violation during Activate Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '1' THEN + Act_b3 := '1'; + Pc_b3 := '0'; + B3_row_addr := Addr; + RCD_chk3 := NOW; + RAS_chk3 := NOW; + -- Precharge to Active Bank 3 + ASSERT (NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Activate Bank 3" + SEVERITY WARNING; + ELSIF Ba = "00" AND Pc_b0 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 0 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 1 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 2 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 3 is not Precharged" + SEVERITY WARNING; + END IF; + -- Active Bank A to Active Bank B + IF ((Previous_bank /= Ba) AND (NOW - RRD_chk < tRRD)) THEN + ASSERT (FALSE) + REPORT "tRRD violation during Activate" + SEVERITY WARNING; + END IF; + -- LMR to ACT + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Activate" + SEVERITY WARNING; + -- AutoRefresh to Activate + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Activate" + SEVERITY WARNING; + -- Record variable for checking violation + RRD_chk := NOW; + Previous_bank := Ba; + END IF; + + -- Precharge Block + IF Prech_enable = '1' THEN + IF Addr(10) = '1' THEN + Pc_b0 := '1'; + Pc_b1 := '1'; + Pc_b2 := '1'; + Pc_b3 := '1'; + Act_b0 := '0'; + Act_b1 := '0'; + Act_b2 := '0'; + Act_b3 := '0'; + RP_chk0 := NOW; + RP_chk1 := NOW; + RP_chk2 := NOW; + RP_chk3 := NOW; + -- Activate to Precharge all banks + ASSERT ((NOW - RAS_chk0 >= tRAS) OR (NOW - RAS_chk1 >= tRAS)) + REPORT "tRAS violation during Precharge all banks" + SEVERITY WARNING; + -- tWR violation check for Write + IF ((NOW - WR_chkp(0) < tWRp) OR (NOW - WR_chkp(1) < tWRp) OR + (NOW - WR_chkp(2) < tWRp) OR (NOW - WR_chkp(3) < tWRp)) THEN + ASSERT (FALSE) + REPORT "tWR violation during Precharge ALL banks" + SEVERITY WARNING; + END IF; + ELSIF Addr(10) = '0' THEN + IF Ba = "00" THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + -- Activate to Precharge bank 0 + ASSERT (NOW - RAS_chk0 >= tRAS) + REPORT "tRAS violation during Precharge bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + -- Activate to Precharge bank 1 + ASSERT (NOW - RAS_chk1 >= tRAS) + REPORT "tRAS violation during Precharge bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + -- Activate to Precharge bank 2 + ASSERT (NOW - RAS_chk2 >= tRAS) + REPORT "tRAS violation during Precharge bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + -- Activate to Precharge bank 3 + ASSERT (NOW - RAS_chk3 >= tRAS) + REPORT "tRAS violation during Precharge bank 3" + SEVERITY WARNING; + END IF; + -- tWR violation check for Write + ASSERT (NOW - WR_chkp(CONV_INTEGER(Ba)) >= tWRp) + REPORT "tWR violation during Precharge" + SEVERITY WARNING; + END IF; + -- Terminate a Write Immediately (if same bank or all banks) + IF (Data_in_enable = '1' AND (Bank = Ba OR Addr(10) = '1')) THEN + Data_in_enable := '0'; + END IF; + -- Precharge Command Pipeline for READ + IF CAS_latency_3 = '1' THEN + Command(2) := PRECH; + Bank_precharge(2) := Ba; + A10_precharge(2) := Addr(10); + ELSIF CAS_latency_2 = '1' THEN + Command(1) := PRECH; + Bank_precharge(1) := Ba; + A10_precharge(1) := Addr(10); + END IF; + END IF; + + -- Burst Terminate + IF Burst_term = '1' THEN + -- Terminate a Write immediately + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + -- Terminate a Read depend on CAS Latency + IF CAS_latency_3 = '1' THEN + Command(2) := BST; + ELSIF CAS_latency_2 = '1' THEN + Command(1) := BST; + END IF; + END IF; + + -- Read, Write, Column Latch + IF Read_enable = '1' OR Write_enable = '1' THEN + -- Check to see if bank is open (ACT) for Read or Write + IF ((Ba = "00" AND Pc_b0 = '1') OR (Ba = "01" AND Pc_b1 = '1') OR (Ba = "10" AND Pc_b2 = '1') OR (Ba = "11" AND Pc_b3 = '1')) THEN + ASSERT (FALSE) + REPORT "Cannot Read or Write - Bank is not Activated" + SEVERITY WARNING; + END IF; + -- Activate to Read or Write + IF Ba = "00" THEN + ASSERT (NOW - RCD_chk0 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + ASSERT (NOW - RCD_chk1 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + ASSERT (NOW - RCD_chk2 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + ASSERT (NOW - RCD_chk3 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 3" + SEVERITY WARNING; + END IF; + -- Read Command + IF Read_enable = '1' THEN + -- CAS Latency Pipeline + IF Cas_latency_3 = '1' THEN + IF Addr(10) = '1' THEN + Command(2) := READ_A; + ELSE + Command(2) := READ; + END IF; + Col_addr (2) := Addr(col_bits - 1 DOWNTO 0); + Bank_addr (2) := Ba; + ELSIF Cas_latency_2 = '1' THEN + IF Addr(10) = '1' THEN + Command(1) := READ_A; + ELSE + Command(1) := READ; + END IF; + Col_addr (1) := Addr(col_bits - 1 DOWNTO 0); + Bank_addr (1) := Ba; + END IF; + + -- Read intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Write Command + ELSIF Write_enable = '1' THEN + IF Addr(10) = '1' THEN + Command(0) := WRITE_A; + ELSE + Command(0) := WRITE; + END IF; + Col_addr (0) := Addr(col_bits - 1 DOWNTO 0); + Bank_addr (0) := Ba; + + -- Write intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Write interrupt a Read (terminate Read immediately) + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + + -- Interrupt a Write with Auto Precharge + IF Auto_precharge(CONV_INTEGER(RW_interrupt_bank)) = '1' AND Write_precharge(CONV_INTEGER(RW_interrupt_bank)) = '1' THEN + RW_interrupt_write(CONV_INTEGER(RW_interrupt_bank)) := '1'; + END IF; + + -- Interrupt a Read with Auto Precharge + IF Auto_precharge(CONV_INTEGER(RW_interrupt_bank)) = '1' AND Read_precharge(CONV_INTEGER(RW_interrupt_bank)) = '1' THEN + RW_interrupt_read(CONV_INTEGER(RW_interrupt_bank)) := '1'; + END IF; + + -- Read or Write with Auto Precharge + IF Addr(10) = '1' THEN + Auto_precharge (CONV_INTEGER(Ba)) := '1'; + Count_precharge (CONV_INTEGER(Ba)) := 0; + RW_interrupt_bank := Ba; + IF Read_enable = '1' THEN + Read_precharge (CONV_INTEGER(Ba)) := '1'; + ELSIF Write_enable = '1' THEN + Write_precharge (CONV_INTEGER(Ba)) := '1'; + END IF; + END IF; + END IF; + + -- Read with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. BL/2 cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Read_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(0) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8))) OR + (RW_interrupt_read(0) = '1')) THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + Auto_precharge(0) := '0'; + Read_precharge(0) := '0'; + RW_interrupt_read(0) := '0'; + END IF; + END IF; + IF ((Auto_precharge(1) = '1') AND (Read_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(1) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8))) OR + (RW_interrupt_read(1) = '1')) THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + Auto_precharge(1) := '0'; + Read_precharge(1) := '0'; + RW_interrupt_read(1) := '0'; + END IF; + END IF; + IF ((Auto_precharge(2) = '1') AND (Read_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(2) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8))) OR + (RW_interrupt_read(2) = '1')) THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + Auto_precharge(2) := '0'; + Read_precharge(2) := '0'; + RW_interrupt_read(2) := '0'; + END IF; + END IF; + IF ((Auto_precharge(3) = '1') AND (Read_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(3) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8))) OR + (RW_interrupt_read(3) = '1')) THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + Auto_precharge(3) := '0'; + Read_precharge(3) := '0'; + RW_interrupt_read(3) := '0'; + END IF; + END IF; + + -- Internal Precharge or Bst + IF Command(0) = PRECH THEN -- PRECH terminate a read if same bank or all banks + IF Bank_precharge(0) = Bank OR A10_precharge(0) = '1' THEN + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Command(0) = BST THEN -- BST terminate a read regardless of bank + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + + IF Data_out_enable = '0' THEN + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tOH; + END IF; + + -- Detect Read or Write Command + IF Command(0) = READ OR Command(0) = READ_A THEN + Bank := Bank_addr (0); + Col := Col_addr (0); + Col_brst := Col_addr (0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '0'; + Data_out_enable := '1'; + ELSIF Command(0) = WRITE OR Command(0) = WRITE_A THEN + Bank := Bank_addr(0); + Col := Col_addr(0); + Col_brst := Col_addr(0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '1'; + Data_out_enable := '0'; + END IF; + + -- DQ (Driver / Receiver) + Row_index := CONV_INTEGER (Row); + Col_index := CONV_INTEGER (Col); + IF Data_in_enable = '1' THEN + IF Dqm /= "1111" THEN + -- Initialize memory + Init_mem (Bank, Row_index); + -- Load memory into buffer + IF Bank = "00" THEN + Dq_temp := Bank0 (Row_index) (Col_index); + ELSIF Bank = "01" THEN + Dq_temp := Bank1 (Row_index) (Col_index); + ELSIF Bank = "10" THEN + Dq_temp := Bank2 (Row_index) (Col_index); + ELSIF Bank = "11" THEN + Dq_temp := Bank3 (Row_index) (Col_index); + END IF; + -- Dqm operation + IF Dqm (0) = '0' THEN + Dq_temp (7 DOWNTO 0) := Dq (7 DOWNTO 0); + END IF; + IF Dqm (1) = '0' THEN + Dq_temp (15 DOWNTO 8) := Dq (15 DOWNTO 8); + END IF; + IF Dqm (2) = '0' THEN + Dq_temp (23 DOWNTO 16) := Dq (23 DOWNTO 16); + END IF; + IF Dqm (3) = '0' THEN + Dq_temp (31 DOWNTO 24) := Dq (31 DOWNTO 24); + END IF; + -- Write back to memory + IF Bank = "00" THEN + Bank0 (Row_index) (Col_index) := Dq_temp; + ELSIF Bank = "01" THEN + Bank1 (Row_index) (Col_index) := Dq_temp; + ELSIF Bank = "10" THEN + Bank2 (Row_index) (Col_index) := Dq_temp; + ELSIF Bank = "11" THEN + Bank3 (Row_index) (Col_index) := Dq_temp; + END IF; + -- Reset tWR counter + WR_chkp(CONV_INTEGER(Bank)) := NOW; + WR_counter(CONV_INTEGER(Bank)) := 0; + END IF; + -- Decode next burst address + Burst_decode; + ELSIF Data_out_enable = '1' THEN + IF Dqm_reg0 /= "1111" THEN + -- Initialize memory + Init_mem (Bank, Row_index); + -- Load memory into buffer + IF Bank = "00" THEN + Dq_temp := Bank0 (Row_index) (Col_index); + ELSIF Bank = "01" THEN + Dq_temp := Bank1 (Row_index) (Col_index); + ELSIF Bank = "10" THEN + Dq_temp := Bank2 (Row_index) (Col_index); + ELSIF Bank = "11" THEN + Dq_temp := Bank3 (Row_index) (Col_index); + END IF; + -- Dqm operation + IF Dqm_reg0 (0) = '0' THEN + Dq (7 DOWNTO 0) <= TRANSPORT Dq_temp(7 DOWNTO 0) AFTER tAC; + ELSE + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + END IF; + IF Dqm_reg0 (1) = '0' THEN + Dq (15 DOWNTO 8) <= TRANSPORT Dq_temp(15 DOWNTO 8) AFTER tAC; + ELSE + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + END IF; + IF Dqm_reg0 (2) = '0' THEN + Dq (23 DOWNTO 16) <= TRANSPORT Dq_temp(23 DOWNTO 16) AFTER tAC; + ELSE + Dq (23 DOWNTO 16) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + END IF; + IF Dqm_reg0 (3) = '0' THEN + Dq (31 DOWNTO 24) <= TRANSPORT Dq_temp(31 DOWNTO 24) AFTER tAC; + ELSE + Dq (31 DOWNTO 24) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + END IF; + ELSE + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tHZ; + END IF; + Burst_decode; + END IF; + + -- Write with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. tWR cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Write_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(0) >= 1 AND NOW - Count_time(0) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2 AND NOW - Count_time(0) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4 AND NOW - Count_time(0) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8 AND NOW - Count_time(0) >= tWRa))) OR + (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 1 AND NOW - WR_time(0) >= tWRa)) THEN + Auto_precharge(0) := '0'; + Write_precharge(0) := '0'; + RW_interrupt_write(0) := '0'; + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + ASSERT FALSE REPORT "Start Internal Precharge Bank 0" SEVERITY NOTE; + END IF; + END IF; + IF ((Auto_precharge(1) = '1') AND (Write_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(1) >= 1 AND NOW - Count_time(1) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2 AND NOW - Count_time(1) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4 AND NOW - Count_time(1) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8 AND NOW - Count_time(1) >= tWRa))) OR + (RW_interrupt_write(1) = '1' AND WR_counter(1) >= 1 AND NOW - WR_time(1) >= tWRa)) THEN + Auto_precharge(1) := '0'; + Write_precharge(1) := '0'; + RW_interrupt_write(1) := '0'; + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + END IF; + END IF; + IF ((Auto_precharge(2) = '1') AND (Write_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(2) >= 1 AND NOW - Count_time(2) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2 AND NOW - Count_time(2) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4 AND NOW - Count_time(2) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8 AND NOW - Count_time(2) >= tWRa))) OR + (RW_interrupt_write(2) = '1' AND WR_counter(2) >= 1 AND NOW - WR_time(2) >= tWRa)) THEN + Auto_precharge(2) := '0'; + Write_precharge(2) := '0'; + RW_interrupt_write(2) := '0'; + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + END IF; + END IF; + IF ((Auto_precharge(3) = '1') AND (Write_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(3) >= 1 AND NOW - Count_time(3) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2 AND NOW - Count_time(3) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4 AND NOW - Count_time(3) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8 AND NOW - Count_time(3) >= tWRa))) OR + (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 1 AND NOW - WR_time(3) >= tWRa)) THEN + Auto_precharge(3) := '0'; + Write_precharge(3) := '0'; + RW_interrupt_write(3) := '0'; + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + END IF; + END IF; + END IF; + END PROCESS; + + -- Clock timing checks + Clock_check : PROCESS + VARIABLE Clk_low, Clk_high : TIME := 0 ns; + BEGIN + WAIT ON Clk; + IF (Clk = '1' AND NOW >= 10 ns) THEN + ASSERT (NOW - Clk_low >= tCL) + REPORT "tCL violation" + SEVERITY WARNING; + ASSERT (NOW - Clk_high >= tCK) + REPORT "tCK violation" + SEVERITY WARNING; + Clk_high := NOW; + ELSIF (Clk = '0' AND NOW /= 0 ns) THEN + ASSERT (NOW - Clk_high >= tCH) + REPORT "tCH violation" + SEVERITY WARNING; + Clk_low := NOW; + END IF; + END PROCESS; + + -- Setup timing checks + Setup_check : PROCESS + BEGIN + WAIT ON Clk; + IF Clk = '1' THEN + ASSERT(Cke'LAST_EVENT >= tCKS) + REPORT "CKE Setup time violation -- tCKS" + SEVERITY WARNING; + ASSERT(Cs_n'LAST_EVENT >= tCMS) + REPORT "CS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT >= tCMS) + REPORT "CAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT >= tCMS) + REPORT "RAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT >= tCMS) + REPORT "WE# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT >= tCMS) + REPORT "Dqm Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Addr'LAST_EVENT >= tAS) + REPORT "ADDR Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT >= tAS) + REPORT "BA Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Dq'LAST_EVENT >= tDS) + REPORT "Dq Setup time violation -- tDS" + SEVERITY WARNING; + END IF; + END PROCESS; + + -- Hold timing checks + Hold_check : PROCESS + BEGIN + WAIT ON Clk'DELAYED (tCKH), Clk'DELAYED (tCMH), Clk'DELAYED (tAH), Clk'DELAYED (tDH); + IF Clk'DELAYED (tCKH) = '1' THEN + ASSERT(Cke'LAST_EVENT > tCKH) + REPORT "CKE Hold time violation -- tCKH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tCMH) = '1' THEN + ASSERT(Cs_n'LAST_EVENT > tCMH) + REPORT "CS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT > tCMH) + REPORT "CAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT > tCMH) + REPORT "RAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT > tCMH) + REPORT "WE# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT > tCMH) + REPORT "Dqm Hold time violation -- tCMH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tAH) = '1' THEN + ASSERT(Addr'LAST_EVENT > tAH) + REPORT "ADDR Hold time violation -- tAH" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT > tAH) + REPORT "BA Hold time violation -- tAH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tDH) = '1' THEN + ASSERT(Dq'LAST_EVENT > tDH) + REPORT "DQ Hold time violation -- tDH" + SEVERITY WARNING; + END IF; + END PROCESS; + +END behave; diff --git a/lib/models/memory/sdram/mt48lc4m32b2/test.do b/lib/models/memory/sdram/mt48lc4m32b2/test.do new file mode 100644 index 0000000..532c7c2 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m32b2/test.do @@ -0,0 +1,5 @@ +vcom mt48lc4m32b2.vhd +vcom test.vhd +vsim -t ps tb +do wave.do +run -all diff --git a/lib/models/memory/sdram/mt48lc4m32b2/test.vhd b/lib/models/memory/sdram/mt48lc4m32b2/test.vhd new file mode 100644 index 0000000..473dccb --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m32b2/test.vhd @@ -0,0 +1,309 @@ +LIBRARY ieee; + USE ieee.std_logic_1164.ALL; + +ENTITY tb IS +END tb; + +ARCHITECTURE test OF tb IS + COMPONENT mt48lc4m32b2 + GENERIC ( -- Timing for -7 CL2 + tCK : TIME := 7.500 ns; + addr_bits : INTEGER := 12; + data_bits : INTEGER := 32 + ); + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '1'; + Cs_n : IN STD_LOGIC := '1'; + Cas_n : IN STD_LOGIC := '1'; + Ras_n : IN STD_LOGIC := '1'; + We_n : IN STD_LOGIC := '1'; + Dqm : IN STD_LOGIC_VECTOR (3 DOWNTO 0) := "0000" + ); + END COMPONENT; + + FOR ALL : mt48lc4m32b2 USE ENTITY work.mt48lc4m32b2 (behave); + + CONSTANT tCK : TIME := 7.500 ns; + CONSTANT addr_bits : INTEGER := 12; + CONSTANT data_bits : INTEGER := 32; + + SIGNAL pDq : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0); + SIGNAL pAddr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + SIGNAL pBa : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL pClk : STD_LOGIC; + SIGNAL pCke : STD_LOGIC; + SIGNAL pCs_n : STD_LOGIC; + SIGNAL pCas_n : STD_LOGIC; + SIGNAL pRas_n : STD_LOGIC; + SIGNAL pWe_n : STD_LOGIC; + SIGNAL pDqm : STD_LOGIC_VECTOR (3 DOWNTO 0); + SIGNAL stim_done : boolean := false; + SIGNAL clk_done : boolean := false; + + +BEGIN + u1: mt48lc4m32b2 + PORT MAP( + Dq => pDq, + Addr => pAddr, + Ba => pBa, + Clk => pClk, + Cke => pCke, + Cs_n => pCs_n, + Ras_n => pRas_n, + Cas_n => pCas_n, + We_n => pWe_n, + Dqm => pDqm + ); + + stimulator : PROCESS + PROCEDURE ACTIVE (Ba_in : STD_LOGIC_VECTOR (1 DOWNTO 0); + Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + Dq_in : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '0'; + pCas_n <= '1'; + pWe_n <= '1'; + pDqm <= "0000"; + pBa <= Ba_in; + pAddr <= Addr_in; + pDq <= Dq_in; + WAIT FOR tCK; + END; + + PROCEDURE AUTO_REFRESH IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '0'; + pCas_n <= '0'; + pWe_n <= '1'; + pDqm <= "0000"; + --pBa <= "00"; + --pAddr <= (OTHERS => '0'); + pDq <= (OTHERS => 'Z'); + WAIT FOR tCK; + END; + + PROCEDURE BURST_TERM IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '1'; + pCas_n <= '1'; + pWe_n <= '0'; + pDqm <= "0000"; + --pBa <= "00"; + --pAddr <= (OTHERS => '0'); + pDq <= (OTHERS => 'Z'); + WAIT FOR tCK; + END; + + PROCEDURE LOAD_MODE_REG (Ba_in : STD_LOGIC_VECTOR (1 DOWNTO 0); + Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0)) IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '0'; + pCas_n <= '0'; + pWe_n <= '0'; + pDqm <= "0000"; + pBa <= Ba_in; + pAddr <= Addr_in; + pDq <= (OTHERS => 'Z'); + WAIT FOR tCK; + END; + + PROCEDURE NOP (Dq_in : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '1'; + pCas_n <= '1'; + pWe_n <= '1'; + pDqm <= "0000"; + --pBa <= "00"; + --pAddr <= (OTHERS => '0'); + pDq <= Dq_in; + WAIT FOR tCK; + END; + + PROCEDURE PRECHARGE (Ba_in : STD_LOGIC_VECTOR (1 DOWNTO 0); + Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + Dq_in : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '0'; + pCas_n <= '1'; + pWe_n <= '0'; + pDqm <= "0000"; + pBa <= Ba_in; + pAddr <= Addr_in; + pDq <= Dq_in; + WAIT FOR tCK; + END; + + PROCEDURE READ (Ba_in : STD_LOGIC_VECTOR (1 DOWNTO 0); + Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + Dq_in : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '1'; + pCas_n <= '0'; + pWe_n <= '1'; + pDqm <= "0000"; + pBa <= Ba_in; + pAddr <= Addr_in; + pDq <= Dq_in; + WAIT FOR tCK; + END; + + -- Write + PROCEDURE WRITE (Ba_in : STD_LOGIC_VECTOR (1 DOWNTO 0); + Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + Dq_in : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '1'; + pCas_n <= '0'; + pWe_n <= '0'; + pDqm <= "0000"; + pBa <= Ba_in; + pAddr <= Addr_in; + pDq <= Dq_in; + WAIT FOR tCK; + END; + BEGIN + -- COMMAND BA ADDR DQ + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + -- We need 100 us power up sequence. I use 10 NOPs here as a required example. + PRECHARGE ("00", "010000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + + AUTO_REFRESH; + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + + AUTO_REFRESH; + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + + LOAD_MODE_REG ("00", "000000100010"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + + ACTIVE ("00", "000000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + + ACTIVE ("01", "000000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + + ACTIVE ("10", "000000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + + ACTIVE ("11", "000000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + + WRITE ("00", "000000000000", "00000000000000000000000000000000"); + NOP ( "00000000000000000000000000000001"); + NOP ( "00000000000000000000000000000010"); + NOP ( "00000000000000000000000000000011"); + + WRITE ("01", "000000000000", "00000000000000000000000000000100"); + NOP ( "00000000000000000000000000000101"); + NOP ( "00000000000000000000000000000110"); + NOP ( "00000000000000000000000000000111"); + + WRITE ("10", "000000000000", "00000000000000000000000000001000"); + NOP ( "00000000000000000000000000001001"); + NOP ( "00000000000000000000000000001010"); + NOP ( "00000000000000000000000000001011"); + + WRITE ("11", "000000000000", "00000000000000000000000000001100"); + NOP ( "00000000000000000000000000001101"); + NOP ( "00000000000000000000000000001110"); + NOP ( "00000000000000000000000000001111"); + + READ ("00", "000000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + READ ("01", "000000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + READ ("10", "000000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + READ ("11", "000000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + + ASSERT false + REPORT "End of Stimulation File Detected!" + SEVERITY note; + stim_done <= true; + WAIT; + END PROCESS; + + clock : PROCESS + VARIABLE done_time : time; + BEGIN + pclk <= '0'; + WAIT for tCK/2; + WHILE not stim_done loop + pclk <= '1'; + WAIT for tCK/2; + pclk <= '0'; + WAIT for tCK/2; + END LOOP; + done_time := now + tCK; + WHILE now < done_time LOOP -- one last clock to finish last command + pclk <= '1'; + WAIT for tCK/2; + pclk <= '0'; + WAIT for tCK/2; + END LOOP; + ASSERT false + REPORT "Suspending clock activity" + SEVERITY note; + clk_done <= true; + WAIT; + END PROCESS; +END test; diff --git a/lib/models/memory/sdram/mt48lc4m32b2/wave.do b/lib/models/memory/sdram/mt48lc4m32b2/wave.do new file mode 100644 index 0000000..26de1d2 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc4m32b2/wave.do @@ -0,0 +1,26 @@ +add wave -noupdate -radix default -format Logic /tb/u1/clk +add wave -noupdate -radix default -format Logic /tb/u1/cke +add wave -noupdate -radix default -format Logic /tb/u1/cs_n +add wave -noupdate -radix default -format Logic /tb/u1/ras_n +add wave -noupdate -radix default -format Logic /tb/u1/cas_n +add wave -noupdate -radix default -format Logic /tb/u1/we_n +add wave -noupdate -radix decimal /tb/u1/addr +add wave -noupdate -radix unsigned /tb/u1/ba +add wave -noupdate -radix decimal /tb/u1/dq +add wave -noupdate -radix default -format Logic /tb/u1/dqm +add wave -noupdate -radix decimal /tb/u1/operation +add wave -noupdate -radix decimal /tb/u1/mode_reg +add wave -noupdate -radix default -format Logic /tb/u1/active_enable +add wave -noupdate -radix default -format Logic /tb/u1/aref_enable +add wave -noupdate -radix default -format Logic /tb/u1/burst_term +add wave -noupdate -radix default -format Logic /tb/u1/mode_reg_enable +add wave -noupdate -radix default -format Logic /tb/u1/prech_enable +add wave -noupdate -radix default -format Logic /tb/u1/read_enable +add wave -noupdate -radix default -format Logic /tb/u1/write_enable +add wave -noupdate -radix default -format Logic /tb/u1/burst_length_1 +add wave -noupdate -radix default -format Logic /tb/u1/burst_length_2 +add wave -noupdate -radix default -format Logic /tb/u1/burst_length_4 +add wave -noupdate -radix default -format Logic /tb/u1/burst_length_8 +add wave -noupdate -radix default -format Logic /tb/u1/cas_latency_2 +add wave -noupdate -radix default -format Logic /tb/u1/cas_latency_3 + diff --git a/lib/models/memory/sdram/mt48lc64m4a2/base.do b/lib/models/memory/sdram/mt48lc64m4a2/base.do new file mode 100644 index 0000000..d2afbcb --- /dev/null +++ b/lib/models/memory/sdram/mt48lc64m4a2/base.do @@ -0,0 +1,5 @@ +vcom util1164.vhd +vcom stdlogar.vhd +vcom io_utils.vhd +vcom mti_pkg.vhd + diff --git a/lib/models/memory/sdram/mt48lc64m4a2/ed_comnd.vhd b/lib/models/memory/sdram/mt48lc64m4a2/ed_comnd.vhd new file mode 100644 index 0000000..bd59d3c --- /dev/null +++ b/lib/models/memory/sdram/mt48lc64m4a2/ed_comnd.vhd @@ -0,0 +1,345 @@ +--------------------------------------------------------------------------------- +--COMMAND FORMAT -- +-- -- +-- write(column address(integer), bank(bit_vector), first data(integer), dqm(bit), cke(bit));-- +-- read(column address(integer), bank(bit_vector), dqm(bit), cke(bit)); -- +-- active(row address(integer), bank(bit_vector), data bus (integer), dqm(bit), cke(bit));-- +-- precharge(bank(bit_vector), address (integer), data bus(integer), dqm(bit), cke(bit)); -- +-- nop(data bus(integer), dqm(bit), cke(bit), cs(bit)); -- +-- burst_term(data bus(integer), dqm(bit), cke(bit)); -- +-- load_array('1'); -- +-- load_mode_reg(register(integer), cke(bit)); -- +-- next_cycle(clk); This is used after every command(incl. nop) to clock -- +-- at the correct clock frequency entered in the clock -- +-- period constant below -- +-- unload_array(row_start(integer), row_end(integer), bank(bit_vector)) -- +-- load_mode_reg(op_code(integer)) -- +-- -- +--------------------------------------------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.all; +USE std.textio.all; +USE work.generate_vectors.all; + +ENTITY vector_generate IS +END vector_generate; + +ARCHITECTURE vector_generate OF vector_generate IS + + SIGNAL stim_done : BOOLEAN := FALSE; + SIGNAL clk : BIT := '0'; + CONSTANT clk_start : time := 15 ns; + CONSTANT clk_period : time := 10 ns; + CONSTANT Z : INTEGER := -100; + +BEGIN + +PROCESS + +BEGIN + +WAIT UNTIL clk = '1' AND clk'EVENT; + +--------------------ENTER COMMANDS BELOW THIS LINE----------------------------- +--******************DO NOT USE -100 FOR A DQ VALUE*************************---- +--*******************Z WILL PLACE HI-Z ON THE BUS**************************---- +--*******USE next_cycle(clk) FOR ADVANCING TO NEXT CLOCK CYCLE*************---- + +nop(Z, '0', '1', '1'); --Always begin with one nop when using Micron's testbench + +--next_cycle(clk); +--load_array('1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +precharge("00", 1024, Z, '0', '1'); + +FOR i IN 1 to 2 LOOP + next_cycle(clk); + nop(Z, '0', '1', '1'); +END LOOP; + +next_cycle(clk); +auto_refresh; + +FOR i IN 1 TO 8 LOOP + next_cycle(clk); + nop(Z, '0', '1', '1'); +END LOOP; + +next_cycle(clk); +auto_refresh; + +FOR i IN 1 TO 8 LOOP + next_cycle(clk); + nop(Z, '0', '1', '1'); +END LOOP; + +next_cycle(clk); +load_mode_reg(51, '1'); -- 19 / 35 / 51 -> lat=3,bl=8,mode=seq + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +-- Write Section + +next_cycle(clk); +active(0, "00", Z, '0', '1'); -- Activate Bank 0 + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); -- Write Bank 0 +write(10, "00", 0, '0', '1'); + +next_cycle(clk); +nop(1, '0', '1', '1'); + +next_cycle(clk); +active(0, "01", 2, '0', '1'); -- Activate Bank 1 + +next_cycle(clk); +nop(3, '0', '1', '1'); + +next_cycle(clk); +nop(4, '0', '1', '1'); + +next_cycle(clk); +nop(5, '0', '1', '1'); + +next_cycle(clk); +nop(6, '0', '1', '1'); + +next_cycle(clk); +nop(7, '0', '1', '1'); + +next_cycle(clk); +write(20, "01", 8, '0', '1'); -- Write Bank 1 + +next_cycle(clk); +precharge("00", 0, 9, '0', '1'); -- Precharge Bank 0 + +next_cycle(clk); +active(0, "10", 10, '0', '1'); -- Activate Bank 2 + +next_cycle(clk); +nop(11, '0', '1', '1'); + +next_cycle(clk); +nop(12, '0', '1', '1'); + +next_cycle(clk); +nop(13, '0', '1', '1'); + +next_cycle(clk); +nop(14, '0', '1', '1'); + +next_cycle(clk); +nop(15, '0', '1', '1'); + +next_cycle(clk); +write(30, "10", 0, '0', '1'); -- Write Bank 2 + +next_cycle(clk); +precharge("01", 0, 1, '0', '1'); -- Precharge Bank 1 + +next_cycle(clk); +active(0, "11", 2, '0', '1'); -- Activate Bank 3 + +next_cycle(clk); +nop(3, '0', '1', '1'); + +next_cycle(clk); +nop(4, '0', '1', '1'); + +next_cycle(clk); +nop(5, '0', '1', '1'); + +next_cycle(clk); +nop(6, '0', '1', '1'); + +next_cycle(clk); +nop(7, '0', '1', '1'); + +next_cycle(clk); +write(40, "11", 8, '0', '1'); -- Write Bank 3 + +next_cycle(clk); +precharge("10", 0, 9, '0', '1'); -- Precharge Bank 2 + +next_cycle(clk); +active(0, "00", 10, '0', '1'); -- Activate Bank 0 + +next_cycle(clk); +nop(11, '0', '1', '1'); + +next_cycle(clk); +nop(12, '0', '1', '1'); + +next_cycle(clk); +nop(13, '0', '1', '1'); + +next_cycle(clk); +nop(14, '0', '1', '1'); + +next_cycle(clk); +nop(15, '0', '1', '1'); + +-- Read Section + +next_cycle(clk); +read(10, "00", '0', '1'); -- Read Bank 0 + +next_cycle(clk); +precharge("11", 0, Z, '0', '1'); -- Precharge Bank 3 + +next_cycle(clk); +active(0, "01", Z, '0', '1'); -- Activate Bank 1 + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +read(20, "01", '0', '1'); -- Read Bank 1 + +next_cycle(clk); +precharge("00", 0, Z, '0', '1'); -- Precharge Bank 0 + +next_cycle(clk); +active(0, "10", Z, '0', '1'); -- Activate Bank 2 + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +read(30, "10", '0', '1'); -- Read Bank 2 + +next_cycle(clk); +precharge("01", 0, Z, '0', '1'); -- Precharge Bank 1 + +next_cycle(clk); +active(0, "11", Z, '0', '1'); -- Activate Bank 3 + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +read(40, "11", '0', '1'); -- Read Bank 3 + +next_cycle(clk); +precharge("10", 0, Z, '0', '1'); -- Precharge Bank 2 + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +precharge("11", 0, Z, '0', '1'); -- Precharge Bank 3 + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +--next_cycle(clk); +--unload_array(0, 0, '0'); + +next_cycle(clk); +nop(Z, '0', '1', '1'); + +stim_done <= TRUE; --always include this line at the end of your stimulus + +------------------------------------------------------------------------------- +--*************************************************************************---- +END PROCESS; + + +clock: + PROCESS + VARIABLE done_time : time; + VARIABLE cycle_var : integer := 0; + BEGIN + cycle <= 0; + clk <= '0'; + WAIT for clk_start; + WHILE not stim_done loop + clk <= '1'; + cycle <= cycle_var; + WAIT for clk_period/2; + cycle_var := cycle_var + 1; + clk <= '0'; + WAIT for clk_period/2; + END LOOP; + + ASSERT (FALSE) + REPORT "Test Vectors Generated" + SEVERITY note; + + WAIT; + END PROCESS; + + +END; diff --git a/lib/models/memory/sdram/mt48lc64m4a2/io_utils.vhd b/lib/models/memory/sdram/mt48lc64m4a2/io_utils.vhd new file mode 100644 index 0000000..dfcb84a --- /dev/null +++ b/lib/models/memory/sdram/mt48lc64m4a2/io_utils.vhd @@ -0,0 +1,266 @@ +LIBRARY ieee; +USE std.textio.ALL; +USE ieee.std_logic_1164.ALL; + +PACKAGE io_utils IS + + PROCEDURE write_string(l : INOUT line; + value : IN string; + justified : IN side := right; + field : IN width := 0); + + TYPE radix IS (binary, octal, decimal, hex); + + -- read a number from the line + -- use this if you have hex numbers that are not in VHDL pound-sign format + PROCEDURE read(l : INOUT line; value : OUT integer; radix : IN positive); + + -- read a number that might be in VHDL pound-sign format + PROCEDURE read_based(l : INOUT line; value : OUT integer); + + PROCEDURE write(l : INOUT line; + value : IN std_logic_vector; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false); + + PROCEDURE write(l : INOUT line; + value : IN integer; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false); +END io_utils; + +PACKAGE BODY io_utils IS + + PROCEDURE write_string(l : INOUT line; + value : IN string; + justified : IN side := right; + field : IN width := 0) + IS + BEGIN + write(l, value, justified, field); + END; + + PROCEDURE shrink_line(l : INOUT line; pos : integer) IS + VARIABLE tmpl : line; + BEGIN + tmpl := l; + l := NEW string'(tmpl(pos TO tmpl'high)); + deallocate(tmpl); + END; + + PROCEDURE read(l : INOUT line; + value : OUT integer; + radix : IN positive) + IS + CONSTANT not_digit : integer := -999; + + -- convert a character to a value from 0 to 15 + FUNCTION digit_value(c : character) RETURN integer IS + BEGIN + IF (c >= '0') AND (c <= '9') THEN + RETURN (character'pos(c) - character'pos('0')); + ELSIF (c >= 'a') AND (c <= 'f') THEN + RETURN (character'pos(c) - character'pos('a') + 10); + ELSIF (c >= 'A') AND (c <= 'F') THEN + RETURN (character'pos(c) - character'pos('A') + 10); + ELSE + RETURN not_digit; + END IF; + END; + + -- skip leading white space in the line + PROCEDURE skip_white(VARIABLE l : IN line; pos : OUT integer) IS + BEGIN + pos := l'low; + FOR i IN l'low TO l'high LOOP + CASE l(i) IS + WHEN ' ' | ht => + pos := i + 1; + WHEN OTHERS => + EXIT; + END CASE; + END LOOP; + END; + + VARIABLE digit : integer; + VARIABLE result : integer := 0; + VARIABLE pos : integer; + BEGIN + -- skip white space + skip_white(l, pos); + + -- calculate the value + FOR i IN pos TO l'right LOOP + digit := digit_value(l(i)); + EXIT WHEN (digit = not_digit) OR (digit >= radix); + result := result * radix + digit; + pos := i + 1; + END LOOP; + value := result; + + -- remove the "used" characters from the line + shrink_line(l, pos); + END; + + PROCEDURE read_based(l : INOUT line; value : OUT integer) IS + VARIABLE digit : integer; + VARIABLE num : integer; + VARIABLE base : integer; + BEGIN + read(l, num, 10); + IF (l'length > 1) AND (l(l'left) = '#') THEN + shrink_line(l, l'left+1); + base := num; + read(l, num, base); + IF (l'length >= 1) AND (l(l'left) = '#') THEN + shrink_line(l, l'left+1); + END IF; + END IF; + value := num; + END; + + PROCEDURE write(l : INOUT line; + value : IN std_logic_vector; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false) + IS + FUNCTION to_int(bv : std_logic_vector) RETURN integer + IS + VARIABLE result : integer := 0; + BEGIN + FOR i IN bv'RANGE LOOP + result := result * 2; + IF (bv(i) = '1') THEN + result := result + 1; + END IF; + END LOOP; + RETURN result; + END; + + TYPE array_of_widths IS ARRAY(radix) OF natural; + CONSTANT nibble_widths : array_of_widths := ( + binary => 1, + octal => 3, + hex => 4, + decimal=> 32); + CONSTANT hex_digit : string(1 TO 16) := "0123456789ABCDEF"; + + ALIAS input_val : std_logic_vector(value'length DOWNTO 1) IS value; + CONSTANT nibble_width : natural := nibble_widths(base); + CONSTANT result_width : natural := (value'length + nibble_width - 1)/nibble_width; + + VARIABLE result : string(1 TO result_width); -- longest possible value + VARIABLE result_pos : positive := 1; + VARIABLE nibble_val : integer; + VARIABLE bitcnt : integer; + BEGIN + IF base = decimal THEN + write(l, to_int(value), justified, field, base, use_pound); + RETURN; + END IF; + + bitcnt := value'length MOD nibble_width; + IF (bitcnt = 0) THEN + bitcnt := nibble_width; + END IF; + FOR i IN input_val'RANGE LOOP + nibble_val := nibble_val * 2; + IF (input_val(i) = '1') THEN + nibble_val := nibble_val + 1; + END IF; + bitcnt := bitcnt - 1; + IF (bitcnt = 0) THEN + result(result_pos) := hex_digit(nibble_val + 1); + result_pos := result_pos + 1; + nibble_val := 0; + bitcnt := nibble_width; + END IF; + END LOOP; + write(l, result, justified, field); + END; + + PROCEDURE write(l : INOUT line; + value : IN integer; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false) + IS + FUNCTION to_bv(int : integer) RETURN std_logic_vector + IS + VARIABLE bv : std_logic_vector(32 DOWNTO 1) := (OTHERS => '0'); + VARIABLE pos : integer := 0; + VARIABLE tmpval : integer := int; + BEGIN + FOR i IN 1 TO 32 LOOP + pos := pos + 1; + IF (tmpval MOD 2) = 1 THEN + bv(i) := '1'; + END IF; + tmpval := tmpval / 2; + EXIT WHEN tmpval = 0; + END LOOP; + RETURN bv(pos DOWNTO 1); + END; + + VARIABLE tmp : line; + BEGIN + IF (base = decimal) THEN + IF (use_pound) THEN + write_string(tmp, "10#"); + END IF; + write(tmp, value); + IF (use_pound) THEN + write_string(tmp, "#"); + END IF; + write(l, tmp.ALL, justified, field); + deallocate(tmp); + ELSE + write(l, to_bv(value), justified, field, base, use_pound); + END IF; + END; + +END io_utils; + + + +-- test the hex number reader +--ENTITY test IS END; + +--USE std.textio.ALL; +--USE work.io_utils.ALL; +--ARCHITECTURE hex_test OF test IS +--BEGIN +-- PROCESS +-- VARIABLE val : integer; +-- FILE myfile : text IS IN "values"; +-- VARIABLE inline : line; +-- VARIABLE outline : line; +-- BEGIN +-- WHILE NOT endfile(myfile) LOOP +-- readline(myfile, inline); + +-- write(outline, inline.ALL); +-- +-- read_based(inline, val); + -- write_string(outline, " binary: "); + -- write(outline, val, base => binary); + -- write_string(outline, " octal: "); + -- write(outline, val, base => octal); + -- write_string(outline, " decimal: "); + -- write(outline, val, base => decimal); +-- write_string(outline, " hex: "); +-- write(outline, val, base => hex); +-- writeline(output, outline); +-- END LOOP; +-- WAIT; +-- END PROCESS; +--END; + + diff --git a/lib/models/memory/sdram/mt48lc64m4a2/mt48lc64m4a2.vhd b/lib/models/memory/sdram/mt48lc64m4a2/mt48lc64m4a2.vhd new file mode 100644 index 0000000..f0ae0e9 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc64m4a2/mt48lc64m4a2.vhd @@ -0,0 +1,1055 @@ +----------------------------------------------------------------------------------------- +-- +-- File Name: MT48LC64M4A2.VHD +-- Version: 0.0f +-- Date: July 8th, 1999 +-- Model: Behavioral +-- Simulator: Model Technology (PC version 5.2e PE) +-- +-- Dependencies: None +-- +-- Author: Son P. Huynh +-- Email: sphuynh@micron.com +-- Phone: (208) 368-3825 +-- Company: Micron Technology, Inc. +-- Part Number: MT48LC64M4A2 (16Mb x 4 x 4 Banks) +-- +-- Description: Micron 256Mb SDRAM +-- +-- Limitation: - Doesn't check for 4096-cycle refresh +-- +-- Note: - Set simulator resolution to "ps" accuracy +-- +-- Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY +-- WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY +-- IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR +-- A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT. +-- +-- Copyright (c) 1998 Micron Semiconductor Products, Inc. +-- All rights researved +-- +-- Rev Author Phone Date Changes +-- ---- ---------------------------- ---------- ------------------------------------- +-- 0.0f Son Huynh 208-368-3825 07/08/1999 Initial Release (from 128Mb) +-- Micron Technology Inc. +-- +----------------------------------------------------------------------------------------- + +LIBRARY ieee; + USE ieee.std_logic_1164.ALL; +LIBRARY work; + USE work.mti_pkg.ALL; + +ENTITY mt48lc64m4a2 IS + GENERIC ( + -- Timing Parameters for -75 (PC133) and CAS Latency = 2 + tAC : TIME := 6.0 ns; + tHZ : TIME := 7.0 ns; + tOH : TIME := 2.7 ns; + tMRD : INTEGER := 2; -- 2 Clk Cycles + tRAS : TIME := 44.0 ns; + tRC : TIME := 66.0 ns; + tRCD : TIME := 20.0 ns; + tRP : TIME := 20.0 ns; + tRRD : TIME := 15.0 ns; + tWRa : TIME := 7.5 ns; -- A2 Version - Auto precharge mode only (1 Clk + 7.5 ns) + tWRp : TIME := 15.0 ns; -- A2 Version - Precharge mode only (15 ns) + + tAH : TIME := 0.8 ns; + tAS : TIME := 1.5 ns; + tCH : TIME := 2.5 ns; + tCL : TIME := 2.5 ns; + tCK : TIME := 10.0 ns; + tDH : TIME := 0.8 ns; + tDS : TIME := 1.5 ns; + tCKH : TIME := 0.8 ns; + tCKS : TIME := 1.5 ns; + tCMH : TIME := 0.8 ns; + tCMS : TIME := 1.5 ns; + addr_bits : INTEGER := 13; + data_bits : INTEGER := 4; + col_bits : INTEGER := 11 + ); + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC_VECTOR := "00"; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '0'; + Cs_n : IN STD_LOGIC := '1'; + Ras_n : IN STD_LOGIC := '0'; + Cas_n : IN STD_LOGIC := '0'; + We_n : IN STD_LOGIC := '0'; + Dqm : IN STD_LOGIC := '0' + ); +END mt48lc64m4a2; + +ARCHITECTURE behave OF mt48lc64m4a2 IS + TYPE State IS (ACT, A_REF, BST, LMR, NOP, PRECH, READ, READ_A, WRITE, WRITE_A); + TYPE Array4xI IS ARRAY (3 DOWNTO 0) OF INTEGER; + TYPE Array4xT IS ARRAY (3 DOWNTO 0) OF TIME; + TYPE Array4xB IS ARRAY (3 DOWNTO 0) OF BIT; + TYPE Array4x2BV IS ARRAY (3 DOWNTO 0) OF BIT_VECTOR (1 DOWNTO 0); + TYPE Array2xB IS ARRAY (1 DOWNTO 0) OF BIT; + TYPE Array4xCBV IS ARRAY (4 DOWNTO 0) OF BIT_VECTOR (Col_bits - 1 DOWNTO 0); + TYPE Array_state IS ARRAY (4 DOWNTO 0) OF State; + SIGNAL Operation : State := NOP; + SIGNAL Mode_reg : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL Active_enable, Aref_enable, Burst_term : BIT := '0'; + SIGNAL Mode_reg_enable, Prech_enable, Read_enable, Write_enable : BIT := '0'; + SIGNAL Burst_length_1, Burst_length_2, Burst_length_4, Burst_length_8 : BIT := '0'; + SIGNAL Cas_latency_2, Cas_latency_3 : BIT := '0'; + SIGNAL Ras_in, Cas_in, We_in : BIT := '0'; + SIGNAL Write_burst_mode : BIT := '0'; + SIGNAL Sys_clk, CkeZ : BIT := '0'; + SIGNAL WR_counter : Array4xI := (0 & 0 & 0 & 0); + + -- Checking internal wires + SIGNAL Pre_chk : BIT_VECTOR (3 DOWNTO 0) := "0000"; + SIGNAL Act_chk : BIT_VECTOR (3 DOWNTO 0) := "0000"; + SIGNAL Dq_in_chk, Dq_out_chk : BIT := '0'; + SIGNAL Bank_chk : BIT_VECTOR (1 DOWNTO 0) := "00"; + SIGNAL Row_chk : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL Col_chk : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + + BEGIN + -- CS# Decode + WITH Cs_n SELECT + Cas_in <= TO_BIT (Cas_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + WITH Cs_n SELECT + Ras_in <= TO_BIT (Ras_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + WITH Cs_n SELECT + We_in <= TO_BIT (We_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + + -- Commands Decode + Active_enable <= NOT(Ras_in) AND Cas_in AND We_in; + Aref_enable <= NOT(Ras_in) AND NOT(Cas_in) AND We_in; + Burst_term <= Ras_in AND Cas_in AND NOT(We_in); + Mode_reg_enable <= NOT(Ras_in) AND NOT(Cas_in) AND NOT(We_in); + Prech_enable <= NOT(Ras_in) AND Cas_in AND NOT(We_in); + Read_enable <= Ras_in AND NOT(Cas_in) AND We_in; + Write_enable <= Ras_in AND NOT(Cas_in) AND NOT(We_in); + + -- Burst Length Decode + Burst_length_1 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND NOT(Mode_reg(0)); + Burst_length_2 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND Mode_reg(0); + Burst_length_4 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND NOT(Mode_reg(0)); + Burst_length_8 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND Mode_reg(0); + + -- CAS Latency Decode + Cas_latency_2 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND NOT(Mode_reg(4)); + Cas_latency_3 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND Mode_reg(4); + + -- Write Burst Mode + Write_burst_mode <= Mode_reg(9); + + -- System Clock + int_clk : PROCESS (Clk) + begin + IF Clk'LAST_VALUE = '0' AND Clk = '1' THEN + CkeZ <= TO_BIT(Cke, '1'); + END IF; + Sys_clk <= CkeZ AND TO_BIT(Clk, '0'); + END PROCESS; + + state_register : PROCESS + TYPE ram_type IS ARRAY (2**col_bits - 1 DOWNTO 0) OF BIT_VECTOR (data_bits - 1 DOWNTO 0); + TYPE ram_pntr IS ACCESS ram_type; + TYPE ram_stor IS ARRAY (2**addr_bits - 1 DOWNTO 0) OF ram_pntr; + VARIABLE Bank0 : ram_stor; + VARIABLE Bank1 : ram_stor; + VARIABLE Bank2 : ram_stor; + VARIABLE Bank3 : ram_stor; + VARIABLE Row_index, Col_index : INTEGER := 0; + VARIABLE Dq_temp : BIT_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => '0'); + + VARIABLE Col_addr : Array4xCBV; + VARIABLE Bank_addr : Array4x2BV; + VARIABLE Dqm_reg : Array2xB; + + VARIABLE Bank, Previous_bank : BIT_VECTOR (1 DOWNTO 0) := "00"; + VARIABLE B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col_brst : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Row : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Burst_counter : INTEGER := 0; + + VARIABLE Command : Array_state; + VARIABLE Bank_precharge : Array4x2BV; + VARIABLE A10_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Auto_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Read_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Write_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Count_precharge : Array4xI := (0 & 0 & 0 & 0); + VARIABLE RW_interrupt_write : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_read : Array4xB := ('0' & '0' & '0' & '0'); + + VARIABLE Data_in_enable, Data_out_enable : BIT := '0'; + VARIABLE Pc_b0, Pc_b1, Pc_b2, Pc_b3 : BIT := '0'; + VARIABLE Act_b0, Act_b1, Act_b2, Act_b3 : BIT := '0'; + + -- Timing Check + VARIABLE MRD_chk : INTEGER := 0; + VARIABLE RC_chk, RRD_chk : TIME := 0 ns; + VARIABLE RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3 : TIME := 0 ns; + VARIABLE RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3 : TIME := 0 ns; + VARIABLE RP_chk0, RP_chk1, RP_chk2, RP_chk3 : TIME := 0 ns; + VARIABLE WR_chk : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + + -- Initialize empty rows + PROCEDURE Init_mem (Bank : BIT_VECTOR (1 DOWNTO 0); Row_index : INTEGER) IS + VARIABLE i, j : INTEGER := 0; + BEGIN + IF Bank = "00" THEN + IF Bank0 (Row_index) = NULL THEN -- Check to see if row empty + Bank0 (Row_index) := NEW ram_type; -- Open new row for access + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP -- Filled row with zeros + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank0 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "01" THEN + IF Bank1 (Row_index) = NULL THEN + Bank1 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank1 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "10" THEN + IF Bank2 (Row_index) = NULL THEN + Bank2 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank2 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "11" THEN + IF Bank3 (Row_index) = NULL THEN + Bank3 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank3 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + END IF; + END; + + -- Burst Counter + PROCEDURE Burst_decode IS + VARIABLE Col_int : INTEGER := 0; + VARIABLE Col_vec, Col_temp : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + BEGIN + -- Advance Burst Counter + Burst_counter := Burst_counter + 1; + + -- Burst Type + IF Mode_reg (3) = '0' THEN + Col_int := TO_INTEGER(Col); + Col_int := Col_int + 1; + TO_BITVECTOR (Col_int, Col_temp); + ELSIF Mode_reg (3) = '1' THEN + TO_BITVECTOR (Burst_counter, Col_vec); + Col_temp (2) := Col_vec (2) XOR Col_brst (2); + Col_temp (1) := Col_vec (1) XOR Col_brst (1); + Col_temp (0) := Col_vec (0) XOR Col_brst (0); + END IF; + + -- Burst Length + IF Burst_length_2 = '1' THEN + Col (0) := Col_temp (0); + ELSIF Burst_length_4 = '1' THEN + Col (1 DOWNTO 0) := Col_temp (1 DOWNTO 0); + ELSIF Burst_length_8 = '1' THEN + Col (2 DOWNTO 0) := Col_temp (2 DOWNTO 0); + ELSE + Col := Col_temp; + END IF; + + -- Burst Read Single Write + IF Write_burst_mode = '1' AND Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Data counter + IF Burst_length_1 = '1' THEN + IF Burst_counter >= 1 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_2 = '1' THEN + IF Burst_counter >= 2 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_4 = '1' THEN + IF Burst_counter >= 4 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_8 = '1' THEN + IF Burst_counter >= 8 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + END IF; + END; + + BEGIN + WAIT ON Sys_clk, WR_counter(0), WR_counter(1), WR_counter(2), WR_counter(3); + IF Sys_clk'event and Sys_clk = '1' THEN + -- Internal Command Pipeline + Command(0) := Command(1); + Command(1) := Command(2); + Command(2) := Command(3); + Command(3) := NOP; + + Col_addr(0) := Col_addr(1); + Col_addr(1) := Col_addr(2); + Col_addr(2) := Col_addr(3); + Col_addr(3) := (OTHERS => '0'); + + Bank_addr(0) := Bank_addr(1); + Bank_addr(1) := Bank_addr(2); + Bank_addr(2) := Bank_addr(3); + Bank_addr(3) := "00"; + + Bank_precharge(0) := Bank_precharge(1); + Bank_precharge(1) := Bank_precharge(2); + Bank_precharge(2) := Bank_precharge(3); + Bank_precharge(3) := "00"; + + A10_precharge(0) := A10_precharge(1); + A10_precharge(1) := A10_precharge(2); + A10_precharge(2) := A10_precharge(3); + A10_precharge(3) := '0'; + + -- Operation Decode (Optional for showing current command on posedge clock / debug feature) + IF Active_enable = '1' THEN + Operation <= ACT; + ELSIF Aref_enable = '1' THEN + Operation <= A_REF; + ELSIF Burst_term = '1' THEN + Operation <= BST; + ELSIF Mode_reg_enable = '1' THEN + Operation <= LMR; + ELSIF Prech_enable = '1' THEN + Operation <= PRECH; + ELSIF Read_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= READ; + ELSE + Operation <= READ_A; + END IF; + ELSIF Write_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= WRITE; + ELSE + Operation <= WRITE_A; + END IF; + ELSE + Operation <= NOP; + END IF; + + -- Dqm pipeline for Read + Dqm_reg(0) := Dqm_reg(1); + Dqm_reg(1) := TO_BIT(Dqm); + + -- Read or Write with Auto Precharge Counter + IF Auto_precharge (0) = '1' THEN + Count_precharge (0) := Count_precharge (0) + 1; + END IF; + IF Auto_precharge (1) = '1' THEN + Count_precharge (1) := Count_precharge (1) + 1; + END IF; + IF Auto_precharge (2) = '1' THEN + Count_precharge (2) := Count_precharge (2) + 1; + END IF; + IF Auto_precharge (3) = '1' THEN + Count_precharge (3) := Count_precharge (3) + 1; + END IF; + + -- tMRD Counter + MRD_chk := MRD_chk + 1; + + -- tWR Counter + WR_counter(0) <= WR_counter(0) + 1; + WR_counter(1) <= WR_counter(1) + 1; + WR_counter(2) <= WR_counter(2) + 1; + WR_counter(3) <= WR_counter(3) + 1; + + -- Auto Refresh + IF Aref_enable = '1' THEN + -- Auto Refresh to Auto Refresh + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Auto Refresh" + SEVERITY WARNING; + -- Precharge to Auto Refresh + ASSERT (NOW - RP_chk0 >= tRP OR NOW - RP_chk1 >= tRP OR NOW - RP_chk2 >= tRP OR NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Auto Refresh" + SEVERITY WARNING; + -- All banks must be idle before refresh + IF (Pc_b3 = '0' OR Pc_b2 = '0' OR Pc_b1 = '0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All banks must be Precharge before Auto Refresh" + SEVERITY WARNING; + END IF; + -- Record current tRC time + RC_chk := NOW; + END IF; + + -- Load Mode Register + IF Mode_reg_enable = '1' THEN + Mode_reg <= TO_BITVECTOR (Addr); + IF (Pc_b3 = '0' OR Pc_b2 = '0' OR Pc_b1 = '0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All bank must be Precharge before Load Mode Register" + SEVERITY WARNING; + END IF; + -- REF to LMR + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Load Mode Register" + SEVERITY WARNING; + -- LMR to LMR + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Load Mode Register" + SEVERITY WARNING; + -- Record current tMRD time + MRD_chk := 0; + END IF; + + -- Active Block (latch Bank and Row Address) + IF Active_enable = '1' THEN + IF Ba = "00" AND Pc_b0 = '1' THEN + Act_b0 := '1'; + Pc_b0 := '0'; + B0_row_addr := TO_BITVECTOR (Addr); + RCD_chk0 := NOW; + RAS_chk0 := NOW; + -- Precharge to Active Bank 0 + ASSERT (NOW - RP_chk0 >= tRP) + REPORT "tRP violation during Activate Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '1' THEN + Act_b1 := '1'; + Pc_b1 := '0'; + B1_row_addr := TO_BITVECTOR (Addr); + RCD_chk1 := NOW; + RAS_chk1 := NOW; + -- Precharge to Active Bank 1 + ASSERT (NOW - RP_chk1 >= tRP) + REPORT "tRP violation during Activate Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '1' THEN + Act_b2 := '1'; + Pc_b2 := '0'; + B2_row_addr := TO_BITVECTOR (Addr); + RCD_chk2 := NOW; + RAS_chk2 := NOW; + -- Precharge to Active Bank 2 + ASSERT (NOW - RP_chk2 >= tRP) + REPORT "tRP violation during Activate Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '1' THEN + Act_b3 := '1'; + Pc_b3 := '0'; + B3_row_addr := TO_BITVECTOR (Addr); + RCD_chk3 := NOW; + RAS_chk3 := NOW; + -- Precharge to Active Bank 3 + ASSERT (NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Activate Bank 3" + SEVERITY WARNING; + ELSIF Ba = "00" AND Pc_b0 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 0 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 1 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 2 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 3 is not Precharged" + SEVERITY WARNING; + END IF; + -- Active Bank A to Active Bank B + IF ((Previous_bank /= TO_BITVECTOR (Ba)) AND (NOW - RRD_chk < tRRD)) THEN + ASSERT (FALSE) + REPORT "tRRD violation during Activate" + SEVERITY WARNING; + END IF; + -- LMR to ACT + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Activate" + SEVERITY WARNING; + -- AutoRefresh to Activate + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Activate" + SEVERITY WARNING; + -- Record variable for checking violation + RRD_chk := NOW; + Previous_bank := TO_BITVECTOR (Ba); + END IF; + + -- Precharge Block + IF Prech_enable = '1' THEN + IF Addr(10) = '1' THEN + Pc_b0 := '1'; + Pc_b1 := '1'; + Pc_b2 := '1'; + Pc_b3 := '1'; + Act_b0 := '0'; + Act_b1 := '0'; + Act_b2 := '0'; + Act_b3 := '0'; + RP_chk0 := NOW; + RP_chk1 := NOW; + RP_chk2 := NOW; + RP_chk3 := NOW; + -- Activate to Precharge all banks + ASSERT ((NOW - RAS_chk0 >= tRAS) OR (NOW - RAS_chk1 >= tRAS)) + REPORT "tRAS violation during Precharge all banks" + SEVERITY WARNING; + -- tWR violation check for Write + IF ((NOW - WR_chk(0) < tWRp) OR (NOW - WR_chk(1) < tWRp) OR + (NOW - WR_chk(2) < tWRp) OR (NOW - WR_chk(3) < tWRp)) THEN + ASSERT (FALSE) + REPORT "tWR violation during Precharge ALL banks" + SEVERITY WARNING; + END IF; + ELSIF Addr(10) = '0' THEN + IF Ba = "00" THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + -- Activate to Precharge bank 0 + ASSERT (NOW - RAS_chk0 >= tRAS) + REPORT "tRAS violation during Precharge bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + -- Activate to Precharge bank 1 + ASSERT (NOW - RAS_chk1 >= tRAS) + REPORT "tRAS violation during Precharge bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + -- Activate to Precharge bank 2 + ASSERT (NOW - RAS_chk2 >= tRAS) + REPORT "tRAS violation during Precharge bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + -- Activate to Precharge bank 3 + ASSERT (NOW - RAS_chk3 >= tRAS) + REPORT "tRAS violation during Precharge bank 3" + SEVERITY WARNING; + END IF; + -- tWR violation check for Write + ASSERT (NOW - WR_chk(TO_INTEGER(Ba)) >= tWRp) + REPORT "tWR violation during Precharge" + SEVERITY WARNING; + END IF; + -- Terminate a Write Immediately (if same bank or all banks) + IF (Data_in_enable = '1' AND (Bank = TO_BITVECTOR(Ba) OR Addr(10) = '1')) THEN + Data_in_enable := '0'; + END IF; + -- Precharge Command Pipeline for READ + IF CAS_latency_3 = '1' THEN + Command(2) := PRECH; + Bank_precharge(2) := TO_BITVECTOR (Ba); + A10_precharge(2) := TO_BIT(Addr(10)); + ELSIF CAS_latency_2 = '1' THEN + Command(1) := PRECH; + Bank_precharge(1) := TO_BITVECTOR (Ba); + A10_precharge(1) := TO_BIT(Addr(10)); + END IF; + END IF; + + -- Burst Terminate + IF Burst_term = '1' THEN + -- Terminate a Write immediately + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + -- Terminate a Read depend on CAS Latency + IF CAS_latency_3 = '1' THEN + Command(2) := BST; + ELSIF CAS_latency_2 = '1' THEN + Command(1) := BST; + END IF; + END IF; + + -- Read, Write, Column Latch + IF Read_enable = '1' OR Write_enable = '1' THEN + -- Check to see if bank is open (ACT) for Read or Write + IF ((Ba = "00" AND Pc_b0 = '1') OR (Ba = "01" AND Pc_b1 = '1') OR (Ba = "10" AND Pc_b2 = '1') OR (Ba = "11" AND Pc_b3 = '1')) THEN + ASSERT (FALSE) + REPORT "Cannot Read or Write - Bank is not Activated" + SEVERITY WARNING; + END IF; + -- Activate to Read or Write + IF Ba = "00" THEN + ASSERT (NOW - RCD_chk0 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + ASSERT (NOW - RCD_chk1 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + ASSERT (NOW - RCD_chk2 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + ASSERT (NOW - RCD_chk3 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 3" + SEVERITY WARNING; + END IF; + -- Read Command + IF Read_enable = '1' THEN + -- CAS Latency Pipeline + IF Cas_latency_3 = '1' THEN + IF Addr(10) = '1' THEN + Command(2) := READ_A; + ELSE + Command(2) := READ; + END IF; + Col_addr (2) := TO_BITVECTOR (Addr(11) & Addr(9 DOWNTO 0)); + Bank_addr (2) := TO_BITVECTOR (Ba); + ELSIF Cas_latency_2 = '1' THEN + IF Addr(10) = '1' THEN + Command(1) := READ_A; + ELSE + Command(1) := READ; + END IF; + Col_addr (1) := TO_BITVECTOR (Addr(11) & Addr(9 DOWNTO 0)); + Bank_addr (1) := TO_BITVECTOR (Ba); + END IF; + + -- Read intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Write Command + ELSIF Write_enable = '1' THEN + IF Addr(10) = '1' THEN + Command(0) := WRITE_A; + ELSE + Command(0) := WRITE; + END IF; + Col_addr (0) := TO_BITVECTOR (Addr(11) & Addr(9 DOWNTO 0)); + Bank_addr (0) := TO_BITVECTOR (Ba); + + -- Write intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Write interrupt a Read (terminate Read immediately) + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + + -- Interrupt a Write with Auto Precharge + IF Auto_precharge(TO_INTEGER(Bank)) = '1' AND Write_precharge(TO_INTEGER(Bank)) = '1' THEN + RW_interrupt_write(TO_INTEGER(Bank)) := '1'; + END IF; + + -- Interrupt a Read with Auto Precharge + IF Auto_precharge(TO_INTEGER(Bank)) = '1' AND Read_precharge(TO_INTEGER(Bank)) = '1' THEN + RW_interrupt_read(TO_INTEGER(Bank)) := '1'; + END IF; + + -- Read or Write with Auto Precharge + IF Addr(10) = '1' THEN + Auto_precharge (TO_INTEGER(Ba)) := '1'; + Count_precharge (TO_INTEGER(Ba)) := 0; + IF Read_enable = '1' THEN + Read_precharge (TO_INTEGER(Ba)) := '1'; + ELSIF Write_enable = '1' THEN + Write_precharge (TO_INTEGER(Ba)) := '1'; + END IF; + END IF; + END IF; + + -- Read with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. BL/2 cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Read_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(0) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8))) OR + (RW_interrupt_read(0) = '1')) THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + Auto_precharge(0) := '0'; + Read_precharge(0) := '0'; + RW_interrupt_read(0) := '0'; + END IF; + END IF; + IF ((Auto_precharge(1) = '1') AND (Read_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(1) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8))) OR + (RW_interrupt_read(1) = '1')) THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + Auto_precharge(1) := '0'; + Read_precharge(1) := '0'; + RW_interrupt_read(1) := '0'; + END IF; + END IF; + IF ((Auto_precharge(2) = '1') AND (Read_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(2) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8))) OR + (RW_interrupt_read(2) = '1')) THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + Auto_precharge(2) := '0'; + Read_precharge(2) := '0'; + RW_interrupt_read(2) := '0'; + END IF; + END IF; + IF ((Auto_precharge(3) = '1') AND (Read_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(3) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8))) OR + (RW_interrupt_read(3) = '1')) THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + Auto_precharge(3) := '0'; + Read_precharge(3) := '0'; + RW_interrupt_read(3) := '0'; + END IF; + END IF; + + -- Internal Precharge or Bst + IF Command(0) = PRECH THEN -- PRECH terminate a read if same bank or all banks + IF Bank_precharge(0) = Bank OR A10_precharge(0) = '1' THEN + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Command(0) = BST THEN -- BST terminate a read regardless of bank + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + + IF Data_out_enable = '0' THEN + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tOH; + END IF; + + -- Detect Read or Write Command + IF Command(0) = READ OR Command(0) = READ_A THEN + Bank := Bank_addr (0); + Col := Col_addr (0); + Col_brst := Col_addr (0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '0'; + Data_out_enable := '1'; + ELSIF Command(0) = WRITE OR Command(0) = WRITE_A THEN + Bank := Bank_addr(0); + Col := Col_addr(0); + Col_brst := Col_addr(0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '1'; + Data_out_enable := '0'; + END IF; + + -- DQ (Driver / Receiver) + Row_index := TO_INTEGER (Row); + Col_index := TO_INTEGER (Col); + IF Data_in_enable = '1' THEN + IF Dqm = '0' THEN + Init_mem (Bank, Row_index); + IF Bank = "00" THEN + Bank0 (Row_index) (Col_index) := TO_BITVECTOR(Dq); + ELSIF Bank = "01" THEN + Bank1 (Row_index) (Col_index) := TO_BITVECTOR(Dq); + ELSIF Bank = "10" THEN + Bank2 (Row_index) (Col_index) := TO_BITVECTOR(Dq); + ELSIF Bank = "11" THEN + Bank3 (Row_index) (Col_index) := TO_BITVECTOR(Dq); + END IF; + WR_chk(TO_INTEGER(Bank)) := NOW; + WR_counter(TO_INTEGER(Bank)) <= 0; + END IF; + Burst_decode; + ELSIF Data_out_enable = '1' THEN + IF Dqm_reg(0) = '0' THEN + Init_mem (Bank, Row_index); + IF Bank = "00" THEN + Dq <= TRANSPORT TO_STDLOGICVECTOR(Bank0 (Row_index) (Col_index)) AFTER tAC; + ELSIF Bank = "01" THEN + Dq <= TRANSPORT TO_STDLOGICVECTOR(Bank1 (Row_index) (Col_index)) AFTER tAC; + ELSIF Bank = "10" THEN + Dq <= TRANSPORT TO_STDLOGICVECTOR(Bank2 (Row_index) (Col_index)) AFTER tAC; + ELSIF Bank = "11" THEN + Dq <= TRANSPORT TO_STDLOGICVECTOR(Bank3 (Row_index) (Col_index)) AFTER tAC; + END IF; + ELSE + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tHZ; + END IF; + Burst_decode; + END IF; + + END IF; + + -- Write with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. tWR cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Write_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(0) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8))) OR + (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 2)) THEN + Auto_precharge(0) := '0'; + Write_precharge(0) := '0'; + RW_interrupt_write(0) := '0'; + WAIT FOR tWRa; + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + END IF; + END IF; + + IF ((Auto_precharge(1) = '1') AND (Write_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(1) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8))) OR + (RW_interrupt_write(1) = '1' AND WR_counter(1) >= 2)) THEN + Auto_precharge(1) := '0'; + Write_precharge(1) := '0'; + RW_interrupt_write(1) := '0'; + WAIT FOR tWRa; + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + END IF; + END IF; + + IF ((Auto_precharge(2) = '1') AND (Write_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(2) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8))) OR + (RW_interrupt_write(2) = '1' AND WR_counter(2) >= 2)) THEN + Auto_precharge(2) := '0'; + Write_precharge(2) := '0'; + RW_interrupt_write(2) := '0'; + WAIT FOR tWRa; + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + END IF; + END IF; + + IF ((Auto_precharge(3) = '1') AND (Write_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(3) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8))) OR + (RW_interrupt_write(3) = '1' AND WR_counter(3) >= 2)) THEN + Auto_precharge(3) := '0'; + Write_precharge(3) := '0'; + RW_interrupt_write(3) := '0'; + WAIT FOR tWRa; + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + END IF; + END IF; + + -- Checking internal wires (Optional for debug purpose) + Pre_chk (0) <= Pc_b0; + Pre_chk (1) <= Pc_b1; + Pre_chk (2) <= Pc_b2; + Pre_chk (3) <= Pc_b3; + Act_chk (0) <= Act_b0; + Act_chk (1) <= Act_b1; + Act_chk (2) <= Act_b2; + Act_chk (3) <= Act_b3; + Dq_in_chk <= Data_in_enable; + Dq_out_chk <= Data_out_enable; + Bank_chk <= Bank; + Row_chk <= Row; + Col_chk <= Col; + END PROCESS; + + + -- Clock timing checks + Clock_check : PROCESS + VARIABLE Clk_low, Clk_high : TIME := 0 ns; + BEGIN + WAIT ON Clk; + IF (Clk = '1' AND NOW >= 10 ns) THEN + ASSERT (NOW - Clk_low >= tCL) + REPORT "tCL violation" + SEVERITY WARNING; + ASSERT (NOW - Clk_high >= tCK) + REPORT "tCK violation" + SEVERITY WARNING; + Clk_high := NOW; + ELSIF (Clk = '0' AND NOW /= 0 ns) THEN + ASSERT (NOW - Clk_high >= tCH) + REPORT "tCH violation" + SEVERITY WARNING; + Clk_low := NOW; + END IF; + END PROCESS; + + -- Setup timing checks + Setup_check : PROCESS + BEGIN + WAIT ON Clk; + IF Clk = '1' THEN + ASSERT(Cke'LAST_EVENT >= tCKS) + REPORT "CKE Setup time violation -- tCKS" + SEVERITY WARNING; + ASSERT(Cs_n'LAST_EVENT >= tCMS) + REPORT "CS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT >= tCMS) + REPORT "CAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT >= tCMS) + REPORT "RAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT >= tCMS) + REPORT "WE# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT >= tCMS) + REPORT "Dqm Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Addr'LAST_EVENT >= tAS) + REPORT "ADDR Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT >= tAS) + REPORT "BA Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Dq'LAST_EVENT >= tDS) + REPORT "Dq Setup time violation -- tDS" + SEVERITY WARNING; + END IF; + END PROCESS; + + -- Hold timing checks + Hold_check : PROCESS + BEGIN + WAIT ON Clk'DELAYED (tCKH), Clk'DELAYED (tCMH), Clk'DELAYED (tAH), Clk'DELAYED (tDH); + IF Clk'DELAYED (tCKH) = '1' THEN + ASSERT(Cke'LAST_EVENT > tCKH) + REPORT "CKE Hold time violation -- tCKH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tCMH) = '1' THEN + ASSERT(Cs_n'LAST_EVENT > tCMH) + REPORT "CS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT > tCMH) + REPORT "CAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT > tCMH) + REPORT "RAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT > tCMH) + REPORT "WE# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT > tCMH) + REPORT "Dqm Hold time violation -- tCMH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tAH) = '1' THEN + ASSERT(Addr'LAST_EVENT > tAH) + REPORT "ADDR Hold time violation -- tAH" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT > tAH) + REPORT "BA Hold time violation -- tAH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tDH) = '1' THEN + ASSERT(Dq'LAST_EVENT > tDH) + REPORT "Dq Hold time violation -- tDH" + SEVERITY WARNING; + END IF; + END PROCESS; + +END behave; diff --git a/lib/models/memory/sdram/mt48lc64m4a2/mti_pkg.vhd b/lib/models/memory/sdram/mt48lc64m4a2/mti_pkg.vhd new file mode 100644 index 0000000..9e4f824 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc64m4a2/mti_pkg.vhd @@ -0,0 +1,129 @@ +--***************************************************************************** +-- +-- Micron Semiconductor Products, Inc. +-- +-- Copyright 1997, Micron Semiconductor Products, Inc. +-- All rights reserved. +-- +--***************************************************************************** + +LIBRARY work; +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +PACKAGE mti_pkg IS + + FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER; + FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER; + FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER; + PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR); + +END mti_pkg; + +PACKAGE BODY mti_pkg IS + + -- Convert BIT to INTEGER + FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + IF input = '1' THEN + result := weight; + ELSE + result := 0; -- if unknowns, default to logic 0 + END IF; + RETURN result; + END TO_INTEGER; + + -- Convert BIT_VECTOR to INTEGER + FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + FOR i IN input'LOW TO input'HIGH LOOP + IF input(i) = '1' THEN + result := result + weight; + ELSE + result := result + 0; -- if unknowns, default to logic 0 + END IF; + weight := weight * 2; + END LOOP; + RETURN result; + END TO_INTEGER; + + -- Convert STD_LOGIC_VECTOR to INTEGER + FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + FOR i IN input'LOW TO input'HIGH LOOP + IF input(i) = '1' THEN + result := result + weight; + ELSE + result := result + 0; -- if unknowns, default to logic 0 + END IF; + weight := weight * 2; + END LOOP; + RETURN result; + END TO_INTEGER; + + -- Conver integer to bit_vector + PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR) IS + VARIABLE work,offset,outputlen,j : INTEGER := 0; + BEGIN + --length of vector + IF output'LENGTH > 32 THEN + outputlen := 32; + offset := output'LENGTH - 32; + IF input >= 0 THEN + FOR i IN offset-1 DOWNTO 0 LOOP + output(output'HIGH - i) := '0'; + END LOOP; + ELSE + FOR i IN offset-1 DOWNTO 0 LOOP + output(output'HIGH - i) := '1'; + END LOOP; + END IF; + ELSE + outputlen := output'LENGTH; + END IF; + --positive value + IF (input >= 0) THEN + work := input; + j := outputlen - 1; + FOR i IN 1 to 32 LOOP + IF j >= 0 then + IF (work MOD 2) = 0 THEN + output(output'HIGH-j-offset) := '0'; + ELSE + output(output'HIGH-j-offset) := '1'; + END IF; + END IF; + work := work / 2; + j := j - 1; + END LOOP; + IF outputlen = 32 THEN + output(output'HIGH) := '0'; + END IF; + --negative value + ELSE + work := (-input) - 1; + j := outputlen - 1; + FOR i IN 1 TO 32 LOOP + IF j>= 0 THEN + IF (work MOD 2) = 0 THEN + output(output'HIGH-j-offset) := '1'; + ELSE + output(output'HIGH-j-offset) := '0'; + END IF; + END IF; + work := work / 2; + j := j - 1; + END LOOP; + IF outputlen = 32 THEN + output(output'HIGH) := '1'; + END IF; + END IF; + END TO_BITVECTOR; + +END mti_pkg; diff --git a/lib/models/memory/sdram/mt48lc64m4a2/readme.txt b/lib/models/memory/sdram/mt48lc64m4a2/readme.txt new file mode 100644 index 0000000..b208964 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc64m4a2/readme.txt @@ -0,0 +1,14 @@ +To operate the test bench for the Micron SDRAM VHDL model, follow the directions +given below: + +1. Be sure all supporting files for the SDRAM are compiled into your library: + + util1164.vhd + stdlogar.vhd + io_utils.vhd + mti_pkg.vhd + +2. Next, compile the mt48lc64m4a2.vhd file and the test.vhd file. + +3. Simulate the "tb" architecture. This is the testbench for the 256Mb SDRAM. + diff --git a/lib/models/memory/sdram/mt48lc64m4a2/stdlogar.vhd b/lib/models/memory/sdram/mt48lc64m4a2/stdlogar.vhd new file mode 100644 index 0000000..e435ea2 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc64m4a2/stdlogar.vhd @@ -0,0 +1,2247 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990,1991,1992 by Synopsys, Inc. All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_ARITH -- +-- -- +-- Purpose: -- +-- A set of arithemtic, conversion, and comparison functions -- +-- for SIGNED, UNSIGNED, SMALL_INT, INTEGER, -- +-- STD_ULOGIC, STD_LOGIC, and STD_LOGIC_VECTOR. -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +package std_logic_arith is + + type UNSIGNED is array (NATURAL range <>) of STD_LOGIC; + type SIGNED is array (NATURAL range <>) of STD_LOGIC; + subtype SMALL_INT is INTEGER range 0 to 1; + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: INTEGER) return SIGNED; + function "+"(L: INTEGER; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: INTEGER) return SIGNED; + function "-"(L: INTEGER; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "+"(L: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED) return SIGNED; + function "-"(L: SIGNED) return SIGNED; + function "ABS"(L: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED) return STD_LOGIC_VECTOR; + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "*"(L: SIGNED; R: SIGNED) return SIGNED; + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + + function CONV_INTEGER(ARG: INTEGER) return INTEGER; + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER; + function CONV_INTEGER(ARG: SIGNED) return INTEGER; + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT; + + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED; + + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED; + + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + -- zero extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- returns STD_LOGIC_VECTOR(SIZE-1 downto 0) + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + + -- sign extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- return STD_LOGIC_VECTOR(SIZE-1 downto 0) + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end Std_logic_arith; + + + +library IEEE; +use IEEE.std_logic_1164.all; + +package body std_logic_arith is + + function max(L, R: INTEGER) return INTEGER is + begin + if L > R then + return L; + else + return R; + end if; + end; + + + function min(L, R: INTEGER) return INTEGER is + begin + if L < R then + return L; + else + return R; + end if; + end; + + -- synopsys synthesis_off + type tbl_type is array (STD_ULOGIC) of STD_ULOGIC; + constant tbl_BINARY : tbl_type := + ('X', 'X', '0', '1', 'X', 'X', '0', '1', 'X'); + -- synopsys synthesis_on + + -- synopsys synthesis_off + type tbl_mvl9_boolean is array (STD_ULOGIC) of boolean; + constant IS_X : tbl_mvl9_boolean := + (true, true, false, false, true, true, false, false, true); + -- synopsys synthesis_on + + + + function MAKE_BINARY(A : STD_ULOGIC) return STD_ULOGIC is + -- synopsys built_in SYN_FEED_THRU + begin + -- synopsys synthesis_off + if (IS_X(A)) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + return ('X'); + end if; + return tbl_BINARY(A); + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return UNSIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : UNSIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return SIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : SIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return UNSIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : UNSIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return SIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : SIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + + + -- Type propagation function which returns a signed type with the + -- size of the left arg. + function LEFT_SIGNED_ARG(A,B: SIGNED) return SIGNED is + variable Z: SIGNED (A'left downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns an unsigned type with the + -- size of the left arg. + function LEFT_UNSIGNED_ARG(A,B: UNSIGNED) return UNSIGNED is + variable Z: UNSIGNED (A'left downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns a signed type with the + -- size of the result of a signed multiplication + function MULT_SIGNED_ARG(A,B: SIGNED) return SIGNED is + variable Z: SIGNED ((A'length+B'length-1) downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns an unsigned type with the + -- size of the result of a unsigned multiplication + function MULT_UNSIGNED_ARG(A,B: UNSIGNED) return UNSIGNED is + variable Z: UNSIGNED ((A'length+B'length-1) downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + + + function mult(A,B: SIGNED) return SIGNED is + + variable BA: SIGNED((A'length+B'length-1) downto 0); + variable PA: SIGNED((A'length+B'length-1) downto 0); + variable AA: SIGNED(A'length downto 0); + variable neg: STD_ULOGIC; + constant one : UNSIGNED(1 downto 0) := "01"; + + -- pragma map_to_operator MULT_TC_OP + -- pragma type_function MULT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + PA := (others => 'X'); + return(PA); + end if; + PA := (others => '0'); + neg := B(B'left) xor A(A'left); + BA := CONV_SIGNED(('0' & ABS(B)),(A'length+B'length)); + AA := '0' & ABS(A); + for i in 0 to A'length-1 loop + if AA(i) = '1' then + PA := PA+BA; + end if; + BA := SHL(BA,one); + end loop; + if (neg= '1') then + return(-PA); + else + return(PA); + end if; + end; + + function mult(A,B: UNSIGNED) return UNSIGNED is + + variable BA: UNSIGNED((A'length+B'length-1) downto 0); + variable PA: UNSIGNED((A'length+B'length-1) downto 0); + constant one : UNSIGNED(1 downto 0) := "01"; + + -- pragma map_to_operator MULT_UNS_OP + -- pragma type_function MULT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + PA := (others => 'X'); + return(PA); + end if; + PA := (others => '0'); + BA := CONV_UNSIGNED(B,(A'length+B'length)); + for i in 0 to A'length-1 loop + if A(i) = '1' then + PA := PA+BA; + end if; + BA := SHL(BA,one); + end loop; + return(PA); + end; + + -- subtract two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function minus(A, B: SIGNED) return SIGNED is + variable carry: STD_ULOGIC; + variable BV: STD_ULOGIC_VECTOR (A'left downto 0); + variable sum: SIGNED (A'left downto 0); + + -- pragma map_to_operator SUB_TC_OP + + -- pragma type_function LEFT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '1'; + BV := not STD_ULOGIC_VECTOR(B); + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + -- add two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function plus(A, B: SIGNED) return SIGNED is + variable carry: STD_ULOGIC; + variable BV, sum: SIGNED (A'left downto 0); + + -- pragma map_to_operator ADD_TC_OP + -- pragma type_function LEFT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '0'; + BV := B; + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + + -- subtract two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_minus(A, B: UNSIGNED) return UNSIGNED is + variable carry: STD_ULOGIC; + variable BV: STD_ULOGIC_VECTOR (A'left downto 0); + variable sum: UNSIGNED (A'left downto 0); + + -- pragma map_to_operator SUB_UNS_OP + -- pragma type_function LEFT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '1'; + BV := not STD_ULOGIC_VECTOR(B); + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + -- add two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_plus(A, B: UNSIGNED) return UNSIGNED is + variable carry: STD_ULOGIC; + variable BV, sum: UNSIGNED (A'left downto 0); + + -- pragma map_to_operator ADD_UNS_OP + -- pragma type_function LEFT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '0'; + BV := B; + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + + + function "*"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to mult + begin + return mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to mult + begin + return mult(CONV_UNSIGNED(L, L'length), + CONV_UNSIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + begin + return mult(CONV_SIGNED(L, L'length+1), + CONV_SIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to plus + begin + return mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length+1)); -- pragma label mult + end; + + + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + begin + return STD_LOGIC_VECTOR (mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length))); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + begin + return STD_LOGIC_VECTOR (mult(CONV_UNSIGNED(L, L'length), + CONV_UNSIGNED(R, R'length))); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + begin + return STD_LOGIC_VECTOR (mult(CONV_SIGNED(L, L'length+1), + CONV_SIGNED(R, R'length))); -- pragma label mult + end; + + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + begin + return STD_LOGIC_VECTOR (mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length+1))); -- pragma label mult + end; + + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "+"(L: SIGNED; R: INTEGER) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: INTEGER; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)) ; -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))) ; -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_minus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: SIGNED; R: INTEGER) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: INTEGER; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (unsigned_minus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + + + function "+"(L: UNSIGNED) return UNSIGNED is + begin + return L; + end; + + + function "+"(L: SIGNED) return SIGNED is + begin + return L; + end; + + + function "-"(L: SIGNED) return SIGNED is + -- pragma label_applies_to minus + begin + return 0 - L; -- pragma label minus + end; + + + function "ABS"(L: SIGNED) return SIGNED is + begin + if (L(L'left) = '0' or L(L'left) = 'L') then + return L; + else + return 0 - L; + end if; + end; + + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L); + end; + + + function "+"(L: SIGNED) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L); + end; + + + function "-"(L: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable tmp: SIGNED(L'length-1 downto 0); + begin + tmp := 0 - L; -- pragma label minus + return STD_LOGIC_VECTOR (tmp); + end; + + + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR is + variable tmp: SIGNED(L'length-1 downto 0); + begin + if (L(L'left) = '0' or L(L'left) = 'L') then + return STD_LOGIC_VECTOR (L); + else + tmp := 0 - L; + return STD_LOGIC_VECTOR (tmp); + end if; + end; + + + -- Type propagation function which returns the type BOOLEAN + function UNSIGNED_RETURN_BOOLEAN(A,B: UNSIGNED) return BOOLEAN is + variable Z: BOOLEAN; + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns the type BOOLEAN + function SIGNED_RETURN_BOOLEAN(A,B: SIGNED) return BOOLEAN is + variable Z: BOOLEAN; + -- pragma return_port_name Z + begin + return(Z); + end; + + + -- compare two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function is_less(A, B: SIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LT_TC_OP + -- pragma type_function SIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + if A(sign) /= B(sign) then + result := A(sign) = '1'; + else + result := FALSE; + for i in 0 to sign-1 loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + end if; + return result; + end; + + + -- compare two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function is_less_or_equal(A, B: SIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LEQ_TC_OP + -- pragma type_function SIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + if A(sign) /= B(sign) then + result := A(sign) = '1'; + else + result := TRUE; + for i in 0 to sign-1 loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + end if; + return result; + end; + + + + -- compare two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_is_less(A, B: UNSIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LT_UNS_OP + -- pragma type_function UNSIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + result := FALSE; + for i in 0 to sign loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + return result; + end; + + + -- compare two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_is_less_or_equal(A, B: UNSIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LEQ_UNS_OP + -- pragma type_function UNSIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + result := TRUE; + for i in 0 to sign loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + return result; + end; + + + + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length, R'length); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := L'length + 1; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := R'length + 1; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := L'length; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := R'length; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less_or_equal(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length, R'length); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := L'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := R'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := L'length; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := R'length; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less(CONV_UNSIGNED(R, length), + CONV_UNSIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length, R'length); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := L'length + 1; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := R'length + 1; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := L'length; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := R'length; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less_or_equal(CONV_UNSIGNED(R, length), + CONV_UNSIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length, R'length); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := L'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := R'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := L'length; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := R'length; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + + + -- for internal use only. Assumes SIGNED arguments of equal length. + function bitwise_eql(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) + return BOOLEAN is + -- pragma built_in SYN_EQL + begin + for i in L'range loop + if L(i) /= R(i) then + return FALSE; + end if; + end loop; + return TRUE; + end; + + -- for internal use only. Assumes SIGNED arguments of equal length. + function bitwise_neq(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) + return BOOLEAN is + -- pragma built_in SYN_NEQ + begin + for i in L'range loop + if L(i) /= R(i) then + return TRUE; + end if; + end loop; + return FALSE; + end; + + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_UNSIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_UNSIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length + 1, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length + 1); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length + 1; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := R'length + 1; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: INTEGER; R: SIGNED) return BOOLEAN is + constant length: INTEGER := R'length; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_UNSIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_UNSIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length + 1, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length + 1); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length + 1; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := R'length + 1; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN is + constant length: INTEGER := R'length; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is UNSIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb downto 2**i) := + result(result_msb - 2**i downto 0); + end if; + result := temp; + end if; + end loop; + return result; + end; + + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is SIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb downto 2**i) := + result(result_msb - 2**i downto 0); + end if; + result := temp; + end if; + end loop; + return result; + end; + + + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is UNSIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb - 2**i downto 0) := + result(result_msb downto 2**i); + end if; + result := temp; + end if; + end loop; + return result; + end; + + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is SIGNED (result_msb downto 0); + variable result, temp: rtype; + variable sign_bit: STD_ULOGIC; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + sign_bit := ARG(ARG'left); + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => sign_bit); + if 2**i <= result_msb then + temp(result_msb - 2**i downto 0) := + result(result_msb downto 2**i); + end if; + result := temp; + end if; + end loop; + return result; + end; + + + + + function CONV_INTEGER(ARG: INTEGER) return INTEGER is + begin + return ARG; + end; + + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER is + variable result: INTEGER; + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_UNSIGNED_TO_INTEGER + begin + -- synopsys synthesis_off + assert ARG'length <= 31 + report "ARG is too large in CONV_INTEGER" + severity FAILURE; + result := 0; + for i in ARG'range loop + result := result * 2; + tmp := tbl_BINARY(ARG(i)); + if tmp = '1' then + result := result + 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_INTEGER(ARG: SIGNED) return INTEGER is + variable result: INTEGER; + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_SIGNED_TO_INTEGER + begin + -- synopsys synthesis_off + assert ARG'length <= 32 + report "ARG is too large in CONV_INTEGER" + severity FAILURE; + result := 0; + for i in ARG'range loop + if i /= ARG'left then + result := result * 2; + tmp := tbl_BINARY(ARG(i)); + if tmp = '1' then + result := result + 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + end if; + end if; + end loop; + tmp := MAKE_BINARY(ARG(ARG'left)); + if tmp = '1' then + if ARG'length = 32 then + result := (result - 2**30) - 2**30; + else + result := result - (2 ** (ARG'length-1)); + end if; + end if; + return result; + -- synopsys synthesis_on + end; + + + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT is + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_FEED_THRU + begin + -- synopsys synthesis_off + tmp := tbl_BINARY(ARG); + if tmp = '1' then + return 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + return 0; + else + return 0; + end if; + -- synopsys synthesis_on + end; + + + -- convert an integer to a unsigned STD_ULOGIC_VECTOR + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED is + variable result: UNSIGNED(SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_UNSIGNED + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable new_bounds: UNSIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable new_bounds: UNSIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED is + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + + -- convert an integer to a 2's complement STD_ULOGIC_VECTOR + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED is + variable result: SIGNED (SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_SIGNED + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is SIGNED (SIZE-1 downto 0); + variable new_bounds : SIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is SIGNED (SIZE-1 downto 0); + variable new_bounds : SIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED is + subtype rtype is SIGNED (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + + -- convert an integer to an STD_LOGIC_VECTOR + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR is + variable result: STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_SIGNED + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) return STD_LOGIC_VECTOR is + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) + return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds: STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + +end std_logic_arith; diff --git a/lib/models/memory/sdram/mt48lc64m4a2/test.do b/lib/models/memory/sdram/mt48lc64m4a2/test.do new file mode 100644 index 0000000..d0c6ff0 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc64m4a2/test.do @@ -0,0 +1,5 @@ +vcom mt48lc64m4a2.vhd +vcom test.vhd +vsim tb +do wave.do +run -all diff --git a/lib/models/memory/sdram/mt48lc64m4a2/test.txt b/lib/models/memory/sdram/mt48lc64m4a2/test.txt new file mode 100644 index 0000000..ad4a459 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc64m4a2/test.txt @@ -0,0 +1,98 @@ +0 ns 1 1 1 1 1 0 00 0 -100 +22 ns 1 1 1 1 1 0 00 0 -100 +32 ns 1 1 1 1 1 0 00 0 -100 +42 ns 1 1 1 1 1 0 00 0 -100 +52 ns 1 1 1 1 1 0 00 0 -100 +62 ns 1 0 0 1 0 0 00 1024 -100 +72 ns 1 1 1 1 1 0 00 0 -100 +82 ns 1 1 1 1 1 0 00 0 -100 +92 ns 1 0 0 0 1 0 00 0 -100 +102 ns 1 1 1 1 1 0 00 0 -100 +112 ns 1 1 1 1 1 0 00 0 -100 +122 ns 1 1 1 1 1 0 00 0 -100 +132 ns 1 1 1 1 1 0 00 0 -100 +142 ns 1 1 1 1 1 0 00 0 -100 +152 ns 1 1 1 1 1 0 00 0 -100 +162 ns 1 1 1 1 1 0 00 0 -100 +172 ns 1 1 1 1 1 0 00 0 -100 +182 ns 1 0 0 0 1 0 00 0 -100 +192 ns 1 1 1 1 1 0 00 0 -100 +202 ns 1 1 1 1 1 0 00 0 -100 +212 ns 1 1 1 1 1 0 00 0 -100 +222 ns 1 1 1 1 1 0 00 0 -100 +232 ns 1 1 1 1 1 0 00 0 -100 +242 ns 1 1 1 1 1 0 00 0 -100 +252 ns 1 1 1 1 1 0 00 0 -100 +262 ns 1 1 1 1 1 0 00 0 -100 +272 ns 1 0 0 0 0 0 00 51 -100 +282 ns 1 1 1 1 1 0 00 0 -100 +292 ns 1 0 0 1 1 0 00 0 -100 +302 ns 1 1 1 1 1 0 00 0 -100 +312 ns 1 0 1 0 0 0 00 10 0 +322 ns 1 1 1 1 1 0 00 0 1 +332 ns 1 0 0 1 1 0 01 0 2 +342 ns 1 1 1 1 1 0 00 0 3 +352 ns 1 1 1 1 1 0 00 0 4 +362 ns 1 1 1 1 1 0 00 0 5 +372 ns 1 1 1 1 1 0 00 0 6 +382 ns 1 1 1 1 1 0 00 0 7 +392 ns 1 0 1 0 0 0 01 20 8 +402 ns 1 0 0 1 0 0 00 0 9 +412 ns 1 0 0 1 1 0 10 0 10 +422 ns 1 1 1 1 1 0 00 0 11 +432 ns 1 1 1 1 1 0 00 0 12 +442 ns 1 1 1 1 1 0 00 0 13 +452 ns 1 1 1 1 1 0 00 0 14 +462 ns 1 1 1 1 1 0 00 0 15 +472 ns 1 0 1 0 0 0 10 30 0 +482 ns 1 0 0 1 0 0 01 0 1 +492 ns 1 0 0 1 1 0 11 0 2 +502 ns 1 1 1 1 1 0 00 0 3 +512 ns 1 1 1 1 1 0 00 0 4 +522 ns 1 1 1 1 1 0 00 0 5 +532 ns 1 1 1 1 1 0 00 0 6 +542 ns 1 1 1 1 1 0 00 0 7 +552 ns 1 0 1 0 0 0 11 40 8 +562 ns 1 0 0 1 0 0 10 0 9 +572 ns 1 0 0 1 1 0 00 0 10 +582 ns 1 1 1 1 1 0 00 0 11 +592 ns 1 1 1 1 1 0 00 0 12 +602 ns 1 1 1 1 1 0 00 0 13 +612 ns 1 1 1 1 1 0 00 0 14 +622 ns 1 1 1 1 1 0 00 0 15 +632 ns 1 0 1 0 1 0 00 10 -100 +642 ns 1 0 0 1 0 0 11 0 -100 +652 ns 1 0 0 1 1 0 01 0 -100 +662 ns 1 1 1 1 1 0 00 0 -100 +672 ns 1 1 1 1 1 0 00 0 -100 +682 ns 1 1 1 1 1 0 00 0 -100 +692 ns 1 1 1 1 1 0 00 0 -100 +702 ns 1 1 1 1 1 0 00 0 -100 +712 ns 1 0 1 0 1 0 01 20 -100 +722 ns 1 0 0 1 0 0 00 0 -100 +732 ns 1 0 0 1 1 0 10 0 -100 +742 ns 1 1 1 1 1 0 00 0 -100 +752 ns 1 1 1 1 1 0 00 0 -100 +762 ns 1 1 1 1 1 0 00 0 -100 +772 ns 1 1 1 1 1 0 00 0 -100 +782 ns 1 1 1 1 1 0 00 0 -100 +792 ns 1 0 1 0 1 0 10 30 -100 +802 ns 1 0 0 1 0 0 01 0 -100 +812 ns 1 0 0 1 1 0 11 0 -100 +822 ns 1 1 1 1 1 0 00 0 -100 +832 ns 1 1 1 1 1 0 00 0 -100 +842 ns 1 1 1 1 1 0 00 0 -100 +852 ns 1 1 1 1 1 0 00 0 -100 +862 ns 1 1 1 1 1 0 00 0 -100 +872 ns 1 0 1 0 1 0 11 40 -100 +882 ns 1 0 0 1 0 0 10 0 -100 +892 ns 1 1 1 1 1 0 00 0 -100 +902 ns 1 1 1 1 1 0 00 0 -100 +912 ns 1 1 1 1 1 0 00 0 -100 +922 ns 1 1 1 1 1 0 00 0 -100 +932 ns 1 1 1 1 1 0 00 0 -100 +942 ns 1 1 1 1 1 0 00 0 -100 +952 ns 1 0 0 1 0 0 11 0 -100 +962 ns 1 1 1 1 1 0 00 0 -100 +972 ns 1 1 1 1 1 0 00 0 -100 +982 ns 1 1 1 1 1 0 00 0 -100 diff --git a/lib/models/memory/sdram/mt48lc64m4a2/test.vhd b/lib/models/memory/sdram/mt48lc64m4a2/test.vhd new file mode 100644 index 0000000..a99a225 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc64m4a2/test.vhd @@ -0,0 +1,168 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE std.textio.ALL; +USE work.std_logic_arith.ALL; +USE work.util_1164.ALL; +USE work.mti_pkg.ALL; + +ENTITY tb IS +END tb; + + +ARCHITECTURE test OF tb IS + CONSTANT addr_bits : INTEGER := 13; + CONSTANT data_bits : INTEGER := 4; + CONSTANT clk_start : time := 5 ns; + CONSTANT clk_period : time := 10 ns; + CONSTANT continue_time : time := 10 ns; + + COMPONENT mt48lc64m4a2 + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '1'; + Cs_n : IN STD_LOGIC := '1'; + Cas_n : IN STD_LOGIC := '1'; + Ras_n : IN STD_LOGIC := '1'; + We_n : IN STD_LOGIC := '1'; + Dqm : IN STD_LOGIC := '0' + ); + END COMPONENT; + + FOR ALL : mt48lc64m4a2 USE ENTITY work.mt48lc64m4a2 (behave); + + SIGNAL pDq : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0); + SIGNAL pAddr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + SIGNAL pBa : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL pClk : STD_LOGIC; + SIGNAL pCke : STD_LOGIC; + SIGNAL pCs : STD_LOGIC; + SIGNAL pCas : STD_LOGIC; + SIGNAL pRas : STD_LOGIC; + SIGNAL pWe : STD_LOGIC; + SIGNAL pDqm : STD_LOGIC; + SIGNAL stim_done : boolean := false; + SIGNAL clk_done : boolean := false; + + +BEGIN + u1: mt48lc64m4a2 + PORT MAP( + Dq => pDq, + Addr => pAddr, + Ba => pBa, + Clk => pClk, + Cke => pCke, + Cs_n => pCs, + Ras_n => pRas, + Cas_n => pCas, + We_n => pWe, + Dqm => pDqm + ); + + stimulator : PROCESS + FILE stim_file:text IS IN "test.txt"; + VARIABLE l : line; + VARIABLE time_var : TIME; + VARIABLE pCke_var : STD_LOGIC; + VARIABLE pCs_var : STD_LOGIC; + VARIABLE pRas_var : STD_LOGIC; + VARIABLE PCas_var : STD_LOGIC; + VARIABLE pWe_var : STD_LOGIC; + VARIABLE pDqm_var : STD_LOGIC; + VARIABLE pBa_var : STD_LOGIC_VECTOR (1 DOWNTO 0); + VARIABLE pAddr_var : INTEGER; + VARIABLE pDq_var : INTEGER; -- -100 is converted to hi-Z state + VARIABLE pMa_var_vect : STD_LOGIC_VECTOR(addr_bits - 1 DOWNTO 0); + CONSTANT HiZ : STD_LOGIC_VECTOR(data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + BEGIN + WHILE not ENDFILE(stim_file) LOOP + readline(stim_file,l); + IF l'length > 0 THEN + read(l, time_var); + read(l, pCke_var); + read(l, pCs_var); + read(l, pRas_var); + read(l, pCas_var); + read(l, pWe_var); + read(l, pDqm_var); + read(l, pBa_var); + read(l, pAddr_var); + read(l, pDq_var); + IF now > time_var THEN + ASSERT false + REPORT "Detected a time in the stim file that is in the past" + SEVERITY error; + ELSE + WAIT FOR time_var-now; + IF pWe_var='1' THEN + pCke <= pCke_var; + pCs <= pCs_var; + pRas <= pRas_var; + pCas <= pCas_var; + pWe <= pWe_var; + pDqm <= pDqm_var; + pBa <= pBa_var; + pMa_var_vect := CONV_STD_LOGIC_VECTOR(pAddr_var, addr_bits); + pAddr <= pMa_var_vect; + IF pDq_var = -100 THEN + pDq <= HiZ; + ELSE + pDq <= CONV_STD_LOGIC_VECTOR(pDq_var, data_bits); + END IF; + ELSE + pCke <= pCke_var; + pCs <= pCs_var; + pRas <= pRas_var; + pCas <= pCas_var; + pWe <= pWe_var; + pDqm <= pDqm_var; + pBa <= pBa_var; + pMa_var_vect := CONV_STD_LOGIC_VECTOR(pAddr_var, addr_bits); + pAddr <= pMa_var_vect; + IF pDq_var = -100 THEN + pDq <= HiZ; + ELSE + pDq <= CONV_STD_LOGIC_VECTOR(pDq_var, data_bits); + END IF; + END IF; + END IF; + END IF; + END LOOP; + ASSERT false + REPORT "End of Stimulation File Detected!" + SEVERITY note; + stim_done <= true; + WAIT; + END PROCESS; + + clock : PROCESS + VARIABLE done_time : time; + BEGIN + pclk <= '0'; + WAIT for clk_start; + WHILE not stim_done loop + pclk <= '1'; + WAIT for clk_period/2; + pclk <= '0'; + WAIT for clk_period/2; + END LOOP; + done_time := now+continue_time; + WHILE now < done_time LOOP --one last clock to finish last command + pclk <= '1'; + WAIT for clk_period/2; + pclk <= '0'; + WAIT for clk_period/2; + END LOOP; + ASSERT false + REPORT "Suspending clock activity" + SEVERITY note; + clk_done <= true; + WAIT; + END PROCESS; + +END test; + + diff --git a/lib/models/memory/sdram/mt48lc64m4a2/util1164.vhd b/lib/models/memory/sdram/mt48lc64m4a2/util1164.vhd new file mode 100644 index 0000000..bb4b5dd --- /dev/null +++ b/lib/models/memory/sdram/mt48lc64m4a2/util1164.vhd @@ -0,0 +1,124 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE STD.textio.ALL; + +PACKAGE util_1164 IS + PROCEDURE read(l: INOUT line; value: OUT std_logic); + PROCEDURE read(l: INOUT line; value: OUT std_logic_vector); + PROCEDURE write(l: INOUT line; value: IN std_logic_vector; + JUSTIFIED: IN SIDE := right; + FIELD: IN WIDTH := 0); + PROCEDURE Grow_line(L : inout LINE; incr : in integer); +END util_1164; + + + +PACKAGE BODY util_1164 IS + + FUNCTION white_space(value:character) RETURN boolean IS + VARIABLE result:boolean; + BEGIN + IF (value = ' ') OR (value = HT) THEN + RETURN true; + ELSE + RETURN false; + END IF; + END white_space; + + PROCEDURE read(l: INOUT line; value: OUT std_logic) IS + VARIABLE char_var: character:= ' '; + BEGIN + WHILE l'LENGTH > 0 LOOP + read(l,char_var); + IF NOT white_space(char_var) THEN + EXIT; + END IF; + END LOOP; + IF white_space(char_var) THEN + ASSERT false REPORT "No std_logic value found in file" + SEVERITY error; + value := 'X'; + RETURN; + END IF; + + CASE char_var IS + WHEN 'U'|'u' => value := 'U'; + WHEN '0' => value := '0'; + WHEN '1' => value := '1'; + WHEN 'X'|'x' => value := 'X'; + WHEN 'L'|'l' => value := 'L'; + WHEN 'H'|'h' => value := 'H'; + WHEN 'W'|'w' => value := 'W'; + WHEN 'Z'|'z' => value := 'Z'; + WHEN '-' => value := '-'; + WHEN OTHERS => + ASSERT false REPORT "Unrecognized value read for std_logic" + SEVERITY error; + value := 'X'; + END CASE; + END read; + + PROCEDURE read(l: INOUT line; value: OUT std_logic_vector) IS + BEGIN + FOR i IN value'HIGH DOWNTO value'LOW LOOP + IF l'LENGTH > 0 THEN + read(l,value(i)); + ELSE + ASSERT false REPORT "Not enough values for std_logic_vector in file" + SEVERITY error; + RETURN; + END IF; + END LOOP; + END read; + + procedure Grow_line(L : inout LINE; incr : in integer) + is + variable old_L : LINE := L; + variable bfp: integer; -- Blank fill pointer. + begin + assert incr > 0 + report "Textio: Grow_line called with zero increment." + severity error; + + if L = null then + bfp := 0; + L := new string(1 to incr); + else + bfp := old_L'high; + L := new string(old_L'low to old_L'high + incr); + L(old_L'low to old_L'high) := old_L.all; + Deallocate(old_L); + end if; + for i in 1 to incr loop + L(bfp + i) := ' '; + end loop; + end; + + + PROCEDURE write(l: INOUT line; value: IN std_logic_vector; + JUSTIFIED: IN SIDE := right; + FIELD: IN WIDTH := 0) IS + variable fw: integer := VALUE'length; + variable bp: integer; + variable offset: integer := 0; + alias normal : std_logic_vector(0 to value'length - 1) is value; + begin + if L /= null then + bp := L'high + 1; + else bp := 1; + end if; + if FIELD > VALUE'length then + fw := FIELD; + if JUSTIFIED = right then + offset := fw - VALUE'length; + end if; + end if; + Grow_line(L, fw); + for i in normal'range loop + L(bp + i + offset) := character'val( + std_logic'pos(normal(i)) + character'pos('0')); + end loop; + end; + + +END util_1164; diff --git a/lib/models/memory/sdram/mt48lc64m4a2/vec_gen.vhd b/lib/models/memory/sdram/mt48lc64m4a2/vec_gen.vhd new file mode 100644 index 0000000..821d321 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc64m4a2/vec_gen.vhd @@ -0,0 +1,372 @@ +------------------------------------------------------------------------------- +-- -- +-- This is a data generator for the testbench for Micron's Synchronous -- +-- DRAM. This generator reads a text file line-by-line and generates -- +-- a file of test vectors that is then read by the testbench and -- +-- applied to the part. -- +-- -- +-- This VHDL program creates a text file of test vectors that is used by the -- +-- test bench. Place your commands in a file (a copy of VEC_GEN.VHD) and run -- +-- VEC_GEN.VHD in your VHDL simulator (make sure you have compiled this -- +-- package prior to running the program VEC_GEN.VHD). This will produce the -- +-- vectors that are required to run the included testbench. Change the name -- +-- of the vector file to save your vectors in separate files. The default -- +-- file name for the output vectors generated from this pacakage is -- +-- "test.txt." -- +-- -- +-- Now compile and run the testbench program embedtb.vhd. The testbench uses -- +-- the default test.txt as input vectors. -- +-- -- +-- -- +-- Copyright 1997 Micron Technology, Inc. -- +-- -- +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.all; +USE std.textio.all; +USE work.io_utils.all; + + +PACKAGE generate_vectors IS + + CONSTANT set_up : TIME; + CONSTANT hold : TIME; + CONSTANT cycle_start : TIME; + + SIGNAL cycle : INTEGER := 0; + SIGNAL sim_time : TIME := 0 ns; + FILE output_file:TEXT IS OUT "test.txt"; + PROCEDURE write(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); + first_data : IN INTEGER; dqm : IN BIT; cke : IN BIT); + PROCEDURE read(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); dqm : IN BIT; cke : IN BIT); + PROCEDURE active(row_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); data_bus : IN INTEGER; dqm : IN BIT; cke : IN BIT); + PROCEDURE precharge(bank : IN BIT_VECTOR(1 DOWNTO 0); address : IN INTEGER; data_bus: IN INTEGER; dqm : IN BIT; cke : IN BIT); + PROCEDURE nop(data_bus : IN INTEGER; dqm : IN BIT; cke : IN BIT; cs : IN BIT); + PROCEDURE burst_term(data_bus : IN INTEGER; dqm : IN BIT; cke : IN BIT); + PROCEDURE auto_refresh; + PROCEDURE next_cycle(SIGNAL clk : IN BIT); + PROCEDURE load_array(load : IN BIT); + PROCEDURE load_mode_reg(op_code : IN INTEGER; cke : IN BIT); + PROCEDURE unload_array(row_start : IN INTEGER; row_end : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0)); + +END generate_vectors; + + +PACKAGE BODY generate_vectors IS + + CONSTANT set_up : TIME := 3 ns; + CONSTANT hold : TIME := 1 ns; + CONSTANT cycle_start : TIME := 0 ns; + + +PROCEDURE write(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); first_data : IN INTEGER; + dqm : IN BIT; cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 0, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, first_data, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE read(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); dqm : IN BIT; cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 0, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, -100, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE active(row_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); data_bus : IN INTEGER; dqm : IN BIT; cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 0, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, row_address, right, 6); --address +write(l, data_bus, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE precharge(bank : IN BIT_VECTOR(1 DOWNTO 0); address : IN INTEGER; data_bus: IN INTEGER; dqm : IN BIT; cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 0, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, address, right, 6); --address +write(l, data_bus, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE nop(data_bus : IN INTEGER; dqm : IN BIT; cke : IN BIT; cs : IN BIT) IS + + +VARIABLE l : LINE; +VARIABLE col_address : INTEGER := 0; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, cke, right, 4); --Cke +write(l, cs, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, data_bus, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + + +PROCEDURE burst_term(data_bus : IN INTEGER; dqm : IN BIT; cke : IN BIT) IS + +VARIABLE l : LINE; +VARIABLE col_address : INTEGER := 0; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, data_bus, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE auto_refresh IS + VARIABLE l : LINE; + VARIABLE dqm : BIT := '0'; + VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; +BEGIN + IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); + ELSE + write(l, now-set_up, left, 4, ns); + END IF; + write(l, 1, right, 4); --Cke + write(l, 0, right, 4); --Cs + write(l, 0, right, 4); --Ras + write(l, 0, right, 4); --Cas + write(l, 1, right, 4); --We + write(l, dqm, right, 4); --Dqm + write(l, bank, right, 4); --Ba + write(l, 0, right, 6); --address + write(l, -100, right, 6); --first data location + --write(l, 0, right, 4); --load + --write(l, 0, right, 4); --unload + --write(l, 0, right, 6); --row_address_start + --write(l, 0, right, 6); --row_address_end + writeline(output_file,l); --write vector to file +END; + + +PROCEDURE next_cycle(SIGNAL clk : IN BIT) IS + +BEGIN + +WAIT UNTIL clk = '1'; + +END; + +PROCEDURE load_array(load : IN BIT) IS + +VARIABLE l : LINE; +VARIABLE dqm : BIT := '0'; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, 1, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, 0, right, 6); --address +write(l, -100, right, 6); --first data location +--write(l, 1, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE unload_array(row_start : IN INTEGER; row_end : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0)) IS + +VARIABLE l : LINE; +VARIABLE dqm : BIT := '0'; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, 1, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, 0, right, 6); --address +write(l, -100, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 1, right, 4); --unload +--write(l, row_start, right, 6); --row_address_start +--write(l, row_end, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE load_mode_reg(op_code : IN INTEGER; cke : IN BIT) IS + +VARIABLE l : LINE; +VARIABLE dqm : BIT := '0'; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 0, right, 4); --Ras +write(l, 0, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, op_code, right, 6); --address +write(l, -100, right, 6); --first data location +--write(l, 0, right, 4); --load +--write(l, 0, right, 4); --unload +--write(l, 0, right, 6); --row_address_start +--write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +END generate_vectors; + diff --git a/lib/models/memory/sdram/mt48lc64m4a2/vector.do b/lib/models/memory/sdram/mt48lc64m4a2/vector.do new file mode 100644 index 0000000..7480359 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc64m4a2/vector.do @@ -0,0 +1,4 @@ +vcom vec_gen.vhd +vcom ed_comnd.vhd +vsim vector_generate +run -all diff --git a/lib/models/memory/sdram/mt48lc64m4a2/wave.do b/lib/models/memory/sdram/mt48lc64m4a2/wave.do new file mode 100644 index 0000000..168e846 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc64m4a2/wave.do @@ -0,0 +1,31 @@ +onerror {resume} +add wave -logic -height 20 /tb/u1/clk +add wave -logic -height 20 /tb/u1/cke +add wave -logic -height 20 /tb/u1/cs_n +add wave -logic -height 20 /tb/u1/ras_n +add wave -logic -height 20 /tb/u1/cas_n +add wave -logic -height 20 /tb/u1/we_n +add wave -logic -unsigned -height 20 /tb/u1/addr +add wave -logic -height 20 /tb/u1/ba +add wave -logic -unsigned -height 20 /tb/u1/dq +add wave -logic -height 20 /tb/u1/dqm +add wave -literal -ascii -height 20 /tb/u1/operation +add wave -logic -unsigned -height 20 /tb/u1/mode_reg +add wave -logic -height 20 /tb/u1/active_enable +add wave -logic -height 20 /tb/u1/aref_enable +add wave -logic -height 20 /tb/u1/burst_term +add wave -logic -height 20 /tb/u1/mode_reg_enable +add wave -logic -height 20 /tb/u1/prech_enable +add wave -logic -height 20 /tb/u1/read_enable +add wave -logic -height 20 /tb/u1/write_enable +add wave -logic -height 20 /tb/u1/burst_length_1 +add wave -logic -height 20 /tb/u1/burst_length_2 +add wave -logic -height 20 /tb/u1/burst_length_4 +add wave -logic -height 20 /tb/u1/burst_length_8 +add wave -logic -height 20 /tb/u1/cas_latency_2 +add wave -logic -height 20 /tb/u1/cas_latency_3 +add wave -logic -height 20 /tb/u1/pre_chk +add wave -logic -height 20 /tb/u1/act_chk +add wave -logic -height 20 /tb/u1/bank_chk +add wave -logic -unsigned -height 20 /tb/u1/row_chk +add wave -logic -unsigned -height 20 /tb/u1/col_chk diff --git a/lib/models/memory/sdram/mt48lc8m16a2/base.do b/lib/models/memory/sdram/mt48lc8m16a2/base.do new file mode 100644 index 0000000..d2afbcb --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m16a2/base.do @@ -0,0 +1,5 @@ +vcom util1164.vhd +vcom stdlogar.vhd +vcom io_utils.vhd +vcom mti_pkg.vhd + diff --git a/lib/models/memory/sdram/mt48lc8m16a2/ed_comnd.vhd b/lib/models/memory/sdram/mt48lc8m16a2/ed_comnd.vhd new file mode 100644 index 0000000..3d7fb12 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m16a2/ed_comnd.vhd @@ -0,0 +1,349 @@ +--------------------------------------------------------------------------------- +--COMMAND FORMAT -- +-- -- +-- write(column address(integer), bank(bit_vector), first data(integer), dqm(bit), cke(bit));-- +-- read(column address(integer), bank(bit_vector), dqm(bit), cke(bit)); -- +-- active(row address(integer), bank(bit_vector), data bus (integer), dqm(bit), cke(bit));-- +-- precharge(bank(bit_vector), address (integer), data bus(integer), dqm(bit), cke(bit)); -- +-- nop(data bus(integer), dqm(bit), cke(bit), cs(bit)); -- +-- burst_term(data bus(integer), dqm(bit_vector), cke(bit)); -- +-- load_array('1'); -- +-- load_mode_reg(register(integer), cke(bit)); -- +-- next_cycle(clk); This is used after every command(incl. nop) to clock -- +-- at the correct clock frequency entered in the clock -- +-- period constant below -- +-- unload_array(row_start(integer), row_end(integer), bank(bit_vector)) -- +-- load_mode_reg(op_code(integer)) -- +-- -- +--------------------------------------------------------------------------------- + +LIBRARY work; +LIBRARY ieee; +USE ieee.std_logic_1164.all; +USE std.textio.all; +USE work.generate_vectors.all; + +ENTITY vector_generate IS +END vector_generate; + +ARCHITECTURE vector_generate OF vector_generate IS + + SIGNAL stim_done : BOOLEAN := FALSE; + SIGNAL clk : BIT := '0'; + CONSTANT clk_start : time := 15 ns; + CONSTANT clk_period : time := 10 ns; + CONSTANT Z : INTEGER := -100; + +BEGIN + +PROCESS + +BEGIN + +WAIT UNTIL clk = '1' AND clk'EVENT; + +--------------------ENTER COMMANDS BELOW THIS LINE----------------------------- +--******************DO NOT USE -100 FOR A DQ VALUE*************************---- +--*******************Z WILL PLACE HI-Z ON THE BUS**************************---- +--*******USE next_cycle(clk) FOR ADVANCING TO NEXT CLOCK CYCLE*************---- + +nop(Z, "00", '1', '1'); --Always begin with one nop when using Micron's testbench + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +load_array('1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +precharge("00", 1024, Z, "00", '1'); + +FOR i IN 1 to 2 LOOP + next_cycle(clk); + nop(Z, "00", '1', '1'); +END LOOP; + +next_cycle(clk); +auto_refresh; + +FOR i IN 1 TO 8 LOOP + next_cycle(clk); + nop(Z, "00", '1', '1'); +END LOOP; + +next_cycle(clk); +auto_refresh; + +FOR i IN 1 TO 8 LOOP + next_cycle(clk); + nop(Z, "00", '1', '1'); +END LOOP; + +next_cycle(clk); +load_mode_reg(51, '1'); -- 19 / 35 / 51 -> lat=3,bl=8,mode=seq + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +-- Write Section + +next_cycle(clk); +active(0, "00", Z, "00", '1'); -- Activate Bank 0 + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); -- Write Bank 0 +write(0, "00", 100, "00", '1'); + +next_cycle(clk); +nop(101, "00", '1', '1'); + +next_cycle(clk); +active(0, "01", 102, "00", '1'); -- Activate Bank 1 + +next_cycle(clk); +nop(103, "00", '1', '1'); + +next_cycle(clk); +nop(104, "00", '1', '1'); + +next_cycle(clk); +nop(105, "00", '1', '1'); + +next_cycle(clk); +nop(106, "00", '1', '1'); + +next_cycle(clk); +nop(107, "00", '1', '1'); + +next_cycle(clk); +write(0, "01", 200, "00", '1'); -- Write Bank 1 + +next_cycle(clk); +precharge("00", 0, 201, "00", '1'); -- Precharge Bank 0 + +next_cycle(clk); +active(0, "10", 202, "00", '1'); -- Activate Bank 2 + +next_cycle(clk); +nop(203, "00", '1', '1'); + +next_cycle(clk); +nop(204, "00", '1', '1'); + +next_cycle(clk); +nop(205, "00", '1', '1'); + +next_cycle(clk); +nop(206, "00", '1', '1'); + +next_cycle(clk); +nop(207, "00", '1', '1'); + +next_cycle(clk); +write(0, "10", 300, "00", '1'); -- Write Bank 2 + +next_cycle(clk); +precharge("01", 0, 301, "00", '1'); -- Precharge Bank 1 + +next_cycle(clk); +active(0, "11", 302, "00", '1'); -- Activate Bank 3 + +next_cycle(clk); +nop(303, "00", '1', '1'); + +next_cycle(clk); +nop(304, "00", '1', '1'); + +next_cycle(clk); +nop(305, "00", '1', '1'); + +next_cycle(clk); +nop(306, "00", '1', '1'); + +next_cycle(clk); +nop(307, "00", '1', '1'); + +next_cycle(clk); +write(0, "11", 400, "00", '1'); -- Write Bank 3 + +next_cycle(clk); +precharge("10", 0, 401, "00", '1'); -- Precharge Bank 2 + +next_cycle(clk); +active(0, "00", 402, "00", '1'); -- Activate Bank 0 + +next_cycle(clk); +nop(403, "00", '1', '1'); + +next_cycle(clk); +nop(404, "00", '1', '1'); + +next_cycle(clk); +nop(405, "00", '1', '1'); + +next_cycle(clk); +nop(406, "00", '1', '1'); + +next_cycle(clk); +nop(407, "00", '1', '1'); + +-- Read Section + +next_cycle(clk); +read(0, "00", "00", '1'); -- Read Bank 0 + +next_cycle(clk); +precharge("11", 0, Z, "00", '1'); -- Precharge Bank 3 + +next_cycle(clk); +active(0, "01", Z, "00", '1'); -- Activate Bank 1 + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +read(0, "01", "00", '1'); -- Read Bank 1 + +next_cycle(clk); +precharge("00", 0, Z, "00", '1'); -- Precharge Bank 0 + +next_cycle(clk); +active(0, "10", Z, "00", '1'); -- Activate Bank 2 + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +read(0, "10", "00", '1'); -- Read Bank 2 + +next_cycle(clk); +precharge("01", 0, Z, "00", '1'); -- Precharge Bank 1 + +next_cycle(clk); +active(0, "11", Z, "00", '1'); -- Activate Bank 3 + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +read(0, "11", "00", '1'); -- Read Bank 3 + +next_cycle(clk); +precharge("10", 0, Z, "00", '1'); -- Precharge Bank 2 + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +precharge("11", 0, Z, "00", '1'); -- Precharge Bank 3 + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +next_cycle(clk); +unload_array(0, 0, "00"); + +next_cycle(clk); +nop(Z, "00", '1', '1'); + +stim_done <= TRUE; --always include this line at the end of your stimulus + +------------------------------------------------------------------------------- +--*************************************************************************---- +END PROCESS; + + +clock: + PROCESS + VARIABLE done_time : time; + VARIABLE cycle_var : integer := 0; + BEGIN + cycle <= 0; + clk <= '0'; + WAIT for clk_start; + WHILE not stim_done loop + clk <= '1'; + cycle <= cycle_var; + WAIT for clk_period/2; + cycle_var := cycle_var + 1; + clk <= '0'; + WAIT for clk_period/2; + END LOOP; + + ASSERT (FALSE) + REPORT "Test Vectors Generated" + SEVERITY note; + + WAIT; + END PROCESS; + + +END; diff --git a/lib/models/memory/sdram/mt48lc8m16a2/io_utils.vhd b/lib/models/memory/sdram/mt48lc8m16a2/io_utils.vhd new file mode 100644 index 0000000..dfcb84a --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m16a2/io_utils.vhd @@ -0,0 +1,266 @@ +LIBRARY ieee; +USE std.textio.ALL; +USE ieee.std_logic_1164.ALL; + +PACKAGE io_utils IS + + PROCEDURE write_string(l : INOUT line; + value : IN string; + justified : IN side := right; + field : IN width := 0); + + TYPE radix IS (binary, octal, decimal, hex); + + -- read a number from the line + -- use this if you have hex numbers that are not in VHDL pound-sign format + PROCEDURE read(l : INOUT line; value : OUT integer; radix : IN positive); + + -- read a number that might be in VHDL pound-sign format + PROCEDURE read_based(l : INOUT line; value : OUT integer); + + PROCEDURE write(l : INOUT line; + value : IN std_logic_vector; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false); + + PROCEDURE write(l : INOUT line; + value : IN integer; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false); +END io_utils; + +PACKAGE BODY io_utils IS + + PROCEDURE write_string(l : INOUT line; + value : IN string; + justified : IN side := right; + field : IN width := 0) + IS + BEGIN + write(l, value, justified, field); + END; + + PROCEDURE shrink_line(l : INOUT line; pos : integer) IS + VARIABLE tmpl : line; + BEGIN + tmpl := l; + l := NEW string'(tmpl(pos TO tmpl'high)); + deallocate(tmpl); + END; + + PROCEDURE read(l : INOUT line; + value : OUT integer; + radix : IN positive) + IS + CONSTANT not_digit : integer := -999; + + -- convert a character to a value from 0 to 15 + FUNCTION digit_value(c : character) RETURN integer IS + BEGIN + IF (c >= '0') AND (c <= '9') THEN + RETURN (character'pos(c) - character'pos('0')); + ELSIF (c >= 'a') AND (c <= 'f') THEN + RETURN (character'pos(c) - character'pos('a') + 10); + ELSIF (c >= 'A') AND (c <= 'F') THEN + RETURN (character'pos(c) - character'pos('A') + 10); + ELSE + RETURN not_digit; + END IF; + END; + + -- skip leading white space in the line + PROCEDURE skip_white(VARIABLE l : IN line; pos : OUT integer) IS + BEGIN + pos := l'low; + FOR i IN l'low TO l'high LOOP + CASE l(i) IS + WHEN ' ' | ht => + pos := i + 1; + WHEN OTHERS => + EXIT; + END CASE; + END LOOP; + END; + + VARIABLE digit : integer; + VARIABLE result : integer := 0; + VARIABLE pos : integer; + BEGIN + -- skip white space + skip_white(l, pos); + + -- calculate the value + FOR i IN pos TO l'right LOOP + digit := digit_value(l(i)); + EXIT WHEN (digit = not_digit) OR (digit >= radix); + result := result * radix + digit; + pos := i + 1; + END LOOP; + value := result; + + -- remove the "used" characters from the line + shrink_line(l, pos); + END; + + PROCEDURE read_based(l : INOUT line; value : OUT integer) IS + VARIABLE digit : integer; + VARIABLE num : integer; + VARIABLE base : integer; + BEGIN + read(l, num, 10); + IF (l'length > 1) AND (l(l'left) = '#') THEN + shrink_line(l, l'left+1); + base := num; + read(l, num, base); + IF (l'length >= 1) AND (l(l'left) = '#') THEN + shrink_line(l, l'left+1); + END IF; + END IF; + value := num; + END; + + PROCEDURE write(l : INOUT line; + value : IN std_logic_vector; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false) + IS + FUNCTION to_int(bv : std_logic_vector) RETURN integer + IS + VARIABLE result : integer := 0; + BEGIN + FOR i IN bv'RANGE LOOP + result := result * 2; + IF (bv(i) = '1') THEN + result := result + 1; + END IF; + END LOOP; + RETURN result; + END; + + TYPE array_of_widths IS ARRAY(radix) OF natural; + CONSTANT nibble_widths : array_of_widths := ( + binary => 1, + octal => 3, + hex => 4, + decimal=> 32); + CONSTANT hex_digit : string(1 TO 16) := "0123456789ABCDEF"; + + ALIAS input_val : std_logic_vector(value'length DOWNTO 1) IS value; + CONSTANT nibble_width : natural := nibble_widths(base); + CONSTANT result_width : natural := (value'length + nibble_width - 1)/nibble_width; + + VARIABLE result : string(1 TO result_width); -- longest possible value + VARIABLE result_pos : positive := 1; + VARIABLE nibble_val : integer; + VARIABLE bitcnt : integer; + BEGIN + IF base = decimal THEN + write(l, to_int(value), justified, field, base, use_pound); + RETURN; + END IF; + + bitcnt := value'length MOD nibble_width; + IF (bitcnt = 0) THEN + bitcnt := nibble_width; + END IF; + FOR i IN input_val'RANGE LOOP + nibble_val := nibble_val * 2; + IF (input_val(i) = '1') THEN + nibble_val := nibble_val + 1; + END IF; + bitcnt := bitcnt - 1; + IF (bitcnt = 0) THEN + result(result_pos) := hex_digit(nibble_val + 1); + result_pos := result_pos + 1; + nibble_val := 0; + bitcnt := nibble_width; + END IF; + END LOOP; + write(l, result, justified, field); + END; + + PROCEDURE write(l : INOUT line; + value : IN integer; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false) + IS + FUNCTION to_bv(int : integer) RETURN std_logic_vector + IS + VARIABLE bv : std_logic_vector(32 DOWNTO 1) := (OTHERS => '0'); + VARIABLE pos : integer := 0; + VARIABLE tmpval : integer := int; + BEGIN + FOR i IN 1 TO 32 LOOP + pos := pos + 1; + IF (tmpval MOD 2) = 1 THEN + bv(i) := '1'; + END IF; + tmpval := tmpval / 2; + EXIT WHEN tmpval = 0; + END LOOP; + RETURN bv(pos DOWNTO 1); + END; + + VARIABLE tmp : line; + BEGIN + IF (base = decimal) THEN + IF (use_pound) THEN + write_string(tmp, "10#"); + END IF; + write(tmp, value); + IF (use_pound) THEN + write_string(tmp, "#"); + END IF; + write(l, tmp.ALL, justified, field); + deallocate(tmp); + ELSE + write(l, to_bv(value), justified, field, base, use_pound); + END IF; + END; + +END io_utils; + + + +-- test the hex number reader +--ENTITY test IS END; + +--USE std.textio.ALL; +--USE work.io_utils.ALL; +--ARCHITECTURE hex_test OF test IS +--BEGIN +-- PROCESS +-- VARIABLE val : integer; +-- FILE myfile : text IS IN "values"; +-- VARIABLE inline : line; +-- VARIABLE outline : line; +-- BEGIN +-- WHILE NOT endfile(myfile) LOOP +-- readline(myfile, inline); + +-- write(outline, inline.ALL); +-- +-- read_based(inline, val); + -- write_string(outline, " binary: "); + -- write(outline, val, base => binary); + -- write_string(outline, " octal: "); + -- write(outline, val, base => octal); + -- write_string(outline, " decimal: "); + -- write(outline, val, base => decimal); +-- write_string(outline, " hex: "); +-- write(outline, val, base => hex); +-- writeline(output, outline); +-- END LOOP; +-- WAIT; +-- END PROCESS; +--END; + + diff --git a/lib/models/memory/sdram/mt48lc8m16a2/loaddata.txt b/lib/models/memory/sdram/mt48lc8m16a2/loaddata.txt new file mode 100644 index 0000000..c7599a9 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m16a2/loaddata.txt @@ -0,0 +1,40 @@ +0 0 00 0 -- ROW (HEX), COL (HEX), BANK (BIN), DATA (HEX) +0 1 00 1 +0 2 00 2 +0 3 00 3 +0 4 00 4 +0 5 00 5 +0 6 00 6 +0 7 00 7 +0 8 00 8 +0 9 00 9 +0 0 01 10 +0 1 01 11 +0 2 01 12 +0 3 01 13 +0 4 01 14 +0 5 01 15 +0 6 01 16 +0 7 01 17 +0 8 01 18 +0 9 01 19 +0 0 10 20 +0 1 10 21 +0 2 10 22 +0 3 10 23 +0 4 10 24 +0 5 10 25 +0 6 10 26 +0 7 10 27 +0 8 10 28 +0 9 10 29 +0 0 11 30 +0 1 11 31 +0 2 11 32 +0 3 11 33 +0 4 11 34 +0 5 11 35 +0 6 11 36 +0 7 11 37 +0 8 11 38 +0 9 11 39 diff --git a/lib/models/memory/sdram/mt48lc8m16a2/mt48lc8m16a2.vhd b/lib/models/memory/sdram/mt48lc8m16a2/mt48lc8m16a2.vhd new file mode 100644 index 0000000..3093c8c --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m16a2/mt48lc8m16a2.vhd @@ -0,0 +1,1426 @@ +----------------------------------------------------------------------------------------- +-- +-- File Name: MT48LC8M16A2.VHD +-- Version: 0.0g +-- Date: May 11th, 1999 +-- Model: Behavioral +-- Simulator: Model Technology (PC version 5.3 PE) +-- +-- Dependencies: None +-- +-- Author: Son P. Huynh +-- Email: sphuynh@micron.com +-- Phone: (208) 368-3825 +-- Company: Micron Technology, Inc. +-- Part Number: MT48LC8M16A2 (2Mb x 16 x 4 Banks) +-- +-- Description: Micron 128Mb SDRAM +-- +-- Limitation: - Doesn't check for 4096-cycle refresh +-- +-- Note: - Set simulator resolution to "ps" accuracy +-- +-- Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY +-- WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY +-- IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR +-- A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT. +-- +-- Copyright (c) 1998 Micron Semiconductor Products, Inc. +-- All rights researved +-- +-- Rev Author Phone Date Changes +-- ---- ---------------------------- ---------- ------------------------------------- +-- 0.0g Son Huynh 208-368-3825 05/11/2000 Fix tWR + tRP timing +-- Micron Technology Inc. +-- +-- 0.0f Son Huynh 208-368-3825 07/08/1999 Fix tWR = 1 Clk + 7.5 ns (Auto) +-- Micron Technology Inc. Fix tWR = 15 ns (Manual) +-- Fix tRP (Autoprecharge to AutoRefresh) +-- +-- 0.0c Son P. Huynh 208-368-3825 04/08/1999 Fix tWR + tRP in Write with AP +-- Micron Technology Inc. Fix tRC check in Load Mode Register +-- +-- 0.0b Son P. Huynh 208-368-3825 01/06/1998 Derive from 64Mb SDRAM model +-- Micron Technology Inc. +-- +----------------------------------------------------------------------------------------- + +LIBRARY std; + USE std.textio.ALL; +LIBRARY ieee; + USE ieee.std_logic_1164.ALL; +LIBRARY work; + USE work.io_utils.ALL; + USE work.mti_pkg.ALL; + +ENTITY mt48lc8m16a2 IS + GENERIC ( + -- Timing Parameters for -7E and CAS Latency = 2 + tAC : TIME := 5.4 ns; + tHZ : TIME := 5.4 ns; + tOH : TIME := 2.7 ns; + tMRD : INTEGER := 2; -- 2 Clk Cycles + tRAS : TIME := 37.0 ns; + tRC : TIME := 60.0 ns; + tRCD : TIME := 15.0 ns; + tRP : TIME := 15.0 ns; + tRRD : TIME := 14.0 ns; + tWRa : TIME := 7.0 ns; -- A2 Version - Auto precharge mode only (1 Clk + 7 ns) + tWRp : TIME := 14.0 ns; -- A2 Version - Precharge mode only (14 ns) + + tAH : TIME := 0.8 ns; + tAS : TIME := 1.5 ns; + tCH : TIME := 2.5 ns; + tCL : TIME := 2.5 ns; + tCK : TIME := 7.5 ns; + tDH : TIME := 0.8 ns; + tDS : TIME := 1.5 ns; + tCKH : TIME := 0.8 ns; + tCKS : TIME := 1.5 ns; + tCMH : TIME := 0.8 ns; + tCMS : TIME := 1.5 ns; + + addr_bits : INTEGER := 12; + data_bits : INTEGER := 16; + col_bits : INTEGER := 9 + ); + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC_VECTOR := "00"; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '1'; + Cs_n : IN STD_LOGIC := '1'; + Ras_n : IN STD_LOGIC := '1'; + Cas_n : IN STD_LOGIC := '1'; + We_n : IN STD_LOGIC := '1'; + Dqm : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"; + Load : IN STD_LOGIC := '0'; + Unload : IN STD_LOGIC := '0'; + Row_start : IN INTEGER := 0; + Row_end : IN INTEGER := 0 + ); +END mt48lc8m16a2; + +ARCHITECTURE behave OF mt48lc8m16a2 IS + TYPE State IS (ACT, A_REF, BST, LMR, NOP, PRECH, READ, READ_A, WRITE, WRITE_A, FILE_LOAD, FILE_UNLOAD); + TYPE Array4xI IS ARRAY (3 DOWNTO 0) OF INTEGER; + TYPE Array4xT IS ARRAY (3 DOWNTO 0) OF TIME; + TYPE Array4xB IS ARRAY (3 DOWNTO 0) OF BIT; + TYPE Array4x2BV IS ARRAY (3 DOWNTO 0) OF BIT_VECTOR (1 DOWNTO 0); + TYPE Array4xCBV IS ARRAY (4 DOWNTO 0) OF BIT_VECTOR (Col_bits - 1 DOWNTO 0); + TYPE Array_state IS ARRAY (4 DOWNTO 0) OF State; + SIGNAL Operation : State := NOP; + SIGNAL Mode_reg : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL Active_enable, Aref_enable, Burst_term : BIT := '0'; + SIGNAL Mode_reg_enable, Prech_enable, Read_enable, Write_enable : BIT := '0'; + SIGNAL Burst_length_1, Burst_length_2, Burst_length_4, Burst_length_8 : BIT := '0'; + SIGNAL Cas_latency_2, Cas_latency_3 : BIT := '0'; + SIGNAL Ras_in, Cas_in, We_in : BIT := '0'; + SIGNAL Write_burst_mode : BIT := '0'; + SIGNAL RAS_clk, Sys_clk, CkeZ : BIT := '0'; + + -- Checking internal wires + SIGNAL Pre_chk : BIT_VECTOR (3 DOWNTO 0) := "0000"; + SIGNAL Act_chk : BIT_VECTOR (3 DOWNTO 0) := "0000"; + SIGNAL Dq_in_chk, Dq_out_chk : BIT := '0'; + SIGNAL Bank_chk : BIT_VECTOR (1 DOWNTO 0) := "00"; + SIGNAL Row_chk : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL Col_chk : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + + BEGIN + -- CS# Decode + WITH Cs_n SELECT + Cas_in <= TO_BIT (Cas_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + WITH Cs_n SELECT + Ras_in <= TO_BIT (Ras_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + WITH Cs_n SELECT + We_in <= TO_BIT (We_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + + -- Commands Decode + Active_enable <= NOT(Ras_in) AND Cas_in AND We_in; + Aref_enable <= NOT(Ras_in) AND NOT(Cas_in) AND We_in; + Burst_term <= Ras_in AND Cas_in AND NOT(We_in); + Mode_reg_enable <= NOT(Ras_in) AND NOT(Cas_in) AND NOT(We_in); + Prech_enable <= NOT(Ras_in) AND Cas_in AND NOT(We_in); + Read_enable <= Ras_in AND NOT(Cas_in) AND We_in; + Write_enable <= Ras_in AND NOT(Cas_in) AND NOT(We_in); + + -- Burst Length Decode + Burst_length_1 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND NOT(Mode_reg(0)); + Burst_length_2 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND Mode_reg(0); + Burst_length_4 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND NOT(Mode_reg(0)); + Burst_length_8 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND Mode_reg(0); + + -- CAS Latency Decode + Cas_latency_2 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND NOT(Mode_reg(4)); + Cas_latency_3 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND Mode_reg(4); + + -- Write Burst Mode + Write_burst_mode <= Mode_reg(9); + + -- RAS Clock for checking tWR and tRP + PROCESS + variable Clk0, Clk1 : integer := 0; + begin + RAS_clk <= '1'; + wait for 0.5 ns; + RAS_clk <= '0'; + wait for 0.5 ns; + if Clk0 > 100 or Clk1 > 100 then + wait; + else + if Clk = '1' then + Clk0 := 0; + Clk1 := Clk1 + 1; + else + Clk0 := Clk0 + 1; + Clk1 := 0; + end if; + end if; + END PROCESS; + + -- System Clock + int_clk : PROCESS (Clk) + begin + IF Clk'LAST_VALUE = '0' AND Clk = '1' THEN + CkeZ <= TO_BIT(Cke, '1'); + END IF; + Sys_clk <= CkeZ AND TO_BIT(Clk, '0'); + END PROCESS; + + state_register : PROCESS + TYPE ram_type IS ARRAY (2**col_bits - 1 DOWNTO 0) OF BIT_VECTOR (data_bits - 1 DOWNTO 0); + TYPE ram_pntr IS ACCESS ram_type; + TYPE ram_stor IS ARRAY (2**addr_bits - 1 DOWNTO 0) OF ram_pntr; + VARIABLE Bank0 : ram_stor; + VARIABLE Bank1 : ram_stor; + VARIABLE Bank2 : ram_stor; + VARIABLE Bank3 : ram_stor; + VARIABLE Row_index, Col_index : INTEGER := 0; + VARIABLE Dq_temp : BIT_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => '0'); + + VARIABLE Col_addr : Array4xCBV; + VARIABLE Bank_addr : Array4x2BV; + VARIABLE Dqm_reg0, Dqm_reg1 : BIT_VECTOR (1 DOWNTO 0) := "00"; + + VARIABLE Bank, Previous_bank : BIT_VECTOR (1 DOWNTO 0) := "00"; + VARIABLE B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col_brst : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Row : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Burst_counter : INTEGER := 0; + + VARIABLE Command : Array_state; + VARIABLE Bank_precharge : Array4x2BV; + VARIABLE A10_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Auto_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Read_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Write_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_read : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_write : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_bank : BIT_VECTOR (1 DOWNTO 0) := "00"; + VARIABLE Count_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE Count_precharge : Array4xI := (0 & 0 & 0 & 0); + + VARIABLE Data_in_enable, Data_out_enable : BIT := '0'; + VARIABLE Pc_b0, Pc_b1, Pc_b2, Pc_b3 : BIT := '0'; + VARIABLE Act_b0, Act_b1, Act_b2, Act_b3 : BIT := '0'; + + -- Timing Check + VARIABLE MRD_chk : INTEGER := 0; + VARIABLE WR_counter : Array4xI := (0 & 0 & 0 & 0); + VARIABLE WR_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE WR_chkp : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE RC_chk, RRD_chk : TIME := 0 ns; + VARIABLE RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3 : TIME := 0 ns; + VARIABLE RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3 : TIME := 0 ns; + VARIABLE RP_chk0, RP_chk1, RP_chk2, RP_chk3 : TIME := 0 ns; + + -- Load and Unload variables + FILE load_file : TEXT IS IN "loaddata.txt"; -- Data load + FILE out_file0 : TEXT IS OUT "outdata0.txt"; -- Data dump for bank 0 + FILE out_file1 : TEXT IS OUT "outdata1.txt"; -- Data dump for bank 1 + FILE out_file2 : TEXT IS OUT "outdata2.txt"; -- Data dump for bank 2 + FILE out_file3 : TEXT IS OUT "outdata3.txt"; -- Data dump for bank 3 + VARIABLE l_in, l_out0, l_out1, l_out2, l_out3 : LINE; + VARIABLE array_buffer : BIT_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE write_data_var : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE row_load, col_load, dq_load : INTEGER; + VARIABLE ba_load : BIT_VECTOR (1 DOWNTO 0); + VARIABLE dq_vec : BIT_VECTOR (data_bits - 1 DOWNTO 0); + VARIABLE i, j, k : INTEGER; + + -- Initialize empty rows + PROCEDURE Init_mem (Bank : BIT_VECTOR (1 DOWNTO 0); Row_index : INTEGER) IS + VARIABLE i, j : INTEGER := 0; + BEGIN + IF Bank = "00" THEN + IF Bank0 (Row_index) = NULL THEN -- Check to see if row empty + Bank0 (Row_index) := NEW ram_type; -- Open new row for access + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP -- Filled row with zeros + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank0 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "01" THEN + IF Bank1 (Row_index) = NULL THEN + Bank1 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank1 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "10" THEN + IF Bank2 (Row_index) = NULL THEN + Bank2 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank2 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "11" THEN + IF Bank3 (Row_index) = NULL THEN + Bank3 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank3 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + END IF; + END; + + -- Burst Counter + PROCEDURE Burst_decode IS + VARIABLE Col_int : INTEGER := 0; + VARIABLE Col_vec, Col_temp : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + BEGIN + -- Advance Burst Counter + Burst_counter := Burst_counter + 1; + + -- Burst Type + IF Mode_reg (3) = '0' THEN + Col_int := TO_INTEGER(Col); + Col_int := Col_int + 1; + TO_BITVECTOR (Col_int, Col_temp); + ELSIF Mode_reg (3) = '1' THEN + TO_BITVECTOR (Burst_counter, Col_vec); + Col_temp (2) := Col_vec (2) XOR Col_brst (2); + Col_temp (1) := Col_vec (1) XOR Col_brst (1); + Col_temp (0) := Col_vec (0) XOR Col_brst (0); + END IF; + + -- Burst Length + IF Burst_length_2 = '1' THEN + Col (0) := Col_temp (0); + ELSIF Burst_length_4 = '1' THEN + Col (1 DOWNTO 0) := Col_temp (1 DOWNTO 0); + ELSIF Burst_length_8 = '1' THEN + Col (2 DOWNTO 0) := Col_temp (2 DOWNTO 0); + ELSE + Col := Col_temp; + END IF; + + -- Burst Read Single Write + IF Write_burst_mode = '1' AND Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Data counter + IF Burst_length_1 = '1' THEN + IF Burst_counter >= 1 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_2 = '1' THEN + IF Burst_counter >= 2 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_4 = '1' THEN + IF Burst_counter >= 4 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_8 = '1' THEN + IF Burst_counter >= 8 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + END IF; + END; + + BEGIN + WAIT ON Sys_clk, RAS_clk; + IF Sys_clk'event and Sys_clk = '1' AND Load = '0' AND Unload = '0' THEN + -- Internal Command Pipeline + Command(0) := Command(1); + Command(1) := Command(2); + Command(2) := Command(3); + Command(3) := NOP; + + Col_addr(0) := Col_addr(1); + Col_addr(1) := Col_addr(2); + Col_addr(2) := Col_addr(3); + Col_addr(3) := (OTHERS => '0'); + + Bank_addr(0) := Bank_addr(1); + Bank_addr(1) := Bank_addr(2); + Bank_addr(2) := Bank_addr(3); + Bank_addr(3) := "00"; + + Bank_precharge(0) := Bank_precharge(1); + Bank_precharge(1) := Bank_precharge(2); + Bank_precharge(2) := Bank_precharge(3); + Bank_precharge(3) := "00"; + + A10_precharge(0) := A10_precharge(1); + A10_precharge(1) := A10_precharge(2); + A10_precharge(2) := A10_precharge(3); + A10_precharge(3) := '0'; + + -- Operation Decode (Optional for showing current command on posedge clock / debug feature) + IF Active_enable = '1' THEN + Operation <= ACT; + ELSIF Aref_enable = '1' THEN + Operation <= A_REF; + ELSIF Burst_term = '1' THEN + Operation <= BST; + ELSIF Mode_reg_enable = '1' THEN + Operation <= LMR; + ELSIF Prech_enable = '1' THEN + Operation <= PRECH; + ELSIF Read_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= READ; + ELSE + Operation <= READ_A; + END IF; + ELSIF Write_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= WRITE; + ELSE + Operation <= WRITE_A; + END IF; + ELSE + Operation <= NOP; + END IF; + + -- Dqm pipeline for Read + Dqm_reg0 := Dqm_reg1; + Dqm_reg1 := TO_BITVECTOR(Dqm); + + -- Read or Write with Auto Precharge Counter + IF Auto_precharge (0) = '1' THEN + Count_precharge (0) := Count_precharge (0) + 1; + END IF; + IF Auto_precharge (1) = '1' THEN + Count_precharge (1) := Count_precharge (1) + 1; + END IF; + IF Auto_precharge (2) = '1' THEN + Count_precharge (2) := Count_precharge (2) + 1; + END IF; + IF Auto_precharge (3) = '1' THEN + Count_precharge (3) := Count_precharge (3) + 1; + END IF; + + -- Auto Precharge Timer for tWR + if (Burst_length_1 = '1' OR Write_burst_mode = '1') then + if (Count_precharge(0) = 1) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 1) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 1) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 1) then + Count_time(3) := NOW; + end if; + elsif (Burst_length_2 = '1') then + if (Count_precharge(0) = 2) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 2) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 2) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 2) then + Count_time(3) := NOW; + end if; + elsif (Burst_length_4 = '1') then + if (Count_precharge(0) = 4) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 4) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 4) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 4) then + Count_time(3) := NOW; + end if; + elsif (Burst_length_8 = '1') then + if (Count_precharge(0) = 8) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 8) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 8) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 8) then + Count_time(3) := NOW; + end if; + end if; + + -- tMRD Counter + MRD_chk := MRD_chk + 1; + + -- tWR Counter + WR_counter(0) := WR_counter(0) + 1; + WR_counter(1) := WR_counter(1) + 1; + WR_counter(2) := WR_counter(2) + 1; + WR_counter(3) := WR_counter(3) + 1; + + -- Auto Refresh + IF Aref_enable = '1' THEN + -- Auto Refresh to Auto Refresh + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Auto Refresh" + SEVERITY WARNING; + -- Precharge to Auto Refresh + ASSERT (NOW - RP_chk0 >= tRP OR NOW - RP_chk1 >= tRP OR NOW - RP_chk2 >= tRP OR NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Auto Refresh" + SEVERITY WARNING; + -- All banks must be idle before refresh + IF (Pc_b3 ='0' OR Pc_b2 = '0' OR Pc_b1 ='0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All banks must be Precharge before Auto Refresh" + SEVERITY WARNING; + END IF; + -- Record current tRC time + RC_chk := NOW; + END IF; + + -- Load Mode Register + IF Mode_reg_enable = '1' THEN + Mode_reg <= TO_BITVECTOR (Addr); + IF (Pc_b3 ='0' OR Pc_b2 = '0' OR Pc_b1 ='0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All bank must be Precharge before Load Mode Register" + SEVERITY WARNING; + END IF; + -- REF to LMR + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Load Mode Register" + SEVERITY WARNING; + -- LMR to LMR + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Load Mode Register" + SEVERITY WARNING; + -- Record current tMRD time + MRD_chk := 0; + END IF; + + -- Active Block (latch Bank and Row Address) + IF Active_enable = '1' THEN + IF Ba = "00" AND Pc_b0 = '1' THEN + Act_b0 := '1'; + Pc_b0 := '0'; + B0_row_addr := TO_BITVECTOR (Addr); + RCD_chk0 := NOW; + RAS_chk0 := NOW; + -- Precharge to Active Bank 0 + ASSERT (NOW - RP_chk0 >= tRP) + REPORT "tRP violation during Activate Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '1' THEN + Act_b1 := '1'; + Pc_b1 := '0'; + B1_row_addr := TO_BITVECTOR (Addr); + RCD_chk1 := NOW; + RAS_chk1 := NOW; + -- Precharge to Active Bank 1 + ASSERT (NOW - RP_chk1 >= tRP) + REPORT "tRP violation during Activate Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '1' THEN + Act_b2 := '1'; + Pc_b2 := '0'; + B2_row_addr := TO_BITVECTOR (Addr); + RCD_chk2 := NOW; + RAS_chk2 := NOW; + -- Precharge to Active Bank 2 + ASSERT (NOW - RP_chk2 >= tRP) + REPORT "tRP violation during Activate Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '1' THEN + Act_b3 := '1'; + Pc_b3 := '0'; + B3_row_addr := TO_BITVECTOR (Addr); + RCD_chk3 := NOW; + RAS_chk3 := NOW; + -- Precharge to Active Bank 3 + ASSERT (NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Activate Bank 3" + SEVERITY WARNING; + ELSIF Ba = "00" AND Pc_b0 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 0 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 1 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 2 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 3 is not Precharged" + SEVERITY WARNING; + END IF; + -- Active Bank A to Active Bank B + IF ((Previous_bank /= TO_BITVECTOR (Ba)) AND (NOW - RRD_chk < tRRD)) THEN + ASSERT (FALSE) + REPORT "tRRD violation during Activate" + SEVERITY WARNING; + END IF; + -- LMR to ACT + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Activate" + SEVERITY WARNING; + -- AutoRefresh to Activate + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Activate" + SEVERITY WARNING; + -- Record variable for checking violation + RRD_chk := NOW; + Previous_bank := TO_BITVECTOR (Ba); + END IF; + + -- Precharge Block + IF Prech_enable = '1' THEN + IF Addr(10) = '1' THEN + Pc_b0 := '1'; + Pc_b1 := '1'; + Pc_b2 := '1'; + Pc_b3 := '1'; + Act_b0 := '0'; + Act_b1 := '0'; + Act_b2 := '0'; + Act_b3 := '0'; + RP_chk0 := NOW; + RP_chk1 := NOW; + RP_chk2 := NOW; + RP_chk3 := NOW; + -- Activate to Precharge all banks + ASSERT ((NOW - RAS_chk0 >= tRAS) OR (NOW - RAS_chk1 >= tRAS)) + REPORT "tRAS violation during Precharge all banks" + SEVERITY WARNING; + -- tWR violation check for Write + IF ((NOW - WR_chkp(0) < tWRp) OR (NOW - WR_chkp(1) < tWRp) OR + (NOW - WR_chkp(2) < tWRp) OR (NOW - WR_chkp(3) < tWRp)) THEN + ASSERT (FALSE) + REPORT "tWR violation during Precharge ALL banks" + SEVERITY WARNING; + END IF; + ELSIF Addr(10) = '0' THEN + IF Ba = "00" THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + -- Activate to Precharge bank 0 + ASSERT (NOW - RAS_chk0 >= tRAS) + REPORT "tRAS violation during Precharge bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + -- Activate to Precharge bank 1 + ASSERT (NOW - RAS_chk1 >= tRAS) + REPORT "tRAS violation during Precharge bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + -- Activate to Precharge bank 2 + ASSERT (NOW - RAS_chk2 >= tRAS) + REPORT "tRAS violation during Precharge bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + -- Activate to Precharge bank 3 + ASSERT (NOW - RAS_chk3 >= tRAS) + REPORT "tRAS violation during Precharge bank 3" + SEVERITY WARNING; + END IF; + -- tWR violation check for Write + ASSERT (NOW - WR_chkp(TO_INTEGER(Ba)) >= tWRp) + REPORT "tWR violation during Precharge" + SEVERITY WARNING; + END IF; + -- Terminate a Write Immediately (if same bank or all banks) + IF (Data_in_enable = '1' AND (Bank = TO_BITVECTOR(Ba) OR Addr(10) = '1')) THEN + Data_in_enable := '0'; + END IF; + -- Precharge Command Pipeline for READ + IF CAS_latency_3 = '1' THEN + Command(2) := PRECH; + Bank_precharge(2) := TO_BITVECTOR (Ba); + A10_precharge(2) := TO_BIT(Addr(10)); + ELSIF CAS_latency_2 = '1' THEN + Command(1) := PRECH; + Bank_precharge(1) := TO_BITVECTOR (Ba); + A10_precharge(1) := TO_BIT(Addr(10)); + END IF; + END IF; + + -- Burst Terminate + IF Burst_term = '1' THEN + -- Terminate a Write immediately + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + -- Terminate a Read depend on CAS Latency + IF CAS_latency_3 = '1' THEN + Command(2) := BST; + ELSIF CAS_latency_2 = '1' THEN + Command(1) := BST; + END IF; + END IF; + + -- Read, Write, Column Latch + IF Read_enable = '1' OR Write_enable = '1' THEN + -- Check to see if bank is open (ACT) for Read or Write + IF ((Ba = "00" AND Pc_b0 = '1') OR (Ba = "01" AND Pc_b1 = '1') OR (Ba = "10" AND Pc_b2 = '1') OR (Ba = "11" AND Pc_b3 = '1')) THEN + ASSERT (FALSE) + REPORT "Cannot Read or Write - Bank is not Activated" + SEVERITY WARNING; + END IF; + -- Activate to Read or Write + IF Ba = "00" THEN + ASSERT (NOW - RCD_chk0 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + ASSERT (NOW - RCD_chk1 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + ASSERT (NOW - RCD_chk2 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + ASSERT (NOW - RCD_chk3 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 3" + SEVERITY WARNING; + END IF; + + -- Read Command + IF Read_enable = '1' THEN + -- CAS Latency Pipeline + IF Cas_latency_3 = '1' THEN + IF Addr(10) = '1' THEN + Command(2) := READ_A; + ELSE + Command(2) := READ; + END IF; + Col_addr (2) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0)); + Bank_addr (2) := TO_BITVECTOR (Ba); + ELSIF Cas_latency_2 = '1' THEN + IF Addr(10) = '1' THEN + Command(1) := READ_A; + ELSE + Command(1) := READ; + END IF; + Col_addr (1) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0)); + Bank_addr (1) := TO_BITVECTOR (Ba); + END IF; + + -- Read intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Write Command + ELSIF Write_enable = '1' THEN + IF Addr(10) = '1' THEN + Command(0) := WRITE_A; + ELSE + Command(0) := WRITE; + END IF; + Col_addr (0) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0)); + Bank_addr (0) := TO_BITVECTOR (Ba); + + -- Write intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Write interrupt a Read (terminate Read immediately) + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + + -- Interrupt a Write with Auto Precharge + IF Auto_precharge(TO_INTEGER(RW_interrupt_bank)) = '1' AND Write_precharge(TO_INTEGER(RW_interrupt_bank)) = '1' THEN + RW_interrupt_write(TO_INTEGER(RW_interrupt_bank)) := '1'; + END IF; + + -- Interrupt a Read with Auto Precharge + IF Auto_precharge(TO_INTEGER(RW_interrupt_bank)) = '1' AND Read_precharge(TO_INTEGER(RW_interrupt_bank)) = '1' THEN + RW_interrupt_read(TO_INTEGER(RW_interrupt_bank)) := '1'; + END IF; + + -- Read or Write with Auto Precharge + IF Addr(10) = '1' THEN + Auto_precharge (TO_INTEGER(Ba)) := '1'; + Count_precharge (TO_INTEGER(Ba)) := 0; + RW_interrupt_bank := TO_BITVECTOR (Ba); + IF Read_enable = '1' THEN + Read_precharge (TO_INTEGER(Ba)) := '1'; + ELSIF Write_enable = '1' THEN + Write_precharge (TO_INTEGER(Ba)) := '1'; + END IF; + END IF; + END IF; + + -- Read with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. BL/2 cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Read_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(0) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8))) OR + (RW_interrupt_read(0) = '1')) THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + Auto_precharge(0) := '0'; + Read_precharge(0) := '0'; + RW_interrupt_read(0) := '0'; + END IF; + END IF; + IF ((Auto_precharge(1) = '1') AND (Read_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(1) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8))) OR + (RW_interrupt_read(1) = '1')) THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + Auto_precharge(1) := '0'; + Read_precharge(1) := '0'; + RW_interrupt_read(1) := '0'; + END IF; + END IF; + IF ((Auto_precharge(2) = '1') AND (Read_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(2) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8))) OR + (RW_interrupt_read(2) = '1')) THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + Auto_precharge(2) := '0'; + Read_precharge(2) := '0'; + RW_interrupt_read(2) := '0'; + END IF; + END IF; + IF ((Auto_precharge(3) = '1') AND (Read_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(3) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8))) OR + (RW_interrupt_read(3) = '1')) THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + Auto_precharge(3) := '0'; + Read_precharge(3) := '0'; + RW_interrupt_read(3) := '0'; + END IF; + END IF; + + -- Internal Precharge or Bst + IF Command(0) = PRECH THEN -- PRECH terminate a read if same bank or all banks + IF Bank_precharge(0) = Bank OR A10_precharge(0) = '1' THEN + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Command(0) = BST THEN -- BST terminate a read regardless of bank + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + + IF Data_out_enable = '0' THEN + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tOH; + END IF; + + -- Detect Read or Write Command + IF Command(0) = READ OR Command(0) = READ_A THEN + Bank := Bank_addr (0); + Col := Col_addr (0); + Col_brst := Col_addr (0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '0'; + Data_out_enable := '1'; + ELSIF Command(0) = WRITE OR Command(0) = WRITE_A THEN + Bank := Bank_addr(0); + Col := Col_addr(0); + Col_brst := Col_addr(0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '1'; + Data_out_enable := '0'; + END IF; + + -- DQ (Driver / Receiver) + Row_index := TO_INTEGER (Row); + Col_index := TO_INTEGER (Col); + IF Data_in_enable = '1' THEN + IF Dqm /= "11" THEN + Init_mem (Bank, Row_index); + IF Bank = "00" THEN + Dq_temp := Bank0 (Row_index) (Col_index); + IF Dqm = "01" THEN + Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8)); + ELSIF Dqm = "10" THEN + Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0)); + ELSE + Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0)); + END IF; + Bank0 (Row_index) (Col_index) := Dq_temp; + ELSIF Bank = "01" THEN + Dq_temp := Bank1 (Row_index) (Col_index); + IF Dqm = "01" THEN + Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8)); + ELSIF Dqm = "10" THEN + Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0)); + ELSE + Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0)); + END IF; + Bank1 (Row_index) (Col_index) := Dq_temp; + ELSIF Bank = "10" THEN + Dq_temp := Bank2 (Row_index) (Col_index); + IF Dqm = "01" THEN + Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8)); + ELSIF Dqm = "10" THEN + Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0)); + ELSE + Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0)); + END IF; + Bank2 (Row_index) (Col_index) := Dq_temp; + ELSIF Bank = "11" THEN + Dq_temp := Bank3 (Row_index) (Col_index); + IF Dqm = "01" THEN + Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8)); + ELSIF Dqm = "10" THEN + Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0)); + ELSE + Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0)); + END IF; + Bank3 (Row_index) (Col_index) := Dq_temp; + END IF; + WR_chkp(TO_INTEGER(Bank)) := NOW; + WR_counter(TO_INTEGER(Bank)) := 0; + END IF; + Burst_decode; + ELSIF Data_out_enable = '1' THEN + IF Dqm_reg0 /= "11" THEN + Init_mem (Bank, Row_index); + IF Bank = "00" THEN + Dq_temp (15 DOWNTO 0) := Bank0 (Row_index) (Col_index); + IF Dqm_reg0 = "00" THEN + Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC; + ELSIF Dqm_reg0 = "01" THEN + Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + ELSIF Dqm_reg0 = "10" THEN + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC; + END IF; + ELSIF Bank = "01" THEN + Dq_temp (15 DOWNTO 0) := Bank1 (Row_index) (Col_index); + IF Dqm_reg0 = "00" THEN + Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC; + ELSIF Dqm_reg0 = "01" THEN + Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + ELSIF Dqm_reg0 = "10" THEN + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC; + END IF; + ELSIF Bank = "10" THEN + Dq_temp (15 DOWNTO 0) := Bank2 (Row_index) (Col_index); + IF Dqm_reg0 = "00" THEN + Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC; + ELSIF Dqm_reg0 = "01" THEN + Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + ELSIF Dqm_reg0 = "10" THEN + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC; + END IF; + ELSIF Bank = "11" THEN + Dq_temp (15 DOWNTO 0) := Bank3 (Row_index) (Col_index); + IF Dqm_reg0 = "00" THEN + Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC; + ELSIF Dqm_reg0 = "01" THEN + Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + ELSIF Dqm_reg0 = "10" THEN + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC; + END IF; + END IF; + ELSE + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tHZ; + END IF; + Burst_decode; + END IF; + + ELSIF Sys_clk'event and Sys_clk = '1' AND Load = '1' AND Unload = '0' THEN + Operation <= FILE_LOAD; + WHILE NOT ENDFILE (load_file) LOOP + READLINE (load_file, l_in); + IF l_in'LENGTH > 0 THEN + read (l_in, row_load, 16); -- Load from HEX to INTEGER + read (l_in, col_load, 16); -- Load from HEX to INTEGER + read (l_in, ba_load); + read (l_in, dq_load, 16); -- Load from HEX to INTEGER + + TO_BITVECTOR (dq_load, dq_vec); + + IF ba_load = "00" THEN + IF Bank0(row_load) = NULL THEN --initialize new memory block + Bank0(row_load) := new ram_type; + FOR i IN (2**(col_bits))-1 DOWNTO 0 LOOP + FOR k IN data_bits - 1 DOWNTO 0 LOOP + Bank0(row_load) (i) (k) := '0'; + END LOOP; + END LOOP; + END IF; + Bank0(row_load)(col_load) := dq_vec; + ELSIF ba_load = "01" THEN + IF Bank1(row_load) = NULL THEN --initialize new memory block + Bank1(row_load) := new ram_type; + FOR i IN (2**(col_bits))-1 DOWNTO 0 LOOP + FOR k IN data_bits - 1 DOWNTO 0 LOOP + Bank1(row_load) (i) (k) := '0'; + END LOOP; + END LOOP; + END IF; + Bank1(row_load)(col_load) := dq_vec; + ELSIF ba_load = "10" THEN + IF Bank2(row_load) = NULL THEN --initialize new memory block + Bank2(row_load) := new ram_type; + FOR i IN (2**(col_bits))-1 DOWNTO 0 LOOP + FOR k IN data_bits - 1 DOWNTO 0 LOOP + Bank2(row_load) (i) (k) := '0'; + END LOOP; + END LOOP; + END IF; + Bank2(row_load)(col_load) := dq_vec; + ELSIF ba_load = "11" THEN + IF Bank3(row_load) = NULL THEN --initialize new memory block + Bank3(row_load) := new ram_type; + FOR i IN (2**(col_bits))-1 DOWNTO 0 LOOP + FOR k IN data_bits - 1 DOWNTO 0 LOOP + Bank3(row_load) (i) (k) := '0'; + END LOOP; + END LOOP; + END IF; + Bank3(row_load)(col_load) := dq_vec; + END IF; + END IF; + END LOOP; + ELSIF Sys_clk'event and Sys_clk = '1' AND Load = '0' AND Unload = '1' THEN + Operation <= FILE_UNLOAD; + ASSERT (Row_start < 2**(Addr'HIGH + 1)) + REPORT "Row_start is out of range for device" + SEVERITY ERROR; + ASSERT (Row_end < 2**(Addr'HIGH + 1)) + REPORT "Row_end is out of range for device" + SEVERITY ERROR; + ASSERT ((Row_end - Row_start) >= 0) + REPORT "The Row ranges for Unload is invalid!" + SEVERITY ERROR; + IF ((Row_end - Row_start) >= 0) THEN + FOR i IN Row_start TO Row_end LOOP + j := 1; + IF (Ba = "00") THEN -- Unload Bank 0 + WRITE (l_out0, STRING'("Micron Technology Inc. - Unload Data Array - Bank 0 Row ")); + WRITE (l_out0, i, RIGHT, 3, HEX, FALSE); + WRITELINE (out_file0, l_out0); + FOR k IN 0 TO ((2**Col_bits) - 1) LOOP -- Display Row and Column + IF (j = 1) THEN + WRITE (l_out0, i, RIGHT, 3, HEX, FALSE); + WRITE (l_out0, STRING'(" : ")); + WRITE (l_out0, k, RIGHT, 3, HEX, FALSE); + WRITE (l_out0, STRING'(" : ")); + END IF; + + IF (Bank0 (i) = NULL) THEN -- Row is empty, write message and exit + WRITE (l_out0, STRING'(" Row ")); + WRITE (l_out0, i); + WRITE (l_out0, STRING'(" is empty.")); + WRITELINE (out_file0, l_out0); + EXIT; + ELSE -- Buffering + array_buffer := Bank0 (i) (k); + END IF; + + write_data_var := TO_STDLOGICVECTOR(array_buffer); -- Convert to STD_LOGIC_VECTOR + WRITE (l_out0, write_data_var, RIGHT, 6, HEX, FALSE); -- Write message + IF (j = 16) then + WRITELINE (out_file0, l_out0); + j := 1; + ELSE + j := j + 1; + END IF; + END LOOP; + ELSIF (Ba = "01") THEN + WRITE (l_out1, STRING'("Micron Technology Inc. - Unload Data Array - Bank 1 Row ")); + WRITE (l_out1, i, RIGHT, 3, HEX, FALSE); + WRITELINE (out_file1, l_out1); + FOR k IN 0 TO ((2**Col_bits) - 1) LOOP + IF (j = 1) THEN + WRITE (l_out1, i, RIGHT, 3, HEX, FALSE); + WRITE (l_out1, STRING'(" : ")); + WRITE (l_out1, k, RIGHT, 3, HEX, FALSE); + WRITE (l_out1, STRING'(" : ")); + END IF; + + IF (Bank1 (i) = NULL) THEN + WRITE (l_out1, STRING'(" Row ")); + WRITE (l_out1, i); + WRITE (l_out1, STRING'(" is empty.")); + WRITELINE (out_file1, l_out1); + EXIT; + ELSE + array_buffer := Bank1 (i) (k); + END IF; + + write_data_var := TO_STDLOGICVECTOR(array_buffer); + WRITE (l_out1, write_data_var, RIGHT, 6, HEX, FALSE); + IF (j = 16) then + WRITELINE (out_file1, l_out1); + j := 1; + ELSE + j := j + 1; + END IF; + END LOOP; + ELSIF (Ba = "10") THEN + WRITE (l_out2, STRING'("Micron Technology Inc. - Unload Data Array - Bank 2 Row ")); + WRITE (l_out2, i, RIGHT, 3, HEX, FALSE); + WRITELINE (out_file2, l_out2); + FOR k IN 0 TO ((2**Col_bits) - 1) LOOP + IF (j = 1) THEN + WRITE (l_out2, i, RIGHT, 3, HEX, FALSE); + WRITE (l_out2, STRING'(" : ")); + WRITE (l_out2, k, RIGHT, 3, HEX, FALSE); + WRITE (l_out2, STRING'(" : ")); + END IF; + + IF (Bank2 (i) = NULL) THEN + WRITE (l_out2, STRING'(" Row ")); + WRITE (l_out2, i); + WRITE (l_out2, STRING'(" is empty.")); + WRITELINE (out_file2, l_out2); + EXIT; + ELSE + array_buffer := Bank2 (i) (k); + END IF; + + write_data_var := TO_STDLOGICVECTOR(array_buffer); + WRITE (l_out2, write_data_var, RIGHT, 6, HEX, FALSE); + IF (j = 16) then + WRITELINE (out_file2, l_out2); + j := 1; + ELSE + j := j + 1; + END IF; + END LOOP; + ELSIF (Ba = "11") THEN + WRITE (l_out3, STRING'("Micron Technology Inc. - Unload Data Array - Bank 3 Row ")); + WRITE (l_out3, i, RIGHT, 3, HEX, FALSE); + WRITELINE (out_file3, l_out3); + FOR k IN 0 TO ((2**Col_bits) - 1) LOOP + IF (j = 1) THEN + WRITE (l_out3, i, RIGHT, 3, HEX, FALSE); + WRITE (l_out3, STRING'(" : ")); + WRITE (l_out3, k, RIGHT, 3, HEX, FALSE); + WRITE (l_out3, STRING'(" : ")); + END IF; + + IF (Bank3 (i) = NULL) THEN + WRITE (l_out3, STRING'(" Row ")); + WRITE (l_out3, i); + WRITE (l_out3, STRING'(" is empty.")); + WRITELINE (out_file3, l_out3); + EXIT; + ELSE + array_buffer := Bank3 (i) (k); + END IF; + + write_data_var := TO_STDLOGICVECTOR(array_buffer); + WRITE (l_out3, write_data_var, RIGHT, 6, HEX, FALSE); + IF (j = 16) then + WRITELINE (out_file3, l_out3); + j := 1; + ELSE + j := j + 1; + END IF; + END LOOP; + END IF; + END LOOP; + END IF; + + END IF; + + -- Write with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. tWR cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Write_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(0) >= 1 AND NOW - Count_time(0) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2 AND NOW - Count_time(0) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4 AND NOW - Count_time(0) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8 AND NOW - Count_time(0) >= tWRa))) OR + (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 1 AND NOW - WR_time(0) >= tWRa)) THEN + Auto_precharge(0) := '0'; + Write_precharge(0) := '0'; + RW_interrupt_write(0) := '0'; + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + ASSERT FALSE REPORT "Start Internal Precharge Bank 0" SEVERITY NOTE; + END IF; + END IF; + IF ((Auto_precharge(1) = '1') AND (Write_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(1) >= 1 AND NOW - Count_time(1) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2 AND NOW - Count_time(1) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4 AND NOW - Count_time(1) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8 AND NOW - Count_time(1) >= tWRa))) OR + (RW_interrupt_write(1) = '1' AND WR_counter(1) >= 1 AND NOW - WR_time(1) >= tWRa)) THEN + Auto_precharge(1) := '0'; + Write_precharge(1) := '0'; + RW_interrupt_write(1) := '0'; + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + END IF; + END IF; + IF ((Auto_precharge(2) = '1') AND (Write_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(2) >= 1 AND NOW - Count_time(2) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2 AND NOW - Count_time(2) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4 AND NOW - Count_time(2) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8 AND NOW - Count_time(2) >= tWRa))) OR + (RW_interrupt_write(2) = '1' AND WR_counter(2) >= 1 AND NOW - WR_time(2) >= tWRa)) THEN + Auto_precharge(2) := '0'; + Write_precharge(2) := '0'; + RW_interrupt_write(2) := '0'; + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + END IF; + END IF; + IF ((Auto_precharge(3) = '1') AND (Write_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(3) >= 1 AND NOW - Count_time(3) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2 AND NOW - Count_time(3) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4 AND NOW - Count_time(3) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8 AND NOW - Count_time(3) >= tWRa))) OR + (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 1 AND NOW - WR_time(3) >= tWRa)) THEN + Auto_precharge(3) := '0'; + Write_precharge(3) := '0'; + RW_interrupt_write(3) := '0'; + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + END IF; + END IF; + + -- Checking internal wires (Optional for debug purpose) + Pre_chk (0) <= Pc_b0; + Pre_chk (1) <= Pc_b1; + Pre_chk (2) <= Pc_b2; + Pre_chk (3) <= Pc_b3; + Act_chk (0) <= Act_b0; + Act_chk (1) <= Act_b1; + Act_chk (2) <= Act_b2; + Act_chk (3) <= Act_b3; + Dq_in_chk <= Data_in_enable; + Dq_out_chk <= Data_out_enable; + Bank_chk <= Bank; + Row_chk <= Row; + Col_chk <= Col; + END PROCESS; + + + -- Clock timing checks + Clock_check : PROCESS + VARIABLE Clk_low, Clk_high : TIME := 0 ns; + BEGIN + WAIT ON Clk; + IF (Clk = '1' AND NOW >= 10 ns) THEN + ASSERT (NOW - Clk_low >= tCL) + REPORT "tCL violation" + SEVERITY WARNING; + ASSERT (NOW - Clk_high >= tCK) + REPORT "tCK violation" + SEVERITY WARNING; + Clk_high := NOW; + ELSIF (Clk = '0' AND NOW /= 0 ns) THEN + ASSERT (NOW - Clk_high >= tCH) + REPORT "tCH violation" + SEVERITY WARNING; + Clk_low := NOW; + END IF; + END PROCESS; + + -- Setup timing checks + Setup_check : PROCESS + BEGIN + WAIT ON Clk; + IF Clk = '1' THEN + ASSERT(Cke'LAST_EVENT >= tCKS) + REPORT "CKE Setup time violation -- tCKS" + SEVERITY WARNING; + ASSERT(Cs_n'LAST_EVENT >= tCMS) + REPORT "CS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT >= tCMS) + REPORT "CAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT >= tCMS) + REPORT "RAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT >= tCMS) + REPORT "WE# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT >= tCMS) + REPORT "Dqm Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Addr'LAST_EVENT >= tAS) + REPORT "ADDR Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT >= tAS) + REPORT "BA Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Dq'LAST_EVENT >= tDS) + REPORT "Dq Setup time violation -- tDS" + SEVERITY WARNING; + END IF; + END PROCESS; + + -- Hold timing checks + Hold_check : PROCESS + BEGIN + WAIT ON Clk'DELAYED (tCKH), Clk'DELAYED (tCMH), Clk'DELAYED (tAH), Clk'DELAYED (tDH); + IF Clk'DELAYED (tCKH) = '1' THEN + ASSERT(Cke'LAST_EVENT > tCKH) + REPORT "CKE Hold time violation -- tCKH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tCMH) = '1' THEN + ASSERT(Cs_n'LAST_EVENT > tCMH) + REPORT "CS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT > tCMH) + REPORT "CAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT > tCMH) + REPORT "RAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT > tCMH) + REPORT "WE# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT > tCMH) + REPORT "Dqm Hold time violation -- tCMH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tAH) = '1' THEN + ASSERT(Addr'LAST_EVENT > tAH) + REPORT "ADDR Hold time violation -- tAH" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT > tAH) + REPORT "BA Hold time violation -- tAH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tDH) = '1' THEN + ASSERT(Dq'LAST_EVENT > tDH) + REPORT "Dq Hold time violation -- tDH" + SEVERITY WARNING; + END IF; + END PROCESS; + +END behave; diff --git a/lib/models/memory/sdram/mt48lc8m16a2/mti_pkg.vhd b/lib/models/memory/sdram/mt48lc8m16a2/mti_pkg.vhd new file mode 100644 index 0000000..9e4f824 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m16a2/mti_pkg.vhd @@ -0,0 +1,129 @@ +--***************************************************************************** +-- +-- Micron Semiconductor Products, Inc. +-- +-- Copyright 1997, Micron Semiconductor Products, Inc. +-- All rights reserved. +-- +--***************************************************************************** + +LIBRARY work; +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +PACKAGE mti_pkg IS + + FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER; + FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER; + FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER; + PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR); + +END mti_pkg; + +PACKAGE BODY mti_pkg IS + + -- Convert BIT to INTEGER + FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + IF input = '1' THEN + result := weight; + ELSE + result := 0; -- if unknowns, default to logic 0 + END IF; + RETURN result; + END TO_INTEGER; + + -- Convert BIT_VECTOR to INTEGER + FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + FOR i IN input'LOW TO input'HIGH LOOP + IF input(i) = '1' THEN + result := result + weight; + ELSE + result := result + 0; -- if unknowns, default to logic 0 + END IF; + weight := weight * 2; + END LOOP; + RETURN result; + END TO_INTEGER; + + -- Convert STD_LOGIC_VECTOR to INTEGER + FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + FOR i IN input'LOW TO input'HIGH LOOP + IF input(i) = '1' THEN + result := result + weight; + ELSE + result := result + 0; -- if unknowns, default to logic 0 + END IF; + weight := weight * 2; + END LOOP; + RETURN result; + END TO_INTEGER; + + -- Conver integer to bit_vector + PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR) IS + VARIABLE work,offset,outputlen,j : INTEGER := 0; + BEGIN + --length of vector + IF output'LENGTH > 32 THEN + outputlen := 32; + offset := output'LENGTH - 32; + IF input >= 0 THEN + FOR i IN offset-1 DOWNTO 0 LOOP + output(output'HIGH - i) := '0'; + END LOOP; + ELSE + FOR i IN offset-1 DOWNTO 0 LOOP + output(output'HIGH - i) := '1'; + END LOOP; + END IF; + ELSE + outputlen := output'LENGTH; + END IF; + --positive value + IF (input >= 0) THEN + work := input; + j := outputlen - 1; + FOR i IN 1 to 32 LOOP + IF j >= 0 then + IF (work MOD 2) = 0 THEN + output(output'HIGH-j-offset) := '0'; + ELSE + output(output'HIGH-j-offset) := '1'; + END IF; + END IF; + work := work / 2; + j := j - 1; + END LOOP; + IF outputlen = 32 THEN + output(output'HIGH) := '0'; + END IF; + --negative value + ELSE + work := (-input) - 1; + j := outputlen - 1; + FOR i IN 1 TO 32 LOOP + IF j>= 0 THEN + IF (work MOD 2) = 0 THEN + output(output'HIGH-j-offset) := '1'; + ELSE + output(output'HIGH-j-offset) := '0'; + END IF; + END IF; + work := work / 2; + j := j - 1; + END LOOP; + IF outputlen = 32 THEN + output(output'HIGH) := '1'; + END IF; + END IF; + END TO_BITVECTOR; + +END mti_pkg; diff --git a/lib/models/memory/sdram/mt48lc8m16a2/outdata0.txt b/lib/models/memory/sdram/mt48lc8m16a2/outdata0.txt new file mode 100644 index 0000000..0e12acc --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m16a2/outdata0.txt @@ -0,0 +1,33 @@ +Micron Technology Inc. - Unload Data Array - Bank 0 Row 0 + 0 : 0 : 0064 0065 0066 0067 0068 0069 006A 006B 0074 0075 006E 006F 0070 0071 0072 0073 + 0 : 10 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 20 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 30 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 40 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 50 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 60 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 70 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 80 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 90 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : A0 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : B0 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : C0 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : D0 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : E0 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : F0 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 100 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 110 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 120 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 130 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 140 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 150 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 160 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 170 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 180 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 190 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 1A0 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 1B0 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 1C0 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 1D0 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 1E0 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 + 0 : 1F0 : 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 diff --git a/lib/models/memory/sdram/mt48lc8m16a2/outdata1.txt b/lib/models/memory/sdram/mt48lc8m16a2/outdata1.txt new file mode 100644 index 0000000..e69de29 diff --git a/lib/models/memory/sdram/mt48lc8m16a2/outdata2.txt b/lib/models/memory/sdram/mt48lc8m16a2/outdata2.txt new file mode 100644 index 0000000..e69de29 diff --git a/lib/models/memory/sdram/mt48lc8m16a2/outdata3.txt b/lib/models/memory/sdram/mt48lc8m16a2/outdata3.txt new file mode 100644 index 0000000..e69de29 diff --git a/lib/models/memory/sdram/mt48lc8m16a2/readme.txt b/lib/models/memory/sdram/mt48lc8m16a2/readme.txt new file mode 100644 index 0000000..9804585 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m16a2/readme.txt @@ -0,0 +1,14 @@ +To operate the test bench for the Micron SDRAM VHDL model, follow the directions +given below: + +1. Be sure all supporting files for the SDRAM are compiled into your library: + + util1164.vhd + stdlogar.vhd + io_utils.vhd + mti_pkg.vhd + +2. Next, compile the mt48lc8m16a2.vhd file and the test.vhd file. + +3. Simulate the "tb" architecture. This is the testbench for the 128Mb SDRAM. + diff --git a/lib/models/memory/sdram/mt48lc8m16a2/runall.do b/lib/models/memory/sdram/mt48lc8m16a2/runall.do new file mode 100644 index 0000000..36da31c --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m16a2/runall.do @@ -0,0 +1,49 @@ +# Compile base libraries +vcom util1164.vhd +vcom stdlogar.vhd +vcom io_utils.vhd +vcom mti_pkg.vhd +# Compile test vectors +vcom vec_gen.vhd +vcom ed_comnd.vhd +vsim vector_generate +run -all +# Compile Micron SDRAM model and testbench +vcom mt48lc8m16a2.vhd +vcom test.vhd +vsim -t ps tb +# Add waveform +add wave -logic /tb/u1/clk +add wave -logic /tb/u1/cke +add wave -logic /tb/u1/cs_n +add wave -logic /tb/u1/ras_n +add wave -logic /tb/u1/cas_n +add wave -logic /tb/u1/we_n +add wave -literal -decimal /tb/u1/addr +add wave -literal -unsigned /tb/u1/ba +add wave -literal -decimal /tb/u1/dq +add wave -literal /tb/u1/dqm +add wave -literal /tb/u1/operation +add wave -literal -decimal /tb/u1/mode_reg +add wave -logic /tb/u1/active_enable +add wave -logic /tb/u1/aref_enable +add wave -logic /tb/u1/burst_term +add wave -logic /tb/u1/mode_reg_enable +add wave -logic /tb/u1/prech_enable +add wave -logic /tb/u1/read_enable +add wave -logic /tb/u1/write_enable +add wave -logic /tb/u1/burst_length_1 +add wave -logic /tb/u1/burst_length_2 +add wave -logic /tb/u1/burst_length_4 +add wave -logic /tb/u1/burst_length_8 +add wave -logic /tb/u1/cas_latency_2 +add wave -logic /tb/u1/cas_latency_3 +add wave -literal /tb/u1/pre_chk +add wave -literal /tb/u1/act_chk +add wave -literal /tb/u1/bank_chk +add wave -literal -decimal /tb/u1/row_chk +add wave -literal -decimal /tb/u1/col_chk +add wave -logic /tb/u1/dq_in_chk +add wave -logic /tb/u1/dq_out_chk +# run all test vectors +run -all diff --git a/lib/models/memory/sdram/mt48lc8m16a2/stdlogar.vhd b/lib/models/memory/sdram/mt48lc8m16a2/stdlogar.vhd new file mode 100644 index 0000000..e435ea2 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m16a2/stdlogar.vhd @@ -0,0 +1,2247 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990,1991,1992 by Synopsys, Inc. All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_ARITH -- +-- -- +-- Purpose: -- +-- A set of arithemtic, conversion, and comparison functions -- +-- for SIGNED, UNSIGNED, SMALL_INT, INTEGER, -- +-- STD_ULOGIC, STD_LOGIC, and STD_LOGIC_VECTOR. -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +package std_logic_arith is + + type UNSIGNED is array (NATURAL range <>) of STD_LOGIC; + type SIGNED is array (NATURAL range <>) of STD_LOGIC; + subtype SMALL_INT is INTEGER range 0 to 1; + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: INTEGER) return SIGNED; + function "+"(L: INTEGER; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: INTEGER) return SIGNED; + function "-"(L: INTEGER; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "+"(L: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED) return SIGNED; + function "-"(L: SIGNED) return SIGNED; + function "ABS"(L: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED) return STD_LOGIC_VECTOR; + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "*"(L: SIGNED; R: SIGNED) return SIGNED; + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + + function CONV_INTEGER(ARG: INTEGER) return INTEGER; + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER; + function CONV_INTEGER(ARG: SIGNED) return INTEGER; + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT; + + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED; + + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED; + + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + -- zero extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- returns STD_LOGIC_VECTOR(SIZE-1 downto 0) + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + + -- sign extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- return STD_LOGIC_VECTOR(SIZE-1 downto 0) + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end Std_logic_arith; + + + +library IEEE; +use IEEE.std_logic_1164.all; + +package body std_logic_arith is + + function max(L, R: INTEGER) return INTEGER is + begin + if L > R then + return L; + else + return R; + end if; + end; + + + function min(L, R: INTEGER) return INTEGER is + begin + if L < R then + return L; + else + return R; + end if; + end; + + -- synopsys synthesis_off + type tbl_type is array (STD_ULOGIC) of STD_ULOGIC; + constant tbl_BINARY : tbl_type := + ('X', 'X', '0', '1', 'X', 'X', '0', '1', 'X'); + -- synopsys synthesis_on + + -- synopsys synthesis_off + type tbl_mvl9_boolean is array (STD_ULOGIC) of boolean; + constant IS_X : tbl_mvl9_boolean := + (true, true, false, false, true, true, false, false, true); + -- synopsys synthesis_on + + + + function MAKE_BINARY(A : STD_ULOGIC) return STD_ULOGIC is + -- synopsys built_in SYN_FEED_THRU + begin + -- synopsys synthesis_off + if (IS_X(A)) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + return ('X'); + end if; + return tbl_BINARY(A); + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return UNSIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : UNSIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return SIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : SIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return UNSIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : UNSIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return SIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : SIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + + + -- Type propagation function which returns a signed type with the + -- size of the left arg. + function LEFT_SIGNED_ARG(A,B: SIGNED) return SIGNED is + variable Z: SIGNED (A'left downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns an unsigned type with the + -- size of the left arg. + function LEFT_UNSIGNED_ARG(A,B: UNSIGNED) return UNSIGNED is + variable Z: UNSIGNED (A'left downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns a signed type with the + -- size of the result of a signed multiplication + function MULT_SIGNED_ARG(A,B: SIGNED) return SIGNED is + variable Z: SIGNED ((A'length+B'length-1) downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns an unsigned type with the + -- size of the result of a unsigned multiplication + function MULT_UNSIGNED_ARG(A,B: UNSIGNED) return UNSIGNED is + variable Z: UNSIGNED ((A'length+B'length-1) downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + + + function mult(A,B: SIGNED) return SIGNED is + + variable BA: SIGNED((A'length+B'length-1) downto 0); + variable PA: SIGNED((A'length+B'length-1) downto 0); + variable AA: SIGNED(A'length downto 0); + variable neg: STD_ULOGIC; + constant one : UNSIGNED(1 downto 0) := "01"; + + -- pragma map_to_operator MULT_TC_OP + -- pragma type_function MULT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + PA := (others => 'X'); + return(PA); + end if; + PA := (others => '0'); + neg := B(B'left) xor A(A'left); + BA := CONV_SIGNED(('0' & ABS(B)),(A'length+B'length)); + AA := '0' & ABS(A); + for i in 0 to A'length-1 loop + if AA(i) = '1' then + PA := PA+BA; + end if; + BA := SHL(BA,one); + end loop; + if (neg= '1') then + return(-PA); + else + return(PA); + end if; + end; + + function mult(A,B: UNSIGNED) return UNSIGNED is + + variable BA: UNSIGNED((A'length+B'length-1) downto 0); + variable PA: UNSIGNED((A'length+B'length-1) downto 0); + constant one : UNSIGNED(1 downto 0) := "01"; + + -- pragma map_to_operator MULT_UNS_OP + -- pragma type_function MULT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + PA := (others => 'X'); + return(PA); + end if; + PA := (others => '0'); + BA := CONV_UNSIGNED(B,(A'length+B'length)); + for i in 0 to A'length-1 loop + if A(i) = '1' then + PA := PA+BA; + end if; + BA := SHL(BA,one); + end loop; + return(PA); + end; + + -- subtract two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function minus(A, B: SIGNED) return SIGNED is + variable carry: STD_ULOGIC; + variable BV: STD_ULOGIC_VECTOR (A'left downto 0); + variable sum: SIGNED (A'left downto 0); + + -- pragma map_to_operator SUB_TC_OP + + -- pragma type_function LEFT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '1'; + BV := not STD_ULOGIC_VECTOR(B); + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + -- add two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function plus(A, B: SIGNED) return SIGNED is + variable carry: STD_ULOGIC; + variable BV, sum: SIGNED (A'left downto 0); + + -- pragma map_to_operator ADD_TC_OP + -- pragma type_function LEFT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '0'; + BV := B; + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + + -- subtract two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_minus(A, B: UNSIGNED) return UNSIGNED is + variable carry: STD_ULOGIC; + variable BV: STD_ULOGIC_VECTOR (A'left downto 0); + variable sum: UNSIGNED (A'left downto 0); + + -- pragma map_to_operator SUB_UNS_OP + -- pragma type_function LEFT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '1'; + BV := not STD_ULOGIC_VECTOR(B); + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + -- add two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_plus(A, B: UNSIGNED) return UNSIGNED is + variable carry: STD_ULOGIC; + variable BV, sum: UNSIGNED (A'left downto 0); + + -- pragma map_to_operator ADD_UNS_OP + -- pragma type_function LEFT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '0'; + BV := B; + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + + + function "*"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to mult + begin + return mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to mult + begin + return mult(CONV_UNSIGNED(L, L'length), + CONV_UNSIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + begin + return mult(CONV_SIGNED(L, L'length+1), + CONV_SIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to plus + begin + return mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length+1)); -- pragma label mult + end; + + + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + begin + return STD_LOGIC_VECTOR (mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length))); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + begin + return STD_LOGIC_VECTOR (mult(CONV_UNSIGNED(L, L'length), + CONV_UNSIGNED(R, R'length))); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + begin + return STD_LOGIC_VECTOR (mult(CONV_SIGNED(L, L'length+1), + CONV_SIGNED(R, R'length))); -- pragma label mult + end; + + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + begin + return STD_LOGIC_VECTOR (mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length+1))); -- pragma label mult + end; + + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "+"(L: SIGNED; R: INTEGER) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: INTEGER; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)) ; -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))) ; -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_minus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: SIGNED; R: INTEGER) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: INTEGER; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (unsigned_minus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + + + function "+"(L: UNSIGNED) return UNSIGNED is + begin + return L; + end; + + + function "+"(L: SIGNED) return SIGNED is + begin + return L; + end; + + + function "-"(L: SIGNED) return SIGNED is + -- pragma label_applies_to minus + begin + return 0 - L; -- pragma label minus + end; + + + function "ABS"(L: SIGNED) return SIGNED is + begin + if (L(L'left) = '0' or L(L'left) = 'L') then + return L; + else + return 0 - L; + end if; + end; + + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L); + end; + + + function "+"(L: SIGNED) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L); + end; + + + function "-"(L: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable tmp: SIGNED(L'length-1 downto 0); + begin + tmp := 0 - L; -- pragma label minus + return STD_LOGIC_VECTOR (tmp); + end; + + + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR is + variable tmp: SIGNED(L'length-1 downto 0); + begin + if (L(L'left) = '0' or L(L'left) = 'L') then + return STD_LOGIC_VECTOR (L); + else + tmp := 0 - L; + return STD_LOGIC_VECTOR (tmp); + end if; + end; + + + -- Type propagation function which returns the type BOOLEAN + function UNSIGNED_RETURN_BOOLEAN(A,B: UNSIGNED) return BOOLEAN is + variable Z: BOOLEAN; + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns the type BOOLEAN + function SIGNED_RETURN_BOOLEAN(A,B: SIGNED) return BOOLEAN is + variable Z: BOOLEAN; + -- pragma return_port_name Z + begin + return(Z); + end; + + + -- compare two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function is_less(A, B: SIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LT_TC_OP + -- pragma type_function SIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + if A(sign) /= B(sign) then + result := A(sign) = '1'; + else + result := FALSE; + for i in 0 to sign-1 loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + end if; + return result; + end; + + + -- compare two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function is_less_or_equal(A, B: SIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LEQ_TC_OP + -- pragma type_function SIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + if A(sign) /= B(sign) then + result := A(sign) = '1'; + else + result := TRUE; + for i in 0 to sign-1 loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + end if; + return result; + end; + + + + -- compare two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_is_less(A, B: UNSIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LT_UNS_OP + -- pragma type_function UNSIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + result := FALSE; + for i in 0 to sign loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + return result; + end; + + + -- compare two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_is_less_or_equal(A, B: UNSIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LEQ_UNS_OP + -- pragma type_function UNSIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + result := TRUE; + for i in 0 to sign loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + return result; + end; + + + + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length, R'length); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := L'length + 1; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := R'length + 1; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := L'length; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := R'length; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less_or_equal(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length, R'length); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := L'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := R'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := L'length; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := R'length; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less(CONV_UNSIGNED(R, length), + CONV_UNSIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length, R'length); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := L'length + 1; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := R'length + 1; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := L'length; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := R'length; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less_or_equal(CONV_UNSIGNED(R, length), + CONV_UNSIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length, R'length); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := L'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := R'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := L'length; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := R'length; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + + + -- for internal use only. Assumes SIGNED arguments of equal length. + function bitwise_eql(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) + return BOOLEAN is + -- pragma built_in SYN_EQL + begin + for i in L'range loop + if L(i) /= R(i) then + return FALSE; + end if; + end loop; + return TRUE; + end; + + -- for internal use only. Assumes SIGNED arguments of equal length. + function bitwise_neq(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) + return BOOLEAN is + -- pragma built_in SYN_NEQ + begin + for i in L'range loop + if L(i) /= R(i) then + return TRUE; + end if; + end loop; + return FALSE; + end; + + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_UNSIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_UNSIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length + 1, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length + 1); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length + 1; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := R'length + 1; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: INTEGER; R: SIGNED) return BOOLEAN is + constant length: INTEGER := R'length; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_UNSIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_UNSIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length + 1, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length + 1); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length + 1; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := R'length + 1; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN is + constant length: INTEGER := R'length; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is UNSIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb downto 2**i) := + result(result_msb - 2**i downto 0); + end if; + result := temp; + end if; + end loop; + return result; + end; + + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is SIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb downto 2**i) := + result(result_msb - 2**i downto 0); + end if; + result := temp; + end if; + end loop; + return result; + end; + + + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is UNSIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb - 2**i downto 0) := + result(result_msb downto 2**i); + end if; + result := temp; + end if; + end loop; + return result; + end; + + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is SIGNED (result_msb downto 0); + variable result, temp: rtype; + variable sign_bit: STD_ULOGIC; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + sign_bit := ARG(ARG'left); + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => sign_bit); + if 2**i <= result_msb then + temp(result_msb - 2**i downto 0) := + result(result_msb downto 2**i); + end if; + result := temp; + end if; + end loop; + return result; + end; + + + + + function CONV_INTEGER(ARG: INTEGER) return INTEGER is + begin + return ARG; + end; + + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER is + variable result: INTEGER; + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_UNSIGNED_TO_INTEGER + begin + -- synopsys synthesis_off + assert ARG'length <= 31 + report "ARG is too large in CONV_INTEGER" + severity FAILURE; + result := 0; + for i in ARG'range loop + result := result * 2; + tmp := tbl_BINARY(ARG(i)); + if tmp = '1' then + result := result + 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_INTEGER(ARG: SIGNED) return INTEGER is + variable result: INTEGER; + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_SIGNED_TO_INTEGER + begin + -- synopsys synthesis_off + assert ARG'length <= 32 + report "ARG is too large in CONV_INTEGER" + severity FAILURE; + result := 0; + for i in ARG'range loop + if i /= ARG'left then + result := result * 2; + tmp := tbl_BINARY(ARG(i)); + if tmp = '1' then + result := result + 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + end if; + end if; + end loop; + tmp := MAKE_BINARY(ARG(ARG'left)); + if tmp = '1' then + if ARG'length = 32 then + result := (result - 2**30) - 2**30; + else + result := result - (2 ** (ARG'length-1)); + end if; + end if; + return result; + -- synopsys synthesis_on + end; + + + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT is + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_FEED_THRU + begin + -- synopsys synthesis_off + tmp := tbl_BINARY(ARG); + if tmp = '1' then + return 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + return 0; + else + return 0; + end if; + -- synopsys synthesis_on + end; + + + -- convert an integer to a unsigned STD_ULOGIC_VECTOR + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED is + variable result: UNSIGNED(SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_UNSIGNED + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable new_bounds: UNSIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable new_bounds: UNSIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED is + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + + -- convert an integer to a 2's complement STD_ULOGIC_VECTOR + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED is + variable result: SIGNED (SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_SIGNED + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is SIGNED (SIZE-1 downto 0); + variable new_bounds : SIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is SIGNED (SIZE-1 downto 0); + variable new_bounds : SIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED is + subtype rtype is SIGNED (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + + -- convert an integer to an STD_LOGIC_VECTOR + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR is + variable result: STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_SIGNED + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) return STD_LOGIC_VECTOR is + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) + return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds: STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + +end std_logic_arith; diff --git a/lib/models/memory/sdram/mt48lc8m16a2/test.do b/lib/models/memory/sdram/mt48lc8m16a2/test.do new file mode 100644 index 0000000..e1f75c3 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m16a2/test.do @@ -0,0 +1,5 @@ +vcom mt48lc8m16a2.vhd +vcom test.vhd +vsim tb +do wave.do +run -all diff --git a/lib/models/memory/sdram/mt48lc8m16a2/test.txt b/lib/models/memory/sdram/mt48lc8m16a2/test.txt new file mode 100644 index 0000000..36bc0ea --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m16a2/test.txt @@ -0,0 +1,115 @@ +0 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +22 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +32 ns 1 0 1 1 1 00 00 0 -100 1 0 0 0 +42 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +52 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +62 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +72 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +82 ns 1 0 0 1 0 00 00 1024 -100 0 0 0 0 +92 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +102 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +112 ns 1 0 0 0 1 00 00 0 -100 0 0 0 0 +122 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +132 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +142 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +152 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +162 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +172 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +182 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +192 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +202 ns 1 0 0 0 1 00 00 0 -100 0 0 0 0 +212 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +222 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +232 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +242 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +252 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +262 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +272 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +282 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +292 ns 1 0 0 0 0 00 00 51 -100 0 0 0 0 +302 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +312 ns 1 0 0 1 1 00 00 0 -100 0 0 0 0 +322 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +332 ns 1 0 1 0 0 00 00 0 100 0 0 0 0 +342 ns 1 1 1 1 1 00 00 0 101 0 0 0 0 +352 ns 1 0 0 1 1 00 01 0 102 0 0 0 0 +362 ns 1 1 1 1 1 00 00 0 103 0 0 0 0 +372 ns 1 1 1 1 1 00 00 0 104 0 0 0 0 +382 ns 1 1 1 1 1 00 00 0 105 0 0 0 0 +392 ns 1 1 1 1 1 00 00 0 106 0 0 0 0 +402 ns 1 1 1 1 1 00 00 0 107 0 0 0 0 +412 ns 1 0 1 0 0 00 01 0 200 0 0 0 0 +422 ns 1 0 0 1 0 00 00 0 201 0 0 0 0 +432 ns 1 0 0 1 1 00 10 0 202 0 0 0 0 +442 ns 1 1 1 1 1 00 00 0 203 0 0 0 0 +452 ns 1 1 1 1 1 00 00 0 204 0 0 0 0 +462 ns 1 1 1 1 1 00 00 0 205 0 0 0 0 +472 ns 1 1 1 1 1 00 00 0 206 0 0 0 0 +482 ns 1 1 1 1 1 00 00 0 207 0 0 0 0 +492 ns 1 0 1 0 0 00 10 0 300 0 0 0 0 +502 ns 1 0 0 1 0 00 01 0 301 0 0 0 0 +512 ns 1 0 0 1 1 00 11 0 302 0 0 0 0 +522 ns 1 1 1 1 1 00 00 0 303 0 0 0 0 +532 ns 1 1 1 1 1 00 00 0 304 0 0 0 0 +542 ns 1 1 1 1 1 00 00 0 305 0 0 0 0 +552 ns 1 1 1 1 1 00 00 0 306 0 0 0 0 +562 ns 1 1 1 1 1 00 00 0 307 0 0 0 0 +572 ns 1 0 1 0 0 00 11 0 400 0 0 0 0 +582 ns 1 0 0 1 0 00 10 0 401 0 0 0 0 +592 ns 1 0 0 1 1 00 00 0 402 0 0 0 0 +602 ns 1 1 1 1 1 00 00 0 403 0 0 0 0 +612 ns 1 1 1 1 1 00 00 0 404 0 0 0 0 +622 ns 1 1 1 1 1 00 00 0 405 0 0 0 0 +632 ns 1 1 1 1 1 00 00 0 406 0 0 0 0 +642 ns 1 1 1 1 1 00 00 0 407 0 0 0 0 +652 ns 1 0 1 0 1 00 00 0 -100 0 0 0 0 +662 ns 1 0 0 1 0 00 11 0 -100 0 0 0 0 +672 ns 1 0 0 1 1 00 01 0 -100 0 0 0 0 +682 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +692 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +702 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +712 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +722 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +732 ns 1 0 1 0 1 00 01 0 -100 0 0 0 0 +742 ns 1 0 0 1 0 00 00 0 -100 0 0 0 0 +752 ns 1 0 0 1 1 00 10 0 -100 0 0 0 0 +762 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +772 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +782 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +792 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +802 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +812 ns 1 0 1 0 1 00 10 0 -100 0 0 0 0 +822 ns 1 0 0 1 0 00 01 0 -100 0 0 0 0 +832 ns 1 0 0 1 1 00 11 0 -100 0 0 0 0 +842 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +852 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +862 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +872 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +882 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +892 ns 1 0 1 0 1 00 11 0 -100 0 0 0 0 +902 ns 1 0 0 1 0 00 10 0 -100 0 0 0 0 +912 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +922 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +932 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +942 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +952 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +962 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +972 ns 1 0 0 1 0 00 11 0 -100 0 0 0 0 +982 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +992 ns 1 0 0 1 1 00 00 0 -100 0 0 0 0 +1002 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +1012 ns 1 0 1 0 0 00 00 1034 110 0 0 0 0 +1022 ns 1 1 1 1 1 00 00 0 111 0 0 0 0 +1032 ns 1 1 1 1 1 00 00 0 112 0 0 0 0 +1042 ns 1 1 1 1 1 00 00 0 113 0 0 0 0 +1052 ns 1 1 1 1 1 00 00 0 114 0 0 0 0 +1062 ns 1 1 1 1 1 00 00 0 115 0 0 0 0 +1072 ns 1 1 1 1 1 00 00 0 116 0 0 0 0 +1082 ns 1 1 1 1 1 00 00 0 117 0 0 0 0 +1092 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +1102 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +1112 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +1122 ns 1 0 0 1 1 00 00 0 -100 0 0 0 0 +1132 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 +1142 ns 1 0 1 1 1 00 00 0 -100 0 1 0 0 +1152 ns 1 1 1 1 1 00 00 0 -100 0 0 0 0 diff --git a/lib/models/memory/sdram/mt48lc8m16a2/test.vhd b/lib/models/memory/sdram/mt48lc8m16a2/test.vhd new file mode 100644 index 0000000..b16346f --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m16a2/test.vhd @@ -0,0 +1,197 @@ +LIBRARY ieee; +LIBRARY work; +USE ieee.std_logic_1164.ALL; +USE work.std_logic_arith.ALL; +USE work.util_1164.ALL; +USE std.textio.ALL; +USE work.mti_pkg.ALL; + +ENTITY tb IS +END tb; + + +ARCHITECTURE test OF tb IS + CONSTANT addr_bits : INTEGER := 12; + CONSTANT data_bits : INTEGER := 16; + CONSTANT clk_start : time := 5 ns; + CONSTANT clk_period : time := 10 ns; + CONSTANT continue_time : time := 10 ns; + + COMPONENT mt48lc8m16a2 + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '1'; + Cs_n : IN STD_LOGIC := '1'; + Cas_n : IN STD_LOGIC := '1'; + Ras_n : IN STD_LOGIC := '1'; + We_n : IN STD_LOGIC := '1'; + Dqm : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := (OTHERS => '0'); + Load : IN STD_LOGIC := '0'; + Unload : IN STD_LOGIC := '0'; + Row_start : IN INTEGER := 0; + Row_end : IN INTEGER := 0 + ); + END COMPONENT; + + FOR ALL : mt48lc8m16a2 USE ENTITY work.mt48lc8m16a2 (behave); + + SIGNAL pDq : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0); + SIGNAL pAddr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + SIGNAL pBa : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL pClk : STD_LOGIC; + SIGNAL pCke : STD_LOGIC; + SIGNAL pCs : STD_LOGIC; + SIGNAL pCas : STD_LOGIC; + SIGNAL pRas : STD_LOGIC; + SIGNAL pWe : STD_LOGIC; + SIGNAL pDqm : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL PLoad : STD_LOGIC; + SIGNAL PUnload : STD_LOGIC; + SIGNAL PRow_start : INTEGER; + SIGNAL PRow_end : INTEGER; + SIGNAL stim_done : boolean := false; + SIGNAL clk_done : boolean := false; + + +BEGIN + u1: mt48lc8m16a2 + PORT MAP( + Dq => pDq, + Addr => pAddr, + Ba => pBa, + Clk => pClk, + Cke => pCke, + Cs_n => pCs, + Ras_n => pRas, + Cas_n => pCas, + We_n => pWe, + Dqm => pDqm, + Load => pLoad, + Unload => pUnload, + Row_start => PRow_start, + Row_end => PRow_end + ); + + stimulator : PROCESS + FILE stim_file:text IS IN "test.txt"; + VARIABLE l : line; + VARIABLE time_var : TIME; + VARIABLE pCke_var : STD_LOGIC; + VARIABLE pCs_var : STD_LOGIC; + VARIABLE pRas_var : STD_LOGIC; + VARIABLE PCas_var : STD_LOGIC; + VARIABLE pWe_var : STD_LOGIC; + VARIABLE pDqm_var : STD_LOGIC_VECTOR (1 DOWNTO 0); + VARIABLE pBa_var : STD_LOGIC_VECTOR (1 DOWNTO 0); + VARIABLE pAddr_var : INTEGER; + VARIABLE pDq_var : INTEGER; -- -100 is converted to hi-Z state + VARIABLE pLoad_var : STD_LOGIC; + VARIABLE pUnload_var : STD_LOGIC; + VARIABLE pRow_start_var : INTEGER; + VARIABLE pRow_end_var : INTEGER; + VARIABLE pMa_var_vect : STD_LOGIC_VECTOR(addr_bits - 1 DOWNTO 0); + CONSTANT HiZ : STD_LOGIC_VECTOR(data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + BEGIN + WHILE not ENDFILE(stim_file) LOOP + readline(stim_file,l); + IF l'length > 0 THEN + read(l, time_var); + read(l, pCke_var); + read(l, pCs_var); + read(l, pRas_var); + read(l, pCas_var); + read(l, pWe_var); + read(l, pDqm_var); + read(l, pBa_var); + read(l, pAddr_var); + read(l, pDq_var); + read (l, pLoad_var); + read (l, pUnload_var); + read (l, pRow_start_var); + read (l, pRow_end_var); + IF now > time_var THEN + ASSERT false + REPORT "Detected a time in the stim file that is in the past" + SEVERITY error; + ELSE + WAIT FOR time_var-now; + IF pWe_var='1' THEN + pCke <= pCke_var; + pCs <= pCs_var; + pRas <= pRas_var; + pCas <= pCas_var; + pWe <= pWe_var; + pDqm <= pDqm_var; + pBa <= pBa_var; + pMa_var_vect := CONV_STD_LOGIC_VECTOR(pAddr_var, addr_bits); + pAddr <= pMa_var_vect; + IF pDq_var = -100 THEN + pDq <= HiZ; + ELSE + pDq <= CONV_STD_LOGIC_VECTOR(pDq_var, data_bits); + END IF; + pLoad <= pLoad_var; + pUnload <= pUnload_var; + pRow_start <= pRow_start_var; + pRow_end <= pRow_end_var; + ELSE + pCke <= pCke_var; + pCs <= pCs_var; + pRas <= pRas_var; + pCas <= pCas_var; + pWe <= pWe_var; + pDqm <= pDqm_var; + pBa <= pBa_var; + pMa_var_vect := CONV_STD_LOGIC_VECTOR(pAddr_var, addr_bits); + pAddr <= pMa_var_vect; + IF pDq_var = -100 THEN + pDq <= HiZ; + ELSE + pDq <= CONV_STD_LOGIC_VECTOR(pDq_var, data_bits); + END IF; + pLoad <= pLoad_var; + pUnload <= pUnload_var; + pRow_start <= pRow_start_var; + pRow_end <= pRow_end_var; + END IF; + END IF; + END IF; + END LOOP; + ASSERT false + REPORT "End of Stimulation File Detected!" + SEVERITY note; + stim_done <= true; + WAIT; + END PROCESS; + + clock : PROCESS + VARIABLE done_time : time; + BEGIN + pclk <= '0'; + WAIT for clk_start; + WHILE not stim_done loop + pclk <= '1'; + WAIT for clk_period/2; + pclk <= '0'; + WAIT for clk_period/2; + END LOOP; + done_time := now+continue_time; + WHILE now < done_time LOOP --one last clock to finish last command + pclk <= '1'; + WAIT for clk_period/2; + pclk <= '0'; + WAIT for clk_period/2; + END LOOP; + ASSERT false + REPORT "Suspending clock activity" + SEVERITY note; + clk_done <= true; + WAIT; + END PROCESS; + +END test; + + diff --git a/lib/models/memory/sdram/mt48lc8m16a2/util1164.vhd b/lib/models/memory/sdram/mt48lc8m16a2/util1164.vhd new file mode 100644 index 0000000..bb4b5dd --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m16a2/util1164.vhd @@ -0,0 +1,124 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE STD.textio.ALL; + +PACKAGE util_1164 IS + PROCEDURE read(l: INOUT line; value: OUT std_logic); + PROCEDURE read(l: INOUT line; value: OUT std_logic_vector); + PROCEDURE write(l: INOUT line; value: IN std_logic_vector; + JUSTIFIED: IN SIDE := right; + FIELD: IN WIDTH := 0); + PROCEDURE Grow_line(L : inout LINE; incr : in integer); +END util_1164; + + + +PACKAGE BODY util_1164 IS + + FUNCTION white_space(value:character) RETURN boolean IS + VARIABLE result:boolean; + BEGIN + IF (value = ' ') OR (value = HT) THEN + RETURN true; + ELSE + RETURN false; + END IF; + END white_space; + + PROCEDURE read(l: INOUT line; value: OUT std_logic) IS + VARIABLE char_var: character:= ' '; + BEGIN + WHILE l'LENGTH > 0 LOOP + read(l,char_var); + IF NOT white_space(char_var) THEN + EXIT; + END IF; + END LOOP; + IF white_space(char_var) THEN + ASSERT false REPORT "No std_logic value found in file" + SEVERITY error; + value := 'X'; + RETURN; + END IF; + + CASE char_var IS + WHEN 'U'|'u' => value := 'U'; + WHEN '0' => value := '0'; + WHEN '1' => value := '1'; + WHEN 'X'|'x' => value := 'X'; + WHEN 'L'|'l' => value := 'L'; + WHEN 'H'|'h' => value := 'H'; + WHEN 'W'|'w' => value := 'W'; + WHEN 'Z'|'z' => value := 'Z'; + WHEN '-' => value := '-'; + WHEN OTHERS => + ASSERT false REPORT "Unrecognized value read for std_logic" + SEVERITY error; + value := 'X'; + END CASE; + END read; + + PROCEDURE read(l: INOUT line; value: OUT std_logic_vector) IS + BEGIN + FOR i IN value'HIGH DOWNTO value'LOW LOOP + IF l'LENGTH > 0 THEN + read(l,value(i)); + ELSE + ASSERT false REPORT "Not enough values for std_logic_vector in file" + SEVERITY error; + RETURN; + END IF; + END LOOP; + END read; + + procedure Grow_line(L : inout LINE; incr : in integer) + is + variable old_L : LINE := L; + variable bfp: integer; -- Blank fill pointer. + begin + assert incr > 0 + report "Textio: Grow_line called with zero increment." + severity error; + + if L = null then + bfp := 0; + L := new string(1 to incr); + else + bfp := old_L'high; + L := new string(old_L'low to old_L'high + incr); + L(old_L'low to old_L'high) := old_L.all; + Deallocate(old_L); + end if; + for i in 1 to incr loop + L(bfp + i) := ' '; + end loop; + end; + + + PROCEDURE write(l: INOUT line; value: IN std_logic_vector; + JUSTIFIED: IN SIDE := right; + FIELD: IN WIDTH := 0) IS + variable fw: integer := VALUE'length; + variable bp: integer; + variable offset: integer := 0; + alias normal : std_logic_vector(0 to value'length - 1) is value; + begin + if L /= null then + bp := L'high + 1; + else bp := 1; + end if; + if FIELD > VALUE'length then + fw := FIELD; + if JUSTIFIED = right then + offset := fw - VALUE'length; + end if; + end if; + Grow_line(L, fw); + for i in normal'range loop + L(bp + i + offset) := character'val( + std_logic'pos(normal(i)) + character'pos('0')); + end loop; + end; + + +END util_1164; diff --git a/lib/models/memory/sdram/mt48lc8m16a2/vec_gen.vhd b/lib/models/memory/sdram/mt48lc8m16a2/vec_gen.vhd new file mode 100644 index 0000000..cc7f9d6 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m16a2/vec_gen.vhd @@ -0,0 +1,364 @@ +------------------------------------------------------------------------------- +-- -- +-- This is a data generator for the testbench for Micron's Synchronous -- +-- DRAM. This generator reads a text file line-by-line and generates -- +-- a file of test vectors that is then read by the testbench and -- +-- applied to the part. -- +-- -- +-- This VHDL program creates a text file of test vectors that is used by the -- +-- test bench. Place your commands in a file (a copy of VEC_GEN.VHD) and run -- +-- VEC_GEN.VHD in your VHDL simulator (make sure you have compiled this -- +-- package prior to running the program VEC_GEN.VHD). This will produce the -- +-- vectors that are required to run the included testbench. Change the name -- +-- of the vector file to save your vectors in separate files. The default -- +-- file name for the output vectors generated from this pacakage is -- +-- "test.txt." -- +-- -- +-- Now compile and run the testbench program embedtb.vhd. The testbench uses -- +-- the default test.txt as input vectors. -- +-- -- +-- -- +-- Copyright 1997 Micron Technology, Inc. -- +-- -- +------------------------------------------------------------------------------- + +LIBRARY work; +LIBRARY ieee; +USE ieee.std_logic_1164.all; +USE std.textio.all; +USE work.io_utils.all; + + +PACKAGE generate_vectors IS + + CONSTANT set_up : TIME; + CONSTANT hold : TIME; + CONSTANT cycle_start : TIME; + + SIGNAL cycle : INTEGER := 0; + SIGNAL sim_time : TIME := 0 ns; + FILE output_file:TEXT IS OUT "test.txt"; + PROCEDURE write(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); + first_data : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE read(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE active(row_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE precharge(bank : IN BIT_VECTOR(1 DOWNTO 0); address : IN INTEGER; data_bus: IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE nop(data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT; cs : IN BIT); + PROCEDURE burst_term(data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT); + PROCEDURE auto_refresh; + PROCEDURE next_cycle(SIGNAL clk : IN BIT); + PROCEDURE load_array(load : IN BIT); + PROCEDURE load_mode_reg(op_code : IN INTEGER; cke : IN BIT); + PROCEDURE unload_array(row_start : IN INTEGER; row_end : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0)); + +END generate_vectors; + + +PACKAGE BODY generate_vectors IS + + CONSTANT set_up : TIME := 3 ns; + CONSTANT hold : TIME := 1 ns; + CONSTANT cycle_start : TIME := 0 ns; + + +PROCEDURE write(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); first_data : IN INTEGER; + dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 0, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, first_data, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +write(l, 0, right, 6); --row_address_start +write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE read(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 0, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, -100, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +write(l, 0, right, 6); --row_address_start +write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE active(row_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 0, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, row_address, right, 6); --address +write(l, data_bus, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +write(l, 0, right, 6); --row_address_start +write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE precharge(bank : IN BIT_VECTOR(1 DOWNTO 0); address : IN INTEGER; data_bus: IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, Cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 0, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, address, right, 6); --address +write(l, data_bus, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +write(l, 0, right, 6); --row_address_start +write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE nop(data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT; cs : IN BIT) IS + + +VARIABLE l : LINE; +VARIABLE col_address : INTEGER := 0; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, cke, right, 4); --Cke +write(l, cs, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, data_bus, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +write(l, 0, right, 6); --row_address_start +write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + + +PROCEDURE burst_term(data_bus : IN INTEGER; dqm : IN BIT_VECTOR(1 DOWNTO 0); cke : IN BIT) IS + +VARIABLE l : LINE; +VARIABLE col_address : INTEGER := 0; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, col_address, right, 6); --address +write(l, data_bus, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +write(l, 0, right, 6); --row_address_start +write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE auto_refresh IS + VARIABLE l : LINE; + VARIABLE dqm : BIT_VECTOR(1 DOWNTO 0) := "00"; + VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; +BEGIN + IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); + ELSE + write(l, now-set_up, left, 4, ns); + END IF; + write(l, 1, right, 4); --Cke + write(l, 0, right, 4); --Cs + write(l, 0, right, 4); --Ras + write(l, 0, right, 4); --Cas + write(l, 1, right, 4); --We + write(l, dqm, right, 4); --Dqm + write(l, bank, right, 4); --Ba + write(l, 0, right, 6); --address + write(l, -100, right, 6); --first data location + write(l, 0, right, 4); --load + write(l, 0, right, 4); --unload + write(l, 0, right, 6); --row_address_start + write(l, 0, right, 6); --row_address_end + writeline(output_file,l); --write vector to file +END; + + +PROCEDURE next_cycle(SIGNAL clk : IN BIT) IS +BEGIN + WAIT UNTIL clk = '1'; +END; + +PROCEDURE load_array(load : IN BIT) IS + VARIABLE l : LINE; + VARIABLE dqm : BIT_VECTOR(1 DOWNTO 0) := "00"; + VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + write(l, 1, right, 4); --Cke + write(l, 0, right, 4); --Cs + write(l, 1, right, 4); --Ras + write(l, 1, right, 4); --Cas + write(l, 1, right, 4); --We + write(l, dqm, right, 4); --Dqm + write(l, bank, right, 4); --Ba + write(l, 0, right, 6); --address + write(l, -100, right, 6); --first data location + write(l, 1, right, 4); --load + write(l, 0, right, 4); --unload + write(l, 0, right, 6); --row_address_start + write(l, 0, right, 6); --row_address_end + writeline(output_file,l); --write vector to file +END; + +PROCEDURE unload_array(row_start : IN INTEGER; row_end : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0)) IS + VARIABLE l : LINE; + VARIABLE dqm : BIT_VECTOR(1 DOWNTO 0) := "00"; +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, 1, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 1, right, 4); --Ras +write(l, 1, right, 4); --Cas +write(l, 1, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, 0, right, 6); --address +write(l, -100, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 1, right, 4); --unload +write(l, row_start, right, 6); --row_address_start +write(l, row_end, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +PROCEDURE load_mode_reg(op_code : IN INTEGER; cke : IN BIT) IS + +VARIABLE l : LINE; +VARIABLE dqm : BIT_VECTOR(1 DOWNTO 0) := "00"; +VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + +IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); +ELSE + write(l, now-set_up, left, 4, ns); +END IF; + +write(l, cke, right, 4); --Cke +write(l, 0, right, 4); --Cs +write(l, 0, right, 4); --Ras +write(l, 0, right, 4); --Cas +write(l, 0, right, 4); --We +write(l, dqm, right, 4); --Dqm +write(l, bank, right, 4); --Ba +write(l, op_code, right, 6); --address +write(l, -100, right, 6); --first data location +write(l, 0, right, 4); --load +write(l, 0, right, 4); --unload +write(l, 0, right, 6); --row_address_start +write(l, 0, right, 6); --row_address_end +writeline(output_file,l); --write vector to file + +END; + +END generate_vectors; + diff --git a/lib/models/memory/sdram/mt48lc8m16a2/vector.do b/lib/models/memory/sdram/mt48lc8m16a2/vector.do new file mode 100644 index 0000000..7480359 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m16a2/vector.do @@ -0,0 +1,4 @@ +vcom vec_gen.vhd +vcom ed_comnd.vhd +vsim vector_generate +run -all diff --git a/lib/models/memory/sdram/mt48lc8m16a2/wave.do b/lib/models/memory/sdram/mt48lc8m16a2/wave.do new file mode 100644 index 0000000..0e59196 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m16a2/wave.do @@ -0,0 +1,33 @@ +onerror {resume} +add wave -logic /tb/u1/clk +add wave -logic /tb/u1/cke +add wave -logic /tb/u1/cs_n +add wave -logic /tb/u1/ras_n +add wave -logic /tb/u1/cas_n +add wave -logic /tb/u1/we_n +add wave -literal -decimal /tb/u1/addr +add wave -literal -unsigned /tb/u1/ba +add wave -literal -decimal /tb/u1/dq +add wave -literal /tb/u1/dqm +add wave -literal /tb/u1/operation +add wave -literal -decimal /tb/u1/mode_reg +add wave -logic /tb/u1/active_enable +add wave -logic /tb/u1/aref_enable +add wave -logic /tb/u1/burst_term +add wave -logic /tb/u1/mode_reg_enable +add wave -logic /tb/u1/prech_enable +add wave -logic /tb/u1/read_enable +add wave -logic /tb/u1/write_enable +add wave -logic /tb/u1/burst_length_1 +add wave -logic /tb/u1/burst_length_2 +add wave -logic /tb/u1/burst_length_4 +add wave -logic /tb/u1/burst_length_8 +add wave -logic /tb/u1/cas_latency_2 +add wave -logic /tb/u1/cas_latency_3 +add wave -literal /tb/u1/pre_chk +add wave -literal /tb/u1/act_chk +add wave -literal /tb/u1/bank_chk +add wave -literal -decimal /tb/u1/row_chk +add wave -literal -decimal /tb/u1/col_chk +add wave -logic /tb/u1/dq_in_chk +add wave -logic /tb/u1/dq_out_chk diff --git a/lib/models/memory/sdram/mt48lc8m8a2/base.do b/lib/models/memory/sdram/mt48lc8m8a2/base.do new file mode 100644 index 0000000..d2afbcb --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m8a2/base.do @@ -0,0 +1,5 @@ +vcom util1164.vhd +vcom stdlogar.vhd +vcom io_utils.vhd +vcom mti_pkg.vhd + diff --git a/lib/models/memory/sdram/mt48lc8m8a2/ed_comnd.vhd b/lib/models/memory/sdram/mt48lc8m8a2/ed_comnd.vhd new file mode 100644 index 0000000..523da89 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m8a2/ed_comnd.vhd @@ -0,0 +1,370 @@ +-------------------------------------------------------------------------------------------------- +-- COMMAND FORMAT -- +-- -- +-- write(column address(integer), bank(bit_vector), first data(integer), dqm(bit), cke(bit)); -- +-- read(column address(integer), bank(bit_vector), dqm(bit), cke(bit)); -- +-- active(row address(integer), bank(bit_vector), data bus (integer), dqm(bit), cke(bit)); -- +-- precharge(bank(bit_vector), address (integer), data bus(integer), dqm(bit), cke(bit)); -- +-- nop(data bus(integer), dqm(bit), cke(bit)); -- +-- burst_term(data bus(integer), dqm(bit), cke(bit)); -- +-- load_array('1'); -- +-- load_mode_reg(register(integer), cke(bit)); -- +-- next_cycle(clk); This is used after every command(incl. nop) to clock -- +-- at the correct clock frequency entered in the clock -- +-- period constant below -- +-- unload_array(row_start(integer), row_end(integer), bank(bit_vector)) -- +-- load_mode_reg(op_code(integer)) -- +-- -- +-------------------------------------------------------------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.all; +USE std.textio.all; +USE work.generate_vectors.all; + +ENTITY vector_generate IS +END vector_generate; + +ARCHITECTURE vector_generate OF vector_generate IS + + SIGNAL stim_done : BOOLEAN := FALSE; + SIGNAL clk : BIT := '0'; + CONSTANT clk_start : time := 15 ns; + CONSTANT clk_period : time := 10 ns; + CONSTANT Z : INTEGER := -100; + +BEGIN + +PROCESS + +BEGIN + +WAIT UNTIL clk = '1' AND clk'EVENT; + +--------------------ENTER COMMANDS BELOW THIS LINE----------------------------- +--******************DO NOT USE -100 FOR A DQ VALUE*************************---- +--*******************Z WILL PLACE HI-Z ON THE BUS**************************---- +--*******USE next_cycle(clk) FOR ADVANCING TO NEXT CLOCK CYCLE*************---- + +nop(Z, '0', '1'); --Always begin with one nop when using Micron's testbench + +next_cycle(clk); +load_array; + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +precharge("00", 1024, Z, '0', '1'); + +FOR i IN 1 to 2 LOOP + next_cycle(clk); + nop(Z, '0', '1'); +END LOOP; + +next_cycle(clk); +auto_refresh; + +FOR i IN 1 TO 8 LOOP + next_cycle(clk); + nop(Z, '0', '1'); +END LOOP; + +next_cycle(clk); +auto_refresh; + +FOR i IN 1 TO 8 LOOP + next_cycle(clk); + nop(Z, '0', '1'); +END LOOP; + +next_cycle(clk); +load_mode_reg(49, '1'); -- 19 / 35 / 51 -> lat=3,bl=8,mode=seq + +next_cycle(clk); +nop(Z, '0', '1'); + +-- Write Section + +next_cycle(clk); +active(0, "00", Z, '0', '1'); -- Activate Bank 0 + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +--write(0, "00", 10, '0', '1'); -- Write Bank 0 +write(1024, "00", 10, '0', '1'); -- Write Bank 0 Auto Precharge + +next_cycle(clk); +nop(11, '0', '1'); + +next_cycle(clk); +active(0, "01", 12, '0', '1'); -- Activate Bank 1 + +next_cycle(clk); +nop(13, '0', '1'); + +next_cycle(clk); +nop(14, '0', '1'); + +next_cycle(clk); +nop(15, '0', '1'); + +next_cycle(clk); +nop(16, '0', '1'); + +next_cycle(clk); +nop(17, '0', '1'); + +next_cycle(clk); +--write(0, "01", 20, '0', '1'); -- Write Bank 1 +write(1024, "01", 20, '0', '1'); -- Write Bank 1 Auto Precharge + +next_cycle(clk); +--precharge("00", 0, 21, '0', '1'); -- Precharge Bank 0 +nop(21, '0', '1'); + +next_cycle(clk); +active(0, "10", 22, '0', '1'); -- Activate Bank 2 + +next_cycle(clk); +nop(23, '0', '1'); + +next_cycle(clk); +nop(24, '0', '1'); + +next_cycle(clk); +nop(25, '0', '1'); + +next_cycle(clk); +nop(26, '0', '1'); + +next_cycle(clk); +nop(27, '0', '1'); + +next_cycle(clk); +--write(0, "10", 30, '0', '1'); -- Write Bank 2 +write(1024, "10", 30, '0', '1'); -- Write Bank 2 Auto Precharge + +next_cycle(clk); +--precharge("01", 0, 31, '0', '1'); -- Precharge Bank 1 +nop(31, '0', '1'); + +next_cycle(clk); +active(0, "11", 32, '0', '1'); -- Activate Bank 3 + +next_cycle(clk); +nop(33, '0', '1'); + +next_cycle(clk); +nop(34, '0', '1'); + +next_cycle(clk); +nop(35, '0', '1'); + +next_cycle(clk); +nop(36, '0', '1'); + +next_cycle(clk); +nop(37, '0', '1'); + +next_cycle(clk); +--write(0, "11", 40, '0', '1'); -- Write Bank 3 +write(1024, "11", 40, '0', '1'); -- Write Bank 3 Auto Precharge + +next_cycle(clk); +--precharge("10", 0, 41, '0', '1'); -- Precharge Bank 2 +nop(41, '0', '1'); + +next_cycle(clk); +active(0, "00", 42, '0', '1'); -- Activate Bank 0 + +next_cycle(clk); +nop(43, '0', '1'); + +next_cycle(clk); +nop(44, '0', '1'); + +next_cycle(clk); +nop(45, '0', '1'); + +next_cycle(clk); +nop(46, '0', '1'); + +next_cycle(clk); +nop(47, '0', '1'); + +-- Read Section + +next_cycle(clk); +--read(0, "00", '0', '1'); -- Read Bank 0 +read(1024, "00", '0', '1'); -- Read Bank 0 Auto Precharge + +next_cycle(clk); +--precharge("11", 0, Z, '0', '1'); -- Precharge Bank 3 +nop(Z, '0', '1'); + +next_cycle(clk); +active(0, "01", Z, '0', '1'); -- Activate Bank 1 + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +--read(0, "01", '0', '1'); -- Read Bank 1 +read(1024, "01", '0', '1'); -- Read Bank 1 Auto Precharge + +next_cycle(clk); +--precharge("00", 0, Z, '0', '1'); -- Precharge Bank 0 +nop(Z, '0', '1'); + +next_cycle(clk); +active(0, "10", Z, '0', '1'); -- Activate Bank 2 + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +--read(0, "10", '0', '1'); -- Read Bank 2 +read(1024, "10", '0', '1'); -- Read Bank 2 Auto Precharge + +next_cycle(clk); +--precharge("01", 0, Z, '0', '1'); -- Precharge Bank 1 +nop(Z, '0', '1'); + +next_cycle(clk); +active(0, "11", Z, '0', '1'); -- Activate Bank 3 + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +--read(0, "11", '0', '1'); -- Read Bank 3 +read(1024, "11", '0', '1'); -- Read Bank 3 Auto Precharge + +next_cycle(clk); +--precharge("10", 0, Z, '0', '1'); -- Precharge Bank 2 +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +--precharge("11", 0, Z, '0', '1'); -- Precharge Bank 3 +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +nop(Z, '0', '1'); + +next_cycle(clk); +unload_array(0, 1, "00"); -- Unload From Row 0-1, Bank 00 + +next_cycle(clk); +unload_array(0, 1, "01"); -- Unload From Row 0-1, Bank 10 + +next_cycle(clk); +unload_array(0, 1, "10"); -- Unload From Row 0-1, Bank 01 + +next_cycle(clk); +unload_array(0, 1, "11"); -- Unload From Row 0-1, Bank 11 + +next_cycle(clk); +nop(Z, '0', '1'); + +stim_done <= TRUE; --always include this line at the end of your stimulus + +------------------------------------------------------------------------------- +--*************************************************************************---- +END PROCESS; + + +clock: + PROCESS + VARIABLE done_time : time; + VARIABLE cycle_var : integer := 0; + BEGIN + cycle <= 0; + clk <= '0'; + WAIT for clk_start; + WHILE not stim_done loop + clk <= '1'; + cycle <= cycle_var; + WAIT for clk_period/2; + cycle_var := cycle_var + 1; + clk <= '0'; + WAIT for clk_period/2; + END LOOP; + + ASSERT (FALSE) + REPORT "Test Vectors Generated" + SEVERITY note; + + WAIT; + END PROCESS; + + +END; diff --git a/lib/models/memory/sdram/mt48lc8m8a2/io_utils.vhd b/lib/models/memory/sdram/mt48lc8m8a2/io_utils.vhd new file mode 100644 index 0000000..dfcb84a --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m8a2/io_utils.vhd @@ -0,0 +1,266 @@ +LIBRARY ieee; +USE std.textio.ALL; +USE ieee.std_logic_1164.ALL; + +PACKAGE io_utils IS + + PROCEDURE write_string(l : INOUT line; + value : IN string; + justified : IN side := right; + field : IN width := 0); + + TYPE radix IS (binary, octal, decimal, hex); + + -- read a number from the line + -- use this if you have hex numbers that are not in VHDL pound-sign format + PROCEDURE read(l : INOUT line; value : OUT integer; radix : IN positive); + + -- read a number that might be in VHDL pound-sign format + PROCEDURE read_based(l : INOUT line; value : OUT integer); + + PROCEDURE write(l : INOUT line; + value : IN std_logic_vector; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false); + + PROCEDURE write(l : INOUT line; + value : IN integer; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false); +END io_utils; + +PACKAGE BODY io_utils IS + + PROCEDURE write_string(l : INOUT line; + value : IN string; + justified : IN side := right; + field : IN width := 0) + IS + BEGIN + write(l, value, justified, field); + END; + + PROCEDURE shrink_line(l : INOUT line; pos : integer) IS + VARIABLE tmpl : line; + BEGIN + tmpl := l; + l := NEW string'(tmpl(pos TO tmpl'high)); + deallocate(tmpl); + END; + + PROCEDURE read(l : INOUT line; + value : OUT integer; + radix : IN positive) + IS + CONSTANT not_digit : integer := -999; + + -- convert a character to a value from 0 to 15 + FUNCTION digit_value(c : character) RETURN integer IS + BEGIN + IF (c >= '0') AND (c <= '9') THEN + RETURN (character'pos(c) - character'pos('0')); + ELSIF (c >= 'a') AND (c <= 'f') THEN + RETURN (character'pos(c) - character'pos('a') + 10); + ELSIF (c >= 'A') AND (c <= 'F') THEN + RETURN (character'pos(c) - character'pos('A') + 10); + ELSE + RETURN not_digit; + END IF; + END; + + -- skip leading white space in the line + PROCEDURE skip_white(VARIABLE l : IN line; pos : OUT integer) IS + BEGIN + pos := l'low; + FOR i IN l'low TO l'high LOOP + CASE l(i) IS + WHEN ' ' | ht => + pos := i + 1; + WHEN OTHERS => + EXIT; + END CASE; + END LOOP; + END; + + VARIABLE digit : integer; + VARIABLE result : integer := 0; + VARIABLE pos : integer; + BEGIN + -- skip white space + skip_white(l, pos); + + -- calculate the value + FOR i IN pos TO l'right LOOP + digit := digit_value(l(i)); + EXIT WHEN (digit = not_digit) OR (digit >= radix); + result := result * radix + digit; + pos := i + 1; + END LOOP; + value := result; + + -- remove the "used" characters from the line + shrink_line(l, pos); + END; + + PROCEDURE read_based(l : INOUT line; value : OUT integer) IS + VARIABLE digit : integer; + VARIABLE num : integer; + VARIABLE base : integer; + BEGIN + read(l, num, 10); + IF (l'length > 1) AND (l(l'left) = '#') THEN + shrink_line(l, l'left+1); + base := num; + read(l, num, base); + IF (l'length >= 1) AND (l(l'left) = '#') THEN + shrink_line(l, l'left+1); + END IF; + END IF; + value := num; + END; + + PROCEDURE write(l : INOUT line; + value : IN std_logic_vector; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false) + IS + FUNCTION to_int(bv : std_logic_vector) RETURN integer + IS + VARIABLE result : integer := 0; + BEGIN + FOR i IN bv'RANGE LOOP + result := result * 2; + IF (bv(i) = '1') THEN + result := result + 1; + END IF; + END LOOP; + RETURN result; + END; + + TYPE array_of_widths IS ARRAY(radix) OF natural; + CONSTANT nibble_widths : array_of_widths := ( + binary => 1, + octal => 3, + hex => 4, + decimal=> 32); + CONSTANT hex_digit : string(1 TO 16) := "0123456789ABCDEF"; + + ALIAS input_val : std_logic_vector(value'length DOWNTO 1) IS value; + CONSTANT nibble_width : natural := nibble_widths(base); + CONSTANT result_width : natural := (value'length + nibble_width - 1)/nibble_width; + + VARIABLE result : string(1 TO result_width); -- longest possible value + VARIABLE result_pos : positive := 1; + VARIABLE nibble_val : integer; + VARIABLE bitcnt : integer; + BEGIN + IF base = decimal THEN + write(l, to_int(value), justified, field, base, use_pound); + RETURN; + END IF; + + bitcnt := value'length MOD nibble_width; + IF (bitcnt = 0) THEN + bitcnt := nibble_width; + END IF; + FOR i IN input_val'RANGE LOOP + nibble_val := nibble_val * 2; + IF (input_val(i) = '1') THEN + nibble_val := nibble_val + 1; + END IF; + bitcnt := bitcnt - 1; + IF (bitcnt = 0) THEN + result(result_pos) := hex_digit(nibble_val + 1); + result_pos := result_pos + 1; + nibble_val := 0; + bitcnt := nibble_width; + END IF; + END LOOP; + write(l, result, justified, field); + END; + + PROCEDURE write(l : INOUT line; + value : IN integer; + justified : IN side := right; + field : IN width := 0; + base : IN radix; + use_pound : boolean := false) + IS + FUNCTION to_bv(int : integer) RETURN std_logic_vector + IS + VARIABLE bv : std_logic_vector(32 DOWNTO 1) := (OTHERS => '0'); + VARIABLE pos : integer := 0; + VARIABLE tmpval : integer := int; + BEGIN + FOR i IN 1 TO 32 LOOP + pos := pos + 1; + IF (tmpval MOD 2) = 1 THEN + bv(i) := '1'; + END IF; + tmpval := tmpval / 2; + EXIT WHEN tmpval = 0; + END LOOP; + RETURN bv(pos DOWNTO 1); + END; + + VARIABLE tmp : line; + BEGIN + IF (base = decimal) THEN + IF (use_pound) THEN + write_string(tmp, "10#"); + END IF; + write(tmp, value); + IF (use_pound) THEN + write_string(tmp, "#"); + END IF; + write(l, tmp.ALL, justified, field); + deallocate(tmp); + ELSE + write(l, to_bv(value), justified, field, base, use_pound); + END IF; + END; + +END io_utils; + + + +-- test the hex number reader +--ENTITY test IS END; + +--USE std.textio.ALL; +--USE work.io_utils.ALL; +--ARCHITECTURE hex_test OF test IS +--BEGIN +-- PROCESS +-- VARIABLE val : integer; +-- FILE myfile : text IS IN "values"; +-- VARIABLE inline : line; +-- VARIABLE outline : line; +-- BEGIN +-- WHILE NOT endfile(myfile) LOOP +-- readline(myfile, inline); + +-- write(outline, inline.ALL); +-- +-- read_based(inline, val); + -- write_string(outline, " binary: "); + -- write(outline, val, base => binary); + -- write_string(outline, " octal: "); + -- write(outline, val, base => octal); + -- write_string(outline, " decimal: "); + -- write(outline, val, base => decimal); +-- write_string(outline, " hex: "); +-- write(outline, val, base => hex); +-- writeline(output, outline); +-- END LOOP; +-- WAIT; +-- END PROCESS; +--END; + + diff --git a/lib/models/memory/sdram/mt48lc8m8a2/loaddata.txt b/lib/models/memory/sdram/mt48lc8m8a2/loaddata.txt new file mode 100644 index 0000000..0a69592 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m8a2/loaddata.txt @@ -0,0 +1,41 @@ +0 0 00 0 -- ROW (HEX), COL (HEX), BANK (BIN), DATA (HEX) +0 1 00 1 +0 2 00 2 +0 3 00 3 +0 4 00 4 +0 5 00 5 +0 6 00 6 +0 7 00 7 +0 8 00 8 +0 9 00 9 +0 0 01 10 +0 1 01 11 +0 2 01 12 +0 3 01 13 +0 4 01 14 +0 5 01 15 +0 6 01 16 +0 7 01 17 +0 8 01 18 +0 9 01 19 +0 0 10 20 +0 1 10 21 +0 2 10 22 +0 3 10 23 +0 4 10 24 +0 5 10 25 +0 6 10 26 +0 7 10 27 +0 8 10 28 +0 9 10 29 +0 0 11 30 +0 1 11 31 +0 2 11 32 +0 3 11 33 +0 4 11 34 +0 5 11 35 +0 6 11 36 +0 7 11 37 +0 8 11 38 +0 9 11 39 + diff --git a/lib/models/memory/sdram/mt48lc8m8a2/mt48lc8m8a2.vhd b/lib/models/memory/sdram/mt48lc8m8a2/mt48lc8m8a2.vhd new file mode 100644 index 0000000..3d8ec4d --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m8a2/mt48lc8m8a2.vhd @@ -0,0 +1,1351 @@ +----------------------------------------------------------------------------------------- +-- +-- File Name: MT48LC8M8A2.VHD +-- Version: 0.0f +-- Date: July 8th, 1999 +-- Model: Behavioral +-- Simulator: Model Technology (PC version 5.2e PE) +-- +-- Dependencies: None +-- +-- Author: Son P. Huynh +-- Email: sphuynh@micron.com +-- Phone: (208) 368-3825 +-- Company: Micron Technology, Inc. +-- Part Number: MT48LC8M8A2 (2Mb x 8 x 4 Banks) +-- +-- Description: Micron 64Mb SDRAM +-- +-- Limitation: - Doesn't check for 4096-cycle refresh +-- +-- Note: - Set simulator resolution to "ps" accuracy +-- +-- Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY +-- WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY +-- IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR +-- A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT. +-- +-- Copyright (c) 1998 Micron Semiconductor Products, Inc. +-- All rights researved +-- +-- Rev Author Phone Date Changes +-- ---- ---------------------------- ---------- ------------------------------------- +-- 0.0f Son Huynh 208-368-3825 07/08/1999 Fix tWR = 1 Clk + 7.5 ns (Auto) +-- Micron Technology Inc. Fix tWR = 15 ns (Manual) +-- Fix tRP (Autoprecharge to AutoRefresh) +-- +-- 0.0e Son P. Huynh 208-368-3825 05/25/1999 Fix R/W Interrupting R/W with AP +-- Micron Technology Inc. +-- +-- 0.0d Son P. Huynh 208-368-3825 04/08/1999 Fix tWR + tRP in Write with AP +-- Micron Technology Inc. +-- +-- 0.0c Son P. Huynh 208-368-3825 01/18/1998 Add Load / Unload memory array +-- Micron Technology Inc. +-- +-- 0.0b Son P. Huynh 208-368-3825 12/09/1998 Fix some timing check problem +-- Micron Technology Inc. - Improve model functionality +-- +-- 0.0a Son P. Huynh 208-368-3825 08/10/1998 First Release +-- Micron Technology Inc. - Simple testbench included +----------------------------------------------------------------------------------------- + +LIBRARY STD; + USE STD.TEXTIO.ALL; +LIBRARY IEEE; + USE IEEE.STD_LOGIC_1164.ALL; +LIBRARY WORK; + USE WORK.IO_UTILS.ALL; + USE WORK.MTI_PKG.ALL; + +ENTITY mt48lc8m8a2 IS + GENERIC ( + -- Timing Parameters for -75 (PC133) and CAS Latency = 2 + tAC : TIME := 6.0 ns; + tHZ : TIME := 7.0 ns; + tOH : TIME := 2.7 ns; + tMRD : INTEGER := 2; -- 2 Clk Cycles + tRAS : TIME := 44.0 ns; + tRC : TIME := 66.0 ns; + tRCD : TIME := 20.0 ns; + tRP : TIME := 20.0 ns; + tRRD : TIME := 15.0 ns; + tWRa : TIME := 7.5 ns; -- A2 Version - Auto precharge mode only (1 Clk + 7.5 ns) + tWRp : TIME := 15.0 ns; -- A2 Version - Precharge mode only (15 ns) + + tAH : TIME := 0.8 ns; + tAS : TIME := 1.5 ns; + tCH : TIME := 2.5 ns; + tCL : TIME := 2.5 ns; + tCK : TIME := 10.0 ns; + tDH : TIME := 0.8 ns; + tDS : TIME := 1.5 ns; + tCKH : TIME := 0.8 ns; + tCKS : TIME := 1.5 ns; + tCMH : TIME := 0.8 ns; + tCMS : TIME := 1.5 ns; + + addr_bits : INTEGER := 12; + data_bits : INTEGER := 8; + col_bits : INTEGER := 9 + ); + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC_VECTOR := "00"; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '0'; + Cs_n : IN STD_LOGIC := '1'; + Ras_n : IN STD_LOGIC := '0'; + Cas_n : IN STD_LOGIC := '0'; + We_n : IN STD_LOGIC := '0'; + Dqm : IN STD_LOGIC := '0'; + Load : IN STD_LOGIC := '0'; + Unload : IN STD_LOGIC := '0'; + Row_start : IN INTEGER := 0; + Row_end : IN INTEGER := 0 + ); +END mt48lc8m8a2; + +ARCHITECTURE behave OF mt48lc8m8a2 IS + TYPE State IS (ACT, A_REF, BST, LMR, NOP, PRECH, READ, READ_A, WRITE, WRITE_A, FILE_LOAD, FILE_UNLOAD); + TYPE Array4xI IS ARRAY (3 DOWNTO 0) OF INTEGER; + TYPE Array4xT IS ARRAY (3 DOWNTO 0) OF TIME; + TYPE Array4xB IS ARRAY (3 DOWNTO 0) OF BIT; + TYPE Array4x2BV IS ARRAY (3 DOWNTO 0) OF BIT_VECTOR (1 DOWNTO 0); + TYPE Array2xB IS ARRAY (1 DOWNTO 0) OF BIT; + TYPE Array4xCBV IS ARRAY (4 DOWNTO 0) OF BIT_VECTOR (Col_bits - 1 DOWNTO 0); + TYPE Array_state IS ARRAY (4 DOWNTO 0) OF State; + SIGNAL Operation : State := NOP; + SIGNAL Mode_reg : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL Active_enable, Aref_enable, Burst_term : BIT := '0'; + SIGNAL Mode_reg_enable, Prech_enable, Read_enable, Write_enable : BIT := '0'; + SIGNAL Burst_length_1, Burst_length_2, Burst_length_4, Burst_length_8 : BIT := '0'; + SIGNAL Cas_latency_2, Cas_latency_3 : BIT := '0'; + SIGNAL Ras_in, Cas_in, We_in : BIT := '0'; + SIGNAL Write_burst_mode : BIT := '0'; + SIGNAL Sys_clk, CkeZ : BIT := '0'; + + -- Checking internal wires + SIGNAL Pre_chk : BIT_VECTOR (3 DOWNTO 0) := "0000"; + SIGNAL Act_chk : BIT_VECTOR (3 DOWNTO 0) := "0000"; + SIGNAL Dq_in_chk, Dq_out_chk : BIT := '0'; + SIGNAL Bank_chk : BIT_VECTOR (1 DOWNTO 0) := "00"; + SIGNAL Row_chk : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL Col_chk : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + + BEGIN + -- CS# Decode + WITH Cs_n SELECT + Cas_in <= TO_BIT (Cas_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + WITH Cs_n SELECT + Ras_in <= TO_BIT (Ras_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + WITH Cs_n SELECT + We_in <= TO_BIT (We_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + + -- Commands Decode + Active_enable <= NOT(Ras_in) AND Cas_in AND We_in; + Aref_enable <= NOT(Ras_in) AND NOT(Cas_in) AND We_in; + Burst_term <= Ras_in AND Cas_in AND NOT(We_in); + Mode_reg_enable <= NOT(Ras_in) AND NOT(Cas_in) AND NOT(We_in); + Prech_enable <= NOT(Ras_in) AND Cas_in AND NOT(We_in); + Read_enable <= Ras_in AND NOT(Cas_in) AND We_in; + Write_enable <= Ras_in AND NOT(Cas_in) AND NOT(We_in); + + -- Burst Length Decode + Burst_length_1 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND NOT(Mode_reg(0)); + Burst_length_2 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND Mode_reg(0); + Burst_length_4 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND NOT(Mode_reg(0)); + Burst_length_8 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND Mode_reg(0); + + -- CAS Latency Decode + Cas_latency_2 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND NOT(Mode_reg(4)); + Cas_latency_3 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND Mode_reg(4); + + -- Write Burst Mode + Write_burst_mode <= Mode_reg(9); + + -- System Clock + int_clk : PROCESS (Clk) + begin + IF Clk'LAST_VALUE = '0' AND Clk = '1' THEN + CkeZ <= TO_BIT(Cke, '1'); + END IF; + Sys_clk <= CkeZ AND TO_BIT(Clk, '0'); + END PROCESS; + + state_register : PROCESS + TYPE ram_type IS ARRAY (2**col_bits - 1 DOWNTO 0) OF BIT_VECTOR (data_bits - 1 DOWNTO 0); + TYPE ram_pntr IS ACCESS ram_type; + TYPE ram_stor IS ARRAY (2**addr_bits - 1 DOWNTO 0) OF ram_pntr; + VARIABLE Bank0 : ram_stor; + VARIABLE Bank1 : ram_stor; + VARIABLE Bank2 : ram_stor; + VARIABLE Bank3 : ram_stor; + VARIABLE Row_index, Col_index : INTEGER := 0; + VARIABLE Dq_temp : BIT_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => '0'); + + VARIABLE Col_addr : Array4xCBV; + VARIABLE Bank_addr : Array4x2BV; + VARIABLE Dqm_reg : Array2xB; + + VARIABLE Bank, Previous_bank : BIT_VECTOR (1 DOWNTO 0) := "00"; + VARIABLE B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col_brst : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Row : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Burst_counter : INTEGER := 0; + + VARIABLE Command : Array_state; + VARIABLE Bank_precharge : Array4x2BV; + VARIABLE A10_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Auto_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Read_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Write_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_write : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_read : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_bank : BIT_VECTOR (1 DOWNTO 0); + VARIABLE Count_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE Count_precharge : Array4xI := (0 & 0 & 0 & 0); + + VARIABLE Data_in_enable, Data_out_enable : BIT := '0'; + VARIABLE Pc_b0, Pc_b1, Pc_b2, Pc_b3 : BIT := '0'; + VARIABLE Act_b0, Act_b1, Act_b2, Act_b3 : BIT := '0'; + + -- Timing Check + VARIABLE MRD_chk : INTEGER := 0; + VARIABLE WR_counter : Array4xI := (0 & 0 & 0 & 0); + VARIABLE WR_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE WR_chkp : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE RC_chk, RRD_chk : TIME := 0 ns; + VARIABLE RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3 : TIME := 0 ns; + VARIABLE RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3 : TIME := 0 ns; + VARIABLE RP_chk0, RP_chk1, RP_chk2, RP_chk3 : TIME := 0 ns; + + -- Load and Unload variables + FILE load_file : TEXT IS IN "loaddata.txt"; -- Data load + FILE out_file0 : TEXT IS OUT "outdata0.txt"; -- Data dump for bank 0 + FILE out_file1 : TEXT IS OUT "outdata1.txt"; -- Data dump for bank 1 + FILE out_file2 : TEXT IS OUT "outdata2.txt"; -- Data dump for bank 2 + FILE out_file3 : TEXT IS OUT "outdata3.txt"; -- Data dump for bank 3 + VARIABLE l_in, l_out0, l_out1, l_out2, l_out3 : LINE; + VARIABLE array_buffer : BIT_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE write_data_var : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE row_load, col_load, dq_load : INTEGER; + VARIABLE ba_load : BIT_VECTOR (1 DOWNTO 0); + VARIABLE dq_vec : BIT_VECTOR (data_bits - 1 DOWNTO 0); + VARIABLE i, j, k : INTEGER; + + -- Initialize empty rows + PROCEDURE Init_mem (Bank : BIT_VECTOR (1 DOWNTO 0); Row_index : INTEGER) IS + VARIABLE i, j : INTEGER := 0; + BEGIN + IF Bank = "00" THEN + IF Bank0 (Row_index) = NULL THEN -- Check to see if row empty + Bank0 (Row_index) := NEW ram_type; -- Open new row for access + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP -- Filled row with zeros + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank0 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "01" THEN + IF Bank1 (Row_index) = NULL THEN + Bank1 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank1 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "10" THEN + IF Bank2 (Row_index) = NULL THEN + Bank2 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank2 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "11" THEN + IF Bank3 (Row_index) = NULL THEN + Bank3 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank3 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + END IF; + END; + + -- Burst Counter + PROCEDURE Burst_decode IS + VARIABLE Col_int : INTEGER := 0; + VARIABLE Col_vec, Col_temp : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + BEGIN + -- Advance Burst Counter + Burst_counter := Burst_counter + 1; + + -- Burst Type + IF Mode_reg (3) = '0' THEN + Col_int := TO_INTEGER(Col); + Col_int := Col_int + 1; + TO_BITVECTOR (Col_int, Col_temp); + ELSIF Mode_reg (3) = '1' THEN + TO_BITVECTOR (Burst_counter, Col_vec); + Col_temp (2) := Col_vec (2) XOR Col_brst (2); + Col_temp (1) := Col_vec (1) XOR Col_brst (1); + Col_temp (0) := Col_vec (0) XOR Col_brst (0); + END IF; + + -- Burst Length + IF Burst_length_2 = '1' THEN + Col (0) := Col_temp (0); + ELSIF Burst_length_4 = '1' THEN + Col (1 DOWNTO 0) := Col_temp (1 DOWNTO 0); + ELSIF Burst_length_8 = '1' THEN + Col (2 DOWNTO 0) := Col_temp (2 DOWNTO 0); + ELSE + Col := Col_temp; + END IF; + + -- Burst Read Single Write + IF Write_burst_mode = '1' AND Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Data counter + IF Burst_length_1 = '1' THEN + IF Burst_counter >= 1 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_2 = '1' THEN + IF Burst_counter >= 2 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_4 = '1' THEN + IF Burst_counter >= 4 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_8 = '1' THEN + IF Burst_counter >= 8 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + END IF; + END; + + BEGIN + WAIT ON Sys_clk; + IF Sys_clk'EVENT AND Sys_clk = '1' AND Load = '0' AND Unload = '0' THEN + -- Operation Decode (Optional for showing current command on posedge clock / debug feature) + IF Active_enable = '1' THEN + Operation <= ACT; + ELSIF Aref_enable = '1' THEN + Operation <= A_REF; + ELSIF Burst_term = '1' THEN + Operation <= BST; + ELSIF Mode_reg_enable = '1' THEN + Operation <= LMR; + ELSIF Prech_enable = '1' THEN + Operation <= PRECH; + ELSIF Read_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= READ; + ELSE + Operation <= READ_A; + END IF; + ELSIF Write_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= WRITE; + ELSE + Operation <= WRITE_A; + END IF; + ELSE + Operation <= NOP; + END IF; + + -- Internal Command Pipeline + Command(0) := Command(1); + Command(1) := Command(2); + Command(2) := Command(3); + Command(3) := NOP; + + Col_addr(0) := Col_addr(1); + Col_addr(1) := Col_addr(2); + Col_addr(2) := Col_addr(3); + Col_addr(3) := (OTHERS => '0'); + + Bank_addr(0) := Bank_addr(1); + Bank_addr(1) := Bank_addr(2); + Bank_addr(2) := Bank_addr(3); + Bank_addr(3) := "00"; + + Bank_precharge(0) := Bank_precharge(1); + Bank_precharge(1) := Bank_precharge(2); + Bank_precharge(2) := Bank_precharge(3); + Bank_precharge(3) := "00"; + + A10_precharge(0) := A10_precharge(1); + A10_precharge(1) := A10_precharge(2); + A10_precharge(2) := A10_precharge(3); + A10_precharge(3) := '0'; + + -- Dqm pipeline for Read + Dqm_reg(0) := Dqm_reg(1); + Dqm_reg(1) := TO_BIT(Dqm); + + -- Read or Write with Auto Precharge Counter + IF Auto_precharge (0) = '1' THEN + Count_precharge (0) := Count_precharge (0) + 1; + END IF; + IF Auto_precharge (1) = '1' THEN + Count_precharge (1) := Count_precharge (1) + 1; + END IF; + IF Auto_precharge (2) = '1' THEN + Count_precharge (2) := Count_precharge (2) + 1; + END IF; + IF Auto_precharge (3) = '1' THEN + Count_precharge (3) := Count_precharge (3) + 1; + END IF; + + -- Auto Precharge Timer for tWR + IF (Burst_Length_1 = '1' OR Write_Burst_Mode = '1') THEN + IF (Count_Precharge(0) = 1) THEN + Count_time(0) := NOW; + END IF; + IF (Count_Precharge(1) = 1) THEN + Count_time(1) := NOW; + END IF; + IF (Count_Precharge(2) = 1) THEN + Count_time(2) := NOW; + END IF; + IF (Count_Precharge(3) = 1) THEN + Count_time(3) := NOW; + END IF; + ELSIF (Burst_Length_2 = '1') THEN + IF (Count_Precharge(0) = 2) THEN + Count_time(0) := NOW; + END IF; + IF (Count_Precharge(1) = 2) THEN + Count_time(1) := NOW; + END IF; + IF (Count_Precharge(2) = 2) THEN + Count_time(2) := NOW; + END IF; + IF (Count_Precharge(3) = 2) THEN + Count_time(3) := NOW; + END IF; + ELSIF (Burst_Length_4 = '1') THEN + IF (Count_Precharge(0) = 4) THEN + Count_time(0) := NOW; + END IF; + IF (Count_Precharge(1) = 4) THEN + Count_time(1) := NOW; + END IF; + IF (Count_Precharge(2) = 4) THEN + Count_time(2) := NOW; + END IF; + IF (Count_Precharge(3) = 4) THEN + Count_time(3) := NOW; + END IF; + ELSIF (Burst_Length_8 = '1') THEN + IF (Count_Precharge(0) = 8) THEN + Count_time(0) := NOW; + END IF; + IF (Count_Precharge(1) = 8) THEN + Count_time(1) := NOW; + END IF; + IF (Count_Precharge(2) = 8) THEN + Count_time(2) := NOW; + END IF; + IF (Count_Precharge(3) = 8) THEN + Count_time(3) := NOW; + END IF; + END IF; + + -- tMRD Counter + MRD_chk := MRD_chk + 1; + + -- tWR Counter + WR_counter(0) := WR_counter(0) + 1; + WR_counter(1) := WR_counter(1) + 1; + WR_counter(2) := WR_counter(2) + 1; + WR_counter(3) := WR_counter(3) + 1; + + -- Auto Refresh + IF Aref_enable = '1' THEN + -- Auto Refresh to Auto Refresh + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Auto Refresh" + SEVERITY WARNING; + -- Precharge to Auto Refresh + ASSERT (NOW - RP_chk0 >= tRP OR NOW - RP_chk1 >= tRP OR NOW - RP_chk2 >= tRP OR NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Auto Refresh" + SEVERITY WARNING; + -- All banks must be idle before refresh + IF (Pc_b3 = '0' OR Pc_b2 = '0' OR Pc_b1 = '0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All banks must be Precharge before Auto Refresh" + SEVERITY WARNING; + END IF; + -- Record current tRC time + RC_chk := NOW; + END IF; + + -- Load Mode Register + IF Mode_reg_enable = '1' THEN + Mode_reg <= TO_BITVECTOR (Addr); + IF (Pc_b3 = '0' OR Pc_b2 = '0' OR Pc_b1 = '0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All bank must be Precharge before Load Mode Register" + SEVERITY WARNING; + END IF; + -- REF to LMR + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Load Mode Register" + SEVERITY WARNING; + -- LMR to LMR + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Load Mode Register" + SEVERITY WARNING; + -- Record current tMRD time + MRD_chk := 0; + END IF; + + -- Active Block (latch Bank and Row Address) + IF Active_enable = '1' THEN + IF Ba = "00" AND Pc_b0 = '1' THEN + Act_b0 := '1'; + Pc_b0 := '0'; + B0_row_addr := TO_BITVECTOR (Addr); + RCD_chk0 := NOW; + RAS_chk0 := NOW; + -- Precharge to Active Bank 0 + ASSERT (NOW - RP_chk0 >= tRP) + REPORT "tRP violation during Activate Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '1' THEN + Act_b1 := '1'; + Pc_b1 := '0'; + B1_row_addr := TO_BITVECTOR (Addr); + RCD_chk1 := NOW; + RAS_chk1 := NOW; + -- Precharge to Active Bank 1 + ASSERT (NOW - RP_chk1 >= tRP) + REPORT "tRP violation during Activate Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '1' THEN + Act_b2 := '1'; + Pc_b2 := '0'; + B2_row_addr := TO_BITVECTOR (Addr); + RCD_chk2 := NOW; + RAS_chk2 := NOW; + -- Precharge to Active Bank 2 + ASSERT (NOW - RP_chk2 >= tRP) + REPORT "tRP violation during Activate Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '1' THEN + Act_b3 := '1'; + Pc_b3 := '0'; + B3_row_addr := TO_BITVECTOR (Addr); + RCD_chk3 := NOW; + RAS_chk3 := NOW; + -- Precharge to Active Bank 3 + ASSERT (NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Activate Bank 3" + SEVERITY WARNING; + ELSIF Ba = "00" AND Pc_b0 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 0 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 1 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 2 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 3 is not Precharged" + SEVERITY WARNING; + END IF; + -- Active Bank A to Active Bank B + IF ((Previous_bank /= TO_BITVECTOR (Ba)) AND (NOW - RRD_chk < tRRD)) THEN + ASSERT (FALSE) + REPORT "tRRD violation during Activate" + SEVERITY WARNING; + END IF; + -- LMR to ACT + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Activate" + SEVERITY WARNING; + -- AutoRefresh to Activate + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Activate" + SEVERITY WARNING; + -- Record variable for checking violation + RRD_chk := NOW; + Previous_bank := TO_BITVECTOR (Ba); + END IF; + + -- Precharge Block + IF Prech_enable = '1' THEN + IF Addr(10) = '1' THEN + Pc_b0 := '1'; + Pc_b1 := '1'; + Pc_b2 := '1'; + Pc_b3 := '1'; + Act_b0 := '0'; + Act_b1 := '0'; + Act_b2 := '0'; + Act_b3 := '0'; + RP_chk0 := NOW; + RP_chk1 := NOW; + RP_chk2 := NOW; + RP_chk3 := NOW; + -- Activate to Precharge all banks + ASSERT ((NOW - RAS_chk0 >= tRAS) OR (NOW - RAS_chk1 >= tRAS)) + REPORT "tRAS violation during Precharge all banks" + SEVERITY WARNING; + -- tWR violation check for Write + IF ((NOW - WR_chkp(0) < tWRp) OR (NOW - WR_chkp(1) < tWRp) OR + (NOW - WR_chkp(2) < tWRp) OR (NOW - WR_chkp(3) < tWRp)) THEN + ASSERT (FALSE) + REPORT "tWR violation during Precharge ALL banks" + SEVERITY WARNING; + END IF; + ELSIF Addr(10) = '0' THEN + IF Ba = "00" THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + -- Activate to Precharge bank 0 + ASSERT (NOW - RAS_chk0 >= tRAS) + REPORT "tRAS violation during Precharge bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + -- Activate to Precharge bank 1 + ASSERT (NOW - RAS_chk1 >= tRAS) + REPORT "tRAS violation during Precharge bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + -- Activate to Precharge bank 2 + ASSERT (NOW - RAS_chk2 >= tRAS) + REPORT "tRAS violation during Precharge bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + -- Activate to Precharge bank 3 + ASSERT (NOW - RAS_chk3 >= tRAS) + REPORT "tRAS violation during Precharge bank 3" + SEVERITY WARNING; + END IF; + -- tWR violation check for Write + ASSERT (NOW - WR_chkp(TO_INTEGER(Ba)) >= tWRp) + REPORT "tWR violation during Precharge" + SEVERITY WARNING; + END IF; + -- Terminate a Write Immediately (if same bank or all banks) + IF (Data_in_enable = '1' AND (Bank = TO_BITVECTOR(Ba) OR Addr(10) = '1')) THEN + Data_in_enable := '0'; + END IF; + -- Precharge Command Pipeline for READ + IF CAS_latency_3 = '1' THEN + Command(2) := PRECH; + Bank_precharge(2) := TO_BITVECTOR (Ba); + A10_precharge(2) := TO_BIT(Addr(10)); + ELSIF CAS_latency_2 = '1' THEN + Command(1) := PRECH; + Bank_precharge(1) := TO_BITVECTOR (Ba); + A10_precharge(1) := TO_BIT(Addr(10)); + END IF; + END IF; + + -- Burst Terminate + IF Burst_term = '1' THEN + -- Terminate a Write immediately + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + -- Terminate a Read depend on CAS Latency + IF CAS_latency_3 = '1' THEN + Command(2) := BST; + ELSIF CAS_latency_2 = '1' THEN + Command(1) := BST; + END IF; + END IF; + + -- Read, Write, Column Latch + IF Read_enable = '1' OR Write_enable = '1' THEN + -- Check to see if bank is open (ACT) for Read or Write + IF ((Ba = "00" AND Pc_b0 = '1') OR (Ba = "01" AND Pc_b1 = '1') OR (Ba = "10" AND Pc_b2 = '1') OR (Ba = "11" AND Pc_b3 = '1')) THEN + ASSERT (FALSE) + REPORT "Cannot Read or Write - Bank is not Activated" + SEVERITY WARNING; + END IF; + -- Activate to Read or Write + IF Ba = "00" THEN + ASSERT (NOW - RCD_chk0 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + ASSERT (NOW - RCD_chk1 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + ASSERT (NOW - RCD_chk2 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + ASSERT (NOW - RCD_chk3 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 3" + SEVERITY WARNING; + END IF; + + -- Read Command + IF Read_enable = '1' THEN + -- CAS Latency Pipeline + IF Cas_latency_3 = '1' THEN + IF Addr(10) = '1' THEN + Command(2) := READ_A; + ELSE + Command(2) := READ; + END IF; + Col_addr (2) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0)); + Bank_addr (2) := TO_BITVECTOR (Ba); + ELSIF Cas_latency_2 = '1' THEN + IF Addr(10) = '1' THEN + Command(1) := READ_A; + ELSE + Command(1) := READ; + END IF; + Col_addr (1) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0)); + Bank_addr (1) := TO_BITVECTOR (Ba); + END IF; + + -- Read intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Write Command + ELSIF Write_enable = '1' THEN + IF Addr(10) = '1' THEN + Command(0) := WRITE_A; + ELSE + Command(0) := WRITE; + END IF; + Col_addr (0) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0)); + Bank_addr (0) := TO_BITVECTOR (Ba); + + -- Write intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Write interrupt a Read (terminate Read immediately) + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + + -- Interrupt a Write with Auto Precharge + IF Auto_precharge(TO_INTEGER (RW_interrupt_bank)) = '1' AND Write_precharge(TO_INTEGER (RW_interrupt_bank)) = '1' THEN + RW_interrupt_write(TO_INTEGER (RW_interrupt_bank)) := '1'; + WR_time(TO_INTEGER (RW_interrupt_bank)) := NOW; + END IF; + + -- Interrupt a Read with Auto Precharge + IF Auto_precharge(TO_INTEGER (RW_interrupt_bank)) = '1' AND Read_precharge(TO_INTEGER (RW_interrupt_bank)) = '1' THEN + RW_interrupt_read(TO_INTEGER (RW_interrupt_bank)) := '1'; + END IF; + + -- Read or Write with Auto Precharge + IF Addr(10) = '1' THEN + Auto_precharge (TO_INTEGER(Ba)) := '1'; + Count_precharge (TO_INTEGER(Ba)) := 0; + RW_interrupt_bank := TO_BITVECTOR(Ba); + IF Read_enable = '1' THEN + Read_precharge (TO_INTEGER(Ba)) := '1'; + ELSIF Write_enable = '1' THEN + Write_precharge (TO_INTEGER(Ba)) := '1'; + END IF; + END IF; + END IF; + + -- Read with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. BL/2 cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Read_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(0) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8))) OR + (RW_interrupt_read(0) = '1')) THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + Auto_precharge(0) := '0'; + Read_precharge(0) := '0'; + RW_interrupt_read(0) := '0'; + END IF; + END IF; + IF ((Auto_precharge(1) = '1') AND (Read_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(1) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8))) OR + (RW_interrupt_read(1) = '1')) THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + Auto_precharge(1) := '0'; + Read_precharge(1) := '0'; + RW_interrupt_read(1) := '0'; + END IF; + END IF; + IF ((Auto_precharge(2) = '1') AND (Read_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(2) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8))) OR + (RW_interrupt_read(2) = '1')) THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + Auto_precharge(2) := '0'; + Read_precharge(2) := '0'; + RW_interrupt_read(2) := '0'; + END IF; + END IF; + IF ((Auto_precharge(3) = '1') AND (Read_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(3) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8))) OR + (RW_interrupt_read(3) = '1')) THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + Auto_precharge(3) := '0'; + Read_precharge(3) := '0'; + RW_interrupt_read(3) := '0'; + END IF; + END IF; + + -- Internal Precharge or Bst + IF Command(0) = PRECH THEN -- PRECH terminate a read if same bank or all banks + IF Bank_precharge(0) = Bank OR A10_precharge(0) = '1' THEN + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Command(0) = BST THEN -- BST terminate a read regardless of bank + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + + IF Data_out_enable = '0' THEN + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tOH; + END IF; + + -- Detect Read or Write Command + IF Command(0) = READ OR Command(0) = READ_A THEN + Bank := Bank_addr (0); + Col := Col_addr (0); + Col_brst := Col_addr (0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '0'; + Data_out_enable := '1'; + ELSIF Command(0) = WRITE OR Command(0) = WRITE_A THEN + Bank := Bank_addr(0); + Col := Col_addr(0); + Col_brst := Col_addr(0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '1'; + Data_out_enable := '0'; + END IF; + + -- DQ (Driver / Receiver) + Row_index := TO_INTEGER (Row); + Col_index := TO_INTEGER (Col); + IF Data_in_enable = '1' THEN + IF Dqm = '0' THEN + Init_mem (Bank, Row_index); + IF Bank = "00" THEN + Bank0 (Row_index) (Col_index) := TO_BITVECTOR(Dq); + ELSIF Bank = "01" THEN + Bank1 (Row_index) (Col_index) := TO_BITVECTOR(Dq); + ELSIF Bank = "10" THEN + Bank2 (Row_index) (Col_index) := TO_BITVECTOR(Dq); + ELSIF Bank = "11" THEN + Bank3 (Row_index) (Col_index) := TO_BITVECTOR(Dq); + END IF; + WR_chkp(TO_INTEGER(Bank)) := NOW; + WR_counter(TO_INTEGER(Bank)) := 0; + END IF; + Burst_decode; + ELSIF Data_out_enable = '1' THEN + IF Dqm_reg(0) = '0' THEN + Init_mem (Bank, Row_index); + IF Bank = "00" THEN + Dq <= TRANSPORT TO_STDLOGICVECTOR(Bank0 (Row_index) (Col_index)) AFTER tAC; + ELSIF Bank = "01" THEN + Dq <= TRANSPORT TO_STDLOGICVECTOR(Bank1 (Row_index) (Col_index)) AFTER tAC; + ELSIF Bank = "10" THEN + Dq <= TRANSPORT TO_STDLOGICVECTOR(Bank2 (Row_index) (Col_index)) AFTER tAC; + ELSIF Bank = "11" THEN + Dq <= TRANSPORT TO_STDLOGICVECTOR(Bank3 (Row_index) (Col_index)) AFTER tAC; + END IF; + ELSE + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tHZ; + END IF; + Burst_decode; + END IF; + + ELSIF Sys_clk'EVENT AND Sys_clk = '1' AND Load = '1' AND Unload = '0' THEN + Operation <= FILE_LOAD; + WHILE NOT ENDFILE (load_file) LOOP + READLINE (load_file, l_in); + IF l_in'LENGTH > 0 THEN + read (l_in, row_load, 16); -- Load from HEX to INTEGER + read (l_in, col_load, 16); -- Load from HEX to INTEGER + read (l_in, ba_load); + read (l_in, dq_load, 16); -- Load from HEX to INTEGER + + TO_BITVECTOR (dq_load, dq_vec); + + IF ba_load = "00" THEN + IF Bank0(row_load) = NULL THEN --initialize new memory block + Bank0(row_load) := new ram_type; + FOR i IN (2**(col_bits))-1 DOWNTO 0 LOOP + FOR k IN data_bits - 1 DOWNTO 0 LOOP + Bank0(row_load) (i) (k) := '0'; + END LOOP; + END LOOP; + END IF; + Bank0(row_load)(col_load) := dq_vec; + ELSIF ba_load = "01" THEN + IF Bank1(row_load) = NULL THEN --initialize new memory block + Bank1(row_load) := new ram_type; + FOR i IN (2**(col_bits))-1 DOWNTO 0 LOOP + FOR k IN data_bits - 1 DOWNTO 0 LOOP + Bank1(row_load) (i) (k) := '0'; + END LOOP; + END LOOP; + END IF; + Bank1(row_load)(col_load) := dq_vec; + ELSIF ba_load = "10" THEN + IF Bank2(row_load) = NULL THEN --initialize new memory block + Bank2(row_load) := new ram_type; + FOR i IN (2**(col_bits))-1 DOWNTO 0 LOOP + FOR k IN data_bits - 1 DOWNTO 0 LOOP + Bank2(row_load) (i) (k) := '0'; + END LOOP; + END LOOP; + END IF; + Bank2(row_load)(col_load) := dq_vec; + ELSIF ba_load = "11" THEN + IF Bank3(row_load) = NULL THEN --initialize new memory block + Bank3(row_load) := new ram_type; + FOR i IN (2**(col_bits))-1 DOWNTO 0 LOOP + FOR k IN data_bits - 1 DOWNTO 0 LOOP + Bank3(row_load) (i) (k) := '0'; + END LOOP; + END LOOP; + END IF; + Bank3(row_load)(col_load) := dq_vec; + END IF; + END IF; + END LOOP; + + ELSIF Sys_clk'EVENT AND Sys_clk = '1' AND Load = '0' AND Unload = '1' THEN + Operation <= FILE_UNLOAD; + ASSERT (Row_start < 2**(Addr'HIGH + 1)) + REPORT "Row_start is out of range for device" + SEVERITY ERROR; + ASSERT (Row_end < 2**(Addr'HIGH + 1)) + REPORT "Row_end is out of range for device" + SEVERITY ERROR; + ASSERT ((Row_end - Row_start) >= 0) + REPORT "The Row ranges for Unload is invalid!" + SEVERITY ERROR; + IF ((Row_end - Row_start) >= 0) THEN + FOR i IN Row_start TO Row_end LOOP + j := 1; + IF (Ba = "00") THEN -- Unload Bank 0 + WRITE (l_out0, STRING'("Micron Technology Inc. - Unload Data Array - Bank 0 Row ")); + WRITE (l_out0, i, RIGHT, 3, HEX, FALSE); + WRITELINE (out_file0, l_out0); + FOR k IN 0 TO ((2**Col_bits) - 1) LOOP -- Display Row and Column + IF (j = 1) THEN + WRITE (l_out0, i, RIGHT, 3, HEX, FALSE); + WRITE (l_out0, STRING'(" : ")); + WRITE (l_out0, k, RIGHT, 3, HEX, FALSE); + WRITE (l_out0, STRING'(" : ")); + END IF; + + IF (Bank0 (i) = NULL) THEN -- Row is empty, write message and exit + WRITE (l_out0, STRING'(" Row ")); + WRITE (l_out0, i); + WRITE (l_out0, STRING'(" is empty.")); + WRITELINE (out_file0, l_out0); + EXIT; + ELSE -- Buffering + array_buffer := Bank0 (i) (k); + END IF; + + write_data_var := TO_STDLOGICVECTOR(array_buffer); -- Convert to STD_LOGIC_VECTOR + WRITE (l_out0, write_data_var, RIGHT, 3, HEX, FALSE); -- Write message + IF (j = 16) then + WRITELINE (out_file0, l_out0); + j := 1; + ELSE + j := j + 1; + END IF; + END LOOP; + ELSIF (Ba = "01") THEN + WRITE (l_out1, STRING'("Micron Technology Inc. - Unload Data Array - Bank 1 Row ")); + WRITE (l_out1, i, RIGHT, 3, HEX, FALSE); + WRITELINE (out_file1, l_out1); + FOR k IN 0 TO ((2**Col_bits) - 1) LOOP + IF (j = 1) THEN + WRITE (l_out1, i, RIGHT, 3, HEX, FALSE); + WRITE (l_out1, STRING'(" : ")); + WRITE (l_out1, k, RIGHT, 3, HEX, FALSE); + WRITE (l_out1, STRING'(" : ")); + END IF; + + IF (Bank1 (i) = NULL) THEN + WRITE (l_out1, STRING'(" Row ")); + WRITE (l_out1, i); + WRITE (l_out1, STRING'(" is empty.")); + WRITELINE (out_file1, l_out1); + EXIT; + ELSE + array_buffer := Bank1 (i) (k); + END IF; + + write_data_var := TO_STDLOGICVECTOR(array_buffer); + WRITE (l_out1, write_data_var, RIGHT, 3, HEX, FALSE); + IF (j = 16) then + WRITELINE (out_file1, l_out1); + j := 1; + ELSE + j := j + 1; + END IF; + END LOOP; + ELSIF (Ba = "10") THEN + WRITE (l_out2, STRING'("Micron Technology Inc. - Unload Data Array - Bank 2 Row ")); + WRITE (l_out2, i, RIGHT, 3, HEX, FALSE); + WRITELINE (out_file2, l_out2); + FOR k IN 0 TO ((2**Col_bits) - 1) LOOP + IF (j = 1) THEN + WRITE (l_out2, i, RIGHT, 3, HEX, FALSE); + WRITE (l_out2, STRING'(" : ")); + WRITE (l_out2, k, RIGHT, 3, HEX, FALSE); + WRITE (l_out2, STRING'(" : ")); + END IF; + + IF (Bank2 (i) = NULL) THEN + WRITE (l_out2, STRING'(" Row ")); + WRITE (l_out2, i); + WRITE (l_out2, STRING'(" is empty.")); + WRITELINE (out_file2, l_out2); + EXIT; + ELSE + array_buffer := Bank2 (i) (k); + END IF; + + write_data_var := TO_STDLOGICVECTOR(array_buffer); + WRITE (l_out2, write_data_var, RIGHT, 3, HEX, FALSE); + IF (j = 16) then + WRITELINE (out_file2, l_out2); + j := 1; + ELSE + j := j + 1; + END IF; + END LOOP; + ELSIF (Ba = "11") THEN + WRITE (l_out3, STRING'("Micron Technology Inc. - Unload Data Array - Bank 3 Row ")); + WRITE (l_out3, i, RIGHT, 3, HEX, FALSE); + WRITELINE (out_file3, l_out3); + FOR k IN 0 TO ((2**Col_bits) - 1) LOOP + IF (j = 1) THEN + WRITE (l_out3, i, RIGHT, 3, HEX, FALSE); + WRITE (l_out3, STRING'(" : ")); + WRITE (l_out3, k, RIGHT, 3, HEX, FALSE); + WRITE (l_out3, STRING'(" : ")); + END IF; + + IF (Bank3 (i) = NULL) THEN + WRITE (l_out3, STRING'(" Row ")); + WRITE (l_out3, i); + WRITE (l_out3, STRING'(" is empty.")); + WRITELINE (out_file3, l_out3); + EXIT; + ELSE + array_buffer := Bank3 (i) (k); + END IF; + + write_data_var := TO_STDLOGICVECTOR(array_buffer); + WRITE (l_out3, write_data_var, RIGHT, 3, HEX, FALSE); + IF (j = 16) then + WRITELINE (out_file3, l_out3); + j := 1; + ELSE + j := j + 1; + END IF; + END LOOP; + END IF; + END LOOP; + END IF; + + END IF; + + -- Write with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. tWR cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Write_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(0) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8))) OR + (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 2)) THEN + Auto_precharge(0) := '0'; + Write_precharge(0) := '0'; + RW_interrupt_write(0) := '0'; + WAIT FOR tWRa; + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + END IF; + END IF; + + IF ((Auto_precharge(1) = '1') AND (Write_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(1) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8))) OR + (RW_interrupt_write(1) = '1' AND WR_counter(1) >= 2)) THEN + Auto_precharge(1) := '0'; + Write_precharge(1) := '0'; + RW_interrupt_write(1) := '0'; + WAIT FOR tWRa; + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + END IF; + END IF; + + IF ((Auto_precharge(2) = '1') AND (Write_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(2) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8))) OR + (RW_interrupt_write(2) = '1' AND WR_counter(2) >= 2)) THEN + Auto_precharge(2) := '0'; + Write_precharge(2) := '0'; + RW_interrupt_write(2) := '0'; + WAIT FOR tWRa; + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + END IF; + END IF; + + IF ((Auto_precharge(3) = '1') AND (Write_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(3) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8))) OR + (RW_interrupt_write(3) = '1' AND WR_counter(3) >= 2)) THEN + Auto_precharge(3) := '0'; + Write_precharge(3) := '0'; + RW_interrupt_write(3) := '0'; + WAIT FOR tWRa; + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + END IF; + END IF; + + -- Checking internal wires (Optional for debug purpose) + Pre_chk (0) <= Pc_b0; + Pre_chk (1) <= Pc_b1; + Pre_chk (2) <= Pc_b2; + Pre_chk (3) <= Pc_b3; + Act_chk (0) <= Act_b0; + Act_chk (1) <= Act_b1; + Act_chk (2) <= Act_b2; + Act_chk (3) <= Act_b3; + Dq_in_chk <= Data_in_enable; + Dq_out_chk <= Data_out_enable; + Bank_chk <= Bank; + Row_chk <= Row; + Col_chk <= Col; + END PROCESS; + + + -- Clock timing checks + Clock_check : PROCESS + VARIABLE Clk_low, Clk_high : TIME := 0 ns; + BEGIN + WAIT ON Clk; + IF (Clk = '1' AND NOW >= 10 ns) THEN + ASSERT (NOW - Clk_low >= tCL) + REPORT "tCL violation" + SEVERITY WARNING; + ASSERT (NOW - Clk_high >= tCK) + REPORT "tCK violation" + SEVERITY WARNING; + Clk_high := NOW; + ELSIF (Clk = '0' AND NOW /= 0 ns) THEN + ASSERT (NOW - Clk_high >= tCH) + REPORT "tCH violation" + SEVERITY WARNING; + Clk_low := NOW; + END IF; + END PROCESS; + + -- Setup timing checks + Setup_check : PROCESS + BEGIN + WAIT ON Clk; + IF Clk = '1' THEN + ASSERT(Cke'LAST_EVENT >= tCKS) + REPORT "CKE Setup time violation -- tCKS" + SEVERITY WARNING; + ASSERT(Cs_n'LAST_EVENT >= tCMS) + REPORT "CS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT >= tCMS) + REPORT "CAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT >= tCMS) + REPORT "RAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT >= tCMS) + REPORT "WE# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT >= tCMS) + REPORT "Dqm Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Addr'LAST_EVENT >= tAS) + REPORT "ADDR Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT >= tAS) + REPORT "BA Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Dq'LAST_EVENT >= tDS) + REPORT "Dq Setup time violation -- tDS" + SEVERITY WARNING; + END IF; + END PROCESS; + + -- Hold timing checks + Hold_check : PROCESS + BEGIN + WAIT ON Clk'DELAYED (tCKH), Clk'DELAYED (tCMH), Clk'DELAYED (tAH), Clk'DELAYED (tDH); + IF Clk'DELAYED (tCKH) = '1' THEN + ASSERT(Cke'LAST_EVENT > tCKH) + REPORT "CKE Hold time violation -- tCKH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tCMH) = '1' THEN + ASSERT(Cs_n'LAST_EVENT > tCMH) + REPORT "CS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT > tCMH) + REPORT "CAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT > tCMH) + REPORT "RAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT > tCMH) + REPORT "WE# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT > tCMH) + REPORT "Dqm Hold time violation -- tCMH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tAH) = '1' THEN + ASSERT(Addr'LAST_EVENT > tAH) + REPORT "ADDR Hold time violation -- tAH" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT > tAH) + REPORT "BA Hold time violation -- tAH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tDH) = '1' THEN + ASSERT(Dq'LAST_EVENT > tDH) + REPORT "Dq Hold time violation -- tDH" + SEVERITY WARNING; + END IF; + END PROCESS; + +END behave; diff --git a/lib/models/memory/sdram/mt48lc8m8a2/mti_pkg.vhd b/lib/models/memory/sdram/mt48lc8m8a2/mti_pkg.vhd new file mode 100644 index 0000000..9e4f824 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m8a2/mti_pkg.vhd @@ -0,0 +1,129 @@ +--***************************************************************************** +-- +-- Micron Semiconductor Products, Inc. +-- +-- Copyright 1997, Micron Semiconductor Products, Inc. +-- All rights reserved. +-- +--***************************************************************************** + +LIBRARY work; +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +PACKAGE mti_pkg IS + + FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER; + FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER; + FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER; + PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR); + +END mti_pkg; + +PACKAGE BODY mti_pkg IS + + -- Convert BIT to INTEGER + FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + IF input = '1' THEN + result := weight; + ELSE + result := 0; -- if unknowns, default to logic 0 + END IF; + RETURN result; + END TO_INTEGER; + + -- Convert BIT_VECTOR to INTEGER + FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + FOR i IN input'LOW TO input'HIGH LOOP + IF input(i) = '1' THEN + result := result + weight; + ELSE + result := result + 0; -- if unknowns, default to logic 0 + END IF; + weight := weight * 2; + END LOOP; + RETURN result; + END TO_INTEGER; + + -- Convert STD_LOGIC_VECTOR to INTEGER + FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + FOR i IN input'LOW TO input'HIGH LOOP + IF input(i) = '1' THEN + result := result + weight; + ELSE + result := result + 0; -- if unknowns, default to logic 0 + END IF; + weight := weight * 2; + END LOOP; + RETURN result; + END TO_INTEGER; + + -- Conver integer to bit_vector + PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR) IS + VARIABLE work,offset,outputlen,j : INTEGER := 0; + BEGIN + --length of vector + IF output'LENGTH > 32 THEN + outputlen := 32; + offset := output'LENGTH - 32; + IF input >= 0 THEN + FOR i IN offset-1 DOWNTO 0 LOOP + output(output'HIGH - i) := '0'; + END LOOP; + ELSE + FOR i IN offset-1 DOWNTO 0 LOOP + output(output'HIGH - i) := '1'; + END LOOP; + END IF; + ELSE + outputlen := output'LENGTH; + END IF; + --positive value + IF (input >= 0) THEN + work := input; + j := outputlen - 1; + FOR i IN 1 to 32 LOOP + IF j >= 0 then + IF (work MOD 2) = 0 THEN + output(output'HIGH-j-offset) := '0'; + ELSE + output(output'HIGH-j-offset) := '1'; + END IF; + END IF; + work := work / 2; + j := j - 1; + END LOOP; + IF outputlen = 32 THEN + output(output'HIGH) := '0'; + END IF; + --negative value + ELSE + work := (-input) - 1; + j := outputlen - 1; + FOR i IN 1 TO 32 LOOP + IF j>= 0 THEN + IF (work MOD 2) = 0 THEN + output(output'HIGH-j-offset) := '1'; + ELSE + output(output'HIGH-j-offset) := '0'; + END IF; + END IF; + work := work / 2; + j := j - 1; + END LOOP; + IF outputlen = 32 THEN + output(output'HIGH) := '1'; + END IF; + END IF; + END TO_BITVECTOR; + +END mti_pkg; diff --git a/lib/models/memory/sdram/mt48lc8m8a2/outdata0.txt b/lib/models/memory/sdram/mt48lc8m8a2/outdata0.txt new file mode 100644 index 0000000..fe40f95 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m8a2/outdata0.txt @@ -0,0 +1,35 @@ +Micron Technology Inc. - Unload Data Array - Bank 0 Row 0 + 0 : 0 : 0A 0B 02 03 04 05 06 07 08 09 00 00 00 00 00 00 + 0 : 10 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 20 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 30 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 40 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 50 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 60 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 70 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 80 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 90 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 100 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 110 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 120 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 130 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 140 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 150 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 160 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 170 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 180 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 190 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +Micron Technology Inc. - Unload Data Array - Bank 0 Row 1 + 1 : 0 : Row 1 is empty. diff --git a/lib/models/memory/sdram/mt48lc8m8a2/outdata1.txt b/lib/models/memory/sdram/mt48lc8m8a2/outdata1.txt new file mode 100644 index 0000000..ae9d17a --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m8a2/outdata1.txt @@ -0,0 +1,35 @@ +Micron Technology Inc. - Unload Data Array - Bank 1 Row 0 + 0 : 0 : 14 15 12 13 14 15 16 17 18 19 00 00 00 00 00 00 + 0 : 10 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 20 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 30 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 40 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 50 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 60 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 70 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 80 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 90 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 100 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 110 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 120 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 130 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 140 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 150 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 160 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 170 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 180 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 190 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +Micron Technology Inc. - Unload Data Array - Bank 1 Row 1 + 1 : 0 : Row 1 is empty. diff --git a/lib/models/memory/sdram/mt48lc8m8a2/outdata2.txt b/lib/models/memory/sdram/mt48lc8m8a2/outdata2.txt new file mode 100644 index 0000000..d67f6e4 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m8a2/outdata2.txt @@ -0,0 +1,35 @@ +Micron Technology Inc. - Unload Data Array - Bank 2 Row 0 + 0 : 0 : 1E 1F 22 23 24 25 26 27 28 29 00 00 00 00 00 00 + 0 : 10 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 20 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 30 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 40 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 50 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 60 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 70 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 80 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 90 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 100 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 110 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 120 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 130 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 140 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 150 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 160 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 170 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 180 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 190 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +Micron Technology Inc. - Unload Data Array - Bank 2 Row 1 + 1 : 0 : Row 1 is empty. diff --git a/lib/models/memory/sdram/mt48lc8m8a2/outdata3.txt b/lib/models/memory/sdram/mt48lc8m8a2/outdata3.txt new file mode 100644 index 0000000..1d4e144 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m8a2/outdata3.txt @@ -0,0 +1,35 @@ +Micron Technology Inc. - Unload Data Array - Bank 3 Row 0 + 0 : 0 : 28 29 32 33 34 35 36 37 38 39 00 00 00 00 00 00 + 0 : 10 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 20 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 30 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 40 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 50 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 60 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 70 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 80 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 90 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 100 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 110 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 120 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 130 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 140 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 150 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 160 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 170 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 180 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 190 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 : 1F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +Micron Technology Inc. - Unload Data Array - Bank 3 Row 1 + 1 : 0 : Row 1 is empty. diff --git a/lib/models/memory/sdram/mt48lc8m8a2/readme.txt b/lib/models/memory/sdram/mt48lc8m8a2/readme.txt new file mode 100644 index 0000000..c594a7e --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m8a2/readme.txt @@ -0,0 +1,14 @@ +To operate the test bench for the Micron SDRAM VHDL model, follow the directions +given below: + +1. Be sure all supporting files for the SDRAM are compiled into your library: + + util1164.vhd + stdlogar.vhd + io_utils.vhd + mti_pkg.vhd + +2. Next, compile the mt48lc8m8a2.vhd file and the test.vhd file. + +3. Simulate the "tb" architecture. This is the testbench for the 64Mb SDRAM. + diff --git a/lib/models/memory/sdram/mt48lc8m8a2/stdlogar.vhd b/lib/models/memory/sdram/mt48lc8m8a2/stdlogar.vhd new file mode 100644 index 0000000..e435ea2 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m8a2/stdlogar.vhd @@ -0,0 +1,2247 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990,1991,1992 by Synopsys, Inc. All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_ARITH -- +-- -- +-- Purpose: -- +-- A set of arithemtic, conversion, and comparison functions -- +-- for SIGNED, UNSIGNED, SMALL_INT, INTEGER, -- +-- STD_ULOGIC, STD_LOGIC, and STD_LOGIC_VECTOR. -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +package std_logic_arith is + + type UNSIGNED is array (NATURAL range <>) of STD_LOGIC; + type SIGNED is array (NATURAL range <>) of STD_LOGIC; + subtype SMALL_INT is INTEGER range 0 to 1; + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: INTEGER) return SIGNED; + function "+"(L: INTEGER; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: INTEGER) return SIGNED; + function "-"(L: INTEGER; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "+"(L: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED) return SIGNED; + function "-"(L: SIGNED) return SIGNED; + function "ABS"(L: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED) return STD_LOGIC_VECTOR; + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "*"(L: SIGNED; R: SIGNED) return SIGNED; + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + + function CONV_INTEGER(ARG: INTEGER) return INTEGER; + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER; + function CONV_INTEGER(ARG: SIGNED) return INTEGER; + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT; + + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED; + + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED; + + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + -- zero extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- returns STD_LOGIC_VECTOR(SIZE-1 downto 0) + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + + -- sign extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- return STD_LOGIC_VECTOR(SIZE-1 downto 0) + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end Std_logic_arith; + + + +library IEEE; +use IEEE.std_logic_1164.all; + +package body std_logic_arith is + + function max(L, R: INTEGER) return INTEGER is + begin + if L > R then + return L; + else + return R; + end if; + end; + + + function min(L, R: INTEGER) return INTEGER is + begin + if L < R then + return L; + else + return R; + end if; + end; + + -- synopsys synthesis_off + type tbl_type is array (STD_ULOGIC) of STD_ULOGIC; + constant tbl_BINARY : tbl_type := + ('X', 'X', '0', '1', 'X', 'X', '0', '1', 'X'); + -- synopsys synthesis_on + + -- synopsys synthesis_off + type tbl_mvl9_boolean is array (STD_ULOGIC) of boolean; + constant IS_X : tbl_mvl9_boolean := + (true, true, false, false, true, true, false, false, true); + -- synopsys synthesis_on + + + + function MAKE_BINARY(A : STD_ULOGIC) return STD_ULOGIC is + -- synopsys built_in SYN_FEED_THRU + begin + -- synopsys synthesis_off + if (IS_X(A)) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + return ('X'); + end if; + return tbl_BINARY(A); + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return UNSIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : UNSIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return SIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : SIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return UNSIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : UNSIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return SIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : SIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + + + -- Type propagation function which returns a signed type with the + -- size of the left arg. + function LEFT_SIGNED_ARG(A,B: SIGNED) return SIGNED is + variable Z: SIGNED (A'left downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns an unsigned type with the + -- size of the left arg. + function LEFT_UNSIGNED_ARG(A,B: UNSIGNED) return UNSIGNED is + variable Z: UNSIGNED (A'left downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns a signed type with the + -- size of the result of a signed multiplication + function MULT_SIGNED_ARG(A,B: SIGNED) return SIGNED is + variable Z: SIGNED ((A'length+B'length-1) downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns an unsigned type with the + -- size of the result of a unsigned multiplication + function MULT_UNSIGNED_ARG(A,B: UNSIGNED) return UNSIGNED is + variable Z: UNSIGNED ((A'length+B'length-1) downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + + + function mult(A,B: SIGNED) return SIGNED is + + variable BA: SIGNED((A'length+B'length-1) downto 0); + variable PA: SIGNED((A'length+B'length-1) downto 0); + variable AA: SIGNED(A'length downto 0); + variable neg: STD_ULOGIC; + constant one : UNSIGNED(1 downto 0) := "01"; + + -- pragma map_to_operator MULT_TC_OP + -- pragma type_function MULT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + PA := (others => 'X'); + return(PA); + end if; + PA := (others => '0'); + neg := B(B'left) xor A(A'left); + BA := CONV_SIGNED(('0' & ABS(B)),(A'length+B'length)); + AA := '0' & ABS(A); + for i in 0 to A'length-1 loop + if AA(i) = '1' then + PA := PA+BA; + end if; + BA := SHL(BA,one); + end loop; + if (neg= '1') then + return(-PA); + else + return(PA); + end if; + end; + + function mult(A,B: UNSIGNED) return UNSIGNED is + + variable BA: UNSIGNED((A'length+B'length-1) downto 0); + variable PA: UNSIGNED((A'length+B'length-1) downto 0); + constant one : UNSIGNED(1 downto 0) := "01"; + + -- pragma map_to_operator MULT_UNS_OP + -- pragma type_function MULT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + PA := (others => 'X'); + return(PA); + end if; + PA := (others => '0'); + BA := CONV_UNSIGNED(B,(A'length+B'length)); + for i in 0 to A'length-1 loop + if A(i) = '1' then + PA := PA+BA; + end if; + BA := SHL(BA,one); + end loop; + return(PA); + end; + + -- subtract two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function minus(A, B: SIGNED) return SIGNED is + variable carry: STD_ULOGIC; + variable BV: STD_ULOGIC_VECTOR (A'left downto 0); + variable sum: SIGNED (A'left downto 0); + + -- pragma map_to_operator SUB_TC_OP + + -- pragma type_function LEFT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '1'; + BV := not STD_ULOGIC_VECTOR(B); + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + -- add two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function plus(A, B: SIGNED) return SIGNED is + variable carry: STD_ULOGIC; + variable BV, sum: SIGNED (A'left downto 0); + + -- pragma map_to_operator ADD_TC_OP + -- pragma type_function LEFT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '0'; + BV := B; + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + + -- subtract two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_minus(A, B: UNSIGNED) return UNSIGNED is + variable carry: STD_ULOGIC; + variable BV: STD_ULOGIC_VECTOR (A'left downto 0); + variable sum: UNSIGNED (A'left downto 0); + + -- pragma map_to_operator SUB_UNS_OP + -- pragma type_function LEFT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '1'; + BV := not STD_ULOGIC_VECTOR(B); + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + -- add two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_plus(A, B: UNSIGNED) return UNSIGNED is + variable carry: STD_ULOGIC; + variable BV, sum: UNSIGNED (A'left downto 0); + + -- pragma map_to_operator ADD_UNS_OP + -- pragma type_function LEFT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '0'; + BV := B; + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + + + function "*"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to mult + begin + return mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to mult + begin + return mult(CONV_UNSIGNED(L, L'length), + CONV_UNSIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + begin + return mult(CONV_SIGNED(L, L'length+1), + CONV_SIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to plus + begin + return mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length+1)); -- pragma label mult + end; + + + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + begin + return STD_LOGIC_VECTOR (mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length))); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + begin + return STD_LOGIC_VECTOR (mult(CONV_UNSIGNED(L, L'length), + CONV_UNSIGNED(R, R'length))); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + begin + return STD_LOGIC_VECTOR (mult(CONV_SIGNED(L, L'length+1), + CONV_SIGNED(R, R'length))); -- pragma label mult + end; + + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + begin + return STD_LOGIC_VECTOR (mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length+1))); -- pragma label mult + end; + + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "+"(L: SIGNED; R: INTEGER) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: INTEGER; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)) ; -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))) ; -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label plus + end; + + + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_minus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: SIGNED; R: INTEGER) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: INTEGER; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1); + end; + + + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (unsigned_minus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length + 1, R'length); + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := max(L'length, R'length + 1); + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), + CONV_SIGNED(R, length)), + length-1)); + end; + + + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR (minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length))); -- pragma label minus + end; + + + + + function "+"(L: UNSIGNED) return UNSIGNED is + begin + return L; + end; + + + function "+"(L: SIGNED) return SIGNED is + begin + return L; + end; + + + function "-"(L: SIGNED) return SIGNED is + -- pragma label_applies_to minus + begin + return 0 - L; -- pragma label minus + end; + + + function "ABS"(L: SIGNED) return SIGNED is + begin + if (L(L'left) = '0' or L(L'left) = 'L') then + return L; + else + return 0 - L; + end if; + end; + + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L); + end; + + + function "+"(L: SIGNED) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L); + end; + + + function "-"(L: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable tmp: SIGNED(L'length-1 downto 0); + begin + tmp := 0 - L; -- pragma label minus + return STD_LOGIC_VECTOR (tmp); + end; + + + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR is + variable tmp: SIGNED(L'length-1 downto 0); + begin + if (L(L'left) = '0' or L(L'left) = 'L') then + return STD_LOGIC_VECTOR (L); + else + tmp := 0 - L; + return STD_LOGIC_VECTOR (tmp); + end if; + end; + + + -- Type propagation function which returns the type BOOLEAN + function UNSIGNED_RETURN_BOOLEAN(A,B: UNSIGNED) return BOOLEAN is + variable Z: BOOLEAN; + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns the type BOOLEAN + function SIGNED_RETURN_BOOLEAN(A,B: SIGNED) return BOOLEAN is + variable Z: BOOLEAN; + -- pragma return_port_name Z + begin + return(Z); + end; + + + -- compare two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function is_less(A, B: SIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LT_TC_OP + -- pragma type_function SIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + if A(sign) /= B(sign) then + result := A(sign) = '1'; + else + result := FALSE; + for i in 0 to sign-1 loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + end if; + return result; + end; + + + -- compare two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function is_less_or_equal(A, B: SIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LEQ_TC_OP + -- pragma type_function SIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + if A(sign) /= B(sign) then + result := A(sign) = '1'; + else + result := TRUE; + for i in 0 to sign-1 loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + end if; + return result; + end; + + + + -- compare two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_is_less(A, B: UNSIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LT_UNS_OP + -- pragma type_function UNSIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + result := FALSE; + for i in 0 to sign loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + return result; + end; + + + -- compare two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_is_less_or_equal(A, B: UNSIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LEQ_UNS_OP + -- pragma type_function UNSIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + result := TRUE; + for i in 0 to sign loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + return result; + end; + + + + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length, R'length); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := L'length + 1; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := R'length + 1; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := L'length; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := R'length; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less_or_equal(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length, R'length); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := L'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := R'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := L'length; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + constant length: INTEGER := R'length; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less(CONV_UNSIGNED(R, length), + CONV_UNSIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length, R'length); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := L'length + 1; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := R'length + 1; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := L'length; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + constant length: INTEGER := R'length; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less_or_equal(CONV_UNSIGNED(R, length), + CONV_UNSIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length, R'length); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := L'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := R'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := L'length; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + constant length: INTEGER := R'length; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + + + -- for internal use only. Assumes SIGNED arguments of equal length. + function bitwise_eql(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) + return BOOLEAN is + -- pragma built_in SYN_EQL + begin + for i in L'range loop + if L(i) /= R(i) then + return FALSE; + end if; + end loop; + return TRUE; + end; + + -- for internal use only. Assumes SIGNED arguments of equal length. + function bitwise_neq(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) + return BOOLEAN is + -- pragma built_in SYN_NEQ + begin + for i in L'range loop + if L(i) /= R(i) then + return TRUE; + end if; + end loop; + return FALSE; + end; + + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_UNSIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_UNSIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length + 1, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length + 1); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length + 1; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := R'length + 1; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: INTEGER; R: SIGNED) return BOOLEAN is + constant length: INTEGER := R'length; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_UNSIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_UNSIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length + 1, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := max(L'length, R'length + 1); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length + 1; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + constant length: INTEGER := R'length + 1; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN is + constant length: INTEGER := L'length; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN is + constant length: INTEGER := R'length; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is UNSIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb downto 2**i) := + result(result_msb - 2**i downto 0); + end if; + result := temp; + end if; + end loop; + return result; + end; + + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is SIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb downto 2**i) := + result(result_msb - 2**i downto 0); + end if; + result := temp; + end if; + end loop; + return result; + end; + + + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is UNSIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb - 2**i downto 0) := + result(result_msb downto 2**i); + end if; + result := temp; + end if; + end loop; + return result; + end; + + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED is + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is SIGNED (result_msb downto 0); + variable result, temp: rtype; + variable sign_bit: STD_ULOGIC; + begin + control := MAKE_BINARY(COUNT); + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := ARG; + sign_bit := ARG(ARG'left); + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => sign_bit); + if 2**i <= result_msb then + temp(result_msb - 2**i downto 0) := + result(result_msb downto 2**i); + end if; + result := temp; + end if; + end loop; + return result; + end; + + + + + function CONV_INTEGER(ARG: INTEGER) return INTEGER is + begin + return ARG; + end; + + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER is + variable result: INTEGER; + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_UNSIGNED_TO_INTEGER + begin + -- synopsys synthesis_off + assert ARG'length <= 31 + report "ARG is too large in CONV_INTEGER" + severity FAILURE; + result := 0; + for i in ARG'range loop + result := result * 2; + tmp := tbl_BINARY(ARG(i)); + if tmp = '1' then + result := result + 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_INTEGER(ARG: SIGNED) return INTEGER is + variable result: INTEGER; + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_SIGNED_TO_INTEGER + begin + -- synopsys synthesis_off + assert ARG'length <= 32 + report "ARG is too large in CONV_INTEGER" + severity FAILURE; + result := 0; + for i in ARG'range loop + if i /= ARG'left then + result := result * 2; + tmp := tbl_BINARY(ARG(i)); + if tmp = '1' then + result := result + 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + end if; + end if; + end loop; + tmp := MAKE_BINARY(ARG(ARG'left)); + if tmp = '1' then + if ARG'length = 32 then + result := (result - 2**30) - 2**30; + else + result := result - (2 ** (ARG'length-1)); + end if; + end if; + return result; + -- synopsys synthesis_on + end; + + + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT is + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_FEED_THRU + begin + -- synopsys synthesis_off + tmp := tbl_BINARY(ARG); + if tmp = '1' then + return 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + return 0; + else + return 0; + end if; + -- synopsys synthesis_on + end; + + + -- convert an integer to a unsigned STD_ULOGIC_VECTOR + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED is + variable result: UNSIGNED(SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_UNSIGNED + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable new_bounds: UNSIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable new_bounds: UNSIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED is + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + + -- convert an integer to a 2's complement STD_ULOGIC_VECTOR + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED is + variable result: SIGNED (SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_SIGNED + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is SIGNED (SIZE-1 downto 0); + variable new_bounds : SIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is SIGNED (SIZE-1 downto 0); + variable new_bounds : SIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED is + subtype rtype is SIGNED (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + + -- convert an integer to an STD_LOGIC_VECTOR + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR is + variable result: STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_SIGNED + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) return STD_LOGIC_VECTOR is + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) + return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds: STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + +end std_logic_arith; diff --git a/lib/models/memory/sdram/mt48lc8m8a2/test.do b/lib/models/memory/sdram/mt48lc8m8a2/test.do new file mode 100644 index 0000000..ea4831f --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m8a2/test.do @@ -0,0 +1,5 @@ +vcom mt48lc8m8a2.vhd +vcom test.vhd +vsim tb +do wave.do +run -all diff --git a/lib/models/memory/sdram/mt48lc8m8a2/test.txt b/lib/models/memory/sdram/mt48lc8m8a2/test.txt new file mode 100644 index 0000000..9f8367a --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m8a2/test.txt @@ -0,0 +1,103 @@ +0 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +22 ns 1 0 1 1 1 0 00 0 -100 1 0 0 0 +32 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +42 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +52 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +62 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +72 ns 1 0 0 1 0 0 00 1024 -100 0 0 0 0 +82 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +92 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +102 ns 1 0 0 0 1 0 00 0 -100 0 0 0 0 +112 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +122 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +132 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +142 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +152 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +162 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +172 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +182 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +192 ns 1 0 0 0 1 0 00 0 -100 0 0 0 0 +202 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +212 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +222 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +232 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +242 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +252 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +262 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +272 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +282 ns 1 0 0 0 0 0 00 49 -100 0 0 0 0 +292 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +302 ns 1 0 0 1 1 0 00 0 -100 0 0 0 0 +312 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +322 ns 1 0 1 0 0 0 00 1024 10 0 0 0 0 +332 ns 1 0 1 1 1 0 00 0 11 0 0 0 0 +342 ns 1 0 0 1 1 0 01 0 12 0 0 0 0 +352 ns 1 0 1 1 1 0 00 0 13 0 0 0 0 +362 ns 1 0 1 1 1 0 00 0 14 0 0 0 0 +372 ns 1 0 1 1 1 0 00 0 15 0 0 0 0 +382 ns 1 0 1 1 1 0 00 0 16 0 0 0 0 +392 ns 1 0 1 1 1 0 00 0 17 0 0 0 0 +402 ns 1 0 1 0 0 0 01 1024 20 0 0 0 0 +412 ns 1 0 1 1 1 0 00 0 21 0 0 0 0 +422 ns 1 0 0 1 1 0 10 0 22 0 0 0 0 +432 ns 1 0 1 1 1 0 00 0 23 0 0 0 0 +442 ns 1 0 1 1 1 0 00 0 24 0 0 0 0 +452 ns 1 0 1 1 1 0 00 0 25 0 0 0 0 +462 ns 1 0 1 1 1 0 00 0 26 0 0 0 0 +472 ns 1 0 1 1 1 0 00 0 27 0 0 0 0 +482 ns 1 0 1 0 0 0 10 1024 30 0 0 0 0 +492 ns 1 0 1 1 1 0 00 0 31 0 0 0 0 +502 ns 1 0 0 1 1 0 11 0 32 0 0 0 0 +512 ns 1 0 1 1 1 0 00 0 33 0 0 0 0 +522 ns 1 0 1 1 1 0 00 0 34 0 0 0 0 +532 ns 1 0 1 1 1 0 00 0 35 0 0 0 0 +542 ns 1 0 1 1 1 0 00 0 36 0 0 0 0 +552 ns 1 0 1 1 1 0 00 0 37 0 0 0 0 +562 ns 1 0 1 0 0 0 11 1024 40 0 0 0 0 +572 ns 1 0 1 1 1 0 00 0 41 0 0 0 0 +582 ns 1 0 0 1 1 0 00 0 42 0 0 0 0 +592 ns 1 0 1 1 1 0 00 0 43 0 0 0 0 +602 ns 1 0 1 1 1 0 00 0 44 0 0 0 0 +612 ns 1 0 1 1 1 0 00 0 45 0 0 0 0 +622 ns 1 0 1 1 1 0 00 0 46 0 0 0 0 +632 ns 1 0 1 1 1 0 00 0 47 0 0 0 0 +642 ns 1 0 1 0 1 0 00 1024 -100 0 0 0 0 +652 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +662 ns 1 0 0 1 1 0 01 0 -100 0 0 0 0 +672 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +682 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +692 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +702 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +712 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +722 ns 1 0 1 0 1 0 01 1024 -100 0 0 0 0 +732 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +742 ns 1 0 0 1 1 0 10 0 -100 0 0 0 0 +752 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +762 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +772 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +782 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +792 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +802 ns 1 0 1 0 1 0 10 1024 -100 0 0 0 0 +812 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +822 ns 1 0 0 1 1 0 11 0 -100 0 0 0 0 +832 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +842 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +852 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +862 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +872 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +882 ns 1 0 1 0 1 0 11 1024 -100 0 0 0 0 +892 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +902 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +912 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +922 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +932 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +942 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +952 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +962 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +972 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +982 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 +992 ns 1 0 1 1 1 0 00 0 -100 0 1 0 1 +1002 ns 1 0 1 1 1 0 01 0 -100 0 1 0 1 +1012 ns 1 0 1 1 1 0 10 0 -100 0 1 0 1 +1022 ns 1 0 1 1 1 0 11 0 -100 0 1 0 1 +1032 ns 1 0 1 1 1 0 00 0 -100 0 0 0 0 diff --git a/lib/models/memory/sdram/mt48lc8m8a2/test.vhd b/lib/models/memory/sdram/mt48lc8m8a2/test.vhd new file mode 100644 index 0000000..a88b117 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m8a2/test.vhd @@ -0,0 +1,196 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE std.textio.ALL; +USE work.std_logic_arith.ALL; +USE work.util_1164.ALL; +USE work.mti_pkg.ALL; + +ENTITY tb IS +END tb; + + +ARCHITECTURE test OF tb IS + CONSTANT addr_bits : INTEGER := 12; + CONSTANT data_bits : INTEGER := 8; + CONSTANT clk_start : time := 5 ns; + CONSTANT clk_period : time := 10 ns; + CONSTANT continue_time : time := 10 ns; + + COMPONENT mt48lc8m8a2 + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '1'; + Cs_n : IN STD_LOGIC := '1'; + Cas_n : IN STD_LOGIC := '1'; + Ras_n : IN STD_LOGIC := '1'; + We_n : IN STD_LOGIC := '1'; + Dqm : IN STD_LOGIC := '0'; + Load : IN STD_LOGIC := '0'; + Unload : IN STD_LOGIC := '0'; + Row_start : IN INTEGER := 0; + Row_end : IN INTEGER := 0 + ); + END COMPONENT; + + FOR ALL : mt48lc8m8a2 USE ENTITY work.mt48lc8m8a2 (behave); + + SIGNAL pDq : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0); + SIGNAL pAddr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + SIGNAL pBa : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL pClk : STD_LOGIC; + SIGNAL pCke : STD_LOGIC; + SIGNAL pCs : STD_LOGIC; + SIGNAL pCas : STD_LOGIC; + SIGNAL pRas : STD_LOGIC; + SIGNAL pWe : STD_LOGIC; + SIGNAL pDqm : STD_LOGIC; + SIGNAL PLoad : STD_LOGIC; + SIGNAL PUnload : STD_LOGIC; + SIGNAL PRow_start : INTEGER; + SIGNAL PRow_end : INTEGER; + SIGNAL stim_done : boolean := false; + SIGNAL clk_done : boolean := false; + + +BEGIN + u1: mt48lc8m8a2 + PORT MAP( + Dq => pDq, + Addr => pAddr, + Ba => pBa, + Clk => pClk, + Cke => pCke, + Cs_n => pCs, + Ras_n => pRas, + Cas_n => pCas, + We_n => pWe, + Dqm => pDqm, + Load => pLoad, + Unload => pUnload, + Row_start => PRow_start, + Row_end => PRow_end + ); + + stimulator : PROCESS + FILE stim_file:text IS IN "test.txt"; + VARIABLE l : line; + VARIABLE time_var : TIME; + VARIABLE pCke_var : STD_LOGIC; + VARIABLE pCs_var : STD_LOGIC; + VARIABLE pRas_var : STD_LOGIC; + VARIABLE PCas_var : STD_LOGIC; + VARIABLE pWe_var : STD_LOGIC; + VARIABLE pDqm_var : STD_LOGIC; + VARIABLE pBa_var : STD_LOGIC_VECTOR (1 DOWNTO 0); + VARIABLE pAddr_var : INTEGER; + VARIABLE pDq_var : INTEGER; -- -100 is converted to hi-Z state + VARIABLE pLoad_var : STD_LOGIC; + VARIABLE pUnload_var : STD_LOGIC; + VARIABLE pRow_start_var : INTEGER; + VARIABLE pRow_end_var : INTEGER; + VARIABLE pMa_var_vect : STD_LOGIC_VECTOR(addr_bits - 1 DOWNTO 0); + CONSTANT HiZ : STD_LOGIC_VECTOR(data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + BEGIN + WHILE not ENDFILE(stim_file) LOOP + readline(stim_file,l); + IF l'length > 0 THEN + read (l, time_var); + read (l, pCke_var); + read (l, pCs_var); + read (l, pRas_var); + read (l, pCas_var); + read (l, pWe_var); + read (l, pDqm_var); + read (l, pBa_var); + read (l, pAddr_var); + read (l, pDq_var); + read (l, pLoad_var); + read (l, pUnload_var); + read (l, pRow_start_var); + read (l, pRow_end_var); + IF now > time_var THEN + ASSERT false + REPORT "Detected a time in the stim file that is in the past" + SEVERITY error; + ELSE + WAIT FOR time_var-now; + IF pWe_var='1' THEN + pCke <= pCke_var; + pCs <= pCs_var; + pRas <= pRas_var; + pCas <= pCas_var; + pWe <= pWe_var; + pDqm <= pDqm_var; + pBa <= pBa_var; + pMa_var_vect := CONV_STD_LOGIC_VECTOR(pAddr_var, addr_bits); + pAddr <= pMa_var_vect; + IF pDq_var = -100 THEN + pDq <= HiZ; + ELSE + pDq <= CONV_STD_LOGIC_VECTOR(pDq_var, data_bits); + END IF; + pLoad <= pLoad_var; + pUnload <= pUnload_var; + pRow_start <= pRow_start_var; + pRow_end <= pRow_end_var; + ELSE + pCke <= pCke_var; + pCs <= pCs_var; + pRas <= pRas_var; + pCas <= pCas_var; + pWe <= pWe_var; + pDqm <= pDqm_var; + pBa <= pBa_var; + pMa_var_vect := CONV_STD_LOGIC_VECTOR(pAddr_var, addr_bits); + pAddr <= pMa_var_vect; + IF pDq_var = -100 THEN + pDq <= HiZ; + ELSE + pDq <= CONV_STD_LOGIC_VECTOR(pDq_var, data_bits); + END IF; + pLoad <= pLoad_var; + pUnload <= pUnload_var; + pRow_start <= pRow_start_var; + pRow_end <= pRow_end_var; + END IF; + END IF; + END IF; + END LOOP; + ASSERT false + REPORT "End of Stimulation File Detected!" + SEVERITY note; + stim_done <= true; + WAIT; + END PROCESS; + + clock : PROCESS + VARIABLE done_time : time; + BEGIN + pclk <= '0'; + WAIT for clk_start; + WHILE not stim_done loop + pclk <= '1'; + WAIT for clk_period/2; + pclk <= '0'; + WAIT for clk_period/2; + END LOOP; + done_time := now+continue_time; + WHILE now < done_time LOOP --one last clock to finish last command + pclk <= '1'; + WAIT for clk_period/2; + pclk <= '0'; + WAIT for clk_period/2; + END LOOP; + ASSERT false + REPORT "Suspending clock activity" + SEVERITY note; + clk_done <= true; + WAIT; + END PROCESS; + +END test; + + diff --git a/lib/models/memory/sdram/mt48lc8m8a2/util1164.vhd b/lib/models/memory/sdram/mt48lc8m8a2/util1164.vhd new file mode 100644 index 0000000..bb4b5dd --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m8a2/util1164.vhd @@ -0,0 +1,124 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE STD.textio.ALL; + +PACKAGE util_1164 IS + PROCEDURE read(l: INOUT line; value: OUT std_logic); + PROCEDURE read(l: INOUT line; value: OUT std_logic_vector); + PROCEDURE write(l: INOUT line; value: IN std_logic_vector; + JUSTIFIED: IN SIDE := right; + FIELD: IN WIDTH := 0); + PROCEDURE Grow_line(L : inout LINE; incr : in integer); +END util_1164; + + + +PACKAGE BODY util_1164 IS + + FUNCTION white_space(value:character) RETURN boolean IS + VARIABLE result:boolean; + BEGIN + IF (value = ' ') OR (value = HT) THEN + RETURN true; + ELSE + RETURN false; + END IF; + END white_space; + + PROCEDURE read(l: INOUT line; value: OUT std_logic) IS + VARIABLE char_var: character:= ' '; + BEGIN + WHILE l'LENGTH > 0 LOOP + read(l,char_var); + IF NOT white_space(char_var) THEN + EXIT; + END IF; + END LOOP; + IF white_space(char_var) THEN + ASSERT false REPORT "No std_logic value found in file" + SEVERITY error; + value := 'X'; + RETURN; + END IF; + + CASE char_var IS + WHEN 'U'|'u' => value := 'U'; + WHEN '0' => value := '0'; + WHEN '1' => value := '1'; + WHEN 'X'|'x' => value := 'X'; + WHEN 'L'|'l' => value := 'L'; + WHEN 'H'|'h' => value := 'H'; + WHEN 'W'|'w' => value := 'W'; + WHEN 'Z'|'z' => value := 'Z'; + WHEN '-' => value := '-'; + WHEN OTHERS => + ASSERT false REPORT "Unrecognized value read for std_logic" + SEVERITY error; + value := 'X'; + END CASE; + END read; + + PROCEDURE read(l: INOUT line; value: OUT std_logic_vector) IS + BEGIN + FOR i IN value'HIGH DOWNTO value'LOW LOOP + IF l'LENGTH > 0 THEN + read(l,value(i)); + ELSE + ASSERT false REPORT "Not enough values for std_logic_vector in file" + SEVERITY error; + RETURN; + END IF; + END LOOP; + END read; + + procedure Grow_line(L : inout LINE; incr : in integer) + is + variable old_L : LINE := L; + variable bfp: integer; -- Blank fill pointer. + begin + assert incr > 0 + report "Textio: Grow_line called with zero increment." + severity error; + + if L = null then + bfp := 0; + L := new string(1 to incr); + else + bfp := old_L'high; + L := new string(old_L'low to old_L'high + incr); + L(old_L'low to old_L'high) := old_L.all; + Deallocate(old_L); + end if; + for i in 1 to incr loop + L(bfp + i) := ' '; + end loop; + end; + + + PROCEDURE write(l: INOUT line; value: IN std_logic_vector; + JUSTIFIED: IN SIDE := right; + FIELD: IN WIDTH := 0) IS + variable fw: integer := VALUE'length; + variable bp: integer; + variable offset: integer := 0; + alias normal : std_logic_vector(0 to value'length - 1) is value; + begin + if L /= null then + bp := L'high + 1; + else bp := 1; + end if; + if FIELD > VALUE'length then + fw := FIELD; + if JUSTIFIED = right then + offset := fw - VALUE'length; + end if; + end if; + Grow_line(L, fw); + for i in normal'range loop + L(bp + i + offset) := character'val( + std_logic'pos(normal(i)) + character'pos('0')); + end loop; + end; + + +END util_1164; diff --git a/lib/models/memory/sdram/mt48lc8m8a2/vec_gen.vhd b/lib/models/memory/sdram/mt48lc8m8a2/vec_gen.vhd new file mode 100644 index 0000000..82b2277 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m8a2/vec_gen.vhd @@ -0,0 +1,319 @@ +------------------------------------------------------------------------------- +-- -- +-- This is a data generator for the testbench for Micron's Synchronous -- +-- DRAM. This generator reads a text file line-by-line and generates -- +-- a file of test vectors that is then read by the testbench and -- +-- applied to the part. -- +-- -- +-- This VHDL program creates a text file of test vectors that is used by the -- +-- test bench. Place your commands in a file (a copy of VEC_GEN.VHD) and run -- +-- VEC_GEN.VHD in your VHDL simulator (make sure you have compiled this -- +-- package prior to running the program VEC_GEN.VHD). This will produce the -- +-- vectors that are required to run the included testbench. Change the name -- +-- of the vector file to save your vectors in separate files. The default -- +-- file name for the output vectors generated from this pacakage is -- +-- "test.txt." -- +-- -- +-- Now compile and run the testbench program embedtb.vhd. The testbench uses -- +-- the default test.txt as input vectors. -- +-- -- +-- -- +-- Copyright 1997 Micron Technology, Inc. -- +-- -- +------------------------------------------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.all; +USE std.textio.all; +USE work.io_utils.all; + + +PACKAGE generate_vectors IS + + CONSTANT set_up : TIME; + CONSTANT hold : TIME; + CONSTANT cycle_start : TIME; + + SIGNAL cycle : INTEGER := 0; + SIGNAL sim_time : TIME := 0 ns; + FILE output_file:TEXT IS OUT "test.txt"; + PROCEDURE write (col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); first_data : IN INTEGER; dqm : IN BIT; cke : IN BIT); + PROCEDURE read (col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); dqm : IN BIT; cke : IN BIT); + PROCEDURE active (row_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); data_bus : IN INTEGER; dqm : IN BIT; cke : IN BIT); + PROCEDURE precharge (bank : IN BIT_VECTOR(1 DOWNTO 0); address : IN INTEGER; data_bus: IN INTEGER; dqm : IN BIT; cke : IN BIT); + PROCEDURE nop (data_bus : IN INTEGER; dqm : IN BIT; cke : IN BIT); + PROCEDURE burst_term (data_bus : IN INTEGER; dqm : IN BIT; cke : IN BIT); + PROCEDURE auto_refresh; + PROCEDURE next_cycle (SIGNAL clk : IN BIT); + PROCEDURE load_array; + PROCEDURE load_mode_reg(op_code : IN INTEGER; cke : IN BIT); + PROCEDURE unload_array(row_start : IN INTEGER; row_end : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0)); + +END generate_vectors; + +PACKAGE BODY generate_vectors IS + + CONSTANT set_up : TIME := 3 ns; + CONSTANT hold : TIME := 1 ns; + CONSTANT cycle_start : TIME := 0 ns; + +PROCEDURE write(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); first_data : IN INTEGER; dqm : IN BIT; cke : IN BIT) IS + VARIABLE l : LINE; +BEGIN + IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); + ELSE + write(l, now-set_up, left, 4, ns); + END IF; + write(l, Cke, right, 4); --Cke + write(l, 0, right, 4); --Cs + write(l, 1, right, 4); --Ras + write(l, 0, right, 4); --Cas + write(l, 0, right, 4); --We + write(l, dqm, right, 4); --Dqm + write(l, bank, right, 4); --Ba + write(l, col_address, right, 6); --address + write(l, first_data, right, 6); --first data location + write(l, 0, right, 4); --load + write(l, 0, right, 4); --unload + write(l, 0, right, 6); --row_address_start + write(l, 0, right, 6); --row_address_end + writeline(output_file,l); --write vector to file +END; + +PROCEDURE read(col_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); dqm : IN BIT; cke : IN BIT) IS + VARIABLE l : LINE; +BEGIN + IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); + ELSE + write(l, now-set_up, left, 4, ns); + END IF; + write(l, Cke, right, 4); --Cke + write(l, 0, right, 4); --Cs + write(l, 1, right, 4); --Ras + write(l, 0, right, 4); --Cas + write(l, 1, right, 4); --We + write(l, dqm, right, 4); --Dqm + write(l, bank, right, 4); --Ba + write(l, col_address, right, 6); --address + write(l, -100, right, 6); --first data location + write(l, 0, right, 4); --load + write(l, 0, right, 4); --unload + write(l, 0, right, 6); --row_address_start + write(l, 0, right, 6); --row_address_end + writeline(output_file,l); --write vector to file +END; + +PROCEDURE active(row_address : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0); data_bus : IN INTEGER; dqm : IN BIT; cke : IN BIT) IS + VARIABLE l : LINE; +BEGIN + IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); + ELSE + write(l, now-set_up, left, 4, ns); + END IF; + write(l, Cke, right, 4); --Cke + write(l, 0, right, 4); --Cs + write(l, 0, right, 4); --Ras + write(l, 1, right, 4); --Cas + write(l, 1, right, 4); --We + write(l, dqm, right, 4); --Dqm + write(l, bank, right, 4); --Ba + write(l, row_address, right, 6); --address + write(l, data_bus, right, 6); --first data location + write(l, 0, right, 4); --load + write(l, 0, right, 4); --unload + write(l, 0, right, 6); --row_address_start + write(l, 0, right, 6); --row_address_end + writeline(output_file,l); --write vector to file +END; + +PROCEDURE precharge(bank : IN BIT_VECTOR(1 DOWNTO 0); address : IN INTEGER; data_bus: IN INTEGER; dqm : IN BIT; cke : IN BIT) IS + VARIABLE l : LINE; +BEGIN + IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); + ELSE + write(l, now-set_up, left, 4, ns); + END IF; + write(l, Cke, right, 4); --Cke + write(l, 0, right, 4); --Cs + write(l, 0, right, 4); --Ras + write(l, 1, right, 4); --Cas + write(l, 0, right, 4); --We + write(l, dqm, right, 4); --Dqm + write(l, bank, right, 4); --Ba + write(l, address, right, 6); --address + write(l, data_bus, right, 6); --first data location + write(l, 0, right, 4); --load + write(l, 0, right, 4); --unload + write(l, 0, right, 6); --row_address_start + write(l, 0, right, 6); --row_address_end + writeline(output_file,l); --write vector to file +END; + +PROCEDURE nop(data_bus : IN INTEGER; dqm : IN BIT; cke : IN BIT) IS + VARIABLE l : LINE; + VARIABLE col_address : INTEGER := 0; + VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; +BEGIN + IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); + ELSE + write(l, now-set_up, left, 4, ns); + END IF; + write(l, cke, right, 4); --Cke + write(l, 0, right, 4); --Cs + write(l, 1, right, 4); --Ras + write(l, 1, right, 4); --Cas + write(l, 1, right, 4); --We + write(l, dqm, right, 4); --Dqm + write(l, bank, right, 4); --Ba + write(l, col_address, right, 6); --address + write(l, data_bus, right, 6); --first data location + write(l, 0, right, 4); --load + write(l, 0, right, 4); --unload + write(l, 0, right, 6); --row_address_start + write(l, 0, right, 6); --row_address_end + writeline(output_file,l); --write vector to file +END; + + +PROCEDURE burst_term(data_bus : IN INTEGER; dqm : IN BIT; cke : IN BIT) IS + VARIABLE l : LINE; + VARIABLE col_address : INTEGER := 0; + VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; +BEGIN + IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); + ELSE + write(l, now-set_up, left, 4, ns); + END IF; + write(l, cke, right, 4); --Cke + write(l, 0, right, 4); --Cs + write(l, 1, right, 4); --Ras + write(l, 1, right, 4); --Cas + write(l, 0, right, 4); --We + write(l, dqm, right, 4); --Dqm + write(l, bank, right, 4); --Ba + write(l, col_address, right, 6); --address + write(l, data_bus, right, 6); --first data location + write(l, 0, right, 4); --load + write(l, 0, right, 4); --unload + write(l, 0, right, 6); --row_address_start + write(l, 0, right, 6); --row_address_end + writeline(output_file,l); --write vector to file +END; + +PROCEDURE auto_refresh IS + VARIABLE l : LINE; + VARIABLE dqm : BIT := '0'; + VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; +BEGIN + IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); + ELSE + write(l, now-set_up, left, 4, ns); + END IF; + write(l, 1, right, 4); --Cke + write(l, 0, right, 4); --Cs + write(l, 0, right, 4); --Ras + write(l, 0, right, 4); --Cas + write(l, 1, right, 4); --We + write(l, dqm, right, 4); --Dqm + write(l, bank, right, 4); --Ba + write(l, 0, right, 6); --address + write(l, -100, right, 6); --first data location + write(l, 0, right, 4); --load + write(l, 0, right, 4); --unload + write(l, 0, right, 6); --row_address_start + write(l, 0, right, 6); --row_address_end + writeline(output_file,l); --write vector to file +END; + + +PROCEDURE next_cycle(SIGNAL clk : IN BIT) IS +BEGIN + WAIT UNTIL clk = '1'; +END; + +PROCEDURE load_array IS + VARIABLE l : LINE; + VARIABLE dqm : BIT := '0'; + VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; +BEGIN + IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); + ELSE + write(l, now-set_up, left, 4, ns); + END IF; + write(l, 1, right, 4); --Cke + write(l, 0, right, 4); --Cs + write(l, 1, right, 4); --Ras + write(l, 1, right, 4); --Cas + write(l, 1, right, 4); --We + write(l, dqm, right, 4); --Dqm + write(l, bank, right, 4); --Ba + write(l, 0, right, 6); --address + write(l, -100, right, 6); --first data location + write(l, 1, right, 4); --load + write(l, 0, right, 4); --unload + write(l, 0, right, 6); --row_address_start + write(l, 0, right, 6); --row_address_end + writeline(output_file,l); --write vector to file +END; + +PROCEDURE unload_array(row_start : IN INTEGER; row_end : IN INTEGER; bank : IN BIT_VECTOR(1 DOWNTO 0)) IS + VARIABLE l : LINE; + VARIABLE dqm : BIT := '0'; +BEGIN + IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); + ELSE + write(l, now-set_up, left, 4, ns); + END IF; + write(l, 1, right, 4); --Cke + write(l, 0, right, 4); --Cs + write(l, 1, right, 4); --Ras + write(l, 1, right, 4); --Cas + write(l, 1, right, 4); --We + write(l, dqm, right, 4); --Dqm + write(l, bank, right, 4); --Ba + write(l, 0, right, 6); --address + write(l, -100, right, 6); --first data location + write(l, 0, right, 4); --load + write(l, 1, right, 4); --unload + write(l, row_start, right, 6); --row_address_start + write(l, row_end, right, 6); --row_address_end + writeline(output_file,l); --write vector to file +END; + +PROCEDURE load_mode_reg(op_code : IN INTEGER; cke : IN BIT) IS + VARIABLE l : LINE; + VARIABLE dqm : BIT := '0'; + VARIABLE bank : BIT_VECTOR(1 DOWNTO 0) := "00"; +BEGIN + IF cycle = 0 THEN + write(l, cycle_start, left, 4, ns); + ELSE + write(l, now-set_up, left, 4, ns); + END IF; + write(l, cke, right, 4); --Cke + write(l, 0, right, 4); --Cs + write(l, 0, right, 4); --Ras + write(l, 0, right, 4); --Cas + write(l, 0, right, 4); --We + write(l, dqm, right, 4); --Dqm + write(l, bank, right, 4); --Ba + write(l, op_code, right, 6); --address + write(l, -100, right, 6); --first data location + write(l, 0, right, 4); --load + write(l, 0, right, 4); --unload + write(l, 0, right, 6); --row_address_start + write(l, 0, right, 6); --row_address_end + writeline(output_file,l); --write vector to file +END; + +END generate_vectors; + diff --git a/lib/models/memory/sdram/mt48lc8m8a2/vector.do b/lib/models/memory/sdram/mt48lc8m8a2/vector.do new file mode 100644 index 0000000..7480359 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m8a2/vector.do @@ -0,0 +1,4 @@ +vcom vec_gen.vhd +vcom ed_comnd.vhd +vsim vector_generate +run -all diff --git a/lib/models/memory/sdram/mt48lc8m8a2/wave.do b/lib/models/memory/sdram/mt48lc8m8a2/wave.do new file mode 100644 index 0000000..f414a82 --- /dev/null +++ b/lib/models/memory/sdram/mt48lc8m8a2/wave.do @@ -0,0 +1,31 @@ +onerror {resume} +add wave -logic /tb/u1/clk +add wave -logic /tb/u1/cke +add wave -logic /tb/u1/cs_n +add wave -logic /tb/u1/ras_n +add wave -logic /tb/u1/cas_n +add wave -logic /tb/u1/we_n +add wave -literal -decimal /tb/u1/addr +add wave -literal -unsigned /tb/u1/ba +add wave -literal -decimal /tb/u1/dq +add wave -logic /tb/u1/dqm +add wave -literal -decimal /tb/u1/operation +add wave -literal -decimal /tb/u1/mode_reg +add wave -logic /tb/u1/active_enable +add wave -logic /tb/u1/aref_enable +add wave -logic /tb/u1/burst_term +add wave -logic /tb/u1/mode_reg_enable +add wave -logic /tb/u1/prech_enable +add wave -logic /tb/u1/read_enable +add wave -logic /tb/u1/write_enable +add wave -logic /tb/u1/burst_length_1 +add wave -logic /tb/u1/burst_length_2 +add wave -logic /tb/u1/burst_length_4 +add wave -logic /tb/u1/burst_length_8 +add wave -logic /tb/u1/cas_latency_2 +add wave -logic /tb/u1/cas_latency_3 +add wave -literal -binary /tb/u1/pre_chk +add wave -literal -binary /tb/u1/act_chk +add wave -literal -unsigned /tb/u1/bank_chk +add wave -literal -decimal /tb/u1/row_chk +add wave -literal -decimal /tb/u1/col_chk diff --git a/lib/models/memory/sdram/mt48v2m32lffc/mt48v2m32lffc.vhd b/lib/models/memory/sdram/mt48v2m32lffc/mt48v2m32lffc.vhd new file mode 100644 index 0000000..e857bd2 --- /dev/null +++ b/lib/models/memory/sdram/mt48v2m32lffc/mt48v2m32lffc.vhd @@ -0,0 +1,1163 @@ +----------------------------------------------------------------------------------------- +-- +-- File Name: MT48LC2M32LFFC.VHD +-- Version: 0.0 +-- Date: June 4th, 2001 +-- Model: Behavioral +-- Simulator: Model Technology +-- +-- Dependencies: None +-- +-- Author: Son P. Huynh +-- Email: sphuynh@micron.com +-- Phone: (208) 368-3825 +-- Company: Micron Technology, Inc. +-- Part Number: MT48LC2M32LFFC (1Mb x 32 x 4 Banks) +-- +-- Description: Micron 64Mb SDRAM +-- +-- Limitation: - Doesn't check for 4096-cycle refresh +-- +-- Note: - Set simulator resolution to "ps" accuracy +-- +-- Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY +-- WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY +-- IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR +-- A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT. +-- +-- Copyright (c) 1998 Micron Semiconductor Products, Inc. +-- All rights researved +-- +-- Rev Author Phone Date Changes +-- --- ---------------------------- ---------- ------------------------------------- +-- 0.0 Son P. Huynh 208-368-3825 06/04/2001 First Release +-- Micron Technology Inc. - Simple testbench included +----------------------------------------------------------------------------------------- + +LIBRARY ieee; + USE ieee.std_logic_1164.ALL; + USE ieee.std_logic_unsigned.conv_integer; + USE ieee.std_logic_arith.conv_std_logic_vector; + +ENTITY mt48v2m32lffc IS + GENERIC ( + -- Timing Parameters for -8 and CAS Latency = 2 + tAC : TIME := 8.0 ns; + tHZ : TIME := 8.0 ns; + tOH : TIME := 2.5 ns; + tMRD : INTEGER := 2; -- 2 Clk Cycles + tRAS : TIME := 48.0 ns; + tRC : TIME := 80.0 ns; + tRCD : TIME := 20.0 ns; + tRFC : TIME := 80.0 ns; + tRP : TIME := 20.0 ns; + tRRD : TIME := 20.0 ns; + tWRa : TIME := 7.0 ns; -- A2 Version - Auto precharge mode only (1 Clk + 6 ns) + tWRp : TIME := 15.0 ns; -- A2 Version - Precharge mode only (12 ns) + + tAH : TIME := 1.0 ns; + tAS : TIME := 2.5 ns; + tCH : TIME := 3.0 ns; + tCL : TIME := 3.0 ns; + tCK : TIME := 13.0 ns; + tDH : TIME := 1.0 ns; + tDS : TIME := 2.5 ns; + tCKH : TIME := 1.0 ns; + tCKS : TIME := 2.5 ns; + tCMH : TIME := 1.0 ns; + tCMS : TIME := 2.5 ns; + + addr_bits : INTEGER := 11; + data_bits : INTEGER := 32; + col_bits : INTEGER := 8 + ); + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC_VECTOR := "00"; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '0'; + Cs_n : IN STD_LOGIC := '1'; + Ras_n : IN STD_LOGIC := '0'; + Cas_n : IN STD_LOGIC := '0'; + We_n : IN STD_LOGIC := '0'; + Dqm : IN STD_LOGIC_VECTOR (3 DOWNTO 0) := (OTHERS => '0') + ); +END mt48v2m32lffc; + +ARCHITECTURE behave OF mt48v2m32lffc IS + TYPE State IS (ACT, A_REF, BST, LMR, NOP, PRECH, READ, READ_A, WRITE, WRITE_A, FILE_LOAD, FILE_UNLOAD); + TYPE Array4xI IS ARRAY (3 DOWNTO 0) OF INTEGER; + TYPE Array4xT IS ARRAY (3 DOWNTO 0) OF TIME; + TYPE Array4xSL IS ARRAY (3 DOWNTO 0) OF STD_LOGIC; + TYPE Array4x2SLV IS ARRAY (3 DOWNTO 0) OF STD_LOGIC_VECTOR (1 DOWNTO 0); -- For Bank Pipeline + TYPE Array2x4SLV IS ARRAY (1 DOWNTO 0) OF STD_LOGIC_VECTOR (3 DOWNTO 0); -- For Dqm Pipeline + TYPE Array4xCSLV IS ARRAY (4 DOWNTO 0) OF STD_LOGIC_VECTOR (Col_bits - 1 DOWNTO 0); -- For Column Pipeline + TYPE Array_state IS ARRAY (4 DOWNTO 0) OF State; + SIGNAL Operation : State := NOP; + SIGNAL Mode_reg : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL Active_enable, Aref_enable, Burst_term : STD_LOGIC := '0'; + SIGNAL Mode_reg_enable, Prech_enable, Read_enable, Write_enable : STD_LOGIC := '0'; + SIGNAL Burst_length_1, Burst_length_2, Burst_length_4, Burst_length_8 : STD_LOGIC := '0'; + SIGNAL Cas_latency_1, Cas_latency_2, Cas_latency_3 : STD_LOGIC := '0'; + SIGNAL Cs_in, Ras_in, Cas_in, We_in : STD_LOGIC := '0'; + SIGNAL Write_burst_mode : STD_LOGIC := '0'; + SIGNAL RAS_clk, Sys_clk, CkeZ : STD_LOGIC := '0'; + +BEGIN + -- Strip the strength + Cs_in <= To_X01 (Cs_n); + Ras_in <= To_X01 (Ras_n); + Cas_in <= To_X01 (Cas_n); + We_in <= To_X01 (We_n); + + -- Commands Decode + Active_enable <= NOT(Cs_in) AND NOT(Ras_in) AND Cas_in AND We_in; + Aref_enable <= NOT(Cs_in) AND NOT(Ras_in) AND NOT(Cas_in) AND We_in; + Burst_term <= NOT(Cs_in) AND Ras_in AND Cas_in AND NOT(We_in); + Mode_reg_enable <= NOT(Cs_in) AND NOT(Ras_in) AND NOT(Cas_in) AND NOT(We_in); + Prech_enable <= NOT(Cs_in) AND NOT(Ras_in) AND Cas_in AND NOT(We_in); + Read_enable <= NOT(Cs_in) AND Ras_in AND NOT(Cas_in) AND We_in; + Write_enable <= NOT(Cs_in) AND Ras_in AND NOT(Cas_in) AND NOT(We_in); + + -- Burst Length Decode + Burst_length_1 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND NOT(Mode_reg(0)); + Burst_length_2 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND Mode_reg(0); + Burst_length_4 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND NOT(Mode_reg(0)); + Burst_length_8 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND Mode_reg(0); + + -- CAS Latency Decode + Cas_latency_1 <= NOT(Mode_reg(6)) AND NOT(Mode_reg(5)) AND Mode_reg(4); + Cas_latency_2 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND NOT(Mode_reg(4)); + Cas_latency_3 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND Mode_reg(4); + + -- Write Burst Mode + Write_burst_mode <= Mode_reg(9); + + -- RAS Clock for checking tWR and tRP + PROCESS + variable Clk0, Clk1 : integer := 0; + begin + RAS_clk <= '1'; + wait for 0.5 ns; + RAS_clk <= '0'; + wait for 0.5 ns; + if Clk0 > 100 or Clk1 > 100 then + wait; + else + if Clk = '1' then + Clk0 := 0; + Clk1 := Clk1 + 1; + else + Clk0 := Clk0 + 1; + Clk1 := 0; + end if; + end if; + END PROCESS; + + -- System Clock + int_clk : PROCESS (Clk) + begin + IF Clk'LAST_VALUE = '0' AND Clk = '1' THEN + CkeZ <= Cke; + END IF; + Sys_clk <= CkeZ AND Clk; + END PROCESS; + + state_register : PROCESS + TYPE ram_type IS ARRAY (2**col_bits - 1 DOWNTO 0) OF STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0); + TYPE ram_pntr IS ACCESS ram_type; + TYPE ram_stor IS ARRAY (2**addr_bits - 1 DOWNTO 0) OF ram_pntr; + VARIABLE Bank0 : ram_stor; + VARIABLE Bank1 : ram_stor; + VARIABLE Bank2 : ram_stor; + VARIABLE Bank3 : ram_stor; + VARIABLE Row_index, Col_index : INTEGER := 0; + VARIABLE Dq_temp : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => '0'); + + VARIABLE Col_addr : Array4xCSLV; + VARIABLE Bank_addr : Array4x2SLV; + VARIABLE Dqm_reg0, Dqm_reg1 : STD_LOGIC_VECTOR (3 DOWNTO 0) := "0000"; + + VARIABLE Bank, Previous_bank : STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"; + VARIABLE B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col_brst : STD_LOGIC_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Row : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col : STD_LOGIC_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Burst_counter : INTEGER := 0; + + VARIABLE Command : Array_state; + VARIABLE Bank_precharge : Array4x2SLV; + VARIABLE A10_precharge : Array4xSL := ('0' & '0' & '0' & '0'); + VARIABLE Auto_precharge : Array4xSL := ('0' & '0' & '0' & '0'); + VARIABLE Read_precharge : Array4xSL := ('0' & '0' & '0' & '0'); + VARIABLE Write_precharge : Array4xSL := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_write : Array4xSL := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_read : Array4xSL := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_bank : STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"; + VARIABLE Count_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE Count_precharge : Array4xI := (0 & 0 & 0 & 0); + + VARIABLE Data_in_enable, Data_out_enable : STD_LOGIC := '0'; + VARIABLE Pc_b0, Pc_b1, Pc_b2, Pc_b3 : STD_LOGIC := '0'; + VARIABLE Act_b0, Act_b1, Act_b2, Act_b3 : STD_LOGIC := '0'; + + -- Timing Check + VARIABLE MRD_chk : INTEGER := 0; + VARIABLE WR_counter : Array4xI := (0 & 0 & 0 & 0); + VARIABLE WR_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE WR_chkp : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE RC_chk, RRD_chk : TIME := 0 ns; + VARIABLE RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3 : TIME := 0 ns; + VARIABLE RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3 : TIME := 0 ns; + VARIABLE RP_chk0, RP_chk1, RP_chk2, RP_chk3 : TIME := 0 ns; + + -- Initialize empty rows + PROCEDURE Init_mem (Bank : STD_LOGIC_VECTOR (1 DOWNTO 0); Row_index : INTEGER) IS + VARIABLE i, j : INTEGER := 0; + BEGIN + IF Bank = "00" THEN + IF Bank0 (Row_index) = NULL THEN -- Check to see if row empty + Bank0 (Row_index) := NEW ram_type; -- Open new row for access + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP -- Filled row with zeros + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank0 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "01" THEN + IF Bank1 (Row_index) = NULL THEN + Bank1 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank1 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "10" THEN + IF Bank2 (Row_index) = NULL THEN + Bank2 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank2 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + ELSIF Bank = "11" THEN + IF Bank3 (Row_index) = NULL THEN + Bank3 (Row_index) := NEW ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits - 1) DOWNTO 0 LOOP + Bank3 (Row_index) (i) (j) := '0'; + END LOOP; + END LOOP; + END IF; + END IF; + END; + + -- Burst Counter + PROCEDURE Burst_decode IS + VARIABLE Col_int : INTEGER := 0; + VARIABLE Col_vec, Col_temp : STD_LOGIC_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + BEGIN + -- Advance Burst Counter + Burst_counter := Burst_counter + 1; + + -- Burst Type + IF Mode_reg (3) = '0' THEN + Col_int := conv_integer(Col) + 1; + Col_temp := CONV_STD_LOGIC_VECTOR(Col_int, col_bits); + ELSIF Mode_reg (3) = '1' THEN + Col_vec := CONV_STD_LOGIC_VECTOR(Burst_counter, col_bits); + Col_temp (2) := Col_vec (2) XOR Col_brst (2); + Col_temp (1) := Col_vec (1) XOR Col_brst (1); + Col_temp (0) := Col_vec (0) XOR Col_brst (0); + END IF; + + -- Burst Length + IF Burst_length_2 = '1' THEN + Col (0) := Col_temp (0); + ELSIF Burst_length_4 = '1' THEN + Col (1 DOWNTO 0) := Col_temp (1 DOWNTO 0); + ELSIF Burst_length_8 = '1' THEN + Col (2 DOWNTO 0) := Col_temp (2 DOWNTO 0); + ELSE + Col := Col_temp; + END IF; + + -- Burst Read Single Write + IF Write_burst_mode = '1' AND Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Data counter + IF Burst_length_1 = '1' THEN + IF Burst_counter >= 1 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_2 = '1' THEN + IF Burst_counter >= 2 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_4 = '1' THEN + IF Burst_counter >= 4 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Burst_length_8 = '1' THEN + IF Burst_counter >= 8 THEN + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + ELSIF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + END IF; + END; + + BEGIN + WAIT ON Sys_clk, RAS_clk; + IF Sys_clk'event AND Sys_clk = '1' THEN + -- Internal Command Pipeline + Command(0) := Command(1); + Command(1) := Command(2); + Command(2) := Command(3); + Command(3) := NOP; + + Col_addr(0) := Col_addr(1); + Col_addr(1) := Col_addr(2); + Col_addr(2) := Col_addr(3); + Col_addr(3) := (OTHERS => '0'); + + Bank_addr(0) := Bank_addr(1); + Bank_addr(1) := Bank_addr(2); + Bank_addr(2) := Bank_addr(3); + Bank_addr(3) := "00"; + + Bank_precharge(0) := Bank_precharge(1); + Bank_precharge(1) := Bank_precharge(2); + Bank_precharge(2) := Bank_precharge(3); + Bank_precharge(3) := "00"; + + A10_precharge(0) := A10_precharge(1); + A10_precharge(1) := A10_precharge(2); + A10_precharge(2) := A10_precharge(3); + A10_precharge(3) := '0'; + + -- Operation Decode (Optional for showing current command on posedge clock / debug feature) + IF Active_enable = '1' THEN + Operation <= ACT; + ELSIF Aref_enable = '1' THEN + Operation <= A_REF; + ELSIF Burst_term = '1' THEN + Operation <= BST; + ELSIF Mode_reg_enable = '1' THEN + Operation <= LMR; + ELSIF Prech_enable = '1' THEN + Operation <= PRECH; + ELSIF Read_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= READ; + ELSE + Operation <= READ_A; + END IF; + ELSIF Write_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= WRITE; + ELSE + Operation <= WRITE_A; + END IF; + ELSE + Operation <= NOP; + END IF; + + -- Dqm pipeline for Read + Dqm_reg0 := Dqm_reg1; + Dqm_reg1 := Dqm; + + -- Read or Write with Auto Precharge Counter + IF Auto_precharge (0) = '1' THEN + Count_precharge (0) := Count_precharge (0) + 1; + END IF; + IF Auto_precharge (1) = '1' THEN + Count_precharge (1) := Count_precharge (1) + 1; + END IF; + IF Auto_precharge (2) = '1' THEN + Count_precharge (2) := Count_precharge (2) + 1; + END IF; + IF Auto_precharge (3) = '1' THEN + Count_precharge (3) := Count_precharge (3) + 1; + END IF; + + -- Auto Precharge Timer for tWR + if (Burst_length_1 = '1' OR Write_burst_mode = '1') then + if (Count_precharge(0) = 1) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 1) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 1) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 1) then + Count_time(3) := NOW; + end if; + elsif (Burst_length_2 = '1') then + if (Count_precharge(0) = 2) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 2) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 2) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 2) then + Count_time(3) := NOW; + end if; + elsif (Burst_length_4 = '1') then + if (Count_precharge(0) = 4) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 4) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 4) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 4) then + Count_time(3) := NOW; + end if; + elsif (Burst_length_8 = '1') then + if (Count_precharge(0) = 8) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 8) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 8) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 8) then + Count_time(3) := NOW; + end if; + end if; + + -- tMRD Counter + MRD_chk := MRD_chk + 1; + + -- tWR Counter + WR_counter(0) := WR_counter(0) + 1; + WR_counter(1) := WR_counter(1) + 1; + WR_counter(2) := WR_counter(2) + 1; + WR_counter(3) := WR_counter(3) + 1; + + -- Auto Refresh + IF Aref_enable = '1' THEN + -- Auto Refresh to Auto Refresh + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Auto Refresh" + SEVERITY WARNING; + -- Precharge to Auto Refresh + ASSERT (NOW - RP_chk0 >= tRP OR NOW - RP_chk1 >= tRP OR NOW - RP_chk2 >= tRP OR NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Auto Refresh" + SEVERITY WARNING; + -- All banks must be idle before refresh + IF (Pc_b3 = '0' OR Pc_b2 = '0' OR Pc_b1 = '0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All banks must be Precharge before Auto Refresh" + SEVERITY WARNING; + END IF; + -- Record current tRC time + RC_chk := NOW; + END IF; + + -- Load Mode Register + IF Mode_reg_enable = '1' THEN + Mode_reg <= Addr; + IF (Pc_b3 = '0' OR Pc_b2 = '0' OR Pc_b1 = '0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All bank must be Precharge before Load Mode Register" + SEVERITY WARNING; + END IF; + -- REF to LMR + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Load Mode Register" + SEVERITY WARNING; + -- LMR to LMR + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Load Mode Register" + SEVERITY WARNING; + -- Record current tMRD time + MRD_chk := 0; + END IF; + + -- Active Block (latch Bank and Row Address) + IF Active_enable = '1' THEN + IF Ba = "00" AND Pc_b0 = '1' THEN + Act_b0 := '1'; + Pc_b0 := '0'; + B0_row_addr := Addr; + RCD_chk0 := NOW; + RAS_chk0 := NOW; + -- Precharge to Active Bank 0 + ASSERT (NOW - RP_chk0 >= tRP) + REPORT "tRP violation during Activate Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '1' THEN + Act_b1 := '1'; + Pc_b1 := '0'; + B1_row_addr := Addr; + RCD_chk1 := NOW; + RAS_chk1 := NOW; + -- Precharge to Active Bank 1 + ASSERT (NOW - RP_chk1 >= tRP) + REPORT "tRP violation during Activate Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '1' THEN + Act_b2 := '1'; + Pc_b2 := '0'; + B2_row_addr := Addr; + RCD_chk2 := NOW; + RAS_chk2 := NOW; + -- Precharge to Active Bank 2 + ASSERT (NOW - RP_chk2 >= tRP) + REPORT "tRP violation during Activate Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '1' THEN + Act_b3 := '1'; + Pc_b3 := '0'; + B3_row_addr := Addr; + RCD_chk3 := NOW; + RAS_chk3 := NOW; + -- Precharge to Active Bank 3 + ASSERT (NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Activate Bank 3" + SEVERITY WARNING; + ELSIF Ba = "00" AND Pc_b0 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 0 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 1 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 2 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 3 is not Precharged" + SEVERITY WARNING; + END IF; + -- Active Bank A to Active Bank B + IF ((Previous_bank /= Ba) AND (NOW - RRD_chk < tRRD)) THEN + ASSERT (FALSE) + REPORT "tRRD violation during Activate" + SEVERITY WARNING; + END IF; + -- LMR to ACT + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Activate" + SEVERITY WARNING; + -- AutoRefresh to Activate + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Activate" + SEVERITY WARNING; + -- Record variable for checking violation + RRD_chk := NOW; + Previous_bank := Ba; + END IF; + + -- Precharge Block + IF Prech_enable = '1' THEN + IF Addr(10) = '1' THEN + Pc_b0 := '1'; + Pc_b1 := '1'; + Pc_b2 := '1'; + Pc_b3 := '1'; + Act_b0 := '0'; + Act_b1 := '0'; + Act_b2 := '0'; + Act_b3 := '0'; + RP_chk0 := NOW; + RP_chk1 := NOW; + RP_chk2 := NOW; + RP_chk3 := NOW; + -- Activate to Precharge all banks + ASSERT ((NOW - RAS_chk0 >= tRAS) OR (NOW - RAS_chk1 >= tRAS)) + REPORT "tRAS violation during Precharge all banks" + SEVERITY WARNING; + -- tWR violation check for Write + IF ((NOW - WR_chkp(0) < tWRp) OR (NOW - WR_chkp(1) < tWRp) OR + (NOW - WR_chkp(2) < tWRp) OR (NOW - WR_chkp(3) < tWRp)) THEN + ASSERT (FALSE) + REPORT "tWR violation during Precharge ALL banks" + SEVERITY WARNING; + END IF; + ELSIF Addr(10) = '0' THEN + IF Ba = "00" THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + -- Activate to Precharge bank 0 + ASSERT (NOW - RAS_chk0 >= tRAS) + REPORT "tRAS violation during Precharge bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + -- Activate to Precharge bank 1 + ASSERT (NOW - RAS_chk1 >= tRAS) + REPORT "tRAS violation during Precharge bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + -- Activate to Precharge bank 2 + ASSERT (NOW - RAS_chk2 >= tRAS) + REPORT "tRAS violation during Precharge bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + -- Activate to Precharge bank 3 + ASSERT (NOW - RAS_chk3 >= tRAS) + REPORT "tRAS violation during Precharge bank 3" + SEVERITY WARNING; + END IF; + -- tWR violation check for Write + ASSERT (NOW - WR_chkp(CONV_INTEGER(Ba)) >= tWRp) + REPORT "tWR violation during Precharge" + SEVERITY WARNING; + END IF; + -- Terminate a Write Immediately (if same bank or all banks) + IF (Data_in_enable = '1' AND (Bank = Ba OR Addr(10) = '1')) THEN + Data_in_enable := '0'; + END IF; + -- Precharge Command Pipeline for READ + IF CAS_latency_3 = '1' THEN + Command(2) := PRECH; + Bank_precharge(2) := Ba; + A10_precharge(2) := Addr(10); + ELSIF CAS_latency_2 = '1' THEN + Command(1) := PRECH; + Bank_precharge(1) := Ba; + A10_precharge(1) := Addr(10); + END IF; + END IF; + + -- Burst Terminate + IF Burst_term = '1' THEN + -- Terminate a Write immediately + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + -- Terminate a Read depend on CAS Latency + IF CAS_latency_3 = '1' THEN + Command(2) := BST; + ELSIF CAS_latency_2 = '1' THEN + Command(1) := BST; + END IF; + END IF; + + -- Read, Write, Column Latch + IF Read_enable = '1' OR Write_enable = '1' THEN + -- Check to see if bank is open (ACT) for Read or Write + IF ((Ba = "00" AND Pc_b0 = '1') OR (Ba = "01" AND Pc_b1 = '1') OR + (Ba = "10" AND Pc_b2 = '1') OR (Ba = "11" AND Pc_b3 = '1')) THEN + ASSERT (FALSE) + REPORT "Cannot Read or Write - Bank is not Activated" + SEVERITY WARNING; + END IF; + -- Activate to Read or Write + IF Ba = "00" THEN + ASSERT (NOW - RCD_chk0 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + ASSERT (NOW - RCD_chk1 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + ASSERT (NOW - RCD_chk2 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + ASSERT (NOW - RCD_chk3 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 3" + SEVERITY WARNING; + END IF; + -- Read Command + IF Read_enable = '1' THEN + -- CAS Latency Pipeline + IF Cas_latency_1 = '1' THEN + IF Addr(10) = '1' THEN + Command(0) := READ_A; + ELSE + Command(0) := READ; + END IF; + Col_addr (0) := Addr(col_bits - 1 DOWNTO 0); + Bank_addr (0) := Ba; + ELSIF Cas_latency_2 = '1' THEN + IF Addr(10) = '1' THEN + Command(1) := READ_A; + ELSE + Command(1) := READ; + END IF; + Col_addr (1) := Addr(col_bits - 1 DOWNTO 0); + Bank_addr (1) := Ba; + ELSIF Cas_latency_3 = '1' THEN + IF Addr(10) = '1' THEN + Command(2) := READ_A; + ELSE + Command(2) := READ; + END IF; + Col_addr (2) := Addr(col_bits - 1 DOWNTO 0); + Bank_addr (2) := Ba; + END IF; + + -- Read intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + -- Interrupt a write with autoprecharge + IF (Auto_precharge (CONV_INTEGER(RW_interrupt_bank)) = '1' AND + Write_precharge (CONV_INTEGER(RW_interrupt_bank)) = '1') THEN + RW_interrupt_write (CONV_INTEGER(RW_interrupt_bank)) := '1'; + WR_time (CONV_INTEGER(RW_interrupt_bank)) := NOW; + END IF; + END IF; + + -- Write Command + ELSIF Write_enable = '1' THEN + IF Addr(10) = '1' THEN + Command(0) := WRITE_A; + ELSE + Command(0) := WRITE; + END IF; + Col_addr (0) := Addr(col_bits - 1 DOWNTO 0); + Bank_addr (0) := Ba; + + -- Write intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + -- Interrupt a Write with Auto Precharge + IF (Auto_precharge(CONV_INTEGER(RW_interrupt_bank)) = '1' AND + Write_precharge(CONV_INTEGER(RW_interrupt_bank)) = '1') THEN + RW_interrupt_write(CONV_INTEGER(RW_interrupt_bank)) := '1'; + WR_time (CONV_INTEGER(RW_interrupt_bank)) := NOW; + END IF; + END IF; + + -- Write interrupt a Read (terminate Read immediately) + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + -- Interrupt a Read with Auto Precharge + IF Auto_precharge(CONV_INTEGER(RW_interrupt_bank)) = '1' AND Read_precharge(CONV_INTEGER(RW_interrupt_bank)) = '1' THEN + RW_interrupt_read(CONV_INTEGER(RW_interrupt_bank)) := '1'; + END IF; + END IF; + END IF; + + -- Read or Write with Auto Precharge + IF Addr(10) = '1' THEN + Auto_precharge (CONV_INTEGER(Ba)) := '1'; + Count_precharge (CONV_INTEGER(Ba)) := 0; + RW_interrupt_bank := Ba; + IF Read_enable = '1' THEN + Read_precharge (CONV_INTEGER(Ba)) := '1'; + ELSIF Write_enable = '1' THEN + Write_precharge (CONV_INTEGER(Ba)) := '1'; + END IF; + END IF; + END IF; + + -- Read with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. BL/2 cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Read_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(0) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8))) OR + (RW_interrupt_read(0) = '1')) THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + Auto_precharge(0) := '0'; + Read_precharge(0) := '0'; + RW_interrupt_read(0) := '0'; + END IF; + END IF; + IF ((Auto_precharge(1) = '1') AND (Read_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(1) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8))) OR + (RW_interrupt_read(1) = '1')) THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + Auto_precharge(1) := '0'; + Read_precharge(1) := '0'; + RW_interrupt_read(1) := '0'; + END IF; + END IF; + IF ((Auto_precharge(2) = '1') AND (Read_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(2) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8))) OR + (RW_interrupt_read(2) = '1')) THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + Auto_precharge(2) := '0'; + Read_precharge(2) := '0'; + RW_interrupt_read(2) := '0'; + END IF; + END IF; + IF ((Auto_precharge(3) = '1') AND (Read_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(3) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8))) OR + (RW_interrupt_read(3) = '1')) THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + Auto_precharge(3) := '0'; + Read_precharge(3) := '0'; + RW_interrupt_read(3) := '0'; + END IF; + END IF; + + -- Internal Precharge or Bst + IF Command(0) = PRECH THEN -- PRECH terminate a read if same bank or all banks + IF Bank_precharge(0) = Bank OR A10_precharge(0) = '1' THEN + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Command(0) = BST THEN -- BST terminate a read regardless of bank + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + + -- Turn off databus + IF (Data_out_enable = '0') THEN + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tHZ; + END IF; + + -- Detect Read or Write Command + IF Command(0) = READ OR Command(0) = READ_A THEN + Bank := Bank_addr (0); + Col := Col_addr (0); + Col_brst := Col_addr (0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '0'; + Data_out_enable := '1'; + ELSIF Command(0) = WRITE OR Command(0) = WRITE_A THEN + Bank := Bank_addr(0); + Col := Col_addr(0); + Col_brst := Col_addr(0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '1'; + Data_out_enable := '0'; + END IF; + + -- DQ (Driver / Receiver) + Row_index := CONV_INTEGER (Row); + Col_index := CONV_INTEGER (Col); + IF Data_in_enable = '1' THEN + IF Dqm /= "1111" THEN + -- Initialize memory + Init_mem (Bank, Row_index); + -- Load memory into buffer + IF Bank = "00" THEN + Dq_temp := Bank0 (Row_index) (Col_index); + ELSIF Bank = "01" THEN + Dq_temp := Bank1 (Row_index) (Col_index); + ELSIF Bank = "10" THEN + Dq_temp := Bank2 (Row_index) (Col_index); + ELSIF Bank = "11" THEN + Dq_temp := Bank3 (Row_index) (Col_index); + END IF; + -- Dqm operation + IF Dqm (0) = '0' THEN + Dq_temp (7 DOWNTO 0) := Dq (7 DOWNTO 0); + END IF; + IF Dqm (1) = '0' THEN + Dq_temp (15 DOWNTO 8) := Dq (15 DOWNTO 8); + END IF; + IF Dqm (2) = '0' THEN + Dq_temp (23 DOWNTO 16) := Dq (23 DOWNTO 16); + END IF; + IF Dqm (3) = '0' THEN + Dq_temp (31 DOWNTO 24) := Dq (31 DOWNTO 24); + END IF; + -- Write back to memory + IF Bank = "00" THEN + Bank0 (Row_index) (Col_index) := Dq_temp; + ELSIF Bank = "01" THEN + Bank1 (Row_index) (Col_index) := Dq_temp; + ELSIF Bank = "10" THEN + Bank2 (Row_index) (Col_index) := Dq_temp; + ELSIF Bank = "11" THEN + Bank3 (Row_index) (Col_index) := Dq_temp; + END IF; + -- Reset tWR counter + WR_chkp(CONV_INTEGER(Bank)) := NOW; + WR_counter(CONV_INTEGER(Bank)) := 0; + END IF; + -- Decode next burst address + Burst_decode; + ELSIF Data_out_enable = '1' THEN + IF Dqm_reg0 /= "1111" THEN + -- Initialize memory + Init_mem (Bank, Row_index); + -- Load memory into buffer + IF Bank = "00" THEN + Dq_temp := Bank0 (Row_index) (Col_index); + ELSIF Bank = "01" THEN + Dq_temp := Bank1 (Row_index) (Col_index); + ELSIF Bank = "10" THEN + Dq_temp := Bank2 (Row_index) (Col_index); + ELSIF Bank = "11" THEN + Dq_temp := Bank3 (Row_index) (Col_index); + END IF; + -- Dqm operation + IF Dqm_reg0 (0) = '0' THEN + Dq (7 DOWNTO 0) <= TRANSPORT Dq_temp(7 DOWNTO 0) AFTER tAC; + ELSE + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + END IF; + IF Dqm_reg0 (1) = '0' THEN + Dq (15 DOWNTO 8) <= TRANSPORT Dq_temp(15 DOWNTO 8) AFTER tAC; + ELSE + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + END IF; + IF Dqm_reg0 (2) = '0' THEN + Dq (23 DOWNTO 16) <= TRANSPORT Dq_temp(23 DOWNTO 16) AFTER tAC; + ELSE + Dq (23 DOWNTO 16) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + END IF; + IF Dqm_reg0 (3) = '0' THEN + Dq (31 DOWNTO 24) <= TRANSPORT Dq_temp(31 DOWNTO 24) AFTER tAC; + ELSE + Dq (31 DOWNTO 24) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + END IF; + ELSE + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tHZ; + END IF; + Burst_decode; + END IF; + + -- Write with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. tWR cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Write_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(0) >= 1 AND NOW - Count_time(0) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2 AND NOW - Count_time(0) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4 AND NOW - Count_time(0) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8 AND NOW - Count_time(0) >= tWRa))) OR + (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 1 AND NOW - WR_time(0) >= tWRa)) THEN + Auto_precharge(0) := '0'; + Write_precharge(0) := '0'; + RW_interrupt_write(0) := '0'; + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + ASSERT FALSE REPORT "Start Internal Precharge Bank 0" SEVERITY NOTE; + END IF; + END IF; + IF ((Auto_precharge(1) = '1') AND (Write_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(1) >= 1 AND NOW - Count_time(1) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2 AND NOW - Count_time(1) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4 AND NOW - Count_time(1) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8 AND NOW - Count_time(1) >= tWRa))) OR + (RW_interrupt_write(1) = '1' AND WR_counter(1) >= 1 AND NOW - WR_time(1) >= tWRa)) THEN + Auto_precharge(1) := '0'; + Write_precharge(1) := '0'; + RW_interrupt_write(1) := '0'; + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + END IF; + END IF; + IF ((Auto_precharge(2) = '1') AND (Write_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(2) >= 1 AND NOW - Count_time(2) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2 AND NOW - Count_time(2) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4 AND NOW - Count_time(2) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8 AND NOW - Count_time(2) >= tWRa))) OR + (RW_interrupt_write(2) = '1' AND WR_counter(2) >= 1 AND NOW - WR_time(2) >= tWRa)) THEN + Auto_precharge(2) := '0'; + Write_precharge(2) := '0'; + RW_interrupt_write(2) := '0'; + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + END IF; + END IF; + IF ((Auto_precharge(3) = '1') AND (Write_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(3) >= 1 AND NOW - Count_time(3) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2 AND NOW - Count_time(3) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4 AND NOW - Count_time(3) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8 AND NOW - Count_time(3) >= tWRa))) OR + (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 1 AND NOW - WR_time(3) >= tWRa)) THEN + Auto_precharge(3) := '0'; + Write_precharge(3) := '0'; + RW_interrupt_write(3) := '0'; + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + END IF; + END IF; + END IF; + END PROCESS; + + -- Clock timing checks + Clock_check : PROCESS + VARIABLE Clk_low, Clk_high : TIME := 0 ns; + BEGIN + WAIT ON Clk; + IF (Clk = '1' AND NOW >= 10 ns) THEN + ASSERT (NOW - Clk_low >= tCL) + REPORT "tCL violation" + SEVERITY WARNING; + ASSERT (NOW - Clk_high >= tCK) + REPORT "tCK violation" + SEVERITY WARNING; + Clk_high := NOW; + ELSIF (Clk = '0' AND NOW /= 0 ns) THEN + ASSERT (NOW - Clk_high >= tCH) + REPORT "tCH violation" + SEVERITY WARNING; + Clk_low := NOW; + END IF; + END PROCESS; + + -- Setup timing checks + Setup_check : PROCESS + BEGIN + WAIT ON Clk; + IF Clk = '1' THEN + ASSERT(Cke'LAST_EVENT >= tCKS) + REPORT "CKE Setup time violation -- tCKS" + SEVERITY WARNING; + ASSERT(Cs_n'LAST_EVENT >= tCMS) + REPORT "CS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT >= tCMS) + REPORT "CAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT >= tCMS) + REPORT "RAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT >= tCMS) + REPORT "WE# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT >= tCMS) + REPORT "Dqm Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Addr'LAST_EVENT >= tAS) + REPORT "ADDR Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT >= tAS) + REPORT "BA Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Dq'LAST_EVENT >= tDS) + REPORT "Dq Setup time violation -- tDS" + SEVERITY WARNING; + END IF; + END PROCESS; + + -- Hold timing checks + Hold_check : PROCESS + BEGIN + WAIT ON Clk'DELAYED (tCKH), Clk'DELAYED (tCMH), Clk'DELAYED (tAH), Clk'DELAYED (tDH); + IF Clk'DELAYED (tCKH) = '1' THEN + ASSERT(Cke'LAST_EVENT > tCKH) + REPORT "CKE Hold time violation -- tCKH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tCMH) = '1' THEN + ASSERT(Cs_n'LAST_EVENT > tCMH) + REPORT "CS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT > tCMH) + REPORT "CAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT > tCMH) + REPORT "RAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT > tCMH) + REPORT "WE# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT > tCMH) + REPORT "Dqm Hold time violation -- tCMH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tAH) = '1' THEN + ASSERT(Addr'LAST_EVENT > tAH) + REPORT "ADDR Hold time violation -- tAH" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT > tAH) + REPORT "BA Hold time violation -- tAH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tDH) = '1' THEN + ASSERT(Dq'LAST_EVENT > tDH) + REPORT "DQ Hold time violation -- tDH" + SEVERITY WARNING; + END IF; + END PROCESS; + +END behave; diff --git a/lib/models/memory/sdram/mt48v2m32lffc/test.do b/lib/models/memory/sdram/mt48v2m32lffc/test.do new file mode 100644 index 0000000..7a7cc2b --- /dev/null +++ b/lib/models/memory/sdram/mt48v2m32lffc/test.do @@ -0,0 +1,5 @@ +vcom mt48v2m32lffc.vhd +vcom test.vhd +vsim -t ps tb +do wave.do +run -all diff --git a/lib/models/memory/sdram/mt48v2m32lffc/test.vhd b/lib/models/memory/sdram/mt48v2m32lffc/test.vhd new file mode 100644 index 0000000..1c37500 --- /dev/null +++ b/lib/models/memory/sdram/mt48v2m32lffc/test.vhd @@ -0,0 +1,309 @@ +LIBRARY ieee; + USE ieee.std_logic_1164.ALL; + +ENTITY tb IS +END tb; + +ARCHITECTURE test OF tb IS + COMPONENT mt48v2m32lffc + GENERIC ( -- Timing for -7 CL2 + tCK : TIME := 13 ns; + addr_bits : INTEGER := 11; + data_bits : INTEGER := 32 + ); + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '1'; + Cs_n : IN STD_LOGIC := '1'; + Cas_n : IN STD_LOGIC := '1'; + Ras_n : IN STD_LOGIC := '1'; + We_n : IN STD_LOGIC := '1'; + Dqm : IN STD_LOGIC_VECTOR (3 DOWNTO 0) := "0000" + ); + END COMPONENT; + + FOR ALL : mt48v2m32lffc USE ENTITY work.mt48v2m32lffc (behave); + + CONSTANT tCK : TIME := 13 ns; + CONSTANT addr_bits : INTEGER := 11; + CONSTANT data_bits : INTEGER := 32; + + SIGNAL pDq : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0); + SIGNAL pAddr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + SIGNAL pBa : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL pClk : STD_LOGIC; + SIGNAL pCke : STD_LOGIC; + SIGNAL pCs_n : STD_LOGIC; + SIGNAL pCas_n : STD_LOGIC; + SIGNAL pRas_n : STD_LOGIC; + SIGNAL pWe_n : STD_LOGIC; + SIGNAL pDqm : STD_LOGIC_VECTOR (3 DOWNTO 0); + SIGNAL stim_done : boolean := false; + SIGNAL clk_done : boolean := false; + + +BEGIN + u1: mt48v2m32lffc + PORT MAP( + Dq => pDq, + Addr => pAddr, + Ba => pBa, + Clk => pClk, + Cke => pCke, + Cs_n => pCs_n, + Ras_n => pRas_n, + Cas_n => pCas_n, + We_n => pWe_n, + Dqm => pDqm + ); + + stimulator : PROCESS + PROCEDURE ACTIVE (Ba_in : STD_LOGIC_VECTOR (1 DOWNTO 0); + Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + Dq_in : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '0'; + pCas_n <= '1'; + pWe_n <= '1'; + pDqm <= "0000"; + pBa <= Ba_in; + pAddr <= Addr_in; + pDq <= Dq_in; + WAIT FOR tCK; + END; + + PROCEDURE AUTO_REFRESH IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '0'; + pCas_n <= '0'; + pWe_n <= '1'; + pDqm <= "0000"; + --pBa <= "00"; + --pAddr <= (OTHERS => '0'); + pDq <= (OTHERS => 'Z'); + WAIT FOR tCK; + END; + + PROCEDURE BURST_TERM IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '1'; + pCas_n <= '1'; + pWe_n <= '0'; + pDqm <= "0000"; + --pBa <= "00"; + --pAddr <= (OTHERS => '0'); + pDq <= (OTHERS => 'Z'); + WAIT FOR tCK; + END; + + PROCEDURE LOAD_MODE_REG (Ba_in : STD_LOGIC_VECTOR (1 DOWNTO 0); + Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0)) IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '0'; + pCas_n <= '0'; + pWe_n <= '0'; + pDqm <= "0000"; + pBa <= Ba_in; + pAddr <= Addr_in; + pDq <= (OTHERS => 'Z'); + WAIT FOR tCK; + END; + + PROCEDURE NOP (Dq_in : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '1'; + pCas_n <= '1'; + pWe_n <= '1'; + pDqm <= "0000"; + --pBa <= "00"; + --pAddr <= (OTHERS => '0'); + pDq <= Dq_in; + WAIT FOR tCK; + END; + + PROCEDURE PRECHARGE (Ba_in : STD_LOGIC_VECTOR (1 DOWNTO 0); + Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + Dq_in : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '0'; + pCas_n <= '1'; + pWe_n <= '0'; + pDqm <= "0000"; + pBa <= Ba_in; + pAddr <= Addr_in; + pDq <= Dq_in; + WAIT FOR tCK; + END; + + PROCEDURE READ (Ba_in : STD_LOGIC_VECTOR (1 DOWNTO 0); + Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + Dq_in : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '1'; + pCas_n <= '0'; + pWe_n <= '1'; + pDqm <= "0000"; + pBa <= Ba_in; + pAddr <= Addr_in; + pDq <= Dq_in; + WAIT FOR tCK; + END; + + -- Write + PROCEDURE WRITE (Ba_in : STD_LOGIC_VECTOR (1 DOWNTO 0); + Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0); + Dq_in : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS + BEGIN + pCke <= '1'; + pCs_n <= '0'; + pRas_n <= '1'; + pCas_n <= '0'; + pWe_n <= '0'; + pDqm <= "0000"; + pBa <= Ba_in; + pAddr <= Addr_in; + pDq <= Dq_in; + WAIT FOR tCK; + END; + BEGIN + -- COMMAND BA ADDR DQ + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + -- We need 100 us power up sequence. I use 10 NOPs here as a required example. + PRECHARGE ("00", "10000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + + AUTO_REFRESH; + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + + AUTO_REFRESH; + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + + LOAD_MODE_REG ("00", "00000100010"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + + ACTIVE ("00", "00000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + + ACTIVE ("01", "00000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + + ACTIVE ("10", "00000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + + ACTIVE ("11", "00000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + + WRITE ("00", "00000000000", "00000000000000000000000000000000"); + NOP ( "00000000000000000000000000000001"); + NOP ( "00000000000000000000000000000010"); + NOP ( "00000000000000000000000000000011"); + + WRITE ("01", "00000000000", "00000000000000000000000000000100"); + NOP ( "00000000000000000000000000000101"); + NOP ( "00000000000000000000000000000110"); + NOP ( "00000000000000000000000000000111"); + + WRITE ("10", "00000000000", "00000000000000000000000000001000"); + NOP ( "00000000000000000000000000001001"); + NOP ( "00000000000000000000000000001010"); + NOP ( "00000000000000000000000000001011"); + + WRITE ("11", "00000000000", "00000000000000000000000000001100"); + NOP ( "00000000000000000000000000001101"); + NOP ( "00000000000000000000000000001110"); + NOP ( "00000000000000000000000000001111"); + + READ ("00", "00000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + READ ("01", "00000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + READ ("10", "00000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + READ ("11", "00000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + NOP ( "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + + ASSERT false + REPORT "End of Stimulation File Detected!" + SEVERITY note; + stim_done <= true; + WAIT; + END PROCESS; + + clock : PROCESS + VARIABLE done_time : time; + BEGIN + pclk <= '0'; + WAIT for tCK/2; + WHILE not stim_done loop + pclk <= '1'; + WAIT for tCK/2; + pclk <= '0'; + WAIT for tCK/2; + END LOOP; + done_time := now + tCK; + WHILE now < done_time LOOP -- one last clock to finish last command + pclk <= '1'; + WAIT for tCK/2; + pclk <= '0'; + WAIT for tCK/2; + END LOOP; + ASSERT false + REPORT "Suspending clock activity" + SEVERITY note; + clk_done <= true; + WAIT; + END PROCESS; +END test; diff --git a/lib/models/memory/sdram/mt48v2m32lffc/wave.do b/lib/models/memory/sdram/mt48v2m32lffc/wave.do new file mode 100644 index 0000000..26de1d2 --- /dev/null +++ b/lib/models/memory/sdram/mt48v2m32lffc/wave.do @@ -0,0 +1,26 @@ +add wave -noupdate -radix default -format Logic /tb/u1/clk +add wave -noupdate -radix default -format Logic /tb/u1/cke +add wave -noupdate -radix default -format Logic /tb/u1/cs_n +add wave -noupdate -radix default -format Logic /tb/u1/ras_n +add wave -noupdate -radix default -format Logic /tb/u1/cas_n +add wave -noupdate -radix default -format Logic /tb/u1/we_n +add wave -noupdate -radix decimal /tb/u1/addr +add wave -noupdate -radix unsigned /tb/u1/ba +add wave -noupdate -radix decimal /tb/u1/dq +add wave -noupdate -radix default -format Logic /tb/u1/dqm +add wave -noupdate -radix decimal /tb/u1/operation +add wave -noupdate -radix decimal /tb/u1/mode_reg +add wave -noupdate -radix default -format Logic /tb/u1/active_enable +add wave -noupdate -radix default -format Logic /tb/u1/aref_enable +add wave -noupdate -radix default -format Logic /tb/u1/burst_term +add wave -noupdate -radix default -format Logic /tb/u1/mode_reg_enable +add wave -noupdate -radix default -format Logic /tb/u1/prech_enable +add wave -noupdate -radix default -format Logic /tb/u1/read_enable +add wave -noupdate -radix default -format Logic /tb/u1/write_enable +add wave -noupdate -radix default -format Logic /tb/u1/burst_length_1 +add wave -noupdate -radix default -format Logic /tb/u1/burst_length_2 +add wave -noupdate -radix default -format Logic /tb/u1/burst_length_4 +add wave -noupdate -radix default -format Logic /tb/u1/burst_length_8 +add wave -noupdate -radix default -format Logic /tb/u1/cas_latency_2 +add wave -noupdate -radix default -format Logic /tb/u1/cas_latency_3 +