OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk
    from Rev 654 to Rev 655
    Reverse comparison

Rev 654 → Rev 655

/orpsocv2/bench/verilog/include/cfi_flash_def.h
0,0 → 1,49
// _/ _/_/
// _/_/ _/_/_/
// _/_/_/_/ _/_/_/
// _/_/_/_/_/ _/_/_/ ____________________________________________
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/ _/_/_/ / 28F256P30 /
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/_/ _/_/_/ / 256Mbit /
// _/_/_/_/_/_/ _/_/_/ / single die /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/ _/_/_/ / Verilog Behavioral Model /
// _/_/_/ _/_/_/ _/_/_/ / Version 1.3 /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/_/_/_/ / Copyright (c) 2010 Numonyx B.V. /
// _/_/_/ _/_/_/_/_/ /___________________________________________/
// _/_/_/ _/_/_/_/
// _/_/ _/_/_/
//
//
// NUMONYX
// *****************************************
// Glogal Definition for Device : M58WR128F
// *****************************************
 
// TimeScale Directive
`timescale 1 ns / 1 ns
 
`define HIGH 1'b1
`define LOW 1'b0
`define Z 1'bZ
`define X 1'bX
`define FALSE 1'b0
`define TRUE 1'b1
`define UNLOCK 1'b0 // Unlocked Block Lock Status
`define LOCK 1'b1 // Locked Block Lock Status
`define UNLOCKDOWN 1'b0 // UnLocked-down Status
`define LOCKDOWN 1'b1 // Locked-down Status
`define BUSY 1'b0
`define READY 1'b1
`define BYTE_range 7:0
`define WORD_range 15:0
`define LOW_range 7:0
`define HIGH_range 15:8
`define WORDNP 16'hFFFF // Memory not programmed
`define Kbyte 1024
`define Kword 1024
`define INTEGER 15:0
 
/orpsocv2/bench/verilog/include/cfi_flash_TimingData.h
0,0 → 1,314
// _/ _/_/
// _/_/ _/_/_/
// _/_/_/_/ _/_/_/
// _/_/_/_/_/ _/_/_/ ____________________________________________
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/ _/_/_/ / 28F256P30 /
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/_/ _/_/_/ / 256Mbit /
// _/_/_/_/_/_/ _/_/_/ / single die /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/ _/_/_/ / Verilog Behavioral Model /
// _/_/_/ _/_/_/ _/_/_/ / Version 1.3 /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/_/_/_/ / Copyright (c) 2010 Numonyx B.V. /
// _/_/_/ _/_/_/_/_/ /___________________________________________/
// _/_/_/ _/_/_/_/
// _/_/ _/_/_/
//
//
// NUMONYX
`include "cfi_flash_data.h"
`include "cfi_flash_UserData.h"
 
`define Reset_time 300000
 
// *********************************************
//
// Table 29
// Program/Erase Characteristics
//
// *********************************************
 
// Vpp = VppL
 
/*
// Too long!
`define ParameterBlockErase_time 800000000// 0.8 sec
`define MainBlockErase_time 800000000
*/
 
/* erase times much reduced for simulation - Julius */
`define ParameterBlockErase_time 8000// 800ns sec
`define MainBlockErase_time 8000
 
/*
`define WordProgram_time 150000 // 150 us
`define ParameterBlockProgram_time 272000 // 32000 us = 32 ms???????verificare
`define MainBlockProgram_time 700000 // 256000 us = 256 ms???????verificare
*/
 
`define WordProgram_time 1500 // 150 us
`define ParameterBlockProgram_time 2720 // 32000 us = 32 ms???????verificare
`define MainBlockProgram_time 7000 // 256000 us = 256 ms???????verificare
 
`define ProgramSuspendLatency_time 20000 // 20 us
`define EraseSuspendLatency_time 20000 // 20 us
`define MainBlankCheck_time 3200000
// Vpp = VppH
 
`define FastParameterBlockErase_time 800000000 // 0.8 sec
`define FastMainBlockErase_time 800000000 // 0.8 sec
`define FastWordProgram_time 150000 // 8 us
`define FastParameterBlockProgram_time 272000 // 32 ms
`define FastMainBlockProgram_time 700000 // 256000 us = 256 ms
 
`define BlockProtect_time 1800
`define BlockUnProtect_time 5000000
 
`define ProgramBuffer_time 700000
 
 
`define EnhBuffProgram_time 512000 //
`define EnhBuffProgramSetupPhase_time 5000
 
 
 
// **********************
//
// Timing Data Module :
// set timing values
//
// **********************
 
module TimingDataModule;
 
// ************************************
//
// AC Read Specifications
//
// Table 27
//
// ************************************
 
integer tAVAV; // Address Valid to Next Address Valid
integer tAVQV; // Address Valid to Output Valid (Random)
integer tAVQV1; // Address Valid to Output Valid (Page)
integer tELTV; // Chip Enable Low to Wait Valid
integer tELQV; // Chip Enable Low to Output Valid
integer tELQX; // Chip Enable Low to Output Transition
integer tEHTZ; // Chip Enable High to Wait Hi-Z
integer tEHQX;//tOH // Chip Enable High to Output Transition
integer tEHQZ; // Chip Enable High to Output Hi-Z
integer tGLQV; // Output Enable Low to Output Valid
integer tGLQX; // Output Enable Low to Output Transition
integer tGHQZ; // Output Enable High to Output Hi-Z
integer tAVLH;//tAVVH // Address Valid to (ADV#) Latch Enable High
integer tELLH; //tELVH // Chip Enable Low to Latch Enable High
integer tLHAX; //tVHAX // Latch Enable High to Address Transition
integer tLLLH; //tVLVH // Latch Enable Low to Latch Enable High
integer tLLQV; //tVLQV // Latch Enable Low to Output Valid
 
integer tGLTV; //// Output Enable Low to Wait Valid
integer tGLTX; //// Output Enable Low to Wait Transition
integer tGHTZ; //// Output Enable high to Wait Hi-Z
 
 
 
 
 
integer tAVKH; //tAVCH/L // Address Valid to Clock High
integer tELKH; //tELCH // Chip Enable Low to Clock High
integer tEHEL;// tEHEL // Chip Enable High to Chip Enable Low (reading)
integer tKHAX;//tCHAX // Clock High to Address Transition
integer tKHQV; //tCHQV // Clock High to Output Enable Valid
integer tKHTV; //tCHTV // Clock High to Wait Valid
integer tKHQX; //tCHQX // Clock High to Output Enable Transition
integer tKHTX; //tCHTX // Clock High to Wait Transition
integer tLLKH; //tVLCH/L // Latch Enable Low to Clock High
integer tLLKL; //tVLCH/L // Latch Enable Low to Clock High
integer tKHLL; //tCHVL //Clock valid to ADV# setup
integer tKHKH; //tCLK // Clock Period
integer tKHKL; //tCH/CL // Clock High to Clock Low
integer tKLKH; // Clock Low to Clock High
integer tCK_fall; //R203 // Clock Fall Time
integer tCK_rise; // Clock Rise Time
 
 
// *************************************************
//
// AC Write Specifications
//
// Table 28
//
// *************************************************
 
integer tAVWH; // Address Valid to Write Enable High
integer tDVWH; // Data Valid to Write Enable High
integer tELWL; // Chip Enable Low to Write Enable Low
integer tWHAV; //W18 // Write Enable High to Address Valid
integer tWHAX; // Write Enable High to Address Transition
integer tWHDX; // Write Enable High to Data Transition
integer tWHEH; // Write Enable High to Chip Enable High
integer tWHGL; // Write Enable High to Output Enable High
integer tWHLL; //W28 tWHVL // Write Enable High to Latch Enable Low
integer tWHWL; // Write Enable High to Latch Enable Low
integer tWHQV; // Write Enable High to Output Enable Valid
integer tWLWH; // Write Enable Low to Write Enable High
integer tQVVPL; //tQVVL // Output (Status Register) Valid to Vpp Low
integer tQVWPL; //tQVBL // Output (Status Register) Valid to Write Protect Low
integer tVPHWH; // Vpp High to Write Enable High
integer tWPHWH; //tBHWH // Write Protect High to Write Enable High
 
 
integer tELEH; // Chip Enable Low to Chip Enable High
 
 
//!// *************************************
//!//
//!// Power and Reset
//!//
//!// Table 20
//!//
//!// **************************************
 
integer tPHWL; //W1 // Reset High to Write Enable Low
integer tPLPH;//P1 // Reset High to Reset Low
 
integer tVDHPH; //tVCCPH // Supply voltages High to Reset High
 
 
 
initial begin
 
setTiming(`t_access);
end
 
// **********************
//
// FUNCTION getTime :
// return time value
//
// **********************
 
function getTime;
 
input [8*31 : 0] time_str;
 
begin
 
 
end
endfunction
 
// **********************
//
// Task setTiming :
// set timing values
//
// **********************
 
task setTiming;
 
input time_access;
 
integer time_access;
 
begin
 
// ***********************************************
//
// AC Read Specifications
//
// Table 27
//
// ***********************************************
 
tELQX = 0;
tEHQX = 0;
tGLQX = 0;
tGHQZ = 15;
tELLH = 10;
 
tAVAV = time_access;
tAVQV = time_access;
tELQV = time_access;
tLLQV = time_access;
tEHTZ = 20;
tAVQV1 = 25;
tELTV = 17;
tEHEL = 17;
tCK_fall = 3;
tCK_rise = 3;
tEHQZ = 20;
tGLQV = 25;
tAVLH = 10;
tLHAX = 9;
tLLLH = 10;
 
tAVKH = 9;
tELKH = 9;
tKHAX = 10;
tKHQV = 17;
tKHTV = 17;
tKHQX = 3;
tKHTX = 3;
tLLKH = 9;
tLLKL = 9;
tKHLL = 3;
tKHKH = 19.2;
tKHKL = 5;
tKLKH = 5;
tGLTV = 17;
tGLTX = 0;
tGHTZ = 20;
 
// *************************************************
//
// AC Write Specifications
//
// Table 28
//
// *************************************************
 
tELWL = 0;
tWHAV = 0;
tWHAX = 0;
tWHDX = 0;
tWHEH = 0;
tWHGL = 0;
tWHLL = 7;
tQVVPL = 0;
tQVWPL = 0;
tVPHWH = 200;
tWPHWH = 200;
tAVWH = 50;
tDVWH = 50;
tWHWL = 20;
tWHQV = tAVQV + 35; //tAVQV+35
tWLWH = 50;
tELEH = 50;
// *************************************
//
// Power and Reset
//
// Table 20
//
// **************************************
 
tPHWL = 150;
tPLPH = 100;
tVDHPH = 300;
 
 
end
endtask
 
endmodule
 
/orpsocv2/bench/verilog/include/cfi_flash_BankLib.h
0,0 → 1,280
// _/ _/_/
// _/_/ _/_/_/
// _/_/_/_/ _/_/_/
// _/_/_/_/_/ _/_/_/ ____________________________________________
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/ _/_/_/ / 28F256P30 /
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/_/ _/_/_/ / 256Mbit /
// _/_/_/_/_/_/ _/_/_/ / single die /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/ _/_/_/ / Verilog Behavioral Model /
// _/_/_/ _/_/_/ _/_/_/ / Version 1.3 /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/_/_/_/ / Copyright (c) 2010 Numonyx B.V. /
// _/_/_/ _/_/_/_/_/ /___________________________________________/
// _/_/_/ _/_/_/_/
// _/_/ _/_/_/
//
//
// NUMONYX
 
// ****************************************************
//
// Block Library :
//
// define the architecture of the blocks and banks
//
// ****************************************************
 
`include "cfi_flash_def.h"
`include "cfi_flash_data.h"
`include "cfi_flash_UserData.h"
 
`define BLOCK_dim 259
`define BLOCKDIM_range 0 : `BLOCK_dim - 1
`define BLOCKADDR_dim 16
`define BLOCKADDR_range `BLOCKADDR_dim - 1 : 0
 
// *********
//
// Parameter Block & Main Block
 
//
// *********
 
`define ParameterBlock_num 4
`define ParameterBlock_size 16 // Size of Parameter Block (Kword)
`define MainBlock_num 255
`define MainBlock_size 64 // Size of Main Block (Kword)
 
 
 
module BankLib;
 
integer BlockBoundaryStartAddr [`BLOCK_dim - 1 : 0]; // Block Boundary Start Address
integer BlockBoundaryEndAddr [`BLOCK_dim - 1 : 0]; // Block Boundary End Address
integer count;
 
initial
begin
 
begin: block_building
for (count = 0; count <= `BLOCK_dim - 1; count = count + 1)
BuildBlockBoundary(`organization, count, BlockBoundaryStartAddr[count], BlockBoundaryEndAddr[count]);
 
end
 
end
 
// ******************************************************************
//
// TASK BuildBlockBoundary: Build the Blocks Boundaries in two arrays
//
// ******************************************************************
 
task BuildBlockBoundary;
input organize;
input n_block;
output StartAddr;
output EndAddr;
 
reg [8*6:1] organize;
integer n_block;
integer StartAddr;
integer EndAddr;
 
begin
if (organize == "top") begin
if (n_block == 0) EndAddr = - 1;
if (n_block > `MainBlock_num - 1 && n_block <= `MainBlock_num + `ParameterBlock_num - 1) // parameter block
begin
StartAddr = EndAddr + 1;
EndAddr = StartAddr + `ParameterBlock_size * `Kword - 1;
end
else // Main block
begin
StartAddr = EndAddr + 1;
EndAddr = StartAddr + `MainBlock_size * `Kword - 1;
end
 
end else begin // organize = "bottom"
if (n_block == 0) EndAddr = - 1;
if (n_block > `ParameterBlock_num - 1)
begin
StartAddr = (`ParameterBlock_num * `ParameterBlock_size * `Kword ) +
(n_block - `ParameterBlock_num) * `MainBlock_size * `Kword;
EndAddr = StartAddr + `MainBlock_size * `Kword - 1;
end
//!
else // parameter block
begin
StartAddr = EndAddr + 1;
EndAddr = StartAddr + `ParameterBlock_size * `Kword - 1;
end
 
end
//!$display("n_block=%d, StartAddr =%h, EndAddr =%h", n_block, StartAddr , EndAddr);
end
endtask
 
 
 
// *********************************************
// FUNCTION getBlock : return block from address
//
// *********************************************
 
function [`INTEGER] getBlock; // BLOCK_dim in binary is 9 bit size
 
input address;
 
reg [`ADDRBUS_dim - 1 : 0] address;
reg found;
integer count;
 
begin
// $display ("function getBlock got address %h", address);
count = 0;
found = 0;
while ((count <= `BLOCK_dim) && (! found))
begin
 
if ((BlockBoundaryStartAddr[count] <= address) && (address <= BlockBoundaryEndAddr[count])) found= 1;
else count = count + 1;
 
end
if (!found) $display("%t address= %h !Error in Block Library : specified block address is out of range",$time,address);
getBlock= count;
end
endfunction
 
 
// ***************************
//
// FUNCTION getBlockAddress :
// return the block address
//
// ***************************
 
function [`ADDRBUS_dim - 1 : 0] getBlockAddress;
 
input block;
 
integer block;
 
begin
 
getBlockAddress = BlockBoundaryStartAddr[block];
 
end
endfunction
 
 
// *********************************************
//
// FUNCTION isParameterBlock :
// return true if the address
// is in a parameter block
//
// *********************************************
 
function isParameterBlock;
 
input address;
 
reg [`ADDRBUS_dim - 1 : 0] address;
reg prm;
integer count;
 
begin
 
prm = `FALSE;
if (`organization=="bottom") begin
 
for (count = 0; count <= `ParameterBlock_num - 1; count = count + 1) begin: cycle
 
if ((BlockBoundaryStartAddr[count] <= address) && (address <= BlockBoundaryEndAddr[count]))
begin
prm= `TRUE;
disable cycle;
end
end
end else begin
for (count = `BLOCK_dim - `ParameterBlock_num + 1; count <= `BLOCK_dim - 1; count = count + 1) begin: cycle1
 
if ((BlockBoundaryStartAddr[count] <= address) && (address <= BlockBoundaryEndAddr[count]))
begin
prm= `TRUE;
disable cycle1;
end
end
end
isParameterBlock = prm;
end
endfunction
 
 
// *********************************************
//
// FUNCTION isMainBlock :
// return true if the address is in a main block
//
// *********************************************
 
function isMainBlock;
 
input address;
 
reg [`ADDRBUS_dim - 1 : 0] address;
reg main;
integer count;
 
begin
 
main = `FALSE;
 
if (`organization=="bottom") begin
for (count = `BLOCK_dim - 1; count >= `BLOCK_dim - `ParameterBlock_num + 1; count = count - 1) begin: cycle2
 
if ((BlockBoundaryStartAddr[count] <= address) && (address <= BlockBoundaryEndAddr[count]))
begin
main = `TRUE;
disable cycle2;
end
end
end else begin
for (count = 0; count <= `MainBlock_num - 1; count = count + 1) begin: cycle3
 
 
if ((BlockBoundaryStartAddr[count] <= address) && (address <= BlockBoundaryEndAddr[count]))
begin
main = `TRUE;
disable cycle3;
end
end
end
isMainBlock = main;
end
endfunction
 
 
endmodule
/orpsocv2/bench/verilog/include/cfi_flash_UserData.h
0,0 → 1,36
// _/ _/_/
// _/_/ _/_/_/
// _/_/_/_/ _/_/_/
// _/_/_/_/_/ _/_/_/ ____________________________________________
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/ _/_/_/ / 28F256P30 /
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/_/ _/_/_/ / 256Mbit /
// _/_/_/_/_/_/ _/_/_/ / single die /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/ _/_/_/ / Verilog Behavioral Model /
// _/_/_/ _/_/_/ _/_/_/ / Version 1.3 /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/_/_/_/ / Copyright (c) 2010 Numonyx B.V. /
// _/_/_/ _/_/_/_/_/ /___________________________________________/
// _/_/_/ _/_/_/_/
// _/_/ _/_/_/
//
//
// NUMONYX
 
// ************************************
//
// User Data definition file :
//
// here are defined all parameters
// that the user can change
//
// ************************************
 
`define organization "top" // top or bottom
`define BLOCKPROTECT "on" // if on the blocks are locked at power-up
`define TimingChecks "on" // on for checking timing constraints
`define t_access 100 // Access Time 100 ns, 110 ns
`define FILENAME_mem "cfi-flash.vmem" // Memory File Name
/orpsocv2/bench/verilog/include/cfi_flash_data.h
0,0 → 1,214
// _/ _/_/
// _/_/ _/_/_/
// _/_/_/_/ _/_/_/
// _/_/_/_/_/ _/_/_/ ____________________________________________
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/ _/_/_/ / 28F256P30 /
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/_/ _/_/_/ / 256Mbit /
// _/_/_/_/_/_/ _/_/_/ / single die /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/ _/_/_/ / Verilog Behavioral Model /
// _/_/_/ _/_/_/ _/_/_/ / Version 1.3 /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/_/_/_/ / Copyright (c) 2010 Numonyx B.V. /
// _/_/_/ _/_/_/_/_/ /___________________________________________/
// _/_/_/ _/_/_/_/
// _/_/ _/_/_/
//
//
// NUMONYX
 
// ******
//
// data.h
//
// ******
 
// ********************
//
// Main Characteristics
//
// ********************
 
`define ADDRBUS_dim 24 // - Address Bus pin numbers
`define DATABUS_dim 16 // - Data Bus pin numbers
`define MEMORY_dim 1 << `ADDRBUS_dim // - Memory Dimension
`define LAST_ADDR (`MEMORY_dim) - 1 // - Last Address
 
// ********************
//
// Address & Data range
//
// ********************
 
`define ADDRBUS_range `ADDRBUS_dim - 1 : 0
`define DATABUS_range `DATABUS_dim - 1 : 0
 
// *****************
//
// Init Memory Files
//
// *****************
 
`define CFI_dim 9'h157
`define CFI_range `CFI_dim - 1:9'h10
// *******************
//
// Protection Register
//
// *******************
 
 
`define REG_addrStart 16'h0
`define REG_addrEnd 16'h15
 
`define REGSTART_addr 9'h80 // Protection Register Start Address
`define REGEND_addr 9'h109 // Protection Register End Address
`define REG_dim `REGEND_addr - `REGSTART_addr + 1
 
`define REG_addrRange `REG_addrEnd:`REG_addrStart
 
`define REG_addrbitStart 8'd0
`define REG_addrbitEnd 8'd8
`define REG_addrbitRange `REG_addrbitEnd:`REG_addrbitStart
 
`define PROTECTREGLOCK_addr 9'h80 // Protection Register Lock Address
 
 
`define UDNREGSTART_addr 9'h81
`define UDNREGEND_addr 9'h84
`define UDNprotect_bit 8'hFE
 
`define UPREGSTART_addr 9'h85
`define UPREGEND_addr 9'h88
`define UPprotect_bit 8'hFD // serve ad indentificare quale bit deve essere 0 nel lock regi
`define PRL_default 16'h0002 // Protection Register Lock default definito anche in def
 
// *****************************
//
// Extended User OTP
//
// *****************************
 
`define ExtREG_dim 8'h20
 
 
`define ExtREG_regiondim 8'h8
`define ExtREGSTART_regionaddr 9'h8A // Ext Protection Register Start Address
`define ExtREGEND_regionaddr 9'h109 // Ext Protection Register End Address
 
`define ExtPROTECTREGLOCK_addr 9'h89 // Ext Protection Register Lock Address
`define ExtPRL_default 16'hFFFF // Protection Register Lock default
 
 
 
// ***********************
//
// Voltage Characteristics
//
// ***********************
`define Voltage_range 35:0
`define VDDmin 36'd01700
`define VDDmax 36'd02000
`define VDDQmin 36'd01700
`define VDDQmax 36'd03600
`define VPPmin 36'd00900
`define VPPmax 36'd03600
`define VPPHmin 36'd08500
`define VPPHmax 36'd09500
 
// **********************
//
// Configuration Register
//
// **********************
 
`define ConfigurationReg_dim 16
`define ConfigReg_default 16'hF94F
 
// ********************
//
// Electronic Signature
//
// ********************
 
`define ManufacturerCode 8'h89
`define TopDeviceCode 8'h19
`define BottomDeviceCode 8'h1C
`define SignAddress_dim 9
`define SignAddress_range `SignAddress_dim - 1 : 0
 
 
 
// *********************
//
// Write Buffer constant
//
// *********************
 
 
`define ProgramBuffer_addrDim 9 // Program Buffer address dimension
`define ProgramBuffer_addrRange `ProgramBuffer_addrDim - 1:0
`define ProgramBuffer_dim 512 // Buffer Size= 2 ^ ProgramBuffer_addrDim
`define ProgramBuffer_range `ProgramBuffer_dim - 1:0
 
// *********************
//
// Buffer Enhanced Program constant
//
// *********************
 
`define BuffEnhProgramBuffer_dim 512
`define BuffEnhProgramBuffer_range `BuffEnhProgramBuffer_dim - 1 : 0
`define BuffEnhProgramBuffer_addrDim 9
`define BuffEnhProgramBuffer_addrRange `BuffEnhProgramBuffer_addrDim - 1:0
 
// Warning and Error Messages
 
`define NoError_msg 0 // No Error Found
`define CmdSeq_msg 1 // Sequence Command Unknown
`define SuspCmd_msg 2 // Cannot execute this command during suspend
`define SuspAcc_msg 3 // Cannot access this address due to suspend
`define AddrRange_msg 4 // Address out of range
`define AddrTog_msg 5 // Cannot change block address during command sequence
`define SuspAccWarn_msg 6 // It isn't possible access this address due to suspend
`define InvVDD_msg 7 // Voltage Supply must be: VDD>VDDmin or VDD<VDDmax
`define InvVPP_msg 8 // Voltage Supply must be: VDD>VDDmin or VDD<VDDmax
`define BlockLock_msg 9 // Cannot complete operation when the block is locked
`define ByteToggle_msg 10 // Cannot toggle BYTE_N while busy
`define NoUnLock_msg 11 // Invalid UnLock Block command in Locked-Down Block
`define AddrCFI_msg 12 // CFI Address out of range
`define PreProg_msg 13 // Program Failure due to cell failure
`define NoBusy_msg 14 // Device is not Busy
`define NoSusp_msg 15 // Nothing previus suspend command
`define Suspend_msg 16 // Device is Suspend mode
`define UDNlock_msg 17 // Unique Device Number Register is locked
`define UPlock_msg 18 // User Programmable Register is locked
`define ExitPHASE_BEFP_msg 19
`define WrongEraseConfirm_msg 20 // Wrong Erase Confirm code
`define SignAddrRange_msg 21 // Signature Address out of range
`define CFIAddrRange_msg 22 // CFI Address out of range
`define WrongBlankCheckConfirm_msg 23 // Wrong Blank Check Confirm code command
`define BlankCheckFailed_msg 24 // Blank Check Failed
`define ProgramPHASE_BEFP_msg 25 // End of Program or Verify Phase on Enhanced Factory Program
`define BlkBuffer_msg 26 // Program Buffer cannot cross block boundary
`define ExtREGLock_msg 27 // Extended User Programmable Register is locked
`define LeastAddr0 28 // Significative bit [%d,0] of Start Address must be 0
`define ProtRegAddrRange_msg 29 // Protect Register Address out of range
`define BuffSize_msg 30 // Buffer size is too large
`define WrongBlankCheckBlock 31 // No main block
 
// ******************
//
// Valid Access Times
//
// ******************
 
`define tAccess_1 100
`define tAccess_2 110
 
 
 
 
/orpsocv2/bench/verilog/include/cfi_flash_CUIcommandData.h
0,0 → 1,106
// _/ _/_/
// _/_/ _/_/_/
// _/_/_/_/ _/_/_/
// _/_/_/_/_/ _/_/_/ ____________________________________________
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/ _/_/_/ / 28F256P30 /
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/_/ _/_/_/ / 256Mbit /
// _/_/_/_/_/_/ _/_/_/ / single die /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/ _/_/_/ / Verilog Behavioral Model /
// _/_/_/ _/_/_/ _/_/_/ / Version 1.3 /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/_/_/_/ / Copyright (c) 2010 Numonyx B.V. /
// _/_/_/ _/_/_/_/_/ /___________________________________________/
// _/_/_/ _/_/_/_/
// _/_/ _/_/_/
//
//
// NUMONYX
 
// **********************
//
// COMMAND USER INTERFACE
//
// **********************
 
// Read Commands
 
`define RD_cmd 8'hFF // Read Memory Array
`define RSR_cmd 8'h70 // Read Status Register
`define RSIG_cmd 8'h90 // Read Electronic Signature
`define RCFI_cmd 8'h98 // Read CFI
 
 
// Program/Erase Commands
 
`define PG_cmd 8'h40 // Program
`define PES_cmd 8'hB0 // Program/Erase Suspend
`define PER_cmd 8'hD0 // Program/Erase Resume
`define BLKEE_cmd 8'h20 // Block Erase
`define BLKEEconfirm_cmd 8'hD0 // Block Erase Confirm
`define CLRSR_cmd 8'h50 // Clear Status Register
`define PRREG_cmd 8'hC0 // Protection Register Program //verificare se va bene x OTP register program setup
 
 
// Protect Commands
 
`define BL_cmd 8'h60 // Block Lock //setup??
`define BUL_cmd 8'h60 // Block UnLock
`define BLD_cmd 8'h60 // Block lock-down
`define BLDconfirm_cmd 8'h2F // Block Lock-down confirm
`define BLconfirm_cmd 8'h01 // Block Lock Confirm
`define BULconfirm_cmd 8'hD0 // Block unLock Confirm
 
 
// Additional Features Commands
 
`define PB_cmd 8'hE8 // Program Buffer
`define PBcfm_cmd 8'hD0 // Close Sequence of Program Buffer Command
 
 
// Configuration Register
 
`define SCR_cmd 8'h60 // Set Configuration Register
`define SCRconfirm_cmd 8'h03 // Set Configuration Register confirm
 
// Additional Features Commands //aggiunto
`define BLNKCHK_cmd 8'hBC // Blank Check Command
`define BLNKCHKconfirm_cmd 8'hD0 // Blank Check Confirm
 
 
// Factory Program Commands
`define BuffEnhProgram_cmd 8'h80 // Enhanced Setup Command
`define BuffEnhProgramCfrm_cmd 8'hD0 // Enhanced Setup confirm
 
`define EnhSetup_cmd 8'h80 // Enhanced Setup Command
`define EnhSetup_cfrm 8'hD0 // Enhanced Setup confirm
 
 
// CUI Status
 
// Read Bus Status Operation
 
`define ReadArray_bus 2'b00 // Read Memory Array
`define ReadSignature_bus 2'b01 // Read Electronic Signature
`define ReadStatusReg_bus 2'b10 // Read Status Register
`define ReadCFI_bus 2'b11 // Read CFI
 
 
// Program/Erase Controller Status
 
`define Free_pes 0 // No Operation
`define Program_pes 1 // Programming
`define ProgramBuff_pes 7 // Programming
 
 
`define BlockErase_pes 2 // Erasing Block
`define ChipErase_pes 3 // Chip Erasing
`define BlockEraseSuspend_pes 4 // Block Erase Suspend
`define ProgramEraseSuspend_pes 5 // Program/Erase Resume
`define ProgramEraseWait_pes 6 // Program/Erase Wait
`define Reset_pes 10 // Reset status
 
 
 
/orpsocv2/bench/verilog/x28fxxxp30.v
0,0 → 1,3793
// _/ _/_/
// _/_/ _/_/_/
// _/_/_/_/ _/_/_/
// _/_/_/_/_/ _/_/_/ ____________________________________________
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/ _/_/_/ / 28F256P30 /
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/_/ _/_/_/ / 256Mbit /
// _/_/_/_/_/_/ _/_/_/ / single die /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/ _/_/_/ / Verilog Behavioral Model /
// _/_/_/ _/_/_/ _/_/_/ / Version 1.3 /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/_/_/_/ / Copyright (c) 2010 Numonyx B.V. /
// _/_/_/ _/_/_/_/_/ /___________________________________________/
// _/_/_/ _/_/_/_/
// _/_/ _/_/_/
//
//
// NUMONYX
`include "cfi_flash_def.h"
`include "cfi_flash_CUIcommandData.h"
`include "cfi_flash_data.h"
`include "cfi_flash_UserData.h"
`include "cfi_flash_BankLib.h"
`include "cfi_flash_TimingData.h"
 
// **********************************
//
// Timing Lib Module :
//
// checks all timing constraints
//
// **********************************
 
module TimingLibModule(A, DQ, W_N, G_N, E_N, L_N, WP_N, CK, VPP);
 
input [`ADDRBUS_dim-1:0] A; // Address Bus
input [`DATABUS_dim-1:0] DQ; // Data I/0 Bus
 
input W_N, G_N, E_N, L_N, WP_N, CK;
input [`Voltage_range] VPP;
 
integer AddValid_time;
integer AddNotValid_time;
integer DataValid_time;
integer DataXX_time;
 
integer WriteEnableLow_time;
integer WriteEnableHigh_time;
integer OutputEnableLow_time;
integer OutputEnableHigh_time;
integer LatchEnableHigh_time;
integer LatchEnableLow_time;
integer ChipEnableLow_time;
integer ChipEnableHigh_time;
integer RisingEdge_time;
integer FallingEdge_time;
 
integer WaitValid_time;
 
integer WriteProtectHigh_time;
integer WriteProtectLow_time;
integer VPPSupplyHigh_time;
integer VPPSupplyLow_time;
 
reg afterReset;
 
reg isValid;
reg dataValid;
reg addressValid;
reg reading;
reg writing;
reg dataXX;
time temp;
 
 
initial begin
 
AddValid_time = 0;
AddNotValid_time = 0;
DataValid_time = 0;
DataXX_time = 0;
 
WriteEnableLow_time = 0;
WriteEnableHigh_time = 0;
OutputEnableLow_time = 0;
OutputEnableHigh_time = 0;
LatchEnableHigh_time = 0;
LatchEnableLow_time = 0;
ChipEnableLow_time = 0;
ChipEnableHigh_time = 0;
 
WaitValid_time = 0;
 
WriteProtectHigh_time = 0;
WriteProtectLow_time = 0;
 
RisingEdge_time = 0;
FallingEdge_time = 0;
 
dataValid = `FALSE;
dataXX = `FALSE;
addressValid = `FALSE;
 
reading = `FALSE;
writing = `FALSE;
 
afterReset = `FALSE;
 
end
 
 
// **************
//
// Change address
//
// **************
 
always @(A) begin : AddressCheck
 
if (`TimingChecks == "off")
disable AddressCheck;
 
if ($time > `Reset_time)
begin
if (isAddValid(A)) // Address Valid
begin
temp = $time - AddValid_time;
checkTiming("tAVAV", TimingData_man.tAVAV, temp, "min");
 
temp = $time - WriteEnableHigh_time;
checkTiming("tWHAV", TimingData_man.tWHAV, temp, "min");
 
AddValid_time = $time;
addressValid = `TRUE;
end
 
else
begin
if (isAddXX(A) || isAddZZ(A)) // Address XXXX o ZZZZ
begin
if (addressValid)
begin
temp = $time - LatchEnableHigh_time;
checkTiming("tLHAX", TimingData_man.tLHAX, temp, "min");
 
temp = $time - WriteEnableHigh_time;
checkTiming("tWHAX", TimingData_man.tWHAX, temp, "min");
 
AddNotValid_time = $time;
end
addressValid = `FALSE;
end
end
end
end
 
 
// ***********
//
// Change data
//
// ***********
 
always @(DQ) begin : DataCheck
 
if (`TimingChecks == "off")
disable DataCheck;
 
if ($time > `Reset_time)
begin
 
if (isDataValid(DQ)) // Data Valid
begin
if (ConfigReg_man.isSynchronous) // Synchronous mode
 
begin
if (reading)
if (ConfigReg_man.isRisingClockEdge)
begin
temp = $time - RisingEdge_time;
end
else
begin
temp = $time - FallingEdge_time;
 
end
end
 
else // Asynchronous mode
begin
temp = $time - AddValid_time;
 
temp = $time - LatchEnableLow_time;
 
temp = $time - ChipEnableLow_time;
 
if (reading)
begin
temp = $time - OutputEnableLow_time;
temp = $time - WriteEnableHigh_time;
end
 
DataValid_time = $time;
dataValid = `TRUE;
dataXX = `FALSE;
end
end
else
begin
if (isDataXX(DQ)) // Data XXXX
begin
if (dataValid)
begin
temp = $time - AddNotValid_time;
 
temp = $time - ChipEnableHigh_time;
checkTiming("tEHQX", TimingData_man.tEHQX, temp, "min");
 
temp = $time - OutputEnableHigh_time;
 
end
 
else
begin
temp = $time - ChipEnableLow_time;
checkTiming("tELQX", TimingData_man.tELQX, temp, "min");
 
if (reading)
begin
temp = $time - OutputEnableLow_time;
checkTiming("tGLQX", TimingData_man.tGLQX, temp, "min");
end
end
 
 
DataXX_time = $time;
dataValid = `FALSE;
dataXX = `TRUE;
end
 
else
if (isDataZZ(DQ))
begin
if (dataXX)
begin
temp = $time - ChipEnableHigh_time;
checkTiming("tEHQZ", TimingData_man.tEHQZ, temp, "max");
temp = $time - OutputEnableHigh_time;
checkTiming("tGHQZ", TimingData_man.tGHQZ, temp, "max");
end
 
if (dataValid)
begin
temp = $time - WriteEnableHigh_time;
checkTiming("tWHDX", TimingData_man.tWHDX, temp, "min");
end
dataValid = `FALSE;
dataXX = `FALSE;
end
end
end
end
 
// ******************
//
// Change Chip Enable
//
// ******************
 
always @(posedge E_N) begin : ChipHighCheck // Chip Enable High
 
if (`TimingChecks == "off")
disable ChipHighCheck;
 
if ($time > `Reset_time)
begin
temp = $time - WriteEnableHigh_time;
checkTiming("tWHEH", TimingData_man.tWHEH, temp, "min");
 
ChipEnableHigh_time = $time;
end
end
 
always @(negedge E_N) begin : ChipLowCheck // Chip Enable Low
 
if (`TimingChecks == "off")
disable ChipLowCheck;
 
if ($time > `Reset_time)
begin
ChipEnableLow_time = $time;
end
 
end
 
always @(posedge L_N) begin : LatchLowCheck // Latch Enable High
 
if (`TimingChecks == "off")
disable LatchLowCheck;
 
if ($time > `Reset_time)
begin
temp = $time - AddValid_time;
checkTiming("tAVLH", TimingData_man.tAVLH, temp, "min");
temp = $time - LatchEnableLow_time;
checkTiming("tLLLH", TimingData_man.tLLLH, temp, "min");
temp = $time - ChipEnableLow_time;
checkTiming("tELLH", TimingData_man.tELLH, temp, "min");
LatchEnableHigh_time = $time;
end
end
 
always @(negedge L_N) begin : LatchHighCheck // Latch Enable Low
 
if (`TimingChecks == "off")
disable LatchHighCheck;
 
if ($time > `Reset_time)
begin
temp = $time - WriteEnableHigh_time;
checkTiming("tWHLL", TimingData_man.tWHLL, temp, "min");
 
temp = $time - RisingEdge_time;
checkTiming("tKHLL", TimingData_man.tKHLL, temp, "min");
 
LatchEnableLow_time = $time;
end
 
end
 
always @(posedge G_N) begin : OutputHighCheck // Output Enable High
 
if (`TimingChecks == "off")
disable OutputHighCheck;
 
if ($time > `Reset_time)
begin
OutputEnableHigh_time = $time;
reading = `FALSE;
end
 
end
 
always @(negedge G_N) begin : OutputLowCheck // Output Enable Low
 
if (`TimingChecks == "off")
disable OutputLowCheck;
 
if ($time > `Reset_time)
begin
 
temp = $time - WriteEnableHigh_time;
checkTiming("tWHGL", TimingData_man.tWHGL, temp, "min");
 
 
OutputEnableLow_time = $time;
reading = `TRUE;
end
 
end
 
always @(posedge W_N) begin : WriteHighCheck // Write Enable High
 
if (`TimingChecks == "off")
disable WriteHighCheck;
 
if ($time > `Reset_time)
begin
 
temp = $time - AddValid_time;
checkTiming("tAVWH", TimingData_man.tAVWH, temp, "min");
 
if (writing)
begin
temp = $time - WriteEnableLow_time;
checkTiming("tWLWH", TimingData_man.tWLWH, temp, "min");
end
temp = $time - DataValid_time;
checkTiming("tDVWH", TimingData_man.tDVWH, temp, "min");
 
temp = $time - WriteProtectHigh_time;
checkTiming("tWPHWH", TimingData_man.tWPHWH, temp, "min");
 
temp = $time - VPPSupplyHigh_time;
checkTiming("tVPHWH", TimingData_man.tVPHWH, temp, "min");
 
WriteEnableHigh_time = $time;
writing = `FALSE;
end
end
 
always @(negedge W_N) begin : WriteLowCheck // Write Enable Low
 
if (`TimingChecks == "off")
disable WriteLowCheck;
 
if ($time > `Reset_time)
begin
temp = $time - ChipEnableLow_time;
checkTiming("tELWL", TimingData_man.tELWL, temp, "min");
 
temp = $time - WriteEnableHigh_time;
checkTiming("tWHWL", TimingData_man.tWHWL, temp, "min");
 
WriteEnableLow_time = $time;
writing = `TRUE;
end
end
 
always @(posedge WP_N) begin : WPHighCheck // Write Protect High
 
if (`TimingChecks == "off")
disable WPHighCheck;
 
if ($time > `Reset_time)
begin
WriteProtectHigh_time = $time;
end
end
 
always @(negedge WP_N) begin : WPLowCheck // Write Protect Low
 
if (`TimingChecks == "off")
disable WPLowCheck;
 
if ($time > `Reset_time)
begin
temp = $time - DataValid_time;
checkTiming("tQVWPL", TimingData_man.tQVWPL, temp, "min");
 
WriteProtectLow_time = $time;
end
end
 
always @(posedge VPP) begin : VPPHighCheck // Write Protect High
 
if (`TimingChecks == "off")
disable VPPHighCheck;
 
if ($time > `Reset_time)
begin
VPPSupplyHigh_time = $time;
end
end
 
always @(negedge VPP) begin : VPPLowCheck // Write Protect Low
 
if (`TimingChecks == "off")
disable VPPLowCheck;
 
if ($time > `Reset_time)
begin
temp = $time - DataValid_time;
checkTiming("tQVVPL", TimingData_man.tQVVPL, temp, "min");
 
VPPSupplyLow_time = $time;
 
end
end
 
always @(posedge CK) begin : RisingCKCheck
 
if (`TimingChecks == "off")
disable RisingCKCheck;
 
if ($time > `Reset_time)
begin
temp = $time - LatchEnableLow_time;
checkTiming("tLLKH", TimingData_man.tLLKH, temp, "min");
 
RisingEdge_time = $time;
end
end
 
always @(negedge CK) begin : FallingCKCheck
 
if (`TimingChecks == "off")
disable FallingCKCheck;
 
if ($time > `Reset_time)
begin
temp = $time - LatchEnableLow_time;
checkTiming("tLLKL", TimingData_man.tLLKL, temp, "min");
FallingEdge_time = $time;
end
end
 
 
 
// **********************************************
//
// FUNCTION isAddValid :
// return true if the input address is valid
//
// **********************************************
 
function isAddValid;
 
input [`ADDRBUS_dim - 1 : 0] Add;
 
reg [`ADDRBUS_dim - 1 : 0] Add;
 
reg valid;
integer count;
 
begin
 
valid = `TRUE;
begin : cycle
for (count = 0; count <= `ADDRBUS_dim - 1; count = count + 1)
begin
if ((Add[count] !== 1'b0) && (Add[count] !== 1'b1))
begin
valid = `FALSE;
disable cycle;
end
end
end
isAddValid = valid;
end
endfunction
 
 
// *********************************************
//
// FUNCTION isAddXX :
// return true if the input address is XXXX
//
// *********************************************
 
function isAddXX;
 
input [`ADDRBUS_dim - 1 : 0] Add;
 
reg [`ADDRBUS_dim - 1 : 0] Add;
 
reg allxx;
integer count;
 
begin
 
allxx = `TRUE;
begin : cycle
for (count = 0; count <= `ADDRBUS_dim - 1; count = count + 1)
begin
if (Add[count] !== 1'bx)
begin
allxx = `FALSE;
disable cycle;
end
end
end
isAddXX = allxx;
end
endfunction
 
// *********************************************
//
// FUNCTION isAddZZ :
// return true if the input address is ZZZZ
//
// *********************************************
 
function isAddZZ;
 
input [`ADDRBUS_dim - 1 : 0] Add;
 
reg [`ADDRBUS_dim - 1 : 0] Add;
 
reg allzz;
integer count;
 
begin
 
allzz = `TRUE;
begin : cycle
for (count = 0; count <= `ADDRBUS_dim - 1; count = count + 1)
begin
if (Add[count] !== 1'bz)
begin
allzz = `FALSE;
disable cycle;
end
end
end
isAddZZ = allzz;
end
endfunction
 
// **********************************************
//
// FUNCTION isDataValid :
// return true if the data is valid
//
// **********************************************
 
function isDataValid;
 
input [`DATABUS_dim - 1 : 0] Data;
 
reg [`DATABUS_dim - 1 : 0] Data;
 
reg valid;
integer count;
 
begin
 
valid = `TRUE;
begin : cycle
for (count = 0; count <= `DATABUS_dim - 1; count = count + 1)
begin
if ((Data[count] !== 1'b0) && (Data[count] !== 1'b1))
begin
valid = `FALSE;
disable cycle;
end
end
end
isDataValid = valid;
end
endfunction
 
// ***************************************
//
// FUNCTION isDataXX :
// return true if the data is unknown
//
// ***************************************
 
function isDataXX;
 
input [`DATABUS_dim - 1 : 0] Data;
 
reg [`DATABUS_dim - 1 : 0] Data;
 
reg allxx;
integer count;
 
begin
 
allxx = `TRUE;
begin : cycle
for (count = 0; count <= `DATABUS_dim - 1; count = count + 1)
begin
if (Data[count] !== 1'bx)
begin
allxx = `FALSE;
disable cycle;
end
end
end
isDataXX = allxx;
end
endfunction
 
// ************************************
//
// FUNCTION isDataZZ :
// return true if the data is Hi-Z
//
// ************************************
 
function isDataZZ;
 
input [`DATABUS_dim - 1 : 0] Data;
 
reg [`DATABUS_dim - 1 : 0] Data;
 
reg allzz;
integer count;
 
begin
 
allzz = `TRUE;
begin : cycle
for (count = 0; count <= `DATABUS_dim - 1; count = count + 1)
begin
if (Data[count] !== 1'bz)
begin
allzz = `FALSE;
disable cycle;
end
end
end
isDataZZ = allzz;
end
endfunction
 
// *****************************
//
// Task Check Timing
// check timing constraints
//
// *****************************
 
task checkTiming;
input [8*6:1] tstr;
input [31:0] tOK, tcheck;
input [8*3:1] check_str;
begin
if ((check_str == "min") && (tcheck < tOK)) begin
$display ("[%t] !ERROR: %0s timing constraint violation!! ", $time, tstr);
end
 
else
if ((check_str == "max") && (tcheck > tOK))
$display ("[%t] !ERROR: %0s timing constraint violation!! ", $time, tstr);
end
endtask
 
 
endmodule
 
 
// Protect Manager
// implements the architecture of the memory blocks
 
module BlockLockModule(address, WP_N, RP_N, Info);
input [`ADDRBUS_range] address;
input WP_N, RP_N;
input Info;
 
reg LockArray [`BLOCK_dim - 1 : 0];
reg LockDownArray [`BLOCK_dim - 1 : 0];
 
reg [`BYTE_range] Status;
integer count;
initial begin // constructor sequence
for (count = 0; count <= `BLOCK_dim - 1; count = count + 1) // all blocks are locked at power-up
begin
LockDownArray[count] = `UNLOCKDOWN;
if (`BLOCKPROTECT == "on") LockArray[count] = `LOCK;
else LockArray[count] = `UNLOCK;
end
end
 
always @(negedge RP_N) begin
initLockArray;
end
 
task initLockArray;
begin
for (count = 0; count <= `BLOCK_dim - 1; count = count + 1) // all blocks are locked at power-up
begin
LockDownArray[count] = `UNLOCKDOWN;
LockArray[count] = `LOCK;
end
end
endtask
 
 
 
// ********************************************
//
// FUNCTION isLocked : return the status of the
// specified block
//
// ********************************************
 
function IsLocked; // boolean function primitive
input [`ADDRBUS_range] address;
integer n_block;
 
begin
n_block = BankLib_man.getBlock(address);
IsLocked = (LockArray[n_block] == `LOCK) ? `TRUE : `FALSE;
end
endfunction
 
// ********************************************
//
// FUNCTION isLocked : return the status of the
// specified block
//
// ********************************************
 
function IsUnLocked; // boolean function primitive
input [`ADDRBUS_range] address;
integer n_block;
 
begin
n_block = BankLib_man.getBlock(address);
IsUnLocked = (LockArray[n_block] == `UNLOCK) ? `TRUE : `FALSE;
end
endfunction
 
 
function getLockBit; // boolean function primitive
input [`ADDRBUS_range] address;
integer n_block;
 
begin
n_block = BankLib_man.getBlock(address);
getLockBit = LockArray[n_block];
end
endfunction
 
function getLockDownBit; // boolean function primitive
input [`ADDRBUS_range] address;
integer n_block;
 
begin
n_block = BankLib_man.getBlock(address);
getLockDownBit = LockDownArray[n_block];
end
endfunction
 
 
// ********************************
//
// Task UnLock :
// implements Block UnLock Command
//
// ********************************
 
task UnLock;
output [`BYTE_range] Status;
reg [`BYTE_range] Status;
 
integer n_block;
begin
n_block = BankLib_man.getBlock(address);
Status = `NoError_msg;
if (LockDownArray[n_block]==`LOCKDOWN && WP_N==`LOW) Status = `NoUnLock_msg;
else LockArray[n_block] = `UNLOCK;
end
endtask
 
// ********************************
//
// Task Lock :
// implements Block Lock Command
//
// ********************************
 
task Lock;
output [`BYTE_range] Status;
reg [`BYTE_range] Status;
 
integer n_block;
begin
n_block = BankLib_man.getBlock(address);
Status = `NoError_msg;
LockArray[n_block] = `LOCK;
end
endtask
 
// *****************************************
//
// Task LockDown :
// implements the Block Lock-Down Command
//
// *****************************************
 
task LockDown;
output [`BYTE_range] Status;
reg [`BYTE_range] Status;
 
integer n_block;
begin
n_block = BankLib_man.getBlock(address);
Status = `NoError_msg;
LockDownArray[n_block] = `LOCKDOWN;
end
endtask
 
 
endmodule
 
 
// *************************
//
// CFI Query Module
// Implements the CFI memory
//
// *************************
 
module CFIqueryModule(); //, isCFI);
 
//input isCFI;
 
reg [`BYTE_range] CFIarray [0:`CFI_dim];
reg error;
reg [8*20:1] CFI_file;
integer i;
 
initial begin
if (`organization == "top") CFI_file = "CFImemory_top.vmf";
else CFI_file= "CFImemory_bottom.vmf";
 
for (i=0; i <= `CFI_dim; i = i + 1) CFIarray[i] = {8{`HIGH}}; // CFI Memory Init
$readmemb(CFI_file,CFIarray);
end
 
always @(posedge error) begin
Kernel.SetWarning(`RCFI_cmd,16'h00,`CFIAddrRange_msg);
error = `FALSE;
end
 
function [`WORD_range] Get;
 
input [`ADDRBUS_range] address;
begin
if (address[`BYTE_range] >= 9'h10 && address[`BYTE_range] <= `CFI_dim ) //verificare se tener conto che il primo indirizzo accessibile e' 10h
begin
if (address[`BYTE_range] >= 9'h39 && address[`BYTE_range] <= 9'h109) begin
Get = 8'hXX;
error = `TRUE;
end else begin
 
Get[`LOW_range] = CFIarray[address[`BYTE_range]];
Get[`HIGH_range] = 8'h00;
end
end else
begin
Get = 8'hXX;
error = `TRUE;
end
end
endfunction
 
endmodule
 
// ********************************
//
// Data Error Module
//
// search for errors in data.h
//
// ********************************
 
module DataErrorModule;
 
reg SevError;
 
initial begin
 
SevError = `FALSE;
 
if ((`organization != "top") && (`organization != "bottom"))
begin
SevError = `TRUE;
$display("!Error: BLOCK ORGANIZATION INVALID: it must be top or bottom!!!");
end
 
if ((`BLOCKPROTECT != "on") && (`BLOCKPROTECT != "off"))
begin
SevError = `TRUE;
$display("!Error: BLOCK PROTECT INVALID: it must be on or off!!!");
end
 
if ((`TimingChecks != "on") && (`TimingChecks != "off"))
begin
SevError = `TRUE;
$display("!Error: TIMING CHECKS INVALID: it must be on or off!!!");
end
 
 
if ((`t_access != 100) && (`t_access != 110))
begin
SevError = `TRUE;
$display("!Error: Access time INVALID: it must be 100 ns or 110 ns!!!");
end
 
 
if (SevError) $finish;
end
 
endmodule
 
// ******************************************
//
// Configuration Register module :
//
// implements the configuration register
//
// ******************************************
 
module ConfigRegModule(address,Info);
input [`ADDRBUS_range] address;
input Info;
 
reg [`ConfigurationReg_dim - 1 : 0] CR_reg;
reg [`BYTE_range] Status;
 
// **********************
//
// Setting default values
//
// **********************
 
`define ReadMode_bit 15
`define ClockLatency_MSBbit 14
`define ClockLatency_LSBbit 11
`define WaitPolarity_bit 10
`define WaitConfig_bit 8
`define BurstType_bit 7
`define ValidClockEdge_bit 6
`define WrapBurst_bit 3
`define BurstLength_MSBbit 2
`define BurstLength_LSBbit 0
 
// Interpreter Config Reg\\
 
wire isASynchronous = CR_reg[`ReadMode_bit] ? `TRUE : `FALSE;
wire isSynchronous = CR_reg[`ReadMode_bit] ? `FALSE : `TRUE;
wire [3:0] Xlatency = (CR_reg[`ClockLatency_MSBbit : `ClockLatency_LSBbit]<2 &&
CR_reg[`ClockLatency_MSBbit : `ClockLatency_LSBbit]>15) ? 0 :
CR_reg[`ClockLatency_MSBbit : `ClockLatency_LSBbit];
wire isWaitPolActiveHigh = CR_reg[`WaitPolarity_bit] ? `TRUE : `FALSE;
wire isWaitBeforeActive = CR_reg[`WaitConfig_bit] ? `TRUE : `FALSE;
wire isRisingClockEdge = CR_reg[`ValidClockEdge_bit] ? `TRUE : `FALSE;
wire isWrapBurst = CR_reg[`WrapBurst_bit] ? `FALSE : `TRUE;
wire isNoWrapBurst = CR_reg[`WrapBurst_bit] ? `TRUE : `FALSE;
 
wire [4:0] BurstLength = CR_reg[`BurstLength_MSBbit : `BurstLength_LSBbit] == 1 ? 4 :
CR_reg[`BurstLength_MSBbit : `BurstLength_LSBbit] == 2 ? 8 :
CR_reg[`BurstLength_MSBbit : `BurstLength_LSBbit] == 3 ? 16:
0; // continous Burst
 
 
wire [2:0] BurstLength_bit = CR_reg[`BurstLength_MSBbit : `BurstLength_LSBbit] == 1 ? 2 :
CR_reg[`BurstLength_MSBbit : `BurstLength_LSBbit] == 2 ? 3 :
CR_reg[`BurstLength_MSBbit : `BurstLength_LSBbit] == 3 ? 4:
0; // continous Burst
 
initial begin
Status = `NoError_msg;
CR_reg = `ConfigReg_default;
end
 
always @(isSynchronous) begin
if (Info)
if (isSynchronous)
$write("[%t] Synchronous Read Mode\n",$time);
else
$write("[%t] ASynchronous Read Mode\n",$time);
end
// **********************
//
// ReSet to default value
//
// **********************
always @(Kernel.ResetEvent) begin
Status = `NoError_msg;
CR_reg = `ConfigReg_default;
end
 
// **************************************
//
// FUNCTION getConfigReg :
//
// return the Configuration Register
//
// **************************************
 
function [`ConfigurationReg_dim - 1 : 0] getConfigReg;
input required;
begin
getConfigReg = CR_reg;
end
endfunction
 
// *************************************
//
// FUNCTION putConfigReg :
//
// write the Configuration Register
//
// *************************************
 
task putConfigReg;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
 
integer count;
 
begin
CR_reg = address[`ConfigurationReg_dim - 1 : 0];
 
outStatus = Status;
 
end
endtask
 
 
endmodule
 
// ***************************
//
// Electronic Signature Module
//
// ***************************
 
module SignatureModule;
 
reg error;
integer i;
integer n_block;
 
initial begin
end
 
always @(posedge error) begin
Kernel.SetWarning(`RSIG_cmd,16'h00,`SignAddrRange_msg);
error = `FALSE;
end
 
function [`WORD_range] Get;
 
input [`ADDRBUS_range] address;
begin
if (address[`SignAddress_range] == 9'h00)
begin
Get[`LOW_range] = `ManufacturerCode;
Get[`HIGH_range] = 8'h00;
end
else if (address[`SignAddress_range] == 9'h01)
begin
if (`organization == "top") Get[`LOW_range] = `TopDeviceCode;
else Get[`LOW_range] = `BottomDeviceCode;
 
Get[`HIGH_range] = 8'h89;
end
else if (address[`SignAddress_range] == 9'h02)
begin
Get[`LOW_range] = { 6'b0, BlockLock_man.getLockDownBit(address), BlockLock_man.getLockBit(address) };
Get[`HIGH_range] = 8'h00;
end
else if (address[`SignAddress_range] == 9'h05) // Configuration Register
Get = ConfigReg_man.getConfigReg(0);
else if ((address[`SignAddress_range] >= `REGSTART_addr) && (address[`SignAddress_range] <= `REGEND_addr))
begin
Get = ProtectReg_man.RegisterMemory[address[`SignAddress_range] - `REGSTART_addr ];
 
end
else begin
Get = 8'hXX;
error = `TRUE;
end
end
endfunction
 
endmodule
 
// ********************
//
// CUI decoder module :
// decode commands
//
// ********************
 
module CUIdecoder1(DataBus,Name,Cmd,CmdAllowed,Info);
input [`BYTE_range] DataBus, Cmd;
input [8*35:1] Name;
input Info;
input CmdAllowed;
always @Kernel.CUIcommandEvent begin
#1;
if (DataBus == Cmd && CmdAllowed) begin // is a First Command ?
#1 -> Kernel.VerifyEvent;
Kernel.CommandDecode1[Cmd] = !Kernel.CommandDecode1[Cmd];
if (Info) $display("[%t] Command Issued: %0s",$time,Name);
end
else begin
if (`FALSE) $display("[%t] The %0s instruction decode unit is waiting for operation to complete.",$time,Name);
@(Kernel.CompleteEvent or Kernel.ErrorEvent)
if (`FALSE) $display("[%t] The %0s instruction decode unit is listening for next command.",$time,Name);
end
end
endmodule
 
 
// ********************
//
// CUIdecoder manager :
// decode commands
//
// ********************
 
module CUIdecoder2(DataBus,Name,Cmd1,Cmd2,CmdAllowed,Info);
input [`BYTE_range] DataBus, Cmd1, Cmd2;
input [8*27:1] Name;
input Info;
input CmdAllowed;
 
always @Kernel.CUIcommandEvent begin
if (DataBus == Cmd1 && CmdAllowed) begin
#1 -> Kernel.VerifyEvent;
 
@Kernel.CUIcommandEvent
 
if (DataBus == Cmd2 && CmdAllowed) begin
#1 -> Kernel.VerifyEvent;
 
Kernel.CommandDecode2[{Cmd1,Cmd2}] = !Kernel.CommandDecode2[{Cmd1,Cmd2}];
if (Info) $display("[%t] Command Issued: %0s",$time,Name);
end
end
else begin
if (`FALSE) $display("%t The %0s instruction decode unit is waiting for operation to complete.",$time,Name);
@(Kernel.CompleteEvent or Kernel.ErrorEvent)
if (`FALSE) $display("%t The %0s instruction decode unit is listening for next command",$time,Name);
end
end
 
endmodule
 
 
// ****************************
//
// CUI Decoder Manager :
// decode the cUI commands
//
// ****************************
 
module CUIdecoder_Busy1(DataBus,Name,Cmd,CmdAllowed,Info);
input [`BYTE_range] DataBus, Cmd;
input [8*8:1] Name;
input Info;
input CmdAllowed;
 
always @Kernel.CUIcommandEvent begin
if ((DataBus == Cmd) && CmdAllowed) begin
-> Kernel.VerifyEvent;
Kernel.CommandDecode1[Cmd] = !Kernel.CommandDecode1[Cmd];
if (Info) $display("[%t] Command Issued: %0s",$time,Name);
end
 
 
 
end
 
endmodule
 
 
// Erase Manager
// manage the erase functionality
 
module EraseModule(address, data, progVoltOK, progHighVoltOK,Info);
input [`ADDRBUS_range] address;
input [`WORD_range] data;
 
input progVoltOK, progHighVoltOK;
 
input Info;
event ErrorCheckEvent, CompleteEvent;
 
reg [`BYTE_range] Status;
reg [`ADDRBUS_range] hold_address;
reg [`BLOCKADDR_range] hold_block;
 
reg Busy, Suspended, first_time;
integer i;
time startTime, delayTime,Erase_time;
 
initial begin // constructor sequence
Busy = `FALSE;
Suspended = `FALSE;
Erase_time = `MainBlockErase_time;
delayTime = Erase_time;
 
end
 
 
function IsBusy; // boolean function primitive
input obbl; // all functions require a parameter
IsBusy = Busy; // return Boolean value
endfunction
 
function IsSuspended; // boolean function primitive
input obbl; // all functions require a parameter
IsSuspended = Suspended; // return Boolean value
endfunction
 
function IsAddrSuspended; // boolean function primitive
input [`ADDRBUS_range] addr;
IsAddrSuspended = (Suspended && (addr == hold_address));
endfunction
 
function IsBlockSuspended; // boolean function primitive
input [`ADDRBUS_range] addr;
IsBlockSuspended = (Suspended && ((BankLib_man.getBlock(addr) == BankLib_man.getBlock(/*hold_*/addr/*ess*/))));
endfunction
 
// *********************
//
// Task checkConfirm :
// check confirm code
//
// *********************
 
task checkConfirm;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
 
begin
 
if (data == `BLKEEconfirm_cmd) outStatus = `NoError_msg;
else outStatus = `WrongEraseConfirm_msg;
 
end
endtask
 
 
task Suspend;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
begin
delayTime = delayTime - ($time - startTime);
#`EraseSuspendLatency_time
outStatus = `NoError_msg;
Status = `Suspend_msg;
Suspended = `TRUE;
-> CompleteEvent;
end
endtask
 
task Resume;
output [`BYTE_range] Status;
begin
Suspended = `FALSE;
BlockErase(Status);
end
endtask
 
task BlockErase;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
begin
 
 
if (progHighVoltOK)
if (BankLib_man.isMainBlock(address)) Erase_time = `FastMainBlockErase_time;
else Erase_time = `FastParameterBlockErase_time;
else
if (BankLib_man.isMainBlock(address)) Erase_time = `MainBlockErase_time;
else Erase_time = `ParameterBlockErase_time;
 
delayTime = Erase_time;
hold_address = address;
hold_block = BankLib_man.getBlock(address);
 
 
 
fork
begin : Operation
Busy = `TRUE;
startTime = $time;
-> ErrorCheckEvent;
#delayTime Memory_man.EraseBlock(hold_block,Status);
delayTime = Erase_time;
-> CompleteEvent;
end
@CompleteEvent
disable Operation;
join
outStatus = Status;
Busy = `FALSE;
end
endtask
 
always @(ErrorCheckEvent) begin
Status = `NoError_msg;
if (BlockLock_man.IsLocked(hold_address))
Status = `BlockLock_msg;
else if (Memory_man.IsBlockSuspended(hold_address))
Status = `SuspCmd_msg;
else if (!progVoltOK)
Status = `InvVDD_msg;
 
if (Status != `NoError_msg)
->CompleteEvent;
else
fork : ErrorCheck
@(negedge progVoltOK) Status = `InvVDD_msg;
@(Status) -> CompleteEvent;
@(CompleteEvent) disable ErrorCheck;
join
end
 
endmodule //end module Erase
 
 
// *********************
//
// Memory Manager :
// the memory array
//
// *********************
 
module MemoryModule(Info);
input Info;
reg [`WORD_range] memory [0:(`MEMORY_dim) - 1]; // the Memory: word organization
 
initial begin
LoadMemory;
end
 
task LoadMemory; // Initialize and load the memory from a file
integer i;
begin
#0 if (Info) $display("[%t] Inizialize the Memory to default value",$time);
for (i = 0; i < `MEMORY_dim; i = i + 1) memory[i] = {16{`HIGH}}; // Memory Init
if (`FILENAME_mem !== "") begin
$readmemh(`FILENAME_mem, memory);
 
if (Info) $display("[%t] Load Memory from file: %s",$time, `FILENAME_mem);
else if (Info) $display("[%t] Warning: File: %s not found",$time, `FILENAME_mem);
end
end
endtask
 
 
function [`WORD_range] Get;
input [`ADDRBUS_range] address;
Get = memory[address];
endfunction
 
 
function IsSuspended;
input [`ADDRBUS_range] address;
IsSuspended = Program_man.IsAddrSuspended(address) || Erase_man.IsAddrSuspended(address) || ProgramBuffer_man.IsAddrSuspended(address);
endfunction
 
function IsBlockSuspended;
input [`ADDRBUS_range] address;
IsBlockSuspended = Program_man.IsBlockSuspended(address) || Erase_man.IsBlockSuspended(address);
endfunction
 
 
task Program;
input [`WORD_range] data;
input [`ADDRBUS_range] address;
output [`BYTE_range] Status;
begin
Status = `NoError_msg;
memory[address] = memory[address] & data;
if (memory[address] != data) Status = `PreProg_msg;
end
endtask
 
task EraseBlock;
input [`INTEGER] block;
output [`BYTE_range] ErrFlag;
 
reg [`ADDRBUS_range] start_address;
reg [`ADDRBUS_range] end_address;
reg [`ADDRBUS_range] address;
 
begin
ErrFlag = `NoError_msg;
start_address = BankLib_man.getBlockAddress(block);
end_address = BankLib_man.BlockBoundaryEndAddr[block];
 
if (start_address > end_address)
begin
address = start_address;
start_address = end_address;
end_address = address;
end
for (address = start_address; address <= end_address; address = address + 1)
memory[address] = `WORDNP;
 
end
endtask
 
task BlockBlankCheck;
input [`INTEGER] block;
output [`BYTE_range] ErrFlag;
 
reg [`ADDRBUS_range] start_address;
reg [`ADDRBUS_range] end_address;
reg [`ADDRBUS_range] address;
 
begin
ErrFlag = `NoError_msg;
start_address = BankLib_man.BlockBoundaryStartAddr[block];
end_address = BankLib_man.BlockBoundaryEndAddr[block];
 
if (start_address > end_address)
begin
address = start_address;
start_address = end_address;
end_address = address;
end
ErrFlag = `NoError_msg;
address = start_address;
while (memory[address] == `WORDNP && address <= end_address )
address = address + 1;
if (memory[address] != `WORDNP)
ErrFlag = `BlankCheckFailed_msg;
 
end
endtask
 
 
 
endmodule //end MemoryModule
 
 
// ***************************************
//
// Output Buffer :
//
// manage the communication between
// the memory and the output data bus
//
// ***************************************
 
module OutputBufferModule(DataInput, DataInputBurst, DataOutput, OutputEnable);
input [`WORD_range] DataInput;
input [`WORD_range] DataInputBurst;
output [`WORD_range] DataOutput;
input OutputEnable;
reg [`WORD_range] DataOutput;
time timeDataV, timeDataX, timeDataZ;
 
initial begin
timeDataV=0;
timeDataX=0;
timeDataZ=0;
SetZ(0);
end
 
task SetValid;
input [63:0] delayTime;
begin
 
if ((delayTime+$time > timeDataV) || (timeDataV < $time)) begin
timeDataV = delayTime + $time;
 
 
disable waitValid;
 
 
disable goValid;
 
end
end
endtask
 
always
fork
begin: goValid
 
#(timeDataV - $time)
if (OutputEnable == 1'b0) begin
if (ConfigReg_man.isASynchronous) DataOutput = DataInput;
else DataOutput = DataInputBurst;
end
end // goValid
begin: waitValid
wait (`FALSE);
end
join
 
task SetX;
input [63:0] delayTime;
begin
if ((delayTime+$time < timeDataX) || (timeDataX < $time)) begin
timeDataX = delayTime + $time;
disable waitX;
 
 
end
end
endtask
 
always fork
begin : goX
#(timeDataX - $time) if ((OutputEnable == `LOW) || (timeDataZ > timeDataX))
DataOutput = 16'hX;
end // goX
begin: waitX
wait (`FALSE);
end
join
 
task SetZ;
input [63:0] delayTime;
begin
if ((delayTime+$time < timeDataZ) || (timeDataZ < $time)) begin
timeDataZ = delayTime + $time;
disable waitZ;
if (timeDataZ < timeDataV)
disable goValid;
if (timeDataZ < timeDataX)
disable goX;
end
end
endtask
 
always begin: waitZ
#(timeDataZ - $time) DataOutput = 16'hZ;
wait (`FALSE);
end
 
endmodule
 
 
// *********************************
//
// Program module :
//
// manage the program operation
//
// *********************************
 
module ProgramModule(address,data, progVoltOK, progHighVoltOK, Info);
input [`WORD_range] data;
input [`ADDRBUS_range] address;
input progVoltOK,progHighVoltOK;
input Info;
event ErrorCheckEvent, CompleteEvent;
reg [`BYTE_range] Status;
reg [`WORD_range] hold_data;
reg [`ADDRBUS_range] hold_address;
reg Busy, Suspended;
 
integer i;
time startTime, delayTime, WordProgram_time;
 
initial begin // constructor sequence
Busy = `FALSE;
Suspended = `FALSE;
WordProgram_time = `WordProgram_time;
delayTime = WordProgram_time;
end
 
always @(progHighVoltOK) begin
if (progHighVoltOK) WordProgram_time=`FastWordProgram_time;
else WordProgram_time=`WordProgram_time;
end
 
function IsBusy; // boolean function primitive
input obbl; // all functions require a parameter
IsBusy = Busy; // return Boolean value
endfunction
 
function IsSuspended; // boolean function primitive
input obbl; // all functions require a parameter
IsSuspended = Suspended; // return Boolean value
endfunction
 
function IsAddrSuspended; // boolean function primitive
input [`ADDRBUS_range] addr;
IsAddrSuspended = (Suspended && (addr == hold_address));
endfunction
 
function IsBlockSuspended; // return true if block is suspended
input [`ADDRBUS_range] addr; begin
IsBlockSuspended = (Suspended && (BankLib_man.getBlock(addr) == BankLib_man.getBlock(/*hold_*/addr/*ess*/)));
end
endfunction
 
 
task Suspend;
output [`BYTE_range] suspErrFlag;
reg [`BYTE_range] suspErrFlag;
begin
delayTime = delayTime - ($time - startTime);
#`ProgramSuspendLatency_time suspErrFlag = `NoError_msg;
Status = `Suspend_msg;
Suspended = `TRUE;
-> CompleteEvent;
end
endtask
 
task Resume;
output [`BYTE_range] ErrFlag;
begin
Suspended = `FALSE;
Program(ErrFlag);
end
endtask
 
task Program;
output [`BYTE_range] outErrFlag;
reg [`BYTE_range] outErrFlag;
begin
if (delayTime == WordProgram_time) begin
hold_data = data;
hold_address = address;
end
fork
begin : Operation
Busy = `TRUE;
startTime = $time;
-> ErrorCheckEvent;
#delayTime Memory_man.Program(hold_data,hold_address,Status);
delayTime = `WordProgram_time;
-> CompleteEvent;
end
@CompleteEvent disable Operation;
join
outErrFlag = Status;
Busy = `FALSE;
end
endtask
 
always @(ErrorCheckEvent) begin
Status = `NoError_msg;
if (BlockLock_man.IsLocked(hold_address))
Status = `BlockLock_msg;
else
if (Memory_man.IsSuspended(hold_address))
Status = `SuspAcc_msg;
else if (!progVoltOK)
Status = `InvVDD_msg;
 
if (Status != `NoError_msg) ->CompleteEvent;
else
fork : ErrorCheck
@(negedge progVoltOK) Status = `InvVDD_msg;
@(Status) -> CompleteEvent;
@(CompleteEvent) disable ErrorCheck;
join
end
 
endmodule // end PrograModule
 
 
// *********************************
//
// Buffer Ehnanced Program module :
//
// program buffer functionality
//
// *********************************
 
module BuffEnhancedFactProgramModule(address, data, progVoltOK, progHighVoltOK, Info);
input [`ADDRBUS_range] address;
input [`WORD_range] data;
input progVoltOK, progHighVoltOK, Info;
 
event ErrorCheckEvent,ErrorCheckEvent_inVerify, CompleteEvent, WatchAddressEvent;
reg [`BYTE_range] Status;
reg [`WORD_range] hold_data, hold_StartBlock;
reg [`ADDRBUS_range] hold_address, startAddress;
reg [`WORD_range] bufferData [`BuffEnhProgramBuffer_range];
 
reg Busy;
time Program_time;
integer i,Len;
 
initial begin // constructor sequence
Busy = `FALSE;
Status = `NoError_msg;
Program_time = `WordProgram_time;
EmptyBuffer;
end
 
task EmptyBuffer;
begin
for (i = 0; i < `BuffEnhProgramBuffer_dim; i = i + 1)
bufferData[i] = 16'hFFFF;
Len=0;
end
endtask
 
function IsBusy; // boolean function primitive
input obbl; // all functions require a parameter
IsBusy = Busy; // return Boolean value
endfunction
 
task Setup;
output [`BYTE_range] outStatus;
begin
Status = `NoError_msg;
Len =0;
startAddress = address;
hold_address = address;
 
hold_StartBlock = BankLib_man.getBlock(address);
-> ErrorCheckEvent;
#0 outStatus=Status;
if (Status == `NoError_msg) begin
if (Info) $display("[%t] Enhanced Factory Program -> Setup Phase",$time);
if (Info) $display("[%t] Enhanced Factory Program: Start address: %h",$time,startAddress);
#`EnhBuffProgramSetupPhase_time;
Busy = `TRUE;
end
end
endtask
 
task Exit;
output [`BYTE_range] outStatus;
begin
Busy = `FALSE;
outStatus = Status;
if (Info) $display("[%t] Enhanced Factory Program -> Exit Phase",$time);
if (Len != `BuffEnhProgramBuffer_dim)
$display("[%t] Warning --- The buffer must be completely filled for programming to occur",$time);
end
endtask
 
task Load;
output [`BYTE_range] outStatus;
begin
if (BankLib_man.getBlock(address) != hold_StartBlock) Status = `ExitPHASE_BEFP_msg;
else begin
bufferData[Len] = data;
if (Info) $display("[%t] Enhanced Factory Program -> Load: data[%d]=%h ",$time,Len,bufferData[Len]);
Len = Len + 1;
if (Len == `BuffEnhProgramBuffer_dim) Status = `ProgramPHASE_BEFP_msg;
end
outStatus = Status;
end
endtask
 
task Program;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
begin
fork
begin : Operation
if (Info) $display("[%t] Enhanced Factory Program {Program Phase}",$time);
#`EnhBuffProgram_time
 
if (Info) $display("[%t] Enhanced Factory Program {End of Program Phase}",$time);
for (i = startAddress;i < (`BuffEnhProgramBuffer_dim + startAddress); i = i + 1) begin
Memory_man.Program(bufferData[i - startAddress],i,Status);
end
-> CompleteEvent; //end of program
end
@CompleteEvent begin
disable Operation;
end
join
if (Status == `ProgramPHASE_BEFP_msg) begin //prova
Status = `NoError_msg;
end
outStatus = Status;
end
endtask
 
always @(ErrorCheckEvent) begin
Status = `NoError_msg;
if (BlockLock_man.IsLocked(hold_address))
Status = `BlockLock_msg;
else if (!progVoltOK)
Status = `InvVDD_msg;
else if (!progHighVoltOK)
Status = `InvVPP_msg;
if (Status != `NoError_msg)
->CompleteEvent;
else
fork : ErrorCheck
@(negedge progVoltOK) Status = `InvVDD_msg;
@(negedge progHighVoltOK) Status = `InvVPP_msg;
@(CompleteEvent) disable ErrorCheck;
join
end
 
 
 
endmodule
 
// ******************************************
//
// Protect Register module :
//
// operations on the protection register
//
// ******************************************
 
module ProtectRegModule(address, data, voltOK, Info);
input [`ADDRBUS_range] address;
input [`DATABUS_range] data;
input voltOK, Info;
reg [`WORD_range] RegisterMemory[`REG_dim - 1 :0];
reg [`BYTE_range] Status;
reg Busy;
reg [`ADDRBUS_range] AddressLatched;
event ErrorCheckEvent, CompleteEvent;
integer i;
reg [`ADDRBUS_range] hold_addr;
reg [`DATABUS_range] hold_data;
 
 
initial begin // constructor sequence
Busy = `FALSE;
RegisterMemory[0] = `PRL_default;
for (i = 1; i < `REG_dim; i = i + 1) begin
RegisterMemory[i] = `WORDNP;
end
end
 
 
function IsBusy; // boolean function primitive
input required; // all functions require a parameter
IsBusy = Busy; // return Boolean value
endfunction
 
function UDNisLocked; // boolean function primitive
input obbl; // input is required
if ((RegisterMemory[`PROTECTREGLOCK_addr - `REGSTART_addr] | `UDNprotect_bit) == `UDNprotect_bit)
UDNisLocked = `TRUE;
else
UDNisLocked = `FALSE;
endfunction
 
function UPisLocked; // boolean function primitive
input obbl; // input is required
UPisLocked = ((RegisterMemory[`PROTECTREGLOCK_addr - `REGSTART_addr] | `UPprotect_bit) == `UPprotect_bit) ? `TRUE : `FALSE;
endfunction
 
function isUDNaddress;
input [`ADDRBUS_range] address;
if ((address >= `UDNREGSTART_addr) && ( address <= `UDNREGEND_addr)) // Check UDN register Address Bound
isUDNaddress = `TRUE;
else isUDNaddress = `FALSE;
endfunction
 
function isUPaddress;
input [`ADDRBUS_range] address;
if ((address >= `UPREGSTART_addr) && (address <= `UPREGEND_addr)) // Check UP register Address Bound
isUPaddress = `TRUE;
else isUPaddress = `FALSE;
endfunction
 
function [`BYTE_range] ExtIndexPRL; // bit index of PRL register
input [`ADDRBUS_range] addr;
ExtIndexPRL=(addr - `ExtREGSTART_regionaddr) / `ExtREG_regiondim;
endfunction
 
function isExtLocked; // boolean function primitive
input [`ADDRBUS_range] addr; // input is required
reg [`BYTE_range] bitIndex;
begin
bitIndex = ExtIndexPRL(addr); // protect bit index of Extended Protection Register Memory
isExtLocked = !(RegisterMemory[(`ExtPROTECTREGLOCK_addr - `REGSTART_addr)][bitIndex]);
end
endfunction
 
function isExtValidAddress;
input [`ADDRBUS_range] address;
if ((address >= `ExtREGSTART_regionaddr) && (address <= `ExtREGEND_regionaddr) ) // Check ExtRegister Address Bound
isExtValidAddress = `TRUE;
else isExtValidAddress = `FALSE;
endfunction
 
task Program;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
begin
Busy = `TRUE;
hold_addr = address[`REG_addrbitRange];
hold_data = data;
if (Info) $write("[%t] OTP Program Memory[%h]=%h\n",$time,hold_addr,data);
fork
begin : Operation
-> ErrorCheckEvent;
#`WordProgram_time RegisterMemory[hold_addr - `REGSTART_addr] = RegisterMemory[hold_addr - `REGSTART_addr] & hold_data;
-> CompleteEvent;
end
@CompleteEvent disable Operation;
join
outStatus = Status;
Busy = `FALSE;
end
endtask
 
always @(ErrorCheckEvent) begin
Status = `NoError_msg;
if (( address < `REGSTART_addr) || ( address > `REGEND_addr)) // Check Address Bound
Status = `AddrRange_msg;
else if ( isUDNaddress(address) && UDNisLocked(1'bX) )
Status = `UDNlock_msg;
else if ((isUPaddress(address) && UPisLocked(1'bX)))
Status = `UPlock_msg;
else if ( isExtValidAddress(hold_addr) & isExtLocked(hold_addr) )
Status = `ExtREGLock_msg;
else if (Kernel.Suspended)
Status = `SuspCmd_msg;
else if (!voltOK)
Status = `InvVDD_msg;
 
if (Status != `NoError_msg)
->CompleteEvent;
else
fork : ErrorCheck
@(negedge voltOK) Status = `InvVDD_msg;
@(Status) -> CompleteEvent;
@(CompleteEvent) disable ErrorCheck;
join
end
endmodule //end ProtectRegModule
 
 
// Read Manager
// Manage the read operation
 
module ReadModule(dataOutput,address,voltOK,Info);
output [`WORD_range] dataOutput;
input [`ADDRBUS_range] address;
input voltOK;
input Info;
reg [`WORD_range] dataOutput, regRead;
reg [1:0] Mode, oldMode;
reg [`BYTE_range] Status;
 
integer i;
 
initial begin
regRead = 0;
Mode = `ReadArray_bus;
oldMode = `ReadArray_bus;
dataOutput = `DATABUS_dim'hzzzz;
end
 
task SetMode;
input [1:0] newMode;
output [`BYTE_range] Status;
begin
Status = `NoError_msg;
if (Info && (newMode!=Mode)) begin
case (newMode)
`ReadArray_bus : $display ("[%t] Device now in Read Array mode ", $time);
`ReadCFI_bus : $display ("[%t] Device now in Read CFI mode ", $time);
`ReadSignature_bus : $display ("[%t] Device now in Read Electronic Signature Mode ", $time);
`ReadStatusReg_bus : $display ("[%t] Device now in Read Status Register Mode ", $time);
default : $display ("[%t] !!!Model Error: Read mode not recognized!!!", $time);
endcase
 
oldMode=Mode;
Mode = newMode;
end
end
endtask
 
 
always @Kernel.ResetEvent begin
Mode = `ReadArray_bus;
end
 
always @(negedge Kernel.Ready) begin // Configure according to status register
Mode = `ReadStatusReg_bus;
end
 
always @Kernel.ReadEvent begin // Main execution of a read is based on an event
 
 
case (Mode)
`ReadArray_bus : begin
dataOutput = Memory_man.Get(address);
if (Info) $display("[%t] Data Read result: memory[%h]=%h", $time,address,dataOutput);
end
`ReadCFI_bus : begin
dataOutput = CFIquery_man.Get(address);
if (Info) $display("[%t] Data Read result: CFI_memory[%h]=%h", $time,address,dataOutput);
end
`ReadSignature_bus : begin
dataOutput = Signature_man.Get(address);
if (Info) $display("[%t] Read Device Identifier(addr=%h) :%h", $time,address,dataOutput);
end
 
`ReadStatusReg_bus : begin
dataOutput = SR_man.SR;
if (Info) $display("[%t] Read Status Register: %b", $time,dataOutput[`BYTE_range]);
end
 
default : $display("[%t] !!!Model Error: Read mode not recognized!!!", $time);
endcase
if ((Mode == `ReadArray_bus) && (Memory_man.IsSuspended(address) == `TRUE)) begin
dataOutput = 16'hXX;
Kernel.SetWarning(`RD_cmd,8'hXX,`SuspAcc_msg);
end
end
 
endmodule
// end Module Read
 
 
// *************************************************
//
// Status Register module :
//
// implements the Status Register of the device
//
// *************************************************
 
module StatusRegModule(Info);
input Info;
 
 
reg EraseStatus, ProgramStatus,
VpenStatus, BlockProtectionStatus, BW_status;
 
reg [`BYTE_range] Status;
 
wire [7:0] SR = {Kernel.Ready, // bit 7
Erase_man.IsSuspended(1'bX), // bit 6
EraseStatus, // bit 5
ProgramStatus, // bit 4
VpenStatus, // bit 3
Program_man.IsSuspended(1'bX) || ProgramBuffer_man.IsSuspended(1'bX), // bit 2
BlockProtectionStatus, // bit 1
BW_status}; // bit 0
wire [7:0] SR_Info = SR;
 
 
 
//-----------------
// Init
//-----------------
 
initial begin
EraseStatus=1'b0;
ProgramStatus=1'b0;
VpenStatus=1'b0;
BlockProtectionStatus=1'b0;
BW_status=1'b0;
end
 
 
always @(SR_Info) if (Kernel.Ready!=1'bZ)
if (Info) $display("[%t] Status Register Update: %b",$time, SR_Info);
 
always @(Kernel.ResetEvent) begin
Clear(Status);
end
 
 
always @(Kernel.Ready,ProtectReg_man.Busy, BuffEnhancedFactProgram_man.Busy)
begin
if (Kernel.Ready)
BW_status = `FALSE;
else
if (BuffEnhancedFactProgram_man.Busy == `TRUE)
BW_status=`TRUE;
 
end
 
always @(Kernel.ErrorEvent) begin //Update status register bits upon specific errors
#0;
case(Kernel.GetError(1'bX))
`InvVDD_msg : begin VpenStatus = `TRUE; end
`InvVPP_msg : begin VpenStatus = `TRUE; end
`BlockLock_msg : begin BlockProtectionStatus = `TRUE; end
`UDNlock_msg : begin ProgramStatus = `TRUE; end
`UPlock_msg : begin ProgramStatus = `TRUE; end
 
`ProtRegAddrRange_msg : begin
BlockProtectionStatus = `TRUE;
end
`ExtREGLock_msg : begin
BlockProtectionStatus = `TRUE;
end
 
`CmdSeq_msg : begin ProgramStatus = `TRUE; EraseStatus = `TRUE; end
`AddrRange_msg : begin ProgramStatus = `TRUE; EraseStatus = `TRUE; end
`AddrTog_msg : begin ProgramStatus = `TRUE; EraseStatus = `TRUE; end
`PreProg_msg : begin ProgramStatus = `TRUE; end
`WrongEraseConfirm_msg : begin ProgramStatus = `TRUE; EraseStatus = `TRUE; end
`WrongBlankCheckConfirm_msg : begin
ProgramStatus = `TRUE; EraseStatus = `TRUE;
end
`BlankCheckFailed_msg : begin
EraseStatus = `TRUE;
end
`LeastAddr0: begin
ProgramStatus = `TRUE;
end
 
endcase
case(Kernel.GetCmd(4'h1))
`PG_cmd : begin ProgramStatus = `TRUE; end
`PRREG_cmd : begin ProgramStatus = `TRUE; end
`PB_cmd : begin ProgramStatus = `TRUE; end
`BLKEE_cmd : begin EraseStatus = `TRUE; end
`BL_cmd : if (Kernel.GetCmd(4'h2) == `BLconfirm_cmd) ProgramStatus = `TRUE;
`BUL_cmd : if (Kernel.GetCmd(4'h2) ==`BULconfirm_cmd) EraseStatus = `TRUE;
`BLD_cmd : if (Kernel.GetCmd(4'h2) ==`BLDconfirm_cmd) ProgramStatus = `TRUE;
`BuffEnhProgram_cmd :
if (Kernel.GetCmd(4'h2) == `BuffEnhProgramCfrm_cmd)
ProgramStatus = `TRUE;
 
endcase
end
 
task Clear;
output [`BYTE_range] Status;
begin
Status = `NoError_msg;
EraseStatus = `FALSE;
ProgramStatus = `FALSE;
VpenStatus = `FALSE;
BlockProtectionStatus = `FALSE;
BW_status = `FALSE;
end
endtask
 
endmodule // end module status register
 
 
// *************
//
// Kernel Module
//
// *************
 
module KernelModule(VDD, VDDQ, VPP, Info);
input [`Voltage_range] VDD, VDDQ, VPP;
input Info;
event CUIcommandEvent, VerifyEvent, ErrorEvent, CompleteEvent, ResetEvent, ReadEvent, ProgramCompleteEvent, EraseCompleteEvent;
 
reg voltOK, progVoltOK, eraseVoltOK, lockVoltOK, ioVoltOK, lockOverrideOK;
reg progHighVoltOK, eraseHighVoltOK;
reg [8'hFF:0] CommandDecode1;
reg [16'hFFFF:0] CommandDecode2;
reg [7:0] lastStatus, lastCmd1, lastCmd2;
 
// Device Status
 
wire Ready = (!Program_man.Busy && !ProgramBuffer_man.Busy && !BuffEnhancedFactProgram_man.Busy
&& !Erase_man.Busy && !ProtectReg_man.Busy && !BlankCheck_man.Busy);
 
 
wire Suspended = Program_man.Suspended || Erase_man.Suspended || ProgramBuffer_man.Suspended;
 
initial begin // constructor sequence
CommandDecode1 = 8'h00; // initialize decode success status variables
CommandDecode2 = 16'h0000;
end
 
 
always @(voltOK) begin
if (!voltOK) begin
$display("[%t] !ERROR: Invalid VDD Voltage.",$time);
-> ErrorEvent;
end
else
$display("[%t] VDD Voltage is OK",$time);
end
 
always @(ioVoltOK) begin
if (!ioVoltOK) begin
$display("[%t] !ERROR: Invalid VDDQ I/O voltage.", $time);
-> ErrorEvent;
end
else
$display("[%t] VDDQ Voltage is OK",$time);
end
 
always @(VDD) begin
if ((VDD < `VDDmin) | (VDD > `VDDmax))
voltOK = `FALSE;
else
voltOK = `TRUE;
end
 
 
always @(VDDQ) begin // check i/o voltage constraints
if ((VDDQ >= `VDDQmin) && (VDDQ <= `VDDQmax))
ioVoltOK = `TRUE;
else
ioVoltOK = `FALSE;
end
 
always @(VPP) begin // program/erase/lock
if ((VPP>=`VPPmin && VPP<=`VPPmax)) begin
progVoltOK = `TRUE;
eraseVoltOK = `TRUE;
lockVoltOK = `TRUE;
progHighVoltOK = `FALSE;
eraseHighVoltOK = `FALSE;
end
else if ((VPP>=`VPPHmin) && (VPP<=`VPPHmax)) begin
progVoltOK = `TRUE;
eraseVoltOK = `TRUE;
lockVoltOK = `TRUE;
progHighVoltOK = `TRUE;
eraseHighVoltOK = `TRUE;
end
else begin
progVoltOK = `FALSE;
eraseVoltOK = `FALSE;
lockVoltOK = `FALSE;
progHighVoltOK = `FALSE;
eraseHighVoltOK = `FALSE;
end
end
 
 
function [7:0] GetError;
input required;
GetError = lastStatus;
endfunction
 
function [7:0] GetCmd;
input commandNum;
GetCmd = (commandNum == 1) ? lastCmd1 : lastCmd2;
endfunction
 
task SetWarning;
input [7:0] Cmd1, Cmd2;
input [7:0] Status;
begin
Report(Cmd1,Cmd2,Status);
lastStatus = Status;
end
endtask
 
task SetError;
input [7:0] Cmd1, Cmd2;
input [7:0] ErrFlag;
begin
SetWarning(Cmd1,Cmd2,ErrFlag);
-> ErrorEvent; // Only errors set error event
end
endtask
 
 
task Report;
input [7:0] Cmd1, Cmd2;
input [7:0] Status;
begin
lastStatus = Status;
lastCmd1 = Cmd1;
lastCmd2 = Cmd2;
if ((lastStatus != `NoError_msg) || Info) begin //Display error .
$write("[%t] ",$time);
case(Status)
`NoError_msg : begin $write(" Command Completion Successful "); end
`CmdSeq_msg : begin $write(" !Error: [Invalid Command]\n Sequence Command Unknown"); -> ErrorEvent; end
`SuspCmd_msg : begin $write(" !Error: [Invalid Command]\n Cannot execute this command during suspend"); -> ErrorEvent; end
`SuspAcc_msg : begin $write(" !Error: [Invalid Command]\n Cannot access this address due to suspend"); -> ErrorEvent; end
`SignAddrRange_msg : begin $write(" !Error: [Invalid Address]\n Signature Address out of range"); end
`CFIAddrRange_msg : begin $write(" !Error: [Invalid Address]\n CFI Address out of range"); end
`AddrRange_msg : begin $write(" !Error: [Invalid Address]\n Address out of range"); -> ErrorEvent; end
`AddrTog_msg : begin $write(" !Error: [Program Buffer]\n Cannot change block address during command sequence"); -> ErrorEvent; end
`BuffSize_msg : begin $write(" !Error: [Program Buffer]\n Buffer size is too large (Max Size is %d) ",`ProgramBuffer_dim); -> ErrorEvent; end
`InvVDD_msg : begin $write(" !Error: [Invalid Supply]\n Voltage Supply must be: VDD>VDDmin and VDD<VDDmax "); -> ErrorEvent; end
`InvVPP_msg : begin $write(" !Error: [Invalid Program Supply]\n Program Supply Voltage must be: VPP>VPPHmin and VPP<VPPHmax for this Operation"); -> ErrorEvent; end
`ByteToggle_msg : begin $write(" !Error: [BYTE_N Toggled]\n Cannot toggle BYTE_N while busy"); -> ErrorEvent; end
`PreProg_msg : begin $write(" !Error: [Program Failure]\n Program Failure due to cell failure"); -> ErrorEvent; end
`UDNlock_msg : begin $write(" !Error: [Program Failure]\n Unique Device Number Register is locked"); -> ErrorEvent; end
`UPlock_msg : begin $write(" !Error: [Program Failure]\n User Programmable Register is locked"); -> ErrorEvent; end
`ExtREGLock_msg : begin $write(" !Error: [Program Failure]\n Extended User Programmable OTP is locked"); -> ErrorEvent; end
`NoUnLock_msg : begin $write(" #Warning: [Locked Down Warning]\n Invalid UnLock Block command in Locked-Down Block"); end
`SuspAccWarn_msg : begin $write(" #Warning: [Invalid Access]\n It isn't possible access this address due to suspend"); end
`BlockLock_msg : begin $write(" !Error: [Locked Error]\n Cannot complete operation when the block is locked "); -> ErrorEvent; end
`BlkBuffer_msg : begin $write(" !Error: [Program Buffer] Program Buffer cannot cross block boundary"); end
`AddrCFI_msg : begin $write(" #Warning: [Invalid CFI Address]\n CFI Address out of range"); end
`NoBusy_msg : begin $write(" #Warning: [NO Busy]\n Device is not Busy"); end
`NoSusp_msg : begin $write(" #Warning: [NO Suspend]\n Nothing previus suspend command"); end
`Suspend_msg : begin $write(" Suspend of "); end
`WrongEraseConfirm_msg : begin
$write(" !Error: [Wrong Erase Confirm Code ");
-> ErrorEvent;
end
`LeastAddr0 : begin
$write(" !Error: [Program Failure]\n Least Significative bit [%2d downto 0] of Start Address must be 0",`ProgramBuffer_addrDim-1);
-> ErrorEvent;
end
`WrongBlankCheckConfirm_msg : begin
$write(" !Error: [Confirm Code] Wrong Blank Check Confirm Code ");
-> ErrorEvent;
end
 
`WrongBlankCheckBlock: begin
$write(" !Error: [Blank Check Failure]\n The block must be a main block");
-> ErrorEvent;
end
 
`BlankCheckFailed_msg : begin $write(" !Error: [Blank Check]\n Blank Check Failed ");
-> ErrorEvent;
end
 
default : begin $write(" !ERROR: [Unknown error]\n Flag=%h, cmd1=%hh, cmd2=%hh",Status,Cmd1,Cmd2); -> ErrorEvent; end
endcase
case (Cmd1)
16'hXX : $display(" !Error: [General Error}\n Error not defined");
`RD_cmd : $display(" { Read Array }");
`RSR_cmd : $display(" { Read Status Register }");
`RSIG_cmd : $display(" { Read Electronic Signature }");
`RCFI_cmd : $display(" { Read CFI }");
`PG_cmd : $display(" { Program }");
`BuffEnhProgram_cmd : $display(" { Buffer Enhanced Factory Program }");
 
`SCR_cmd | `BL_cmd | `BUL_cmd | `BLD_cmd
: begin
if (Cmd2 == `SCRconfirm_cmd) $display(" { Set Configuration Register }");
if (Cmd2 == `BLconfirm_cmd) $display(" { Block Lock }");
if (Cmd2 == `BULconfirm_cmd) $display(" { Block UnLock }");
if (Cmd2 == `BLDconfirm_cmd) $display(" { Block Lock-Down }");
end
`PER_cmd : $display(" { Program/Erase Resume }");
`PRREG_cmd : $display(" { Protection Register Command }");
`BLKEE_cmd : $display(" { Block Erase }");
`BLNKCHK_cmd : $display(" { Blank Check }");
`CLRSR_cmd : $display(" { Clear Status Register }");
`PES_cmd : $display(" { Program/Erase Suspend }");
`PB_cmd : $display(" { Write to Buffer and Program }");
default : $display(" {unknown command: %hh}", Cmd1);
endcase
end
end
endtask
 
task CheckTime;
input [8*6:1] tstr;
input [31:0] tdiff, tprev;
begin
if ($time - tprev < tdiff) begin
$display ("[%t] !ERROR: %0s timing constraint violation: %0d-%0d < %0dns ", $time, tstr, $time, tprev, tdiff);
-> ErrorEvent;
end
end
endtask
 
endmodule // end module Kernel
 
 
 
 
 
module x28fxxxp30(A, DQ, W_N, G_N, E_N, L_N, K, WAIT, WP_N, RP_N, VDD, VDDQ, VPP, Info);
 
// Signal Bus
input [`ADDRBUS_dim-1:0] A; // Address Bus
inout [`DATABUS_dim-1:0] DQ; // Data I/0 Bus
// Control Signal
input W_N; // Write Enable
input G_N; // Output Enable
input E_N; // Chip Enable
input L_N; // Latch Enable
input K; // Clock
input WP_N; // Write Protect
input RP_N; // Reset/Power-Down
 
// Voltage signal rappresentad by integer Vector which correspond to millivolts
input [`Voltage_range] VDD; // Supply Voltage
input [`Voltage_range] VDDQ; // Input/Output Supply Voltage
input [`Voltage_range] VPP; // Optional Supply Voltage for fast Program & Erase
 
// Others Signal
output WAIT; // Wait
reg wait_;
assign WAIT = wait_;
input Info; // Enable/Disable Information of the operation in the memory
wire CLK;
assign CLK = (K ~^ ConfigReg_man.isRisingClockEdge);
reg CLOCK;
// === Internal Signal ===
// Chip Enable
wire CE_N = E_N & Kernel.voltOK & RP_N;
 
// Output Enable
wire OE_N = G_N | CE_N | !Kernel.ioVoltOK | !RP_N;
// Write Enable
wire WE_N = W_N | CE_N;
 
// Latch Enable
 
wire LE_N = L_N | CE_N;
// === Bus Latch ===
// Data Bus
wire [`DATABUS_dim-1:0] DataBusIn;
wire [`DATABUS_dim-1:0] DataBurst;
 
// read burst is in wait state
wire isWait;
 
// Address Bus
reg [`ADDRBUS_dim - 1:0] AddrBusIn;
 
// Status
//aggiunti stati buffenha...e blank....
reg [`BYTE_range] KernelStatus, ReadStatus, EraseStatus, ProgramStatus, BuffEnhancedProgramStatus,
LockStatus, ConfigStatus, BufferStatus,BlankCheckStatus,ProgramBufferStatus,
SuspendStatus, ResumeStatus, ClearSRStatus, ProtectRegStatus;
 
 
reg [`BYTE_range] status=`Free_pes;
 
//address latching in read operation
always @(negedge LE_N) if (W_N==`HIGH) begin
if (KernelStatus == `READY && ConfigReg_man.isASynchronous)
@(posedge LE_N) begin
if (L_N)
 
AddrBusIn = A; // AddressBus has been Latched
 
end
end
 
always @(negedge LE_N) if (W_N==`HIGH) begin :latching_a
if (KernelStatus == `READY) begin
if(ConfigReg_man.isSynchronous)
fork
begin : L_Address
 
@(posedge LE_N) if (L_N) begin
AddrBusIn = A; // AddressBus has been Latched
disable K_Address;
 
end
end
begin : K_Address
 
@(posedge CLK) begin
 
AddrBusIn = A; // AddressBus has been Latched
disable L_Address;
end
end
join
 
end
end
 
 
always @(negedge WE_N) begin
if (KernelStatus==`READY)
@(posedge WE_N) begin
if(OE_N==`HIGH)
AddrBusIn = A; // AddressBus has been Latched
 
end
end
 
integer i;
integer n_block;
 
// Wait Driver
time timeWaitDriver,timeWaitDriverZ;
 
reg PB_init=0;
reg P_init=0;
reg BP_init=0;
reg Prog_init=0;
 
always @(PB_init,P_init,BP_init) begin
Prog_init=(PB_init ||P_init || BP_init);
end
 
wire [`BYTE_range] AccessTime;
 
// ****************
//
// Modules Istances
//
// ****************
 
DataErrorModule DataError_man(); // Check for errors on UserData.h
 
CUIdecoder1 ReadArray_Command (DQ[`LOW_range], "Read Array ", `RD_cmd, (Kernel.Ready && !Prog_init), Info),
ReadSR_Command (DQ[`LOW_range], "Read Status Register ", `RSR_cmd, !Prog_init, Info),
ReadSign_Command (DQ[`LOW_range], "Read Electronic Signature ", `RSIG_cmd, (Kernel.Ready && !Prog_init), Info),
ReadCFI_Command (DQ[`LOW_range], "Read CFI ", `RCFI_cmd, (Kernel.Ready && !Prog_init), Info),
Program_Command (DQ[`LOW_range], "Program ", `PG_cmd, (Kernel.Ready && !Prog_init), Info),
 
ProgramBuffer_Command (DQ[`LOW_range], "Program Buffer ", `PB_cmd, (Kernel.Ready && !Prog_init), Info),
ProgramReg_Command (DQ[`LOW_range], "Protection Register Program ", `PRREG_cmd, (Kernel.Ready && !Prog_init), Info),
Resume_Command (DQ[`LOW_range], "Resume ", `PER_cmd, (Kernel.Ready && Kernel.Suspended), Info),
BlockErase_Command (DQ[`LOW_range], "Block Erase ", `BLKEE_cmd,(Kernel.Ready && !Prog_init), Info),
ClearSR_Command (DQ[`LOW_range], "Clear Status Register ", `CLRSR_cmd, (Kernel.Ready && !Prog_init), Info),
 
BlankCheck_Command (DQ[`LOW_range], "Blank Check ", `BLNKCHK_cmd, (Kernel.Ready && !Prog_init), Info),
BuffEnhactoryProgram_Command (DQ[`LOW_range], "Buffer Enh.Factory Program [Setup]", `BuffEnhProgram_cmd,(Kernel.Ready && !Prog_init), Info);
 
 
CUIdecoder_Busy1 Suspend_Command (DQ[`LOW_range], "Suspend ", `PES_cmd, !Kernel.Ready, Info);
 
CUIdecoder2 BlockLock_Command (DQ[`LOW_range], "Block Lock ", `BL_cmd, `BLconfirm_cmd, (Kernel.Ready && !Prog_init), Info),
BlockUnlock_Command (DQ[`LOW_range], "Block UnLock ", `BUL_cmd, `BULconfirm_cmd, (Kernel.Ready && !Prog_init), Info),
BlockLockDown_Command (DQ[`LOW_range], "Block Lock-Down ", `BLD_cmd, `BLDconfirm_cmd, (Kernel.Ready && !Prog_init), Info),
SetConfigReg_Command (DQ[`LOW_range], "Set Configuration Register ", `SCR_cmd, `SCRconfirm_cmd, (Kernel.Ready && !Prog_init), Info);
 
KernelModule Kernel (VDD, VDDQ, VPP, Info);
ReadModule Read_man (DataBusIn, AddrBusIn, Kernel.ioVoltOK, Info);
OutputBufferModule OutputBuffer_man (DataBusIn, DataBurst, DQ, OE_N);
StatusRegModule SR_man (Info);
MemoryModule Memory_man (Info);
ProgramModule Program_man (AddrBusIn, DQ, Kernel.progVoltOK, Kernel.progHighVoltOK, Info);
 
BuffEnhancedFactProgramModule BuffEnhancedFactProgram_man(AddrBusIn, DQ, Kernel.progVoltOK, Kernel.progHighVoltOK, Info);
ProtectRegModule ProtectReg_man (AddrBusIn, DQ, Kernel.progVoltOK, Info);
EraseModule Erase_man (AddrBusIn, DQ, Kernel.eraseVoltOK, Kernel.progHighVoltOK, Info);
 
 
BlankCheckModule BlankCheck_man (AddrBusIn, DQ, Kernel.eraseVoltOK, Kernel.progHighVoltOK, Info);
 
BlockLockModule BlockLock_man (AddrBusIn, WP_N, RP_N, Info);
ProgramBufferModule ProgramBuffer_man (AddrBusIn, DQ, Kernel.progVoltOK, Info);
SignatureModule Signature_man (); // , `FALSE);
CFIqueryModule CFIquery_man (); // , `TRUE);
ConfigRegModule ConfigReg_man (AddrBusIn,Info); // implements the Configuration Register
BurstModule Burst_man (AddrBusIn, DataBurst, isWait, CLK, CLOCK, L_N, G_N,W_N, Info);
 
BankLib BankLib_man ();
TimingDataModule TimingData_man ();
TimingLibModule TimingLib_man (A,DQ,W_N,G_N,E_N,L_N,WP_N,K,VPP);
 
initial begin
 
$timeformat(-9, 0, " ns", 12); // Format time displays to screen
-> Kernel.ResetEvent; // Reset Device
KernelStatus = `BUSY; // Device is Busy
$display ("[%t] --- Device is Busy (start up time) --- ", $time);
#(TimingData_man.tVDHPH) KernelStatus = `READY; // End of Start-Up Time
$display ("[%t] --- Device is Ready (end of start-up time) --- ", $time);
 
AddrBusIn = `ADDRBUS_dim'hZ;
 
wait_ = 1'hZ;
CLOCK = 1'b0;
end
 
// Recognize command input
always @(negedge WE_N) begin
if (KernelStatus==`READY)
@(posedge WE_N) begin
 
-> Kernel.CUIcommandEvent; // new command has been written into Kernel.
 
end
end
 
// Check error
always @(Kernel.CUIcommandEvent) begin : Timeout
#3
-> Kernel.ErrorEvent;
disable Verify;
end
 
// Verify command issued
always @(Kernel.CUIcommandEvent) begin : Verify
@(Kernel.VerifyEvent)
 
disable Timeout;
end
 
// Default to Read Array command
always @(negedge OE_N) begin
if (OE_N == `LOW && (ConfigReg_man.isASynchronous)) begin
if (L_N==0) AddrBusIn=A;
#1
-> Kernel.ReadEvent;
end
end
 
// Page Read
always @(A) begin
if ((OE_N == `LOW) && (A !== `ADDRBUS_dim'hZ) && (A !== `ADDRBUS_dim'hx) && (ConfigReg_man.isASynchronous)) begin
AddrBusIn = A;
#0 -> Kernel.ReadEvent;
end
end
 
 
// Reset the Kernel
always @(negedge RP_N) begin
-> Kernel.ResetEvent;
if (Info) $display ("[%t] Device has been reset ", $time);
KernelStatus = `BUSY;
@(posedge RP_N) KernelStatus = `READY;
end
 
// ----- Recognize Command Input -----
always @(Kernel.CommandDecode1[`RD_cmd]) if (KernelStatus==`READY) begin // Read Array
Read_man.SetMode(`ReadArray_bus, ReadStatus);
Kernel.Report(`RD_cmd, 8'hXX, ReadStatus);
#1 -> Kernel.CompleteEvent;
end
 
always @(Kernel.CommandDecode1[`RSR_cmd]) if (KernelStatus==`READY) begin // Read Status Register
Read_man.SetMode(`ReadStatusReg_bus, ReadStatus);
Kernel.Report(`RSR_cmd, 8'hXX, ReadStatus);
#1 -> Kernel.CompleteEvent;
end
 
 
always @(Kernel.CommandDecode1[`RSIG_cmd]) if (KernelStatus==`READY ) begin // Read Electronic Signature
Read_man.SetMode(`ReadSignature_bus, ReadStatus);
Kernel.Report(`RSIG_cmd, 8'hXX, ReadStatus);
#1 -> Kernel.CompleteEvent;
end
 
always @(Kernel.CommandDecode1[`RCFI_cmd]) if (KernelStatus==`READY) begin // Read CFI
Read_man.SetMode(`ReadCFI_bus, ReadStatus);
Kernel.Report(`RCFI_cmd, 8'hXX, ReadStatus);
#1 -> Kernel.CompleteEvent;
end
 
always @(Kernel.CommandDecode1[`PG_cmd]) if (KernelStatus==`READY) begin // Program
P_init=1;
@Kernel.CUIcommandEvent
#1 -> Kernel.VerifyEvent;
Program_man.Program(ProgramStatus);
Kernel.Report(`PG_cmd, 8'hXX, ProgramStatus);
-> Kernel.CompleteEvent;
P_init=0;
end
 
 
always @(Kernel.CommandDecode1[`PRREG_cmd]) if (KernelStatus==`READY) begin // Protection Register Program
@Kernel.CUIcommandEvent
#1 -> Kernel.VerifyEvent;
ProtectReg_man.Program(ProtectRegStatus);
Kernel.Report(`PRREG_cmd, 8'hXX, ProtectRegStatus);
-> Kernel.CompleteEvent;
end
 
always @(Kernel.CommandDecode1[`PES_cmd]) if (KernelStatus==`READY) begin // Suspend
if (Program_man.IsBusy(1'bX))
Program_man.Suspend(SuspendStatus);
else if (ProgramBuffer_man.IsBusy(1'bX))
ProgramBuffer_man.Suspend(SuspendStatus);
else if (Erase_man.IsBusy(1'bX))
Erase_man.Suspend(SuspendStatus);
-> Kernel.CompleteEvent;
end
 
 
always @(Kernel.CommandDecode1[`PER_cmd]) if (KernelStatus==`READY) begin // Program/Erase Resume
ResumeStatus = `NoError_msg;
if (Program_man.IsSuspended(1'bX)) begin
Program_man.Resume(ProgramStatus);
Kernel.Report(`PG_cmd, 8'hXX, ProgramStatus);
end
else if (ProgramBuffer_man.IsSuspended(1'bX)) begin
ProgramBuffer_man.Resume(BufferStatus);
Kernel.Report(`PB_cmd, 8'hXX, BufferStatus);
end
else if (Erase_man.IsSuspended(1'bX)) begin
Erase_man.Resume(EraseStatus);
Kernel.Report(`BLKEE_cmd, 8'hXX, EraseStatus);
end
else
ResumeStatus = `NoSusp_msg;
Kernel.Report(`PER_cmd, 8'hXX, ResumeStatus);
-> Kernel.CompleteEvent;
 
end
 
always @(Kernel.CommandDecode1[`BLKEE_cmd]) if (KernelStatus==`READY) begin // Block Erase
Read_man.SetMode(`ReadStatusReg_bus,ReadStatus);
EraseStatus=`NoError_msg;
@Kernel.CUIcommandEvent
Erase_man.checkConfirm(EraseStatus);
#1 -> Kernel.VerifyEvent;
if (EraseStatus != `NoError_msg)
Kernel.Report(`BLKEE_cmd, `BLKEEconfirm_cmd, EraseStatus);
else
begin
Erase_man.BlockErase(EraseStatus);
Kernel.Report(`BLKEE_cmd, `BLKEEconfirm_cmd , EraseStatus);
-> Kernel.CompleteEvent;
end
end
 
always @(Kernel.CommandDecode1[`CLRSR_cmd]) if (KernelStatus==`READY) begin // Clear Status Register
SR_man.Clear(ClearSRStatus);
Kernel.Report(`CLRSR_cmd, 8'hXX, ClearSRStatus);
#1 -> Kernel.CompleteEvent;
end
 
 
//aggiunta ************************************************
// PB Fast Program Commands
always @(Kernel.CommandDecode1[`PB_cmd]) if (KernelStatus==`READY) begin // Write to Program and Buffer
ProgramBufferStatus = `NoError_msg;
PB_init=1;
Read_man.SetMode(`ReadStatusReg_bus, ReadStatus);
@Kernel.CUIcommandEvent
ProgramBuffer_man.SetCount(ProgramBufferStatus);
#1 -> Kernel.VerifyEvent;
if (ProgramBufferStatus == `NoError_msg) begin
for (i=1; i <= ProgramBuffer_man.GetCount(1'bX); i=i+1) begin : GetData
@Kernel.CUIcommandEvent
#1;
 
ProgramBuffer_man.Load(ProgramBufferStatus);
#1 -> Kernel.VerifyEvent;
if (ProgramBufferStatus != `NoError_msg)
disable GetData;
end
@Kernel.CUIcommandEvent
if (DQ[`BYTE_range] != `PBcfm_cmd)
ProgramBufferStatus = `CmdSeq_msg;
else begin
#1 -> Kernel.VerifyEvent;
ProgramBuffer_man.Program(ProgramBufferStatus);
end
end
Kernel.Report(`PB_cmd, 8'hXX, ProgramBufferStatus);
->Kernel.CompleteEvent;
PB_init=0;
end
//*************************************************************************
 
always @(Kernel.CommandDecode2[{`BL_cmd,`BLconfirm_cmd}]) if (KernelStatus==`READY) begin // Block Lock
BlockLock_man.Lock(LockStatus);
Kernel.Report(`BL_cmd, `BLconfirm_cmd, LockStatus);
-> Kernel.CompleteEvent;
end
 
always @(Kernel.CommandDecode2[{`BUL_cmd,`BULconfirm_cmd}]) if (KernelStatus==`READY) begin // Block UnLock
BlockLock_man.UnLock(LockStatus);
Kernel.Report(`BUL_cmd,`BULconfirm_cmd, LockStatus);
-> Kernel.CompleteEvent;
end
 
always @(Kernel.CommandDecode2[{`BLD_cmd,`BLDconfirm_cmd}]) if (KernelStatus==`READY) begin // Block Lock-Down
BlockLock_man.LockDown(LockStatus);
Kernel.Report(`BLD_cmd,`BLDconfirm_cmd, LockStatus);
-> Kernel.CompleteEvent;
end
 
always @(Kernel.CommandDecode2[{`SCR_cmd,`SCRconfirm_cmd}]) if (KernelStatus==`READY) begin // Set Configuration Register
ConfigReg_man.putConfigReg(ConfigStatus);
Kernel.Report(`SCR_cmd,`SCRconfirm_cmd, ConfigStatus);
-> Kernel.CompleteEvent;
end
 
 
// BC
always @(Kernel.CommandDecode1[`BLNKCHK_cmd]) if (KernelStatus==`READY) begin // Blank Check
BlankCheckStatus=`NoError_msg;
Read_man.SetMode(`ReadStatusReg_bus, ReadStatus);
@Kernel.CUIcommandEvent
BlankCheck_man.checkConfirm(BlankCheckStatus);
#1 -> Kernel.VerifyEvent;
if (BlankCheckStatus != `NoError_msg) begin
Kernel.Report(`BLNKCHK_cmd, `BLNKCHKconfirm_cmd, BlankCheckStatus);
end else
begin
BlankCheck_man.BlankCheck(BlankCheckStatus);
Kernel.Report(`BLNKCHK_cmd, `BLNKCHKconfirm_cmd, BlankCheckStatus);
end
-> Kernel.CompleteEvent;
 
end
// BEFP
always @(Kernel.CommandDecode1[`BuffEnhProgram_cmd]) if (KernelStatus==`READY) begin // Buffer Enhanced Factory Program: Setup Phase
Read_man.SetMode(`ReadStatusReg_bus, ReadStatus);
BP_init=1;
@Kernel.CUIcommandEvent
#1 -> Kernel.VerifyEvent;
if (Kernel.Suspended | !Kernel.Ready)
BuffEnhancedProgramStatus = `SuspCmd_msg;
else begin
if (DQ[`LOW_range]!=`BuffEnhProgramCfrm_cmd)
BuffEnhancedProgramStatus=`CmdSeq_msg;
else begin
if (Info) $display("[%t] Command Issued: Buffer Enh.Factory Program [Confirm]",$time);
BuffEnhancedFactProgram_man.Setup(BuffEnhancedProgramStatus);
if (BuffEnhancedProgramStatus == `NoError_msg) begin
while (BuffEnhancedProgramStatus == `NoError_msg) begin // Loop Program - Enhanced Factory Program: Program Phase
if (Info) $display("[%t] Enhanced Factory Program -> Load Phase",$time);
while (BuffEnhancedProgramStatus == `NoError_msg ) begin // Loop Load - Enhanced Factory Program: Load Phase
@Kernel.CUIcommandEvent
#1 -> Kernel.VerifyEvent;
BuffEnhancedFactProgram_man.Load(BuffEnhancedProgramStatus);
end
if (BuffEnhancedProgramStatus==`ProgramPHASE_BEFP_msg) begin
BuffEnhancedFactProgram_man.Program(BuffEnhancedProgramStatus);
end
end
BuffEnhancedFactProgram_man.Exit(BuffEnhancedProgramStatus);
end
end
if (BuffEnhancedProgramStatus == `ExitPHASE_BEFP_msg)
BuffEnhancedProgramStatus = `NoError_msg;
end
Kernel.Report(`BuffEnhProgram_cmd,`BuffEnhProgramCfrm_cmd, BuffEnhancedProgramStatus);
-> Kernel.CompleteEvent;
BP_init=0;
end
 
 
 
//***********************************************************
 
// Decode Delays for Page Mode Reads
 
//******************************************************
 
// Page mode
always
begin :nopage
@(A[`ADDRBUS_dim - 1:4])
disable page;
 
OutputBuffer_man.SetValid(TimingData_man.tAVQV);
end
 
// Page mode
always
begin :page
@(A[3:0]) //pagina di 16 words
OutputBuffer_man.SetValid(TimingData_man.tAVQV1);
end
 
 
// Output Buffer delays
 
always @(negedge E_N) begin
OutputBuffer_man.SetX(TimingData_man.tELQX);
OutputBuffer_man.SetValid(TimingData_man.tELQV);
 
end
 
always @(negedge G_N) begin
#0;
OutputBuffer_man.SetX(TimingData_man.tGLQX);
OutputBuffer_man.SetValid(TimingData_man.tGLQV);
 
end
 
always @(posedge CLK) begin
CLOCK = !CLOCK;
end
 
always @(negedge CLK) begin
CLOCK = !CLOCK;
end
 
 
 
reg waiting=1;
 
always @(posedge G_N) begin
 
waiting=1;
 
end
 
 
 
always @(CLK) begin
 
if ((!G_N) && (CE_N == `LOW) && (ConfigReg_man.isSynchronous) && (CLK)) begin
 
if (ConfigReg_man.isWaitBeforeActive && Burst_man.firstEOWL && waiting) begin
OutputBuffer_man.SetX(TimingData_man.tKHQX);
@(posedge (CLK))
OutputBuffer_man.SetX(TimingData_man.tKHQX);
OutputBuffer_man.SetValid(TimingData_man.tKHQV);
waiting=0;
 
end else begin
OutputBuffer_man.SetX(TimingData_man.tKHQX);
OutputBuffer_man.SetValid(TimingData_man.tKHQV);
end
end
end
 
always @(negedge L_N) if(W_N==`HIGH)begin
if (ConfigReg_man.isSynchronous && CE_N==`LOW) begin
OutputBuffer_man.SetValid(TimingData_man.tLLQV);
 
end
end
 
 
always @(RP_N) begin
if (RP_N == `HIGH)
OutputBuffer_man.SetValid(TimingData_man.tPHWL);
end
 
always @(posedge CE_N) begin
OutputBuffer_man.SetZ(TimingData_man.tEHQZ);
end
 
always @(posedge G_N) begin
OutputBuffer_man.SetZ(TimingData_man.tGHQZ);
OutputBuffer_man.SetZ(TimingData_man.tGHTZ);
 
end
 
 
 
////////////////////////////////
always @(CE_N) begin
if (CE_N == `LOW && W_N==`HIGH && G_N == `LOW) begin
if (ConfigReg_man.isSynchronous)
wait_ = #(TimingData_man.tELTV) ConfigReg_man.isWaitPolActiveHigh;
else wait_ = #(TimingData_man.tELTV) !ConfigReg_man.isWaitPolActiveHigh;
end
else
wait_ = #(TimingData_man.tEHTZ) 1'hZ;
end
 
always @(G_N) begin
if (G_N == `LOW && CE_N == `LOW && W_N==`HIGH) begin
if (ConfigReg_man.isSynchronous) begin
wait_ = #(TimingData_man.tGLTV) ConfigReg_man.isWaitPolActiveHigh;
end else begin
wait_ = #(TimingData_man.tGLTV) !ConfigReg_man.isWaitPolActiveHigh;
end
end
else begin if (G_N == `HIGH )
wait_ = #(TimingData_man.tGHTZ) 1'hZ;
disable Burst_man.pollingBurst;
end
end
 
 
 
 
always @(isWait) begin
 
if ((CE_N == `LOW) && (G_N == `LOW) && ConfigReg_man.isSynchronous ) begin
if (CLK) begin
if (isWait == `LOW ) begin
if(!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) ConfigReg_man.isWaitPolActiveHigh;
else wait_ = #(TimingData_man.tKHTX) ConfigReg_man.isWaitPolActiveHigh;
end else begin
if (!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) !ConfigReg_man.isWaitPolActiveHigh;
else wait_ = #(TimingData_man.tKHTX) !ConfigReg_man.isWaitPolActiveHigh;
end
 
end else
fork
begin
@(posedge(CLK))
if (isWait == `LOW) begin
if(!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) ConfigReg_man.isWaitPolActiveHigh;
else wait_ = #(TimingData_man.tKHTX) ConfigReg_man.isWaitPolActiveHigh;
end else begin
if (!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) !ConfigReg_man.isWaitPolActiveHigh;
else wait_ = #(TimingData_man.tKHTX) !ConfigReg_man.isWaitPolActiveHigh;
end
end
 
begin
@(isWait)
if (CLK) begin
if (isWait == `LOW) begin
if(!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) ConfigReg_man.isWaitPolActiveHigh;
else wait_ = #(TimingData_man.tKHTX) ConfigReg_man.isWaitPolActiveHigh;
end else begin
if (!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) !ConfigReg_man.isWaitPolActiveHigh;
else wait_ = #(TimingData_man.tKHTX) !ConfigReg_man.isWaitPolActiveHigh;
end
 
end
end
 
join
end else if (G_N == `HIGH && isWait == `HIGH && W_N==`HIGH)
$display("%t --- WARNING --- WAIT should be deasserted but OE# is not yet LOW. Please check the timings!",$time);
end
 
 
endmodule
 
 
 
// *********************************
//
// Burst module :
//
// manage the Read Burst operation
//
// *********************************
 
module BurstModule(address, data, ISWAIT, CLK, CLOCK, L_N, G_N, W_N, Info);
input [`ADDRBUS_range] address;
output [`WORD_range] data;
reg [`WORD_range] data;
 
input CLK;
input CLOCK;
input L_N;
input G_N;
input W_N;
output ISWAIT;
input Info;
 
reg [`ADDRBUS_range] Start_address, Sync_address,new_address;
reg EnableBurst, isValidData, IsNowWait, endSingleSynchronous;
reg [2:0] incLSBaddress, incMSBaddress, temp_address;
 
wire isSingleSynchronous = (Read_man.Mode != `ReadArray_bus) ? `TRUE : `FALSE;
 
integer WaitState,nWait,nRead,xLatency;
//aggiunta per il calcolo degli nwait
integer boundary,offset;
reg firstEOWL;
 
initial begin // constructor sequence
Start_address = `ADDRBUS_dim'h000000;
EnableBurst = `FALSE;
endSingleSynchronous = `FALSE;
data = 16'hZZ;
nWait = 0;
IsNowWait = `FALSE;
isValidData = `FALSE;
xLatency=0;
nRead=0;
WaitState=0;
firstEOWL=0;
end
 
always @(G_N) if (G_N==`TRUE) begin
IsNowWait = `FALSE;
isValidData = `FALSE;
EnableBurst = `FALSE;
endSingleSynchronous = `FALSE;
data = 16'hZZ;
nWait = 0;
xLatency=0;
nRead=0;
WaitState=0;
firstEOWL=0;
end
 
 
always @(isValidData) begin
case (isValidData)
 
1: if (!ConfigReg_man.isWaitBeforeActive) begin
IsNowWait = `TRUE;
end
 
0: begin if (!ConfigReg_man.isWaitBeforeActive)
IsNowWait = `FALSE;
 
end
endcase
end
 
 
assign ISWAIT = (IsNowWait) ? `TRUE : `FALSE;
 
 
always @(negedge L_N) if(W_N==`HIGH) begin : pollingBurst
fork : pollingBurst
 
begin: L_lacthing
@(posedge L_N) if (ConfigReg_man.isSynchronous) begin
#1;
Start_address = address;
Sync_address = address;
firstEOWL=0;
disable K_lacthing;
@(posedge CLK) begin
 
case(ConfigReg_man.BurstLength)
 
0: begin
boundary =16;
offset = address[3:0];
end
16:begin
boundary =16;
offset = address[3:0];
end
 
8: begin
boundary =8;
offset = address[2:0];
end
 
 
4:begin
boundary =4;
offset = address[1:0];
end
endcase
xLatency = ConfigReg_man.Xlatency;
WaitState = xLatency - (boundary - offset);
if (WaitState < 0) WaitState =0;
nWait = 0;
EnableBurst = `TRUE;
data = 16'hXX;
nRead = 0;
isValidData = `FALSE;
endSingleSynchronous=`FALSE;
disable pollingBurst;
end
end
else EnableBurst = `FALSE;
end
 
begin: K_lacthing
@(posedge CLK) if (ConfigReg_man.isSynchronous && L_N==`LOW) begin
#1;
Start_address = address;
Sync_address = address;
firstEOWL=0;
disable L_lacthing;
 
@(posedge CLK) begin
 
case(ConfigReg_man.BurstLength)
 
0: begin
boundary =16;
offset = address[3:0];
end
16:begin
boundary =16;
offset = address[3:0];
end
 
8: begin
boundary =8;
offset = address[2:0];
end
 
 
4:begin
boundary =4;
offset = address[1:0];
end
endcase
xLatency = ConfigReg_man.Xlatency;
WaitState = xLatency - (boundary - offset); //
if (WaitState < 0) WaitState =0;
nWait = 0;
EnableBurst = `TRUE;
data = 16'hXX;
nRead = 0;
isValidData = `FALSE;
endSingleSynchronous=`FALSE;
disable pollingBurst;
end
end
else EnableBurst = `FALSE;
end
join
$display(" %t address=%h",$time,Start_address);
end
 
 
always @(posedge (CLK)) if(G_N==`LOW) begin
if (EnableBurst) begin
if (xLatency == 2 && ConfigReg_man.isWaitBeforeActive)
IsNowWait = `TRUE;
 
if (xLatency == 1) begin
isValidData = `TRUE;
if (offset == 4'd15 && ConfigReg_man.isWaitBeforeActive && WaitState!=0 && (ConfigReg_man.isNoWrapBurst || ConfigReg_man.BurstLength == 5'd00)) begin
IsNowWait = `FALSE;
 
end
 
end
if (xLatency) xLatency = xLatency - 1; //vuol dire se xLatency e' >1 o diverso da zero????
end
end
 
always @(nRead) begin
if (isSingleSynchronous && nRead>=1) begin //End of SingleBurstRead???
endSingleSynchronous=`TRUE;
isValidData = `FALSE;
end
if((offset + nRead) == 4'd15 && ConfigReg_man.isWaitBeforeActive && WaitState!=0 && (ConfigReg_man.isNoWrapBurst || ConfigReg_man.BurstLength == 5'd00)) begin
IsNowWait = `FALSE;
 
end
end
 
 
always @(CLK) begin
if (EnableBurst) begin
if (!xLatency) begin // burst is ongoing(after xLatency)
if (!G_N) begin
if (nWait || endSingleSynchronous) data = `DATABUS_dim'hXXXX; //Wait State;
else begin // Read is Possible!
// -- \\
case (Read_man.Mode)
`ReadArray_bus : begin
data = Memory_man.Get(Sync_address);
@(posedge (CLK)) if (Info && !G_N) $write("[%t] Burst Read: Memory[%h]=%h\n",$time,Sync_address,data);
end
`ReadCFI_bus : begin
data = CFIquery_man.Get(Sync_address);
@(posedge (CLK)) if (Info && !G_N) $write("[%t] Burst Read: CFIMemory[%h]=%h\n",$time,Sync_address,data);
end
`ReadSignature_bus : begin
data = Signature_man.Get(Sync_address);
@(posedge (CLK)) if (Info && !G_N) $write("[%t] Burst Read: Electronic Signature[%h]=%h\n",$time,Sync_address,data);
end
`ReadStatusReg_bus : begin
data = SR_man.SR;
@(posedge (CLK)) if (Info && !G_N) $write("[%t] Burst Read: StatusRegister: %b\n",$time,data[`BYTE_range]);
end
default : $display("[%t] !!!Model Error: Read mode not recognized!!!", $time);
endcase
// -- \\
end
if((CLK)) begin
if (!nWait) // Wait State??? if no calculate next address
begin
new_address = Sync_address + 1;
nRead = nRead + 1;
end
if (!isSingleSynchronous) begin
 
// Calcultate Address for Sequential and Wrap Burst
if ((ConfigReg_man.BurstLength != 5'd00) && ConfigReg_man.isWrapBurst) begin
case (ConfigReg_man.BurstLength_bit)
3'd2: new_address = {Sync_address[`ADDRBUS_dim - 1 : 2], new_address[1:0] };
3'd3: new_address = {Sync_address[`ADDRBUS_dim - 1 : 3], new_address[2:0] };
3'd4: new_address = {Sync_address[`ADDRBUS_dim - 1 : 4], new_address[3:0] };
endcase
end
// Calculate Next Wait State
if (ConfigReg_man.isNoWrapBurst || (ConfigReg_man.BurstLength == 5'd00) ) //Calculate WAIT STATE
if ((new_address[3:0]==4'd0) && (Sync_address[3:0] == 4'd15)) begin
if(!ConfigReg_man.isWaitBeforeActive) begin
 
if (nWait<WaitState && !firstEOWL) begin
nWait = nWait+1; // Another Wait State???
isValidData = `FALSE;
end else begin
nWait = 0; // end of wait state
Sync_address = new_address;
isValidData = `TRUE;
firstEOWL =1;
 
end
 
end else begin
if (nWait<WaitState-1 && !firstEOWL ) begin
nWait = nWait+1; // Another Wait State???
IsNowWait = `FALSE;
end else begin
nWait = 0; // end of wait state
Sync_address = new_address;
IsNowWait = `TRUE;
firstEOWL =1;
 
end
end
 
end
if (!nWait)
if ((nRead<ConfigReg_man.BurstLength) || (ConfigReg_man.BurstLength==5'd00) // Read Data is Over Burst Lenght???
&& !endSingleSynchronous) // end of SingleSinchronous Burst Read ???
Sync_address = new_address;
end // !isSyn
end //aggiunta
end //G_N
end // XLatency
end //Enable Burst
end
 
 
endmodule // end Burst Module
 
 
// Erase Manager
// manage the erase functionality
 
module BlankCheckModule(address, data, progVoltOK, progHighVoltOK,Info);
 
input [`WORD_range] data;
input [`ADDRBUS_range] address;
input progVoltOK, progHighVoltOK;
input Info;
 
event ErrorCheckEvent, CompleteEvent;
 
reg [`BYTE_range] Status;
reg [`ADDRBUS_range] hold_address;
reg [`BLOCKADDR_range] hold_block;
 
 
reg Busy;
integer i;
time startTime, delayTime, Erase_time;
 
initial begin // constructor sequence
Busy = `FALSE;
Erase_time = `MainBlockErase_time; //modificato
delayTime = Erase_time;
end
 
always @(progVoltOK,progHighVoltOK,address) begin
if (progHighVoltOK)
if (BankLib_man.isMainBlock(address)) Erase_time=`FastMainBlockErase_time;
else Erase_time=`FastParameterBlockErase_time;
else
if (BankLib_man.isMainBlock(address)) Erase_time=`MainBlockErase_time;
else Erase_time=`ParameterBlockErase_time;
end
 
 
function IsBusy; // boolean function primitive
input obbl; // all functions require a parameter
IsBusy = Busy; // return Boolean value
endfunction
 
 
 
// *********************
//
// Task checkConfirm :
// check confirm code
//
// *********************
 
task checkConfirm;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
 
begin
 
if (data == `BLNKCHKconfirm_cmd) outStatus = `NoError_msg;
else outStatus = `WrongBlankCheckConfirm_msg;
end
endtask
 
 
 
 
 
// ****************
//
// Task Blank Check
//
// ****************
 
task BlankCheck;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
 
integer hold_block;
reg [`ADDRBUS_range] hold_address;
 
begin
hold_address = address;
hold_block = BankLib_man.getBlock(hold_address);
if (BankLib_man.isMainBlock(address)) begin
// Main Block
delayTime = `MainBlankCheck_time;
end else // Parameter Block
-> ErrorCheckEvent;
disable Operation;
 
fork
begin: Operation
Busy = `TRUE;
startTime = $time;
-> ErrorCheckEvent;
#delayTime
Memory_man.BlockBlankCheck(hold_block, Status);
-> CompleteEvent;
end
@CompleteEvent
disable Operation;
join
outStatus = Status;
Busy = `FALSE;
end
endtask
 
 
 
always @(ErrorCheckEvent) begin
Status = `NoError_msg;
if (!progVoltOK)
Status = `InvVDD_msg;
if (BankLib_man.isParameterBlock(address)) begin
Status = `WrongBlankCheckBlock;
$display("parameter block");
end
if (Status != `NoError_msg) begin
->CompleteEvent;
disable ErrorCheck;
end
else
fork : ErrorCheck
@(negedge progVoltOK) Status = `InvVDD_msg;
@(Status) -> CompleteEvent;
@(CompleteEvent) disable ErrorCheck;
join
end
 
endmodule //end module Erase
 
 
// *********************************
//
// Program Buffer module :
//
// program buffer functionality
//
// *********************************
 
module ProgramBufferModule(address,data,voltOK,Info);
input [`ADDRBUS_range] address;
input [`WORD_range] data;
input voltOK, Info;
event ErrorCheckEvent, CompleteEvent, WatchAddressEvent;
reg [`BYTE_range] Status;
reg [`DATABUS_dim-1:0] Count;
 
reg [`WORD_range] bufferData [`ProgramBuffer_range];
 
reg [`ADDRBUS_range] AddressLatched, startAddress,newAddress;
reg Busy, Suspended, Empty;
time startTime, delayTime;
integer i;
 
initial begin // constructor sequence
Busy = `FALSE;
Suspended = `FALSE;
Empty = `TRUE;
delayTime = `ProgramBuffer_time;
end
 
function IsBusy; // boolean function primitive
input obbl; // all functions require a parameter
IsBusy = Busy; // return Boolean value
endfunction
 
function IsSuspended; // boolean function primitive
input obbl; // all functions require a parameter
IsSuspended = Suspended; // return Boolean value
endfunction
 
function IsAddrSuspended; // boolean function primitive
input [`ADDRBUS_range] addr;
IsAddrSuspended = (Suspended && ((addr >= startAddress) && (addr < (startAddress + Count))));
endfunction
 
 
function [`DATABUS_dim-1:0] GetCount;
input required;
GetCount = Count;
endfunction
 
task SetCount; // sets the number of writes
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
begin
outStatus = `NoError_msg;
AddressLatched = address;
Count = data + 1;
 
if (Count > `ProgramBuffer_dim)
outStatus = `BuffSize_msg;
else if (BankLib_man.getBlock(AddressLatched) != BankLib_man.getBlock(AddressLatched + Count - 1))
outStatus = `BlkBuffer_msg;
else
-> WatchAddressEvent;
end
endtask
 
task Suspend;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
begin
delayTime = delayTime - ($time - startTime);
#`ProgramSuspendLatency_time;
outStatus = `NoError_msg;
Status = `Suspend_msg;
Suspended = `TRUE;
-> CompleteEvent;
end
endtask
 
task Resume;
output [`BYTE_range] Status;
begin
Suspended = `FALSE;
Program(Status);
end
endtask
 
task Load;
output [`BYTE_range] Status;
begin
if (Empty) begin
startAddress = address;
if (Info) $display("[%t] Buffer start address: %h",$time,startAddress);
Empty = `FALSE;
end
bufferData[address[`ProgramBuffer_addrRange]] = data;
 
end
endtask
 
task Program;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
begin
 
fork
begin : Operation
Busy = `TRUE;
startTime = $time;
-> ErrorCheckEvent;
-> WatchAddressEvent; // disable address watch
#delayTime
for (i = startAddress;i < ( Count + startAddress); i = i + 1) begin
Memory_man.Program(bufferData[i[`ProgramBuffer_addrRange]],i,Status);
 
end
delayTime = `ProgramBuffer_time;
-> CompleteEvent;
end
@CompleteEvent
disable Operation;
 
join
if(!Suspended)
for (i = 0; i < `ProgramBuffer_dim; i = i + 1) begin
bufferData[i] =16'hFFFF;
end
Empty = `TRUE;
outStatus = Status;
Busy = `FALSE;
end
endtask
 
always @(ErrorCheckEvent) begin
Status = `NoError_msg;
if (BlockLock_man.IsLocked(AddressLatched))
Status = `BlockLock_msg;
else if (Suspended)
Status = `SuspAcc_msg;
else if (!voltOK)
Status = `InvVDD_msg;
 
if (Status != `NoError_msg)
->CompleteEvent;
else
fork : ErrorCheck
@(negedge voltOK) Status = `InvVDD_msg;
@(Status) -> CompleteEvent;
@(CompleteEvent) disable ErrorCheck;
join
end
 
always @(WatchAddressEvent) fork : AddressWatch
while (`TRUE)
@address
if (BankLib_man.getBlock(address) != BankLib_man.getBlock(AddressLatched)) begin
Status = `AddrTog_msg;
-> CompleteEvent;
end
@WatchAddressEvent
disable AddressWatch;
join
 
endmodule
/orpsocv2/rtl/verilog/cfi_ctrl/cfi_ctrl.v
0,0 → 1,547
////////////////////////////////////////////////////////////////// ////
//// ////
//// Common Flash Interface (CFI) controller ////
//// ////
//// This file is part of the cfi_ctrl project ////
//// http://opencores.org/project,cfi_ctrl ////
//// ////
//// Description ////
//// See below ////
//// ////
//// To Do: ////
//// - ////
//// ////
//// Author(s): ////
//// - Julius Baxter, julius@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2011 Authors and OPENCORES.ORG ////
//// ////
//// 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 ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.gnu.org/copyleft/lesser.html ////
//// ////
//////////////////////////////////////////////////////////////////////
 
/*
Top level of CFI controller with 32-bit Wishbone classic interface
Intended to be used at about 66MHz with a 32MB CFI flash part with 16-bit
data interface.
 
This module has two configurations - one where it pulls in the CFI control
engine, which is intended to simplify accesses to a CFI flash, such as block
unlock, erase, and programming. The alternate configuration is essentially
mapping Wishbone accesses to the flash's bus.
CFI Engine Wishbone interface:
Basic functionality:
Bits [27:26] decode the operation.
2'b00 : read/write to the flash memory
2'b01 : unlock block
2'b10 : erase block
2'b11 : block registers, other flash control features
0xc00_0000 : block status/control register
bits:
[0]: r/o : CFI controller busy
[1]: w/o : clear flash status register
[2]: w/o : reset flash device and controller
0xc00_0004 : flash device status register
bits
[7:0] : r/o : flash device status register
 
0xe00_0000 : read device identifier information
User is able to access the device identifier information such as:
offset 0x0 : manufacturer code
offset 0x2 : device id
offset bba + 0x4 : block (add increments of 128KB block size)
offset 0xa : read config register
See CFI docs for further details (shift offset left by 1)
0xe01_0000 : CFI query
User is able to access the CFI query information
The hex offsets in the CFI spec should be shifted left by one before
applying to the Wishbone bus.
Addresses under 0x000_0000 cause direct access to the flash
Addresses under 0x400_0000 cause the block (addressed in [24:0]) to be unlocked
Addresses under 0x800_0000 cause the block (addressed in [24:0]) to be erased
*/
 
module cfi_ctrl
(
wb_clk_i, wb_rst_i,
wb_dat_i, wb_adr_i,
wb_stb_i, wb_cyc_i,
wb_we_i, wb_sel_i,
wb_dat_o, wb_ack_o,
wb_err_o, wb_rty_o,
 
 
flash_dq_io,
flash_adr_o,
flash_adv_n_o,
flash_ce_n_o,
flash_clk_o,
flash_oe_n_o,
flash_rst_n_o,
flash_wait_i,
flash_we_n_o,
flash_wp_n_o
);
 
parameter flash_dq_width = 16;
parameter flash_adr_width = 24;
 
parameter flash_write_cycles = 4; // wlwh/Tclk = 50ns / 15 ns (66Mhz)
parameter flash_read_cycles = 7; // elqv/Tclk = 95 / 15 ns (66MHz)
 
parameter cfi_engine = "ENABLED";
 
inout [flash_dq_width-1:0] flash_dq_io;
output [flash_adr_width-1:0] flash_adr_o;
 
output flash_adv_n_o;
output flash_ce_n_o;
output flash_clk_o;
output flash_oe_n_o;
output flash_rst_n_o;
input flash_wait_i;
output flash_we_n_o;
output flash_wp_n_o;
 
 
input wb_clk_i, wb_rst_i;
 
 
input [31:0] wb_dat_i, wb_adr_i;
input wb_stb_i, wb_cyc_i,
wb_we_i;
input [3:0] wb_sel_i;
output reg [31:0] wb_dat_o;
output reg wb_ack_o;
output wb_err_o, wb_rty_o;
 
reg [3:0] wb_state;
generate
if (cfi_engine == "ENABLED") begin : cfi_engine_gen
wire do_rst, do_init, do_readstatus;
wire do_clearstatus, do_eraseblock, do_write,
do_read, do_unlockblock;
 
/* Track when we have new bus accesses and are currently serving them */
reg wb_req_in_progress;
wire wb_req_new;
always @(posedge wb_clk_i)
if (wb_rst_i)
wb_req_in_progress <= 0;
else if (wb_req_new)
wb_req_in_progress <= 1'b1;
else if (wb_ack_o)
wb_req_in_progress <= 0;
assign wb_req_new = (wb_stb_i & wb_cyc_i) & !wb_req_in_progress;
 
/* Registers for interfacing with the CFI controller */
reg [15:0] cfi_bus_dat_i;
wire [15:0] cfi_bus_dat_o;
reg [23:0] cfi_bus_adr_i;
wire cfi_bus_ack_o;
wire cfi_bus_busy_o;
wire cfi_rw_sel;
wire cfi_unlock_sel;
wire cfi_erase_sel;
wire cfi_scr_sel;
wire cfi_readstatus_sel;
wire cfi_clearstatus_sel;
wire cfi_rst_sel;
wire cfi_busy_sel;
wire cfi_readdeviceident_sel;
wire cfi_cfiquery_sel;
 
reg cfi_bus_go;
 
reg cfi_first_of_two_accesses;
assign cfi_rw_sel = wb_adr_i[27:26]==2'b00;
assign cfi_unlock_sel = wb_adr_i[27:26]==2'b01 && wb_we_i;
assign cfi_erase_sel = wb_adr_i[27:26]==2'b10 && wb_we_i;
assign cfi_scr_sel = wb_adr_i[27:26]==2'b11 && wb_adr_i[25:0]==26'd0;
assign cfi_readstatus_sel = wb_adr_i[27:26]==2'b11 &&
wb_adr_i[25:0]==26'd4 && !wb_we_i;
assign cfi_clearstatus_sel = cfi_scr_sel && wb_dat_i[1] && wb_we_i;
assign cfi_rst_sel = cfi_scr_sel && wb_dat_i[2] && wb_we_i;
assign cfi_busy_sel = cfi_scr_sel & !wb_we_i;
assign cfi_readdeviceident_sel = wb_adr_i[27:26]==2'b11 &&
wb_adr_i[25]==1'b1 && !wb_adr_i[16]==1'b1 &&
!wb_we_i;
 
assign cfi_cfiquery_sel = wb_adr_i[27:26]==2'b11 &&
wb_adr_i[25]==1'b1 && wb_adr_i[16]==1'b1 &&
!wb_we_i;
 
assign do_rst = cfi_rst_sel & cfi_bus_go;
assign do_init = 0;
assign do_readstatus = cfi_readstatus_sel & cfi_bus_go;
assign do_clearstatus = cfi_clearstatus_sel & cfi_bus_go;
assign do_eraseblock = cfi_erase_sel & cfi_bus_go;
assign do_write = cfi_rw_sel & wb_we_i & cfi_bus_go ;
assign do_read = cfi_rw_sel & !wb_we_i & cfi_bus_go ;
assign do_unlockblock = cfi_unlock_sel & cfi_bus_go ;
assign do_readdeviceident = cfi_readdeviceident_sel & cfi_bus_go ;
assign do_cfiquery = cfi_cfiquery_sel & cfi_bus_go ;
 
/* Main statemachine */
`define WB_FSM_IDLE 0
`define WB_FSM_CFI_CMD_WAIT 2
always @(posedge wb_clk_i)
if (wb_rst_i) begin
wb_state <= `WB_FSM_IDLE;
cfi_bus_go <= 0;
 
/* Wishbone regs */
wb_dat_o <= 0;
wb_ack_o <= 0;
 
cfi_first_of_two_accesses <= 0;
end
else begin
case (wb_state)
`WB_FSM_IDLE: begin
wb_ack_o <= 0;
cfi_bus_go <= 0;
/* Pickup new incoming accesses */
/* Potentially get into a state where we received a bus request
but the CFI was still busy so waited. In this case we'll get a
ACK from the controller and have a new request registered */
if (wb_req_new) begin
if (cfi_busy_sel) /* want to read the busy flag */
begin
wb_ack_o <= 1;
wb_dat_o <= {30'd0, cfi_bus_busy_o};
end
else if (!cfi_bus_busy_o | (wb_req_in_progress & cfi_bus_ack_o))
begin
if (cfi_rw_sel | cfi_unlock_sel | cfi_erase_sel |
cfi_readstatus_sel | cfi_clearstatus_sel |
cfi_rst_sel | cfi_readdeviceident_sel |
cfi_cfiquery_sel)
begin
wb_state <= `WB_FSM_CFI_CMD_WAIT;
cfi_bus_go <= 1;
if (cfi_rw_sel) begin
/* Map address onto the 16-bit word bus*/
/* Reads always do full 32-bits, so adjust
address accordingly.*/
 
/* setup address and number of cycles depending
on request */
if (wb_we_i) begin /* Writing */
/* Only possible to write shorts at a time */
cfi_bus_dat_i <= wb_sel_i[1:0]==2'b11 ?
wb_dat_i[15:0] :
wb_dat_i[31:16];
cfi_bus_adr_i[23:0] <= wb_adr_i[24:1];
end
else begin /* Reading */
/* Full or part word? */
if ((&wb_sel_i)) begin /* 32-bits */
cfi_first_of_two_accesses <= 1;
cfi_bus_adr_i[23:0] <= {wb_adr_i[24:2],1'b0};
end
else begin /*16-bits or byte */
cfi_bus_adr_i[23:0] <= {wb_adr_i[24:1]};
end
end
end
if (cfi_unlock_sel | cfi_erase_sel)
cfi_bus_adr_i[23:0] <= wb_adr_i[24:1];
if (cfi_readdeviceident_sel)
cfi_bus_adr_i[23:0] <= {wb_adr_i[24:17],1'b0,
7'd0,wb_adr_i[9:1]};
if (cfi_cfiquery_sel)
cfi_bus_adr_i[23:0] <= {14'd0,wb_adr_i[10:1]};
end // if (cfi_rw_sel | cfi_unlock_sel | ...
end // if (!cfi_bus_busy_o | (wb_req_in_progress & ...
end // if (wb_req_new)
end // case: `WB_FSM_IDLE
`WB_FSM_CFI_CMD_WAIT: begin
cfi_bus_go <= 0;
/* Wait for the CFI controller to do its thing */
if (cfi_bus_ack_o) begin
if (cfi_rw_sel) begin
/* Is this the first of two accesses? */
if (cfi_first_of_two_accesses) begin
cfi_bus_adr_i <= cfi_bus_adr_i+1;
cfi_first_of_two_accesses <= 0;
cfi_bus_go <= 1;
/* Dealing with a read or a write */
/*
if (wb_we_i)
cfi_bus_dat_i <= wb_dat_i[31:16];
else
*/
wb_dat_o[31:16] <= cfi_bus_dat_o;
end
else begin
wb_state <= `WB_FSM_IDLE;
wb_ack_o <= 1'b1;
if (!wb_we_i) begin
if (&wb_sel_i)
wb_dat_o[15:0] <= cfi_bus_dat_o;
else begin
case (wb_sel_i)
4'b0001 :
wb_dat_o[31:0] <= {4{cfi_bus_dat_o[7:0]}};
4'b0010:
wb_dat_o[31:0] <= {4{cfi_bus_dat_o[15:8]}};
4'b0011 :
wb_dat_o[31:0] <= {cfi_bus_dat_o,cfi_bus_dat_o};
4'b0100 :
wb_dat_o[31:0] <= {4{cfi_bus_dat_o[7:0]}};
4'b1100 :
wb_dat_o[31:0] <= {cfi_bus_dat_o,cfi_bus_dat_o};
4'b1000 :
wb_dat_o[31:0] <= {4{cfi_bus_dat_o[15:8]}};
endcase // case (wb_sel_i)
end
 
end
end // else: !if(cfi_first_of_two_accesses)
end // if (cfi_rw_sel)
else begin
/* All other accesses should be a single go of the CFI
controller */
wb_state <= `WB_FSM_IDLE;
wb_ack_o <= 1'b1;
/* Get the read status data out */
if (cfi_readstatus_sel)
wb_dat_o <= {4{cfi_bus_dat_o[7:0]}};
if (cfi_readdeviceident_sel | cfi_cfiquery_sel)
wb_dat_o <= {2{cfi_bus_dat_o[15:0]}};
end
end // if (cfi_bus_ack_o)
else if (cfi_rst_sel)begin
/* The reset command won't ACK back over the bus, incase
the FSM hung and it actually reset all of its internals */
wb_state <= `WB_FSM_IDLE;
wb_ack_o <= 1'b1;
end
end // case: `WB_FSM_CFI_CMD_WAIT
endcase // case (wb_state)
end // else: !if(wb_rst_i)
assign wb_err_o = 0;
assign wb_rty_o = 0;
 
cfi_ctrl_engine
# (.cfi_part_wlwh_cycles(flash_write_cycles),
.cfi_part_elqv_cycles(flash_read_cycles)
)
cfi_ctrl_engine0
(
.clk_i(wb_clk_i),
.rst_i(wb_rst_i),
 
.do_rst_i(do_rst),
.do_init_i(do_init),
.do_readstatus_i(do_readstatus),
.do_clearstatus_i(do_clearstatus),
.do_eraseblock_i(do_eraseblock),
.do_unlockblock_i(do_unlockblock),
.do_write_i(do_write),
.do_read_i(do_read),
.do_readdeviceident_i(do_readdeviceident),
.do_cfiquery_i(do_cfiquery),
 
.bus_dat_o(cfi_bus_dat_o),
.bus_dat_i(cfi_bus_dat_i),
.bus_adr_i(cfi_bus_adr_i),
.bus_req_done_o(cfi_bus_ack_o),
.bus_busy_o(cfi_bus_busy_o),
 
.flash_dq_io(flash_dq_io),
.flash_adr_o(flash_adr_o),
.flash_adv_n_o(flash_adv_n_o),
.flash_ce_n_o(flash_ce_n_o),
.flash_clk_o(flash_clk_o),
.flash_oe_n_o(flash_oe_n_o),
.flash_rst_n_o(flash_rst_n_o),
.flash_wait_i(flash_wait_i),
.flash_we_n_o(flash_we_n_o),
.flash_wp_n_o(flash_wp_n_o)
 
);
end // if (cfi_engine == "ENABLED")
else begin : cfi_simple
 
reg long_read;
reg [4:0] flash_ctr;
reg [3:0] wb_state;
 
 
reg [flash_dq_width-1:0] flash_dq_o_r;
reg [flash_adr_width-1:0] flash_adr_o_r;
reg flash_oe_n_o_r;
reg flash_we_n_o_r;
reg flash_rst_n_o_r;
wire our_flash_oe;
assign flash_ce_n_o = 0;
assign flash_clk_o = 1;
assign flash_rst_n_o = flash_rst_n_o_r;
assign flash_wp_n_o = 1;
assign flash_adv_n_o = 0;
assign flash_dq_io = (our_flash_oe) ? flash_dq_o_r :
{flash_dq_width{1'bz}};
assign flash_adr_o = flash_adr_o_r;
assign flash_oe_n_o = flash_oe_n_o_r;
assign flash_we_n_o = flash_we_n_o_r;
 
`define WB_STATE_IDLE 0
`define WB_STATE_WAIT 1
 
assign our_flash_oe = (wb_state == `WB_STATE_WAIT ||
wb_ack_o) & wb_we_i;
always @(posedge wb_clk_i)
if (wb_rst_i)
begin
wb_ack_o <= 0;
wb_dat_o <= 0;
wb_state <= `WB_STATE_IDLE;
flash_dq_o_r <= 0;
flash_adr_o_r <= 0;
flash_oe_n_o_r <= 1;
flash_we_n_o_r <= 1;
flash_rst_n_o_r <= 0; /* active */
long_read <= 0;
flash_ctr <= 0;
end
else begin
if (|flash_ctr)
flash_ctr <= flash_ctr - 1;
case(wb_state)
`WB_STATE_IDLE: begin
/* reset some signals to NOP status */
wb_ack_o <= 0;
flash_oe_n_o_r <= 1;
flash_we_n_o_r <= 1;
flash_rst_n_o_r <= 1;
 
if (wb_stb_i & wb_cyc_i & !wb_ack_o) begin
flash_adr_o_r <= wb_adr_i[flash_adr_width:1];
wb_state <= `WB_STATE_WAIT;
if (wb_adr_i[27]) begin
/* Reset the flash, no matter the access */
flash_rst_n_o_r <= 0;
flash_ctr <= 5'd16;
end
else if (wb_we_i) begin
/* load counter with write cycle counter */
flash_ctr <= flash_write_cycles - 1;
/* flash bus write command */
flash_we_n_o_r <= 0;
flash_dq_o_r <= (|wb_sel_i[3:2]) ? wb_dat_i[31:16] :
wb_dat_i[15:0];
end
else begin
/* load counter with write cycle counter */
flash_ctr <= flash_read_cycles - 1;
if (&wb_sel_i)
long_read <= 1; // Full 32-bit read, 2 read cycles
flash_oe_n_o_r <= 0;
end // else: !if(wb_we_i)
end // if (wb_stb_i & wb_cyc_i)
end
`WB_STATE_WAIT: begin
if (!(|flash_ctr)) begin
if (wb_we_i) begin
/* write finished */
wb_ack_o <= 1;
wb_state <= `WB_STATE_IDLE;
flash_we_n_o_r <= 1;
end
else begin
/* read finished */
if (!(&wb_sel_i)) /* short or byte read */ begin
case (wb_sel_i)
4'b0001,
4'b0100:
wb_dat_o <= {4{flash_dq_io[7:0]}};
4'b1000,
4'b0010:
wb_dat_o <= {4{flash_dq_io[15:8]}};
default:
wb_dat_o <= {2{flash_dq_io}};
endcase // case (wb_sel_i)
wb_state <= `WB_STATE_IDLE;
wb_ack_o <= 1;
flash_oe_n_o_r <= 1;
end
else if (long_read) begin
/* now go on to read next word */
wb_dat_o[31:16] <= flash_dq_io;
long_read <= 0;
flash_ctr <= flash_read_cycles;
flash_adr_o_r <= flash_adr_o_r + 1;
end
else begin
/* finished two-part read */
wb_dat_o[15:0] <= flash_dq_io;
wb_state <= `WB_STATE_IDLE;
wb_ack_o <= 1;
flash_oe_n_o_r <= 1;
end
end
end
end
 
default:
wb_state <= `WB_STATE_IDLE;
endcase // case (wb_state)
end // else: !if(wb_rst_i)
end // block: cfi_simple
endgenerate
 
endmodule // cfi_ctrl
 
/orpsocv2/rtl/verilog/cfi_ctrl/cfi_ctrl_engine.v
0,0 → 1,479
////////////////////////////////////////////////////////////////// ////
//// ////
//// Common Flash Interface (CFI) controller ////
//// ////
//// This file is part of the cfi_ctrl project ////
//// http://opencores.org/project,cfi_ctrl ////
//// ////
//// Description ////
//// See below ////
//// ////
//// To Do: ////
//// - ////
//// ////
//// Author(s): ////
//// - Julius Baxter, julius@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2011 Authors and OPENCORES.ORG ////
//// ////
//// 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 ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.gnu.org/copyleft/lesser.html ////
//// ////
//////////////////////////////////////////////////////////////////////
/*
CFI controller engine.
Contains main state machine and bus controls.
 
Controlled via a simple interface to a bus controller interface.
For now just implements an asynchronous controller.
do_rst_i - reset the flash device
do_init_i - initialise the device (write "read configuration register")
do_readstatus_i - read the status of the device
do_eraseblock_i - erase a block
do_write_i - write a word an address
do_read_i - read a word from an address
bus_dat_o - data out to bus controller
bus_dat_i - data in from bus controller
bus_req_done_o - bus request done
*/
 
 
module cfi_ctrl_engine
(
 
clk_i, rst_i,
 
do_rst_i,
do_init_i,
do_readstatus_i,
do_clearstatus_i,
do_eraseblock_i,
do_unlockblock_i,
do_write_i,
do_read_i,
do_readdeviceident_i,
do_cfiquery_i,
 
bus_dat_o,
bus_dat_i,
bus_adr_i,
bus_req_done_o,
bus_busy_o,
flash_dq_io,
flash_adr_o,
flash_adv_n_o,
flash_ce_n_o,
flash_clk_o,
flash_oe_n_o,
flash_rst_n_o,
flash_wait_i,
flash_we_n_o,
flash_wp_n_o
 
);
 
parameter flash_dq_width = 16;
parameter flash_adr_width = 24;
input clk_i, rst_i;
input do_rst_i,
do_init_i,
do_readstatus_i,
do_clearstatus_i,
do_eraseblock_i,
do_unlockblock_i,
do_write_i,
do_read_i,
do_readdeviceident_i,
do_cfiquery_i;
output reg [flash_dq_width-1:0] bus_dat_o;
input [flash_dq_width-1:0] bus_dat_i;
input [flash_adr_width-1:0] bus_adr_i;
output bus_req_done_o;
output bus_busy_o;
inout [flash_dq_width-1:0] flash_dq_io;
output [flash_adr_width-1:0] flash_adr_o;
output flash_adv_n_o;
output flash_ce_n_o;
output flash_clk_o;
output flash_oe_n_o;
output flash_rst_n_o;
input flash_wait_i;
output flash_we_n_o;
output flash_wp_n_o;
 
wire clk, rst;
 
assign clk = clk_i;
assign rst = rst_i;
 
reg [5:0] bus_control_state;
reg [flash_dq_width-1:0] flash_cmd_to_write;
 
/* regs for flash bus control signals */
reg flash_adv_n_r;
reg flash_ce_n_r;
reg flash_oe_n_r;
reg flash_we_n_r;
reg flash_wp_n_r;
reg flash_rst_n_r;
reg [flash_dq_width-1:0] flash_dq_o_r;
reg [flash_adr_width-1:0] flash_adr_r;
 
reg [3:0] flash_phy_state;
reg [3:0] flash_phy_ctr;
wire flash_phy_async_wait;
`define CFI_PHY_FSM_IDLE 0
`define CFI_PHY_FSM_WRITE_GO 1
`define CFI_PHY_FSM_WRITE_WAIT 2
`define CFI_PHY_FSM_WRITE_DONE 3
`define CFI_PHY_FSM_READ_GO 4
`define CFI_PHY_FSM_READ_WAIT 5
`define CFI_PHY_FSM_READ_DONE 6
`define CFI_PHY_FSM_RESET_GO 7
`define CFI_PHY_FSM_RESET_WAIT 8
`define CFI_PHY_FSM_RESET_DONE 9
 
/* Defines according to CFI spec */
`define CFI_CMD_DAT_READ_STATUS_REG 8'h70
`define CFI_CMD_DAT_CLEAR_STATUS_REG 8'h50
`define CFI_CMD_DAT_WORD_PROGRAM 8'h40
`define CFI_CMD_DAT_BLOCK_ERASE 8'h20
`define CFI_CMD_DAT_READ_ARRAY 8'hff
`define CFI_CMD_DAT_WRITE_RCR 8'h60
`define CFI_CMD_DAT_CONFIRM_WRITE_RCR 8'h03
`define CFI_CMD_DAT_UNLOCKBLOCKSETUP 8'h60
`define CFI_CMD_DAT_CONFIRM_CMD 8'hd0
`define CFI_CMD_DAT_READDEVICEIDENT 8'h90
`define CFI_CMD_DAT_CFIQUERY 8'h98
 
 
/* Main bus-controlled FSM states */
`define CFI_FSM_IDLE 0
`define CFI_FSM_DO_WRITE 1
`define CFI_FSM_DO_WRITE_WAIT 2
`define CFI_FSM_DO_READ 3
`define CFI_FSM_DO_READ_WAIT 4
`define CFI_FSM_DO_BUS_ACK 5
`define CFI_FSM_DO_RESET 6
`define CFI_FSM_DO_RESET_WAIT 7
 
/* Used to internally track what read more we're in
2'b00 : read array mode
2'b01 : read status mode
else : something else*/
reg [1:0] flash_device_read_mode;
/* Track what read mode we're in */
always @(posedge clk)
if (rst)
flash_device_read_mode <= 2'b00;
else if (!flash_rst_n_o)
flash_device_read_mode <= 2'b00;
else if (flash_phy_state == `CFI_PHY_FSM_WRITE_DONE) begin
if (flash_cmd_to_write == `CFI_CMD_DAT_READ_ARRAY)
flash_device_read_mode <= 2'b00;
else if (flash_cmd_to_write == `CFI_CMD_DAT_READ_STATUS_REG)
flash_device_read_mode <= 2'b01;
else
/* Some other mode */
flash_device_read_mode <= 2'b11;
end
/* Main control state machine, controlled by the bus */
always @(posedge clk)
if (rst) begin
/* Power up and start an asynchronous write to the "read config reg" */
bus_control_state <= `CFI_FSM_IDLE;
flash_cmd_to_write <= 0;
end
else
case (bus_control_state)
`CFI_FSM_IDLE : begin
if (do_readstatus_i) begin
// if (flash_device_read_mode != 2'b01) begin
flash_cmd_to_write <= `CFI_CMD_DAT_READ_STATUS_REG;
bus_control_state <= `CFI_FSM_DO_WRITE;
// end
// else begin
// flash_cmd_to_write <= 0;
// bus_control_state <= `CFI_FSM_DO_READ;
// end
end
if (do_clearstatus_i) begin
flash_cmd_to_write <= `CFI_CMD_DAT_CLEAR_STATUS_REG;
bus_control_state <= `CFI_FSM_DO_WRITE;
end
if (do_eraseblock_i) begin
flash_cmd_to_write <= `CFI_CMD_DAT_BLOCK_ERASE;
bus_control_state <= `CFI_FSM_DO_WRITE;
end
if (do_write_i) begin
flash_cmd_to_write <= `CFI_CMD_DAT_WORD_PROGRAM;
bus_control_state <= `CFI_FSM_DO_WRITE;
end
if (do_read_i) begin
if (flash_device_read_mode != 2'b00) begin
flash_cmd_to_write <= `CFI_CMD_DAT_READ_ARRAY;
bus_control_state <= `CFI_FSM_DO_WRITE;
end
else begin
flash_cmd_to_write <= 0;
bus_control_state <= `CFI_FSM_DO_READ;
end
end
if (do_unlockblock_i) begin
flash_cmd_to_write <= `CFI_CMD_DAT_UNLOCKBLOCKSETUP;
bus_control_state <= `CFI_FSM_DO_WRITE;
end
if (do_rst_i) begin
flash_cmd_to_write <= 0;
bus_control_state <= `CFI_FSM_DO_RESET;
end
if (do_readdeviceident_i) begin
flash_cmd_to_write <= `CFI_CMD_DAT_READDEVICEIDENT;
bus_control_state <= `CFI_FSM_DO_WRITE;
end
if (do_cfiquery_i) begin
flash_cmd_to_write <= `CFI_CMD_DAT_CFIQUERY;
bus_control_state <= `CFI_FSM_DO_WRITE;
end
end // case: `CFI_FSM_IDLE
`CFI_FSM_DO_WRITE : begin
bus_control_state <= `CFI_FSM_DO_WRITE_WAIT;
end
`CFI_FSM_DO_WRITE_WAIT : begin
/* Wait for phy controller to finish the write command */
if (flash_phy_state==`CFI_PHY_FSM_WRITE_DONE) begin
if (flash_cmd_to_write == `CFI_CMD_DAT_READ_STATUS_REG ||
flash_cmd_to_write == `CFI_CMD_DAT_READ_ARRAY ||
flash_cmd_to_write == `CFI_CMD_DAT_READDEVICEIDENT ||
flash_cmd_to_write == `CFI_CMD_DAT_CFIQUERY) begin
/* we just changed the read mode, so go ahead and do the
read */
bus_control_state <= `CFI_FSM_DO_READ;
end
else if (flash_cmd_to_write == `CFI_CMD_DAT_WORD_PROGRAM) begin
/* Setting up to do a word write, go to write again */
/* clear the command, to use the incoming data from the bus */
flash_cmd_to_write <= 0;
bus_control_state <= `CFI_FSM_DO_WRITE;
end
else if (flash_cmd_to_write == `CFI_CMD_DAT_BLOCK_ERASE ||
flash_cmd_to_write == `CFI_CMD_DAT_UNLOCKBLOCKSETUP)
begin
/* first stage of a two-stage command requiring confirm */
bus_control_state <= `CFI_FSM_DO_WRITE;
flash_cmd_to_write <= `CFI_CMD_DAT_CONFIRM_CMD;
end
else
/* All other operations should see us acking the bus */
bus_control_state <= `CFI_FSM_DO_BUS_ACK;
end
end // case: `CFI_FSM_DO_WRITE_WAIT
`CFI_FSM_DO_READ : begin
bus_control_state <= `CFI_FSM_DO_READ_WAIT;
end
`CFI_FSM_DO_READ_WAIT : begin
if (flash_phy_state==`CFI_PHY_FSM_READ_DONE) begin
bus_control_state <= `CFI_FSM_DO_BUS_ACK;
end
end
`CFI_FSM_DO_BUS_ACK :
bus_control_state <= `CFI_FSM_IDLE;
`CFI_FSM_DO_RESET :
bus_control_state <= `CFI_FSM_DO_RESET_WAIT;
`CFI_FSM_DO_RESET_WAIT : begin
if (flash_phy_state==`CFI_PHY_FSM_RESET_DONE)
bus_control_state <= `CFI_FSM_IDLE;
end
default :
bus_control_state <= `CFI_FSM_IDLE;
endcase // case (bus_control_state)
 
/* Tell the bus we're done */
assign bus_req_done_o = (bus_control_state==`CFI_FSM_DO_BUS_ACK);
assign bus_busy_o = !(bus_control_state == `CFI_FSM_IDLE);
 
/* Sample flash data for the system bus interface */
always @(posedge clk)
if (rst)
bus_dat_o <= 0;
else if ((flash_phy_state == `CFI_PHY_FSM_READ_WAIT) &&
/* Wait for t_vlqv */
(!flash_phy_async_wait))
/* Sample flash data */
bus_dat_o <= flash_dq_io;
 
/* Flash physical interface control state machine */
always @(posedge clk)
if (rst)
begin
flash_adv_n_r <= 1'b0;
flash_ce_n_r <= 1'b1;
flash_oe_n_r <= 1'b1;
flash_we_n_r <= 1'b1;
flash_dq_o_r <= 0;
flash_adr_r <= 0;
flash_rst_n_r <= 0;
 
flash_phy_state <= `CFI_PHY_FSM_IDLE;
end
else
begin
case (flash_phy_state)
`CFI_PHY_FSM_IDLE : begin
flash_rst_n_r <= 1'b1;
flash_ce_n_r <= 1'b0;
/* Take address from the bus controller */
flash_adr_r <= bus_adr_i;
 
/* Wait for a read or write command */
if (bus_control_state == `CFI_FSM_DO_WRITE)
begin
flash_phy_state <= `CFI_PHY_FSM_WRITE_GO;
/* Are we going to write a command? */
if (flash_cmd_to_write) begin
flash_dq_o_r <= {{(flash_dq_width-8){1'b0}},
flash_cmd_to_write};
end
else
flash_dq_o_r <= bus_dat_i;
end
if (bus_control_state == `CFI_FSM_DO_READ) begin
flash_phy_state <= `CFI_PHY_FSM_READ_GO;
end
if (bus_control_state == `CFI_FSM_DO_RESET) begin
flash_phy_state <= `CFI_PHY_FSM_RESET_GO;
end
end
`CFI_PHY_FSM_WRITE_GO: begin
/* Assert CE, WE */
flash_we_n_r <= 1'b0;
flash_phy_state <= `CFI_PHY_FSM_WRITE_WAIT;
end
`CFI_PHY_FSM_WRITE_WAIT: begin
/* Wait for t_wlwh */
if (!flash_phy_async_wait) begin
flash_phy_state <= `CFI_PHY_FSM_WRITE_DONE;
flash_we_n_r <= 1'b1;
end
end
`CFI_PHY_FSM_WRITE_DONE: begin
flash_phy_state <= `CFI_PHY_FSM_IDLE;
end
 
`CFI_PHY_FSM_READ_GO: begin
/* Assert CE, OE */
/*flash_adv_n_r <= 1'b1;*/
flash_ce_n_r <= 1'b0;
flash_oe_n_r <= 1'b0;
flash_phy_state <= `CFI_PHY_FSM_READ_WAIT;
end
`CFI_PHY_FSM_READ_WAIT: begin
/* Wait for t_vlqv */
if (!flash_phy_async_wait) begin
flash_oe_n_r <= 1'b1;
flash_phy_state <= `CFI_PHY_FSM_READ_DONE;
end
end
`CFI_PHY_FSM_READ_DONE: begin
flash_phy_state <= `CFI_PHY_FSM_IDLE;
end
`CFI_PHY_FSM_RESET_GO: begin
flash_phy_state <= `CFI_PHY_FSM_RESET_WAIT;
flash_rst_n_r <= 1'b0;
flash_oe_n_r <= 1'b1;
end
`CFI_PHY_FSM_RESET_WAIT : begin
if (!flash_phy_async_wait) begin
flash_rst_n_r <= 1'b1;
flash_phy_state <= `CFI_PHY_FSM_RESET_DONE;
end
end
`CFI_PHY_FSM_RESET_DONE : begin
flash_phy_state <= `CFI_PHY_FSM_IDLE;
end
default:
flash_phy_state <= `CFI_PHY_FSM_IDLE;
endcase
end
 
/* Defaults are for 95ns access time part, 66MHz (15.15ns) system clock */
/* wlwh: cycles for WE assert to WE de-assert: write time */
parameter cfi_part_wlwh_cycles = 4; /* wlwh = 50ns, tck = 15ns, cycles = 4*/
/* elqv: cycles from adress to data valid */
parameter cfi_part_elqv_cycles = 7; /* tsop 256mbit elqv = 95ns, tck = 15ns, cycles = 6*/
 
assign flash_phy_async_wait = (|flash_phy_ctr);
 
/* Load counter with wait times in cycles, determined by parameters. */
always @(posedge clk)
if (rst)
flash_phy_ctr <= 0;
else if (flash_phy_state==`CFI_PHY_FSM_WRITE_GO)
flash_phy_ctr <= cfi_part_wlwh_cycles - 1;
else if (flash_phy_state==`CFI_PHY_FSM_READ_GO)
flash_phy_ctr <= cfi_part_elqv_cycles - 2;
else if (flash_phy_state==`CFI_PHY_FSM_RESET_GO)
flash_phy_ctr <= 10;
else if (|flash_phy_ctr)
flash_phy_ctr <= flash_phy_ctr - 1;
 
/* Signal to indicate when we should drive the data bus */
wire flash_bus_write_enable;
assign flash_bus_write_enable = (bus_control_state == `CFI_FSM_DO_WRITE) |
(bus_control_state == `CFI_FSM_DO_WRITE_WAIT);
/* Assign signals to physical bus */
assign flash_dq_io = flash_bus_write_enable ? flash_dq_o_r :
{flash_dq_width{1'bz}};
assign flash_adr_o = flash_adr_r;
assign flash_adv_n_o = flash_adv_n_r;
assign flash_wp_n_o = 1'b1; /* Never write protect */
assign flash_ce_n_o = flash_ce_n_r;
assign flash_oe_n_o = flash_oe_n_r;
assign flash_we_n_o = flash_we_n_r;
assign flash_clk_o = 1'b1;
assign flash_rst_n_o = flash_rst_n_r;
endmodule // cfi_ctrl_engine
 
 
/orpsocv2/rtl/verilog/ram_wb/ram_wb_b3.v
1,3 → 1,4
//`include "synthesis-defines.v"
module ram_wb_b3(
wb_adr_i, wb_bte_i, wb_cti_i, wb_cyc_i, wb_dat_i, wb_sel_i,
wb_stb_i, wb_we_i,
119,7 → 120,7
If not Verilator model, always do load, otherwise only load when called
from SystemC testbench.
*/
 
// synthesis translate_off
parameter memory_file = "sram.vmem";
 
`ifdef verilator
135,9 → 136,11
begin
$readmemh(memory_file, mem);
end
 
`endif // !`ifdef verilator
`endif // !`ifdef verilator
 
//synthesis translate_on
assign wb_rty_o = 0;
 
// mux for data to ram, RMW on part sel != 4'hf
209,9 → 212,9
// Error signal generation
//
// Error when out of bounds of memory - skip top byte of address in case
// this is mapped somewhere other than 0x00.
assign addr_err = wb_cyc_i & wb_stb_i & (|wb_adr_i[aw-1-8:mem_adr_width]);
// Error when out of bounds of memory - skip top nibble of address in case
// this is mapped somewhere other than 0x0.
assign addr_err = wb_cyc_i & wb_stb_i & (|wb_adr_i[aw-1-4:mem_adr_width]);
// OR in other errors here...
assign wb_err_o = wb_ack_o_r & wb_stb_i &
/orpsocv2/doc/orpsoc.texi
32,7 → 32,7
@c @subtitle second-subtitle
@author Julius Baxter
@author OpenCores
@author Issue 3 for @value{ORPSOC}
@author Issue 4 for @value{ORPSOC}
 
@c The following two commands
@c start the copyright page.
982,7 → 982,7
 
Not all peripherals are supported, and adding support for each is a goal.
 
At present the build contains a memory controller for the DDR2 SDRAM (based around a Xilinx MIG derived controller) and SSRAM. None of the other peripherals (VGA/AC97/PS2/USB/LCD) have controllers in the design yet.
At present the build contains a memory controller for the DDR2 SDRAM (based around a Xilinx MIG derived controller), SSRAM (remains to be verified), and CFI flash. None of the other peripherals (VGA/AC97/PS2/USB/LCD) have controllers in the design yet.
 
The OpenCores 10/100 Ethernet MAC can be used for Ethernet, but only with the PHY in 10/100 mode using the MII interface to the Marvel Alaska Ethernet PHY IC. There still may be bugs in the FIFO buffer configuration in the ML501's @code{ethmac_defines.v} file should not be changed.
 
999,6 → 999,8
 
The Verilog RTL specific to this board is under @code{rtl/verilog} in the board path. The @code{include} path in there is the place where all required definitions files, configuring the RTL, are found.
 
The default configuration will result in a design which executes from the RAM at reset. For simulation, the @code{PRELOAD_RAM} option will need to be used to ensure the processor starts up correctly. To configure and simulate the build to boot from flash, see below.
 
Backend files, mainly binary NGC files for mapping, are found in the board's @code{backend/bin} path.
 
@node ML501 Xilinx Environment Setup
1076,8 → 1078,49
 
@end table
 
@node ML501 Simulating Boot From Flash
@subsection Simulating Boot From Flash
@cindex simulating ML501 flash boot
 
By default, the build will boot from RAM, but it is often useful to compile the design for FPGA so that it boots from a large software image in the 32MB CFI flash part (u-boot bootloader or a Linux kernel image, etc.)
 
It is, then, useful to be able to simulate this.
 
@subsubsection Configure the design
 
First, ensure the build is configured to boot from the flash memory. @xref{ML501 boot from flash configuration}.
 
@subsubsection Prepare the image
 
Next, generate an image to preload into the flash. @emph{Note}: this is not done automatically at present and must be done manually.
 
Create the executable for the program you wish to boot out of flash. Generate a binary of it using @code{or32-elf-objcopy} like so:
 
@example
@kbd{or32-elf-objcopy -O binary @emph{yourexe.elf} @emph{youroutputfile.bin}}
@end example
 
@emph{Note}: how to create software to execute out of flash on OpenRISC is not covered here, but it's likely an executable intended to execute from RAM will require subtle modifications to the reset vector code and linker script to ensure it executes from flash correctly. Consulting the OpenRISC project wiki is recommended.
 
Next, turn this into a VMEM image that the flash model can load. To do this use the tool found in the root @kbd{sw/utils} path called @kbd{bin2vmem}. Save this resulting VMEM it into the board's @kbd{sim/run} path and name it @kbd{cfi-flash.vmem}.
 
@example
@kbd{.../orpsocv2/sw/utils/bin2vmem @emph{youroutputfile.bin} -bpw=2 > \}
@kbd{.../orpsocv2/boards/xilinx/ml501/sim/run/cfi-flash.vmem}
@end example
 
The resulting VMEM file should consist of the program in 2-byte words (the point of the @kbd{-bpw=2} switch.)
 
@subsubsection Run the simulation
 
As the software to be run is potentially not from ORPSoC's testsuite, and there's no way to override the name of the test being run in a way that allows things to compile correctly, simply run the following, and all results will be stored in the board's @kbd{sim/out} path prefixed with the name of the default test, @kbd{or1200-simple}.
 
@example
@kbd{make rtl-test}
@end example
 
The processor will now boot from @kbd{0xf0000100} and begin executing the image from the flash.
 
@node ML501 Synthesis
@section Synthesis
 
1263,7 → 1306,25
 
@emph{Note:} iMPACT from ISE 12 introduced errors in the software image when being programmed. It is advisable that versions of iMPACT from ISEs other than 12 are used until this bug is fixed.
 
@node ML501 platform flash programming file
@subsection platform flash programming file generation
 
There are options in the backend makefile to generate programming files for the platform flash found on the ML501.
 
The following command will make the @code{orpsoc_platformflash.mcs} file which can be programmed into the flash via the iMPACT tool.
 
@example
@kbd{boards/xilinx/ml501/backend/par/run$ make orpsoc_platformflash.mcs}
@end example
 
This flash is designed to be loaded in the high-speed selectMAP mode, as it is formatted in such a way as it should be read out over a 16-bit data bus.
 
To program the platform flash, launch iMPACT, and initialise the scanchain.
 
Assign the orpsoc_platformflash.mcs file to the xcf32p part. @emph{Note:} I got a warning about the .mcs file not appearing to be a configuration file and that ``This file will not configure a Xilinx device in Serial or SelectMap modes and may not be intended for configuration.''
 
The option where the PROM is slave during programming was left enabled.
 
@node ML501 Customising
@section Customising
 
1271,6 → 1332,28
 
The following sections have information on how to configure the design.
 
@node ML501 boot from flash configuration
@subsection Enabling Flash Boot Configuration
 
The following will outline how to make the OR1200 boot from the CFI flash part at reset.
 
In the board's @code{rtl/verilog/include/orpsoc-defines.v} ensure the following is uncommented:
 
@example
@kbd{`define CFI_FLASH}
@end example
 
In the board's @code{rtl/verilog/include/or1200_defines.v} ensure the following is uncommented:
@example
@kbd{`define OR1200_BOOT_PCREG_DEFAULT 30'h3c00003f}
@kbd{`define OR1200_BOOT_ADR 32'hf0000100}
@end example
 
All other @code{OR1200_BOOT_*} defines nearby should be commented out.
 
This will ensure that (1) the CFI flash controller is enabled, and (2) the OR1200 will go straight to its reset vector in the flash memory at reset. Note that this will completely bypass the bootrom (at @code{0xe0000000}) so its configuration now is meaningless. This is on purpose, as any init code can and should be handled by software in the flash (such as u-boot.)
 
@node ML501 Customising Enabling Existing Modules
@subsection Enabling Existing RTL Modules
 
/orpsocv2/scripts/make/Makefile-sim-definesgen.inc
18,6 → 18,9
$(Q)if [ ! -z $$VCD_DELAY ]; \
then echo "\`define VCD_DELAY "$$VCD_DELAY >> $@; \
fi
$(Q)if [ ! -z $$VCD_DELAY_MULTIPLY ]; \
then echo "\`define VCD_DELAY_MULTIPLY "$$VCD_DELAY_MULTIPLY >> $@; \
fi
$(Q)if [ ! -z $$VCD_DEPTH ]; \
then echo "\`define VCD_DEPTH "$$VCD_DEPTH >> $@; \
fi
/orpsocv2/scripts/make/Makefile-swrules.inc
23,6 → 23,10
$(Q)if [ -L $@ ]; then unlink $@; fi
$(Q)ln -s $< $@
 
flash16.in: $(SW_TEST_DIR)/$(TEST).flash16
$(Q)if [ -L $@ ]; then unlink $@; fi
$(Q)ln -s $< $@
 
sram.vmem: $(SW_TEST_DIR)/$(TEST).vmem
$(Q)if [ -L $@ ]; then unlink $@; fi
$(Q)ln -s $< $@
37,6 → 41,11
$(Q) echo; echo "\t### Compiling software ###"; echo;
$(Q)$(MAKE) -C $(SW_TEST_DIR) $(TEST).vmem
 
.PHONY: $(SW_TEST_DIR)/$(TEST).flash16
$(SW_TEST_DIR)/$(TEST).flash16:
$(Q) echo; echo "\t### Compiling software ###"; echo;
$(Q)$(MAKE) -C $(SW_TEST_DIR) $(TEST).flash16
 
# Create test software disassembly
 
sw-dis: $(SW_TEST_DIR)/$(TEST).dis
/orpsocv2/sw/tests/cfi_ctrl/board/cfi_ctrl-readid.c
0,0 → 1,27
#include "board.h"
#include "cpu-utils.h"
#include "cfi_ctrl.h"
#include "uart.h"
#include "printf.h"
 
#include "orpsoc-defines.h"
 
 
int main(void)
{
uart_init(DEFAULT_UART);
 
printf("\nReading some CFI ID\n");
printf("manufacturer code: %04x\n",cfi_ctrl_read_identifier(0x00)&0xffff);
printf("Device ID: %04x\n",cfi_ctrl_read_identifier(0x01)&0xffff);
printf("RCR: %04x\n",cfi_ctrl_read_identifier(0x05)&0xffff);
printf("query info: %04x\n",cfi_ctrl_query_info(0x10)&0xffff);
printf("query info: %04x\n",cfi_ctrl_query_info(0x11)&0xffff);
printf("query info: %04x\n",cfi_ctrl_query_info(0x12)&0xffff);
printf("device timing & voltage info: %04x\n",
cfi_ctrl_query_info(0x1b)&0xffff);
 
report(0x8000000d);
exit(0);
}
/orpsocv2/sw/tests/cfi_ctrl/board/Makefile
0,0 → 1,13
SW_ROOT=../../..
 
include $(SW_ROOT)/Makefile.inc
 
%.dis: %.elf
$(Q)$(OR32_OBJDUMP) -d $< > $@
 
%.bin: %.elf
$(Q)$(OR32_OBJCOPY) -O binary $< $@
 
clean:
$(Q)rm -f *.elf *.bin *.vmem *.flashin *.dis
 
/orpsocv2/sw/tests/cfi_ctrl/board/cfi_ctrl-simple.c
0,0 → 1,72
#include "board.h"
#include "cpu-utils.h"
#include "cfi_ctrl.h"
#include "uart.h"
#include "printf.h"
#include "orpsoc-defines.h"
 
 
int main(void)
{
uart_init(DEFAULT_UART);
 
printf("cfi_ctrl-simple test");
 
/* Reset the flash */
cfi_ctrl_reset_flash();
 
/* wait for the controller to be done */
while (cfi_ctrl_busy());
 
#define NUM_PAGES 8
#define TEST_LENGTH 64
int i,j;
unsigned int page_base;
unsigned short check_data[TEST_LENGTH];
unsigned short tmp;
 
/* test for number of blocks... */
for(j=0;j<NUM_PAGES;j++)
{
page_base = j*(128*1024);
printf("Status before clear: %02x\n",cfi_ctrl_get_status()&0xff);
cfi_ctrl_clear_status();
printf("Status after clear: %02x\n",cfi_ctrl_get_status()&0xff);
 
/* Erase block */
if (cfi_ctrl_erase_block(page_base))
{
//exit(0xbaaaaaad);
printf("Error erasing block at %08x\n",page_base);
printf("Aborting test\n");
exit(1);
}
 
cfi_ctrl_clear_status();
for (i=0;i<TEST_LENGTH;i++)
{
tmp = (unsigned short)rand();
//report(tmp&0xffff);
printf("writing data: %04x\n", tmp&0xffff);
cfi_ctrl_write_short(tmp,page_base+i*2);
check_data[i] = tmp;
}
 
/* Read back the data and check it */
cfi_ctrl_enable_data_read();
for (i=0;i<TEST_LENGTH;i++)
{
tmp = REG16(CFI_CTRL_BASE + page_base + (i*2));
if (tmp != check_data[i])
//exit(0xbaaaaaad);
printf("read data was not written data: %04x != %04x\n", tmp&0xffff,
check_data[i]);
}
}
 
report(0x8000000d);
exit(0);
}
/orpsocv2/sw/tests/cfi_ctrl/sim/cfi_ctrl-readid.c
0,0 → 1,24
#include "board.h"
#include "cpu-utils.h"
#include "cfi_ctrl.h"
#include "printf.h"
 
#include "orpsoc-defines.h"
 
 
int main(void)
{
printf("\nReading some CFI ID\n");
printf("manufacturer code: %04x\n",cfi_ctrl_read_identifier(0x00)&0xffff);
printf("Device ID: %04x\n",cfi_ctrl_read_identifier(0x01)&0xffff);
printf("RCR: %04x\n",cfi_ctrl_read_identifier(0x05)&0xffff);
printf("query info: %04x\n",cfi_ctrl_query_info(0x10)&0xffff);
printf("query info: %04x\n",cfi_ctrl_query_info(0x11)&0xffff);
printf("query info: %04x\n",cfi_ctrl_query_info(0x12)&0xffff);
printf("device timing & voltage info: %04x\n",
cfi_ctrl_query_info(0x1b)&0xffff);
 
report(0x8000000d);
exit(0);
}
/orpsocv2/sw/tests/cfi_ctrl/sim/Makefile
0,0 → 1,13
SW_ROOT=../../..
 
include $(SW_ROOT)/Makefile.inc
 
%.dis: %.elf
$(Q)$(OR32_OBJDUMP) -d $< > $@
 
%.bin: %.elf
$(Q)$(OR32_OBJCOPY) -O binary $< $@
 
clean:
$(Q)rm -f *.elf *.bin *.vmem *.flashin *.dis
 
/orpsocv2/sw/tests/cfi_ctrl/sim/cfi_ctrl-simple.c
0,0 → 1,85
#include "board.h"
#include "cpu-utils.h"
#include "cfi_ctrl.h"
 
#include "orpsoc-defines.h"
 
 
int main(void)
{
/* Reset the flash */
cfi_ctrl_reset_flash();
 
/* wait for the controller to be done */
while (cfi_ctrl_busy());
 
#define NUM_PAGES 8
#define TEST_LENGTH 64
int i,j;
unsigned int page_base;
unsigned short check_data[TEST_LENGTH];
unsigned short tmp;
unsigned short* flash_data_short_ptr;
 
/* test for number of blocks... */
for(j=0;j<NUM_PAGES;j++)
{
page_base = j*(128*1024);
cfi_ctrl_clear_status();
 
/* Erase block */
if (cfi_ctrl_erase_block(page_base))
exit(0xbaaaaaad);
 
cfi_ctrl_clear_status();
 
for (i=0;i<TEST_LENGTH;i++)
{
tmp = (unsigned short)rand();
report(tmp&0xffff);
cfi_ctrl_write_short(tmp,page_base+i*2);
check_data[i] = tmp;
}
 
/* Read back as shorts and check it */
cfi_ctrl_enable_data_read();
for (i=0;i<TEST_LENGTH;i++)
{
//tmp = REG16(CFI_CTRL_BASE + page_base + (i*2));
flash_data_short_ptr = (short*) (CFI_CTRL_BASE + page_base);
//if (tmp != check_data[i])
if (flash_data_short_ptr[i] != check_data[i])
exit(0xbaaaaaad);
}
char * flash_data_char_ptr = (char*) CFI_CTRL_BASE + page_base;
char * chardata = (char*) check_data;
/* Read back as bytes and check it */
cfi_ctrl_enable_data_read();
for (i=0;i<TEST_LENGTH*2;i++)
{
if (flash_data_char_ptr[i] != chardata[i])
exit(0xbaaaaaad);
}
 
long * flash_data_long_ptr = CFI_CTRL_BASE + page_base;
long * longdata = (long*) check_data;
/* Read back as longs and check it */
cfi_ctrl_enable_data_read();
for (i=0;i<TEST_LENGTH/2;i++)
{
if (flash_data_long_ptr[i] != longdata[i])
exit(0xbaaaaaad);
}
 
 
}
 
report(0x8000000d);
exit(0);
}
/orpsocv2/sw/apps/cfi_ctrl_programmer/cfi_ctrl_programmer.c
0,0 → 1,366
// Program that will erase and program a flash via cfi_ctrl module
 
#include "cpu-utils.h"
#include "board.h"
#include "uart.h"
#include "printf.h"
#include "cfi_ctrl.h"
 
// TODO: detect this manually - it is CFI after all!
#define BLOCK_SIZE_BYTES (128*1024)
 
//#define VERBOSE_PROGRAMMING
#define VERBOSE_VERIFY_ERRORS
//#define VERIFY_WHEN_WRITE
 
unsigned long programming_file_start;
unsigned long programming_file_end;
unsigned long programming_file_length;
 
extern unsigned long userprogram_data, _userprogram_data;
extern unsigned long end_userprogram_data, _end_userprogram_data;
 
// Globals
int timeout_counter;
volatile char dump;
int programming_base_offset;
 
#define RESET_PC 0xf0000100
 
int
console_get_num(void)
{
char c = 0x30;
int num_nums = 0;
int num_nums_total;
char nums[16]; // up to 16 decimal digits long
int retval = 0;
int decimal_multiplier;
int i;
printf("Enter decimal value: ");
while (c >= 0x30 && c < 0x40)
{
c = uart_getc(DEFAULT_UART);
if (c >= 0x30 && c < 0x40)
{
printf("%d", c-0x30);
nums[num_nums] = c-0x30;
num_nums++;
}
}
printf("\n");
 
num_nums_total = num_nums;
 
while(num_nums--)
{
decimal_multiplier = 1;
for(i=1;i<num_nums_total - num_nums;i++)
decimal_multiplier *= 10;
//printf("%d * %d\n",decimal_multiplier,nums[num_nums]);
retval += (decimal_multiplier * nums[num_nums]);
}
//printf("%d\n",retval);
return retval;
}
 
void
console_browse_buffer(char* buf)
{
char c = 0;
int offset = 0;
const int linesize = 16;
int i;
printf("Press space to scroll through buffer, q to return\n");
printf("+/- alter address offset\n");
cfi_ctrl_enable_data_read();
while (1)
{
c = uart_getc(DEFAULT_UART);
 
if (c == 'q')
return;
else if (c == 'r')
offset=0;
else if (c == '+')
{
offset+=linesize;
printf("%04x:\r",offset);
}
else if (c == '-')
{
if (offset >=linesize)
offset-=linesize;
 
printf("%04x:\r",offset);
}
else if (c == 0x20) // space, print al ine
{
printf("%04x:",offset);
// print another line of the buffer
for (i=0;i<linesize;i++)
{
printf(" %02x", buf[offset+i]&0xff);
}
printf("\n");
offset += linesize;
}
}
}
 
void
delay(int n)
{
volatile int i=0;
while(i<n)
i++;
}
 
void
timeout_reset(void)
{
timeout_counter = 0;
}
 
int
timeout(void)
{
timeout_counter++;
if (timeout_counter == 20000)
{
printf("timeout\n");
cfi_ctrl_reset_flash();
 
return 1;
}
return 0;
}
 
void
print_cfi_status(void)
{
char flashid[5];
int i;
printf("\tcfi_ctrl flash status:\n");
 
printf("Device status byte: 0x%02x\n",cfi_ctrl_get_status()&0xff);
printf("\n");
printf("Programming file from 0x%x-0x%x, %d bytes\n",
programming_file_start, programming_file_end,
programming_file_length);
// printf("Embedded length: %d\n", (unsigned long) userprogram_data);
printf("Page programming base: %d (set with 'o' command)\n",
programming_base_offset);
}
 
void
verify_image(int base_offset, char* data, int length_bytes)
{
 
int base_block = base_offset / BLOCK_SIZE_BYTES;
int num_blocks = (length_bytes/BLOCK_SIZE_BYTES) + 1;
int i;
int verify_error = 0;
 
printf("\tVerifying %d bytes of image from 0x%08x\n",length_bytes,
base_offset);
 
unsigned int waddr;
short * data_shorts;
int short_counter;
data_shorts = (short*) data;
// Read the pages
cfi_ctrl_enable_data_read();
for(waddr=base_offset, short_counter=0;
waddr<(base_offset + length_bytes);
waddr +=2, short_counter++)
{
/* Check what we wrote */
short verify_data = REG16(CFI_CTRL_BASE+waddr);
if (verify_data != data_shorts[short_counter])
{
printf("\tERROR: word verify failed at 0x%08x.\n",waddr);
printf("\tERROR: Read 0x%04x instead of 0x%04x.\n",verify_data,
data_shorts[short_counter]);
verify_error ++;
}
}
if (verify_error)
printf("\tVerify complete - %d errors were detected\n",
verify_error);
else
printf("\tImage verified. Press esacpe to boot from 0x%08x.\n",RESET_PC);
}
 
void
program_image(int base_offset, char* data, int length_bytes)
{
 
int base_block = base_offset / BLOCK_SIZE_BYTES;
int num_blocks = (length_bytes/BLOCK_SIZE_BYTES) + 1;
int i;
 
unsigned int waddr;
short * data_shorts;
int short_counter;
printf("\tErasing blocks (%d - %d)\n",base_block,
base_block + num_blocks-1);
// Erase the appropriate blocks
for(i=base_block;i<base_block + num_blocks;i++)
{
printf("\tErasing block %d\n",i);
cfi_ctrl_unlock_block(i*BLOCK_SIZE_BYTES);
if (cfi_ctrl_erase_block(i*BLOCK_SIZE_BYTES))
{
printf("\tErase failed, trying again\n");
i--; // Try erasing again
continue;
}
}
printf("\tErase complete\n");
printf("\n\tProgramming %d bytes\n", length_bytes);
 
data_shorts = (short*) data;
 
// Program the pages
for(waddr=base_offset, short_counter=0;
waddr<(base_offset + length_bytes);
waddr +=2, short_counter++)
{
if (cfi_ctrl_write_short(data_shorts[short_counter],waddr))
{
printf("\tERROR: word program failed at 0x%08x\n",waddr);
return;
}
else
{
#ifdef VERIFY_WHEN_WRITE
/* Check what we wrote */
cfi_ctrl_enable_data_read();
short verify_data = REG16(CFI_CTRL_BASE+waddr);
if (verify_data != data_shorts[short_counter])
{
printf("\tERROR: word verify failed at 0x%08x.\n",waddr);
printf("\tERROR: Read 0x%04x instead of 0x%04x.\n",verify_data,
data_shorts[short_counter]);
return;
}
#endif
}
}
printf("\tProgramming %d bytes complete\n", length_bytes);
}
 
#define printhelp() printf("\nUsage: \n \
\t[p]rogram\t\terase req. blocks, write image to flash\n \
\t[o]ffset\t\tset page offset to write to\n \
\t[v]erify\t\tverify written program\n \
\t[s]tatus\t\tprint status of CFI flash\n \
\t[e]rase\t\t\terase block of CFI flash\n \
\t[r]ead\t\t\tread, browse page of CFI flash\n \
\t[i]nspect\t\tinspect page of image in RAM\n \
\t[R]eset\t\t\treset CFI flash controller\n \
\t[ESC]\t\t\treset by jumping to 0x%08x\n \
\n",RESET_PC)
 
int
main()
{
uart_init(0); // init the UART before we can printf
volatile char c;
int i,j;
 
programming_base_offset = 0;
programming_file_start = (unsigned long) &userprogram_data;
programming_file_end = (unsigned long) &end_userprogram_data;
programming_file_length = programming_file_end - programming_file_start;
 
printf("\n\n\tcfi_ctrl flash programming app\n\n");
printf("\ttype 'h' for help menu\n\n");
 
while(1){
printf(" > ");
c = uart_getc(DEFAULT_UART);
printf("%c",c);
printf("\n");
if (c == 'h')
printhelp();
else if (c == 's')
print_cfi_status();
else if (c == 'c')
cfi_ctrl_clear_status();
else if (c == 'p')
program_image(programming_base_offset,
(char *) &userprogram_data,
programming_file_length);
else if (c == 'v')
verify_image(programming_base_offset,
(char *) &userprogram_data,
programming_file_length);
else if (c == 'o')
{
printf("Enter byte offset to program from.\n");
programming_base_offset = console_get_num();
}
// Support/debug commands:
else if (c == 'e')
{
printf("Erase a block.\n");
i = console_get_num();
// program a specific page
cfi_ctrl_erase_block_no_wait(i*BLOCK_SIZE_BYTES);
}
else if (c == 'r')
{
printf("Inspect memory.\n");
i = console_get_num();
// read a page
console_browse_buffer((char*)CFI_CTRL_BASE + i);
}
else if (c == 'i')
{
printf("Inspect image to program.\n");
console_browse_buffer((char*) &userprogram_data);
}
else if (c == 'R')
{
printf("Reset command to controller\n");
cfi_ctrl_reset_flash();
}
else if (c == 0x1b) // Esacpe key
{
// Reset
void (*reset_function) (void) =
(void *)RESET_PC;
(*reset_function)();
}
 
}
return 0;
 
}
/orpsocv2/sw/apps/cfi_ctrl_programmer/Makefile
0,0 → 1,31
# Program to control the cfi_ctrl module to manage contents of flash memory.
#
# author: julius.baxter@orsoc.se
#
 
SW_ROOT=../..
 
#PROGRAMMINGFILE=
PROGRAMMINGFILE_SWBIN=progfile.swbin # Binary file with sizeword
PROGRAMMINGFILE_DATA=progfile.o
 
ELF_DEPENDS +=$(PROGRAMMINGFILE_DATA)
 
include $(SW_ROOT)/Makefile.inc
 
OR32_LDFLAGS = -L$(SW_ROOT)/lib -lorpsoc -lgcc -Tcfi_ctrl_programmer.ld -e 256
 
$(PROGRAMMINGFILE_DATA): $(PROGRAMMINGFILE)
$(Q)$(OR32_LD) -r -b binary -o $@ $<
$(Q)$(OR32_OBJCOPY) --rename-section .data=.userprogram $@
 
%.dis: %.elf
$(Q)$(OR32_OBJDUMP) -d $< > $@
 
%.bin: %.elf
$(Q)$(OR32_OBJCOPY) -O binary $< $@
 
clean:
$(Q)rm -f *.elf *.bin *.vmem *.flashin *.dis $(PROGRAMMINGFILE_SWBIN) $(PROGRAMMINGFILE_DATA)
 
#distclean: clean
/orpsocv2/sw/apps/cfi_ctrl_programmer/cfi_ctrl_programmer.ld
0,0 → 1,113
/*STARTUP(../support/crt0.o)*/
/*ENTRY()*/
OUTPUT_ARCH(or32)
/*GROUP()*/
SEARCH_DIR(.)
__DYNAMIC = 0;
 
MEMORY
{
vectors : ORIGIN = 0, LENGTH = 0x1000
ram : ORIGIN = 0x1000, LENGTH = (8M - 0x1000)
}
 
 
/*
* Allocate the stack to be at the top of memory, since the stack
* grows down.
*/
_min_stack = 0x2000; /* 8K - minimum stack space to reserve */
 
SECTIONS
{
.vectors :
{
*(.vectors)
} > vectors
.text : {
stext = .;
_stext = .;
*(.text)
_etext = .;
__CTOR_LIST__ = .;
LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
*(.ctors)
LONG(0)
__CTOR_END__ = .;
__DTOR_LIST__ = .;
LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
*(.dtors)
LONG(0)
__DTOR_END__ = .;
*(.lit)
*(.shdata)
_endtext = .;
} > ram
 
.rodata : {
*(.rodata);
*(.rodata.*)
} > ram
 
/* Section we'll use for storing the program to load into the flash */
.shbss :
{
*(.shbss)
} > ram
.talias :
{
} > ram
.data : {
sdata = .;
_sdata = .;
*(.data)
edata = .;
_edata = .;
} > ram
.bss SIZEOF(.data) + ADDR(.data) :
{
_bss_start = ALIGN(0x8);
*(.bss)
*(COMMON)
_bss_end = .;
}
/* ensure there is enough room for stack */
.stack (NOLOAD): {
. = ALIGN(4);
sstack = . ;
_sstack = . ;
. = . + _min_stack ;
. = ALIGN(4);
stack = . ;
_stack = . ;
estack = . ;
_estack = . ;
} > ram
 
. = . + 0x2000 ;
.userprogram : {
. = ALIGN(4);
userprogram_data = .;
_userprogram_data = .;
*(.userprogram)
end_userprogram_data = .;
_end_userprogram_data = .;
} > ram
 
.stab 0 (NOLOAD) :
{
[ .stab ]
}
.stabstr 0 (NOLOAD) :
{
[ .stabstr ]
}
}
/orpsocv2/sw/Makefile.inc
202,6 → 202,9
%.vmem: %.bin $(UTILS_BIN2VMEM)
$(Q)$(UTILS_BIN2VMEM) $< > $@
 
%.flash16: %.bin $(UTILS_BIN2VMEM)
$(Q)$(UTILS_BIN2VMEM) $< -bpw=2 > $@
 
%.elf: %.c $(VECTORS_OBJ) $(ELF_DEPENDS) $(SUPPORT_LIBS)
$(Q)$(OR32_CC) $< $(VECTORS_OBJ) $(ELF_DEPENDS) $(OR32_CFLAGS) \
$(OR32_LDFLAGS) -o $@
/orpsocv2/sw/lib/Makefile
20,5 → 20,5
$(USER_ELF_BIN): $(USER_ELF)
$(Q)$(OR32_OBJCOPY) -O binary $< $@
$(USER_ELF_VMEM): $(USER_ELF_BIN) $(UTILS_BIN2VMEM)
$(Q)$(UTILS_BIN2VMEM) $< > $@
$(Q)$(UTILS_BIN2VMEM) $< $(USER_ELF_VMEM_GEN_OPTS) > $@
gen-user-elf-vmem: $(USER_ELF_VMEM)
/orpsocv2/sw/drivers/cfi-ctrl/include/cfi_ctrl.h
0,0 → 1,38
/* cfi_ctrl driver header */
 
#define CFI_CTRL_UNLOCKBLOCK_OFFSET 0x04000000
#define CFI_CTRL_ERASEBLOCK_OFFSET 0x08000000
#define CFI_CTRL_REGS_OFFSET 0x0c000000
#define CFI_CTRL_DEVICEIDENT_OFFSET 0x0e000000
#define CFI_CTRL_CFIQUERY_OFFSET 0x0e010000
 
#define CFI_CTRL_SCR_OFFSET (CFI_CTRL_REGS_OFFSET + 0)
#define CFI_CTRL_FSR_OFFSET (CFI_CTRL_REGS_OFFSET + 4)
 
#define CFI_CTRL_SCR_CONTROLLER_BUSY (1 << 0)
#define CFI_CTRL_SCR_CLEAR_FSR (1 << 1)
#define CFI_CTRL_SCR_RESET_DEVICE (1 << 2)
 
/* Flash status register (FSR) bit meanings - from CFI standard */
#define CFI_FSR_DWS (1<<7) /* Device write status. 0 - busy, 1 - ready */
#define CFI_FSR_ERR (1<<6) /* Erase suspend status - N/A here */
#define CFI_FSR_ES (1<<5) /* Erase status. 0 - successful, 1 - fail/seq err. */
#define CFI_FSR_PS (1<<4) /* Program status. 0 - successful, 1 - fail/seq err*/
#define CFI_FSR_VPPS (1<<3) /* VPP status. N/A here */
#define CFI_FSR_PSS (1<<2) /* Program suspend status. N/A here */
#define CFI_FSR_BLS (1<<1) /* Block-locked status */
#define CFI_FSR_BWS (1<<0) /* Buffer-enhanced programming status - N/A here */
 
 
/* Driver function prototypes */
void cfi_ctrl_reset_flash(void);
void cfi_ctrl_clear_status(void);
int cfi_ctrl_busy(void);
unsigned char cfi_ctrl_get_status(void);
void cfi_ctrl_unlock_block(unsigned int addr);
int cfi_ctrl_erase_block(unsigned int addr);
void cfi_ctrl_erase_block_no_wait(unsigned int addr);
int cfi_ctrl_write_short(short data, unsigned int addr);
short cfi_ctrl_read_identifier(unsigned int addr);
short cfi_ctrl_query_info(unsigned int addr);
void cfi_ctrl_enable_data_read(void);
/orpsocv2/sw/drivers/cfi-ctrl/cfi_ctrl.c
0,0 → 1,112
/* Driver functions for cfi_ctrl module which is to control
CFI flash devices.
*/
 
#include "board.h"
#include "cpu-utils.h"
#include "cfi_ctrl.h"
 
void cfi_ctrl_reset_flash(void)
{
//REG32((CFI_CTRL_BASE + CFI_CTRL_SCR_OFFSET)) = CFI_CTRL_SCR_RESET_DEVICE;
// Put in array read mode, like reset would
REG16(CFI_CTRL_BASE) = 0x00ff;
}
 
int cfi_ctrl_busy(void)
{
// return REG32((CFI_CTRL_BASE + CFI_CTRL_SCR_OFFSET)) &
//CFI_CTRL_SCR_CONTROLLER_BUSY;
return 0;
}
 
void cfi_ctrl_clear_status(void)
{
//REG32((CFI_CTRL_BASE + CFI_CTRL_SCR_OFFSET)) = CFI_CTRL_SCR_CLEAR_FSR;
REG16(CFI_CTRL_BASE) = 0x0050;
}
 
unsigned char cfi_ctrl_get_status(void)
{
//return (unsigned char) (REG32((CFI_CTRL_BASE + CFI_CTRL_FSR_OFFSET)) & 0xff);
REG16(CFI_CTRL_BASE) = 0x0070;
return (unsigned char) REG16(CFI_CTRL_BASE);
}
 
void cfi_ctrl_unlock_block(unsigned int addr)
{
//REG32((CFI_CTRL_BASE + CFI_CTRL_UNLOCKBLOCK_OFFSET + addr)) = 0;
REG16(CFI_CTRL_BASE + addr) = 0x0060;
REG16(CFI_CTRL_BASE + addr) = 0x00d0;
}
 
int cfi_ctrl_erase_block(unsigned int addr)
{
cfi_ctrl_clear_status();
 
/* Unlock block first */
cfi_ctrl_unlock_block(addr);
//REG32((CFI_CTRL_BASE + CFI_CTRL_ERASEBLOCK_OFFSET + addr)) = 0;
REG16(CFI_CTRL_BASE + addr) = 0x0020;
REG16(CFI_CTRL_BASE + addr) = 0x00d0;
 
/* Wait for device to be finished erasing */
while(!(cfi_ctrl_get_status() & CFI_FSR_DWS));
 
/* Check if programming was successful */
return !!(cfi_ctrl_get_status() & CFI_FSR_ES);
}
 
void cfi_ctrl_erase_block_no_wait(unsigned int addr)
{
cfi_ctrl_clear_status();
 
/* Unlock block first */
cfi_ctrl_unlock_block(addr);
/* Now erase the block */
REG16(CFI_CTRL_BASE + addr) = 0x0020;
REG16(CFI_CTRL_BASE + addr) = 0x00d0;
// REG32((CFI_CTRL_BASE + CFI_CTRL_ERASEBLOCK_OFFSET + addr)) = 0;
return;
}
 
int cfi_ctrl_write_short(short data, unsigned int addr)
{
 
cfi_ctrl_clear_status();
 
REG16(CFI_CTRL_BASE + addr) = 0x0040;
REG16(CFI_CTRL_BASE + addr) = data;
/* Wait for device to write */
while(!(cfi_ctrl_get_status() & CFI_FSR_DWS));
 
/* Check if programming was successful */
return !!(cfi_ctrl_get_status() & CFI_FSR_PS);
}
 
void cfi_ctrl_enable_data_read(void)
{
REG16(CFI_CTRL_BASE) = 0x00ff;
}
 
short cfi_ctrl_read_identifier(unsigned int addr)
{
//return REG16(CFI_CTRL_BASE + CFI_CTRL_DEVICEIDENT_OFFSET + (addr<<1));
REG16(CFI_CTRL_BASE) = 0x0090;
return REG16(CFI_CTRL_BASE + (addr<<1));
}
 
short cfi_ctrl_query_info(unsigned int addr)
{
REG16(CFI_CTRL_BASE) = 0x0098;
return REG16(CFI_CTRL_BASE + (addr<<1));
}
 
 
/orpsocv2/sw/drivers/cfi-ctrl/Makefile
0,0 → 1,8
SW_ROOT=../..
 
COMPILE_SRCS=cfi_ctrl.c
 
include $(SW_ROOT)/Makefile.inc
 
clean:
$(Q)rm -f *.a *.o
/orpsocv2/boards/xilinx/ml501/bench/verilog/orpsoc_testbench.v
162,7 → 162,19
wire sram_flash_we_n;
wire sram_mode;
`endif
`ifdef CFI_FLASH
wire [15:0] flash_dq_io;
wire [23:0] flash_adr_o;
wire flash_adv_n_o;
wire flash_ce_n_o;
wire flash_clk_o;
wire flash_oe_n_o;
wire flash_rst_n_o;
wire flash_wait_i;
wire flash_we_n_o;
`endif // `ifdef CFI_FLASH
 
orpsoc_top dut
(
`ifdef JTAG_DEBUG
198,7 → 210,18
.sram_mode (sram_mode),
.sram_clk_fb (sram_clk_fb),
.sram_flash_data (sram_flash_data),
`endif
`endif // `ifdef XILINX_SSRAM
`ifdef CFI_FLASH
.flash_dq_io (flash_dq_io),
.flash_adr_o (flash_adr_o),
.flash_adv_n_o (flash_adv_n_o),
.flash_ce_n_o (flash_ce_n_o),
.flash_clk_o (flash_clk_o),
.flash_oe_n_o (flash_oe_n_o),
.flash_rst_n_o (flash_rst_n_o),
.flash_wait_i (flash_wait_i),
.flash_we_n_o (flash_we_n_o),
`endif
`ifdef UART0
.uart0_stx_pad_o (uart0_stx_pad_o),
.uart0_srx_pad_i (uart0_srx_pad_i),
492,7 → 515,16
begin
`ifdef VCD_DELAY
#(`VCD_DELAY);
#(`VCD_DELAY);/*#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);
#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);
#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);
#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);
#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);
#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);
#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);
#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);
#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);#(`VCD_DELAY);
*/
`endif
 
// Delay by x insns
575,7 → 607,36
assign uart0_srx_pad_i = uart0_stx_pad_o;
 
`endif // `ifdef UART0
 
`ifdef CFI_FLASH
wire [35:0] VCC; // Supply Voltage
wire [35:0] VCCQ; // Supply Voltage for I/O Buffers
wire [35:0] VPP; // Optional Supply Voltage for Fast Program & Erase
wire Info; // Activate/Deactivate info device operation
assign Info = 1;
assign VCC = 36'd1700;
assign VCCQ = 36'd1700;
assign VPP = 36'd2000;
 
x28fxxxp30 cfi_flash(flash_adr_o,
flash_dq_io,
flash_we_n_o,
flash_oe_n_o,
flash_ce_n_o,
flash_adv_n_o,
flash_clk_o,
flash_wait_i,
1'b1,
flash_rst_n_o,
VCC,
VCCQ,
VPP,
Info);
`endif // `ifdef CFI_FLASH
endmodule // orpsoc_testbench
 
// Local Variables:
/orpsocv2/boards/xilinx/ml501/rtl/verilog/include/or1200_defines.v
862,7 → 862,7
// 1'b0 - OR1200_EXCEPT_EPH0_P (0x0000_0000)
// 1'b1 - OR1200_EXCEPT_EPH1_P (0xF000_0000)
//
`define OR1200_SR_EPH_DEF 1'b0
`define OR1200_SR_EPH_DEF 1'b1
 
 
//
1814,9 → 1814,12
// comment below. //
// //
///////////////////////////////////////////////////////////////////////////////
// Boot from 0xe0000100
`define OR1200_BOOT_PCREG_DEFAULT 30'h3800003f
`define OR1200_BOOT_ADR 32'he0000100
// Boot from 0xf0000100
`define OR1200_BOOT_PCREG_DEFAULT 30'h3c00003f
`define OR1200_BOOT_ADR 32'hf0000100
//`define OR1200_BOOT_PCREG_DEFAULT 30'h3c00003f
//`define OR1200_BOOT_ADR 32'hf0000100
// Boot from 0x100
//`define OR1200_BOOT_PCREG_DEFAULT 30'h0000003f
//`define OR1200_BOOT_ADR 32'h00000100
/orpsocv2/boards/xilinx/ml501/rtl/verilog/include/orpsoc-defines.v
51,10 → 51,11
`define JTAG_DEBUG
// `define RAM_WB
// `define XILINX_SSRAM
`define CFI_FLASH
`define XILINX_DDR2
`define UART0
`define GPIO0
`define SPI0
// `define SPI0
`define I2C0
`define I2C1
`define ETH0
/orpsocv2/boards/xilinx/ml501/rtl/verilog/include/orpsoc-params.v
80,8 → 80,15
// ROM
parameter wbs_i_rom0_data_width = 32;
parameter wbs_i_rom0_addr_width = 6;
parameter rom0_wb_adr = 4'hf;
parameter rom0_wb_adr = 4'he;
 
// CFI flash
parameter wbs_i_flash_data_width = 32;
parameter wbs_i_flash_addr_width = 32;
parameter wbs_d_flash_data_width = 32;
parameter wbs_d_flash_addr_width = 32;
parameter flash_wb_adr = 4'hf;
 
// MC0 (SDRAM, or other)
parameter wbs_i_mc0_data_width = 32;
parameter wbs_d_mc0_data_width = 32;
94,9 → 101,14
parameter wbm_eth0_addr_width = 32;
 
// Memory sizing for synthesis (small)
parameter internal_sram_mem_span = 32'h0080_0000;
parameter internal_sram_adr_width_for_span = 23;
//parameter internal_sram_mem_span = 32'h0200_0000; /* 32MB */
//parameter internal_sram_adr_width_for_span = 25;
//parameter internal_sram_mem_span = 32'h0080_0000; /* 8MB */
//parameter internal_sram_adr_width_for_span = 23;
parameter internal_sram_mem_span = 32'h0001_0000; /* 64KB */
parameter internal_sram_adr_width_for_span = 17;
 
 
//////////////////////////////////////////////////////
// //
// Wishbone bus parameters //
119,8 → 131,9
///////////////////////////
parameter ibus_arb_addr_match_width = 4;
// Slave addresses
parameter ibus_arb_slave0_adr = rom0_wb_adr; // FLASH ROM
parameter ibus_arb_slave0_adr = rom0_wb_adr; // ROM
parameter ibus_arb_slave1_adr = 4'h0; // Main memory (SDRAM/FPGA SRAM)
parameter ibus_arb_slave2_adr = flash_wb_adr; // Flash
 
///////////////////////////
// //
133,6 → 146,7
// Slave addresses
parameter dbus_arb_slave0_adr = 4'h0; // Main memory (SDRAM/FPGA SRAM)
parameter dbus_arb_slave1_adr = eth0_wb_adr; // Ethernet 0
parameter dbus_arb_slave2_adr = flash_wb_adr; // Flash
 
///////////////////////////////
// //
/orpsocv2/boards/xilinx/ml501/rtl/verilog/orpsoc_top/orpsoc_top.v
49,6 → 49,11
sram_clk, sram_clk_fb, sram_flash_addr, sram_flash_data,
sram_cen, sram_flash_oe_n, sram_flash_we_n, sram_bw,
sram_adv_ld_n, sram_mode,
`endif
`ifdef CFI_FLASH
flash_dq_io, flash_adr_o, flash_adv_n_o, flash_ce_n_o,
flash_clk_o, flash_oe_n_o, flash_rst_n_o, flash_wait_i,
flash_we_n_o,
`endif
`ifdef UART0
uart0_srx_pad_i, uart0_stx_pad_o,
124,7 → 129,18
output [3:0] sram_bw;
output sram_adv_ld_n;
output sram_mode;
`endif
`endif // `ifdef XILINX_SSRAM
`ifdef CFI_FLASH
inout [15:0] flash_dq_io;
output [23:0] flash_adr_o;
output flash_adv_n_o;
output flash_ce_n_o;
output flash_clk_o;
output flash_oe_n_o;
output flash_rst_n_o;
input flash_wait_i;
output flash_we_n_o;
`endif
`ifdef UART0
input uart0_srx_pad_i;
output uart0_stx_pad_o;
308,6 → 324,20
wire wbs_i_mc0_ack_o;
wire wbs_i_mc0_err_o;
wire wbs_i_mc0_rty_o;
 
// flash instruction bus wires
wire [31:0] wbs_i_flash_adr_i;
wire [wbs_i_flash_data_width-1:0] wbs_i_flash_dat_i;
wire [3:0] wbs_i_flash_sel_i;
wire wbs_i_flash_we_i;
wire wbs_i_flash_cyc_i;
wire wbs_i_flash_stb_i;
wire [2:0] wbs_i_flash_cti_i;
wire [1:0] wbs_i_flash_bte_i;
wire [wbs_i_flash_data_width-1:0] wbs_i_flash_dat_o;
wire wbs_i_flash_ack_o;
wire wbs_i_flash_err_o;
wire wbs_i_flash_rty_o;
// Data bus slave wires //
423,6 → 453,20
wire wbm_eth0_err_i;
wire wbm_eth0_rty_i;
 
// flash slave wires
wire [31:0] wbs_d_flash_adr_i;
wire [wbs_d_flash_data_width-1:0] wbs_d_flash_dat_i;
wire [3:0] wbs_d_flash_sel_i;
wire wbs_d_flash_we_i;
wire wbs_d_flash_cyc_i;
wire wbs_d_flash_stb_i;
wire [2:0] wbs_d_flash_cti_i;
wire [1:0] wbs_d_flash_bte_i;
wire [wbs_d_flash_data_width-1:0] wbs_d_flash_dat_o;
wire wbs_d_flash_ack_o;
wire wbs_d_flash_err_o;
wire wbs_d_flash_rty_o;
 
 
//
479,6 → 523,22
.wbs1_err_o (wbs_i_mc0_err_o),
.wbs1_rty_o (wbs_i_mc0_rty_o),
 
// Slave 2
// Inputs to slave from arbiter
.wbs2_adr_i (wbs_i_flash_adr_i),
.wbs2_dat_i (wbs_i_flash_dat_i),
.wbs2_sel_i (wbs_i_flash_sel_i),
.wbs2_we_i (wbs_i_flash_we_i),
.wbs2_cyc_i (wbs_i_flash_cyc_i),
.wbs2_stb_i (wbs_i_flash_stb_i),
.wbs2_cti_i (wbs_i_flash_cti_i),
.wbs2_bte_i (wbs_i_flash_bte_i),
// Outputs from slave to arbiter
.wbs2_dat_o (wbs_i_flash_dat_o),
.wbs2_ack_o (wbs_i_flash_ack_o),
.wbs2_err_o (wbs_i_flash_err_o),
.wbs2_rty_o (wbs_i_flash_rty_o),
 
// Clock, reset inputs
.wb_clk (wb_clk),
.wb_rst (wb_rst));
485,8 → 545,9
 
defparam arbiter_ibus0.wb_addr_match_width = ibus_arb_addr_match_width;
 
defparam arbiter_ibus0.slave0_adr = ibus_arb_slave0_adr; // FLASH ROM
defparam arbiter_ibus0.slave1_adr = ibus_arb_slave1_adr; // Main memory
defparam arbiter_ibus0.slave0_adr = ibus_arb_slave0_adr; // flash ROM
defparam arbiter_ibus0.slave1_adr = ibus_arb_slave1_adr; // main memory
defparam arbiter_ibus0.slave2_adr = ibus_arb_slave2_adr; // CFI flash
 
//
// Wishbone data bus arbiter
553,19 → 614,32
.wbs1_ack_o (wbs_d_eth0_ack_o),
.wbs1_err_o (wbs_d_eth0_err_o),
.wbs1_rty_o (wbs_d_eth0_rty_o),
 
.wbs2_adr_i (wbs_d_flash_adr_i),
.wbs2_dat_i (wbs_d_flash_dat_i),
.wbs2_sel_i (wbs_d_flash_sel_i),
.wbs2_we_i (wbs_d_flash_we_i),
.wbs2_cyc_i (wbs_d_flash_cyc_i),
.wbs2_stb_i (wbs_d_flash_stb_i),
.wbs2_cti_i (wbs_d_flash_cti_i),
.wbs2_bte_i (wbs_d_flash_bte_i),
.wbs2_dat_o (wbs_d_flash_dat_o),
.wbs2_ack_o (wbs_d_flash_ack_o),
.wbs2_err_o (wbs_d_flash_err_o),
.wbs2_rty_o (wbs_d_flash_rty_o),
.wbs2_adr_i (wbm_b_d_adr_o),
.wbs2_dat_i (wbm_b_d_dat_o),
.wbs2_sel_i (wbm_b_d_sel_o),
.wbs2_we_i (wbm_b_d_we_o),
.wbs2_cyc_i (wbm_b_d_cyc_o),
.wbs2_stb_i (wbm_b_d_stb_o),
.wbs2_cti_i (wbm_b_d_cti_o),
.wbs2_bte_i (wbm_b_d_bte_o),
.wbs2_dat_o (wbm_b_d_dat_i),
.wbs2_ack_o (wbm_b_d_ack_i),
.wbs2_err_o (wbm_b_d_err_i),
.wbs2_rty_o (wbm_b_d_rty_i),
.wbs3_adr_i (wbm_b_d_adr_o),
.wbs3_dat_i (wbm_b_d_dat_o),
.wbs3_sel_i (wbm_b_d_sel_o),
.wbs3_we_i (wbm_b_d_we_o),
.wbs3_cyc_i (wbm_b_d_cyc_o),
.wbs3_stb_i (wbm_b_d_stb_o),
.wbs3_cti_i (wbm_b_d_cti_o),
.wbs3_bte_i (wbm_b_d_bte_o),
.wbs3_dat_o (wbm_b_d_dat_i),
.wbs3_ack_o (wbm_b_d_ack_i),
.wbs3_err_o (wbm_b_d_err_i),
.wbs3_rty_o (wbm_b_d_rty_i),
 
// Clock, reset inputs
.wb_clk (wb_clk),
576,6 → 650,7
defparam arbiter_dbus0.wb_num_slaves = dbus_arb_wb_num_slaves;
defparam arbiter_dbus0.slave0_adr = dbus_arb_slave0_adr;
defparam arbiter_dbus0.slave1_adr = dbus_arb_slave1_adr;
defparam arbiter_dbus0.slave2_adr = dbus_arb_slave2_adr;
 
//
// Wishbone byte-wide bus arbiter
1072,12 → 1147,128
defparam ram_wb0.aw = wb_aw;
defparam ram_wb0.dw = wb_dw;
defparam ram_wb0.mem_size_bytes = (8192*1024); // 8MB
defparam ram_wb0.mem_adr_width = 23; // log2(8192*1024)
defparam ram_wb0.mem_size_bytes = internal_sram_mem_span;
defparam ram_wb0.mem_adr_width = internal_sram_adr_width_for_span;
////////////////////////////////////////////////////////////////////////
`endif // `ifdef RAM_WB
 
`ifdef CFI_FLASH
 
/* Lighweight arbiter between instruction and data busses going
into the CFI controller */
 
wire [31:0] flash_wb_adr_i;
wire [31:0] flash_wb_dat_i;
wire [31:0] flash_wb_dat_o;
wire [3:0] flash_wb_sel_i;
wire flash_wb_cyc_i;
wire flash_wb_stb_i;
wire flash_wb_we_i;
wire flash_wb_ack_o;
 
reg [1:0] flash_mst_sel;
reg [9:0] flash_arb_timeout;
wire flash_arb_reset;
always @(posedge wb_clk)
if (wb_rst)
flash_mst_sel <= 0;
else begin
if (flash_mst_sel==2'b00) begin
/* wait for new access from masters. data takes priority */
if (wbs_d_flash_cyc_i & wbs_d_flash_stb_i)
flash_mst_sel[1] <= 1;
else if (wbs_i_flash_cyc_i & wbs_i_flash_stb_i)
flash_mst_sel[0] <= 1;
end
else begin
if (flash_wb_ack_o | flash_arb_reset)
flash_mst_sel <= 0;
end // else: !if(flash_mst_sel==2'b00)
end // else: !if(wb_rst)
assign flash_wb_adr_i = flash_mst_sel[0] ? wbs_i_flash_adr_i :
wbs_d_flash_adr_i;
assign flash_wb_dat_i = flash_mst_sel[0] ? wbs_i_flash_dat_i :
wbs_d_flash_dat_i;
assign flash_wb_stb_i = flash_mst_sel[0] ? wbs_i_flash_stb_i :
flash_mst_sel[1] ? wbs_d_flash_stb_i : 0;
assign flash_wb_cyc_i = flash_mst_sel[0] ? wbs_i_flash_cyc_i :
flash_mst_sel[1] ? wbs_d_flash_cyc_i : 0;
assign flash_wb_we_i = flash_mst_sel[0] ? wbs_i_flash_we_i :
wbs_d_flash_we_i;
assign flash_wb_sel_i = flash_mst_sel[0] ? wbs_i_flash_sel_i :
wbs_d_flash_sel_i;
 
assign wbs_i_flash_dat_o = flash_wb_dat_o;
assign wbs_d_flash_dat_o = flash_wb_dat_o;
assign wbs_i_flash_ack_o = flash_wb_ack_o & flash_mst_sel[0];
assign wbs_d_flash_ack_o = flash_wb_ack_o & flash_mst_sel[1];
assign wbs_i_flash_err_o = flash_arb_reset & flash_mst_sel[0];
assign wbs_i_flash_rty_o = 0;
assign wbs_d_flash_err_o = flash_arb_reset & flash_mst_sel[1];
assign wbs_d_flash_rty_o = 0;
 
always @(posedge wb_clk)
if (wb_rst)
flash_arb_timeout <= 0;
else if (flash_wb_ack_o)
flash_arb_timeout <= 0;
else if (flash_wb_stb_i & flash_wb_cyc_i)
flash_arb_timeout <= flash_arb_timeout + 1;
 
assign flash_arb_reset = (&flash_arb_timeout);
cfi_ctrl
/* Use the simple flash interface */
#(.cfi_engine("DISABLED"))
cfi_ctrl0
(
.wb_clk_i(wb_clk),
.wb_rst_i(wb_rst | flash_arb_reset),
 
.wb_adr_i(flash_wb_adr_i),
.wb_dat_i(flash_wb_dat_i),
.wb_stb_i(flash_wb_stb_i),
.wb_cyc_i(flash_wb_cyc_i),
.wb_we_i (flash_wb_we_i ),
.wb_sel_i(flash_wb_sel_i),
.wb_dat_o(flash_wb_dat_o),
.wb_ack_o(flash_wb_ack_o),
.wb_err_o(),
.wb_rty_o(),
.flash_dq_io(flash_dq_io),
.flash_adr_o(flash_adr_o),
.flash_adv_n_o(flash_adv_n_o),
.flash_ce_n_o(flash_ce_n_o),
.flash_clk_o(flash_clk_o),
.flash_oe_n_o(flash_oe_n_o),
.flash_rst_n_o(flash_rst_n_o),
.flash_wait_i(flash_wait_i),
.flash_we_n_o(flash_we_n_o),
.flash_wp_n_o()
);
 
`else
 
assign wbs_i_flash_dat_o = 0;
assign wbs_i_flash_ack_o = 0;
assign wbs_i_flash_err_o = 0;
assign wbs_i_flash_rty_o = 0;
 
assign wbs_d_flash_dat_o = 0;
assign wbs_d_flash_ack_o = 0;
assign wbs_d_flash_err_o = 0;
assign wbs_d_flash_rty_o = 0;
`endif // `ifdef CFI_FLASH
`ifdef ETH0
 
//
/orpsocv2/boards/xilinx/ml501/rtl/verilog/arbiter/arbiter_dbus.v
117,7 → 117,7
wbs2_ack_o,
wbs2_err_o,
wbs2_rty_o,
/*
 
// Slave four
// Wishbone Slave interface
wbs3_adr_i,
133,7 → 133,7
wbs3_ack_o,
wbs3_err_o,
wbs3_rty_o,
 
/*
// Slave five
// Wishbone Slave interface
wbs4_adr_i,
450,7 → 450,7
input wbs2_ack_o;
input wbs2_err_o;
input wbs2_rty_o;
/*
 
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs3_adr_i;
465,7 → 465,7
input wbs3_ack_o;
input wbs3_err_o;
input wbs3_rty_o;
 
/*
// Wishbone Slave interface
output [wb_adr_width-1:0] wbs4_adr_i;
870,14 → 870,15
//
// Slave selects
//
assign wb_slave_sel[0] = wbm_adr_o[31:28] == slave0_adr | wbm_adr_o[31:28] == 4'hf; // Special case, point all reads to ROM address to here
assign wb_slave_sel[0] = wbm_adr_o[31:28] == slave0_adr;
assign wb_slave_sel[1] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave1_adr;
assign wb_slave_sel[2] = wbm_adr_o[31:28] == slave2_adr;
// Auto select last slave when others are not selected
assign wb_slave_sel[2] = !(wb_slave_sel_r[0] | wb_slave_sel_r[1]);
assign wb_slave_sel[3] = !(wb_slave_sel_r[0] | wb_slave_sel_r[1]
| wb_slave_sel_r[2]);
 
/*
assign wb_slave_sel[2] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave2_adr;
/*
assign wb_slave_sel[3] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave3_adr;
assign wb_slave_sel[4] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave4_adr;
assign wb_slave_sel[5] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] == slave5_adr;
941,7 → 942,6
assign wbs_err_o_mux_i[0] = wbs0_err_o & wb_slave_sel_r[0];
assign wbs_rty_o_mux_i[0] = wbs0_rty_o & wb_slave_sel_r[0];
 
 
// Slave 1 inputs
assign wbs1_adr_i = wbm_adr_o;
assign wbs1_dat_i = wbm_dat_o;
956,7 → 956,6
assign wbs_err_o_mux_i[1] = wbs1_err_o & wb_slave_sel_r[1];
assign wbs_rty_o_mux_i[1] = wbs1_rty_o & wb_slave_sel_r[1];
 
 
// Slave 2 inputs
assign wbs2_adr_i = wbm_adr_o;
assign wbs2_dat_i = wbm_dat_o;
970,7 → 969,6
assign wbs_ack_o_mux_i[2] = wbs2_ack_o & wb_slave_sel_r[2];
assign wbs_err_o_mux_i[2] = wbs2_err_o & wb_slave_sel_r[2];
assign wbs_rty_o_mux_i[2] = wbs2_rty_o & wb_slave_sel_r[2];
/*
 
// Slave 3 inputs
assign wbs3_adr_i = wbm_adr_o;
985,7 → 983,7
assign wbs_ack_o_mux_i[3] = wbs3_ack_o & wb_slave_sel_r[3];
assign wbs_err_o_mux_i[3] = wbs3_err_o & wb_slave_sel_r[3];
assign wbs_rty_o_mux_i[3] = wbs3_rty_o & wb_slave_sel_r[3];
 
/*
// Slave 4 inputs
assign wbs4_adr_i = wbm_adr_o;
assign wbs4_dat_i = wbm_dat_o;
1188,8 → 1186,8
assign wbm_dat_i = wb_slave_sel_r[0] ? wbs_dat_o_mux_i[0] :
wb_slave_sel_r[1] ? wbs_dat_o_mux_i[1] :
wb_slave_sel_r[2] ? wbs_dat_o_mux_i[2] :
/* wb_slave_sel_r[3] ? wbs_dat_o_mux_i[3] :
wb_slave_sel_r[4] ? wbs_dat_o_mux_i[4] :
wb_slave_sel_r[3] ? wbs_dat_o_mux_i[3] :
/* wb_slave_sel_r[4] ? wbs_dat_o_mux_i[4] :
wb_slave_sel_r[5] ? wbs_dat_o_mux_i[5] :
wb_slave_sel_r[6] ? wbs_dat_o_mux_i[6] :
wb_slave_sel_r[7] ? wbs_dat_o_mux_i[7] :
1208,8 → 1206,8
// Master out acks, or together
assign wbm_ack_i = wbs_ack_o_mux_i[0] |
wbs_ack_o_mux_i[1] |
wbs_ack_o_mux_i[2] /*|
wbs_ack_o_mux_i[3] |
wbs_ack_o_mux_i[2] |
wbs_ack_o_mux_i[3] /*|
wbs_ack_o_mux_i[4] |
wbs_ack_o_mux_i[5] |
wbs_ack_o_mux_i[6] |
1228,8 → 1226,8
 
assign wbm_err_i = wbs_err_o_mux_i[0] |
wbs_err_o_mux_i[1] |
wbs_err_o_mux_i[2] |/*
wbs_err_o_mux_i[3] |
wbs_err_o_mux_i[2] |
wbs_err_o_mux_i[3] |/*
wbs_err_o_mux_i[4] |
wbs_err_o_mux_i[5] |
wbs_err_o_mux_i[6] |
1248,8 → 1246,8
 
assign wbm_rty_i = wbs_rty_o_mux_i[0] |
wbs_rty_o_mux_i[1] |
wbs_rty_o_mux_i[2] /*|
wbs_rty_o_mux_i[3] |
wbs_rty_o_mux_i[2] |
wbs_rty_o_mux_i[3] /*|
wbs_rty_o_mux_i[4] |
wbs_rty_o_mux_i[5] |
wbs_rty_o_mux_i[6] |
/orpsocv2/boards/xilinx/ml501/rtl/verilog/arbiter/arbiter_ibus.v
10,7 → 10,7
/// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG ////
//// Copyright (C) 2009, 2010, 2011 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
87,6 → 87,24
wbs1_err_o,
wbs1_rty_o,
 
 
// Slave three
// Wishbone Slave interface
wbs2_adr_i,
wbs2_dat_i,
wbs2_sel_i,
wbs2_we_i,
wbs2_cyc_i,
wbs2_stb_i,
wbs2_cti_i,
wbs2_bte_i,
wbs2_dat_o,
wbs2_ack_o,
wbs2_err_o,
wbs2_rty_o,
wb_clk,
wb_rst
);
97,8 → 115,9
 
parameter wb_addr_match_width = 8;
 
parameter slave0_adr = 8'hf0; // FLASH ROM
parameter slave0_adr = 8'he0; // FLASH ROM
parameter slave1_adr = 8'h00; // Main memory (SDRAM/FPGA SRAM)
parameter slave2_adr = 8'hf0; // External flash
 
`define WB_ARB_ADDR_MATCH_SEL wb_adr_width-1:wb_adr_width-wb_addr_match_width
148,8 → 167,24
input wbs1_err_o;
input wbs1_rty_o;
 
wire [1:0] slave_sel; // One bit per slave
 
// WB Slave 2
output [wb_adr_width-1:0] wbs2_adr_i;
output [wb_dat_width-1:0] wbs2_dat_i;
output [3:0] wbs2_sel_i;
output wbs2_we_i;
output wbs2_cyc_i;
output wbs2_stb_i;
output [2:0] wbs2_cti_i;
output [1:0] wbs2_bte_i;
input [wb_dat_width-1:0] wbs2_dat_o;
input wbs2_ack_o;
input wbs2_err_o;
input wbs2_rty_o;
 
wire [2:0] slave_sel; // One bit per slave
 
reg watchdog_err;
`ifdef ARBITER_IBUS_WATCHDOG
212,6 → 247,10
reg wbs1_ack_o_r;
reg wbs1_err_o_r;
reg wbs1_rty_o_r;
reg [wb_dat_width-1:0] wbs2_dat_o_r;
reg wbs2_ack_o_r;
reg wbs2_err_o_r;
reg wbs2_rty_o_r;
 
wire wbm_ack_i_pre_reg;
 
238,6 → 277,10
wbs1_ack_o_r <= wbs1_ack_o;
wbs1_err_o_r <= wbs1_err_o;
wbs1_rty_o_r <= wbs1_rty_o;
wbs2_dat_o_r <= wbs2_dat_o;
wbs2_ack_o_r <= wbs2_ack_o;
wbs2_err_o_r <= wbs2_err_o;
wbs2_rty_o_r <= wbs2_rty_o;
end // always @ (posedge wb_clk)
 
248,6 → 291,9
assign slave_sel[1] = wbm_adr_o_r[`WB_ARB_ADDR_MATCH_SEL] ==
slave1_adr;
 
assign slave_sel[2] = wbm_adr_o_r[`WB_ARB_ADDR_MATCH_SEL] ==
slave2_adr;
 
// Slave out assigns
assign wbs0_adr_i = wbm_adr_o_r;
assign wbs0_dat_i = wbm_dat_o_r;
267,25 → 313,39
assign wbs1_cyc_i = wbm_cyc_o_r & slave_sel[1];
assign wbs1_stb_i = wbm_stb_o_r & slave_sel[1];
 
assign wbs2_adr_i = wbm_adr_o_r;
assign wbs2_dat_i = wbm_dat_o_r;
assign wbs2_we_i = wbm_dat_o_r;
assign wbs2_sel_i = wbm_sel_o_r;
assign wbs2_cti_i = wbm_cti_o_r;
assign wbs2_bte_i = wbm_bte_o_r;
assign wbs2_cyc_i = wbm_cyc_o_r & slave_sel[1];
assign wbs2_stb_i = wbm_stb_o_r & slave_sel[1];
 
// Master out assigns
// Don't care about none selected...
assign wbm_dat_i = slave_sel[1] ? wbs1_dat_o_r :
assign wbm_dat_i = slave_sel[2] ? wbs2_dat_o_r :
slave_sel[1] ? wbs1_dat_o_r :
wbs0_dat_o_r ;
assign wbm_ack_i = (slave_sel[0] & wbs0_ack_o_r) |
(slave_sel[1] & wbs1_ack_o_r)
;
(slave_sel[1] & wbs1_ack_o_r) |
(slave_sel[2] & wbs2_ack_o_r);
assign wbm_err_i = (slave_sel[0] & wbs0_err_o_r) |
(slave_sel[1] & wbs1_err_o_r) |
(slave_sel[2] & wbs2_err_o_r) |
watchdog_err;
assign wbm_rty_i = (slave_sel[0] & wbs0_rty_o_r) |
(slave_sel[1] & wbs1_rty_o_r);
(slave_sel[1] & wbs1_rty_o_r) |
(slave_sel[2] & wbs2_rty_o_r);
 
// Non-registered ack
assign wbm_ack_i_pre_reg = (slave_sel[0] & wbs0_ack_o) |
(slave_sel[1] & wbs1_ack_o);
(slave_sel[1] & wbs1_ack_o) |
(slave_sel[2] & wbs2_ack_o);
`else // !`ifdef ARBITER_IBUS_REGISTERING
 
296,6 → 356,10
assign slave_sel[1] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] ==
slave1_adr;
 
assign slave_sel[2] = wbm_adr_o[`WB_ARB_ADDR_MATCH_SEL] ==
slave2_adr;
 
// Slave out assigns
assign wbs0_adr_i = wbm_adr_o;
assign wbs0_dat_i = wbm_dat_o;
315,21 → 379,34
assign wbs1_cyc_i = wbm_cyc_o & slave_sel[1];
assign wbs1_stb_i = wbm_stb_o & slave_sel[1];
 
assign wbs2_adr_i = wbm_adr_o;
assign wbs2_dat_i = wbm_dat_o;
assign wbs2_we_i = wbm_we_o;
assign wbs2_sel_i = wbm_sel_o;
assign wbs2_cti_i = wbm_cti_o;
assign wbs2_bte_i = wbm_bte_o;
assign wbs2_cyc_i = wbm_cyc_o & slave_sel[2];
assign wbs2_stb_i = wbm_stb_o & slave_sel[2];
 
// Master out assigns
// Don't care about none selected...
assign wbm_dat_i = slave_sel[1] ? wbs1_dat_o :
assign wbm_dat_i = slave_sel[2] ? wbs2_dat_o :
slave_sel[1] ? wbs1_dat_o :
wbs0_dat_o ;
assign wbm_ack_i = (slave_sel[0] & wbs0_ack_o) |
(slave_sel[1] & wbs1_ack_o);
(slave_sel[1] & wbs1_ack_o) |
(slave_sel[2] & wbs2_ack_o);
assign wbm_err_i = (slave_sel[0] & wbs0_err_o) |
(slave_sel[1] & wbs1_err_o) |
(slave_sel[2] & wbs2_err_o) |
watchdog_err;
assign wbm_rty_i = (slave_sel[0] & wbs0_rty_o) |
(slave_sel[1] & wbs1_rty_o);
(slave_sel[1] & wbs1_rty_o) |
(slave_sel[2] & wbs2_rty_o);
 
`endif
/orpsocv2/boards/xilinx/ml501/backend/par/bin/ml501.ucf
272,8 → 272,8
## # IO Pad Locations Constraints for SPI memory
## #------------------------------------------------------------------------------
 
NET spi0_mosi_o LOC = AA9 | IOSTANDARD = LVCMOS33 | DRIVE = 6 | SLEW = FAST | TIG;
NET spi0_ss_o<0> LOC = AC14 | IOSTANDARD = LVCMOS33 | DRIVE = 6 | SLEW = FAST | TIG;
#NET spi0_mosi_o LOC = AA9 | IOSTANDARD = LVCMOS33 | DRIVE = 6 | SLEW = FAST | TIG;
#NET spi0_ss_o<0> LOC = AC14 | IOSTANDARD = LVCMOS33 | DRIVE = 6 | SLEW = FAST | TIG;
# These go through the STARTUP_VIRTEX5 block - don't worry about assigning them
# here.
#NET spi0_miso_i LOC = K11 | IOSTANDARD = LVCMOS33 | DRIVE = 6 | SLEW = FAST | TIG;
842,6 → 842,66
#NET sram_mode LOC = AC23 | IOSTANDARD = LVDCI_33;
# NET flash_audio_reset_n LOC = AD10 | IOSTANDARD = LVCMOS33;
 
 
## #------------------------------------------------------------------------------
## # IO Pad Location Constraints / Properties for CFI Flash (shared with SRAM)
## #------------------------------------------------------------------------------
NET flash_adr_o<23> LOC = Y10;
NET flash_adr_o<22> LOC = Y11;
NET flash_adr_o<21> LOC = AA17;
NET flash_adr_o<20> LOC = AB17;
NET flash_adr_o<19> LOC = G14;
NET flash_adr_o<18> LOC = F13;
NET flash_adr_o<17> LOC = H14;
NET flash_adr_o<16> LOC = H13;
NET flash_adr_o<15> LOC = F15;
NET flash_adr_o<14> LOC = G15;
NET flash_adr_o<13> LOC = G12;
NET flash_adr_o<12> LOC = H12;
NET flash_adr_o<11> LOC = G16;
NET flash_adr_o<10> LOC = H16;
NET flash_adr_o<9> LOC = H11;
NET flash_adr_o<8> LOC = G11;
NET flash_adr_o<7> LOC = H17;
NET flash_adr_o<6> LOC = G17;
NET flash_adr_o<5> LOC = G10;
NET flash_adr_o<4> LOC = G9;
NET flash_adr_o<3> LOC = G19;
NET flash_adr_o<2> LOC = H18;
NET flash_adr_o<1> LOC = H9;
NET flash_adr_o<0> LOC = H8;
NET flash_adr_o<*> IOSTANDARD = LVCMOS33;
NET flash_adr_o<*> SLEW = FAST;
NET flash_adr_o<*> DRIVE = 8;
 
 
NET flash_dq_io<15> LOC = AD18 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
NET flash_dq_io<14> LOC = AC18 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
NET flash_dq_io<13> LOC = AB10 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
NET flash_dq_io<12> LOC = AB9 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
NET flash_dq_io<11> LOC = AC17 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
NET flash_dq_io<10> LOC = AC16 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
NET flash_dq_io<9> LOC = AC8 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
NET flash_dq_io<8> LOC = AC9 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
NET flash_dq_io<7> LOC = Y12 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
NET flash_dq_io<6> LOC = Y13 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
NET flash_dq_io<5> LOC = AA15 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
NET flash_dq_io<4> LOC = AB14 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
NET flash_dq_io<3> LOC = AA12 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
NET flash_dq_io<2> LOC = AB11 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
NET flash_dq_io<1> LOC = AA13 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
NET flash_dq_io<0> LOC = AA14 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
 
NET flash_dq_io<*> PULLDOWN;
 
NET flash_adv_n_o LOC = AA20 | IOSTANDARD = LVCMOS33;
NET flash_oe_n_o LOC = AA9 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
NET flash_we_n_o LOC = AB15 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
NET flash_ce_n_o LOC = AA10 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
NET flash_clk_o LOC = AB19 | IOSTANDARD = LVCMOS33 | DRIVE = 12 | SLEW = FAST;
NET flash_wait_i LOC = AA19 | IOSTANDARD = LVCMOS33;
NET flash_rst_n_o LOC = AD10 | IOSTANDARD = LVCMOS33;
 
#------------------------------------------------------------------------------
# IO Pad Location Constraints / Properties for TFT VGA LCD Controller
#------------------------------------------------------------------------------
/orpsocv2/boards/xilinx/ml501/backend/par/bin/Makefile
48,8 → 48,12
XILINX_MAP_FLAGS=-logic_opt off
XILINX_AREA_TARGET = speed
TIMING_REPORT_OPTIONS = -u 1000 -e 1000
#
# Board programming generation settings
#
SPI_FLASH_SIZE_KBYTES ?=2048
SPI_BOOTLOADER_SW_OFFSET_HEX ?=1c0000
PLATFORMFLASH_PART ?= xcf32p
 
print-config:
$(Q)echo; echo "\t### Backend make configuration ###"; echo
69,9 → 73,12
PCF_FILE=$(DESIGN_NAME).pcf
BIT_FILE=$(DESIGN_NAME).bit
BIT_FILE_FOR_SPI=$(DESIGN_NAME)_spiboot.bit
BIT_FILE_FOR_PLATFORMFLASH=$(DESIGN_NAME)_platformflash.bit
BATCH_FILE=$(DESIGN_NAME).batch
MCS_FILE=$(DESIGN_NAME).mcs
SPI_MCS_FILE=$(DESIGN_NAME)_spi.mcs
PLATFORMFLASH_MCS_FILE=$(DESIGN_NAME)_platformflash.mcs
 
 
$(NGC_FILE):
$(Q)$(MAKE) -C $(BOARD_SYN_RUN_DIR) $(DESIGN_NAME).ngc
 
102,18 → 109,27
@echo; echo "\t#### Generating .bit file for SPI load ####";
$(Q)bitgen -w $(XILINX_FLAGS) -g StartUpClk:CClk $< $@
 
$(BIT_FILE_FOR_PLATFORMFLASH): $(PARRED_NCD)
@echo; echo "\t#### Generating .bit file for platform flash load ####";
$(Q)bitgen -w $(XILINX_FLAGS) -g StartUpClk:CClk $< $@
 
# Generate MCS with bootloader specified by user, if BOOTLOADER_BIN defined.
ifeq ($(BOOTLOADER_BIN),)
$(MCS_FILE): $(BIT_FILE_FOR_SPI)
$(SPI_MCS_FILE): $(BIT_FILE_FOR_SPI)
@echo; echo "\t#### Generating .mcs file for SPI load ####";
$(Q)promgen -spi -p mcs -w -o $@ -s $(SPI_FLASH_SIZE_KBYTES) -u 0 $<
else
$(MCS_FILE): $(BIT_FILE_FOR_SPI)
$(SPI_MCS_FILE): $(BIT_FILE_FOR_SPI)
@echo; echo "\t#### Generating .mcs file with bootloader for SPI load ####";
$(Q)promgen -spi -p mcs -w -o $@ -s $(SPI_FLASH_SIZE_KBYTES) -u 0 $< \
-data_file up $(SPI_BOOTLOADER_SW_OFFSET_HEX) $(BOOTLOADER_BIN)
endif
 
$(PLATFORMFLASH_MCS_FILE): $(BIT_FILE_FOR_PLATFORMFLASH)
@echo; echo "\t#### Generating .mcs file for platform flash load ####";
$(Q)promgen -p mcs -w -o $@ -x $(PLATFORMFLASH_PART) -data_width 16 \
-u 0 $<
 
#this target downloads the bitstream to the target fpga
download: $(BIT_FILE) $(BATCH_FILE)
$(Q)impact -batch $(BATCH_FILE)
/orpsocv2/boards/xilinx/ml501/sw/board/include/board.h
11,8 → 11,8
// file, which is compiled and converted into Verilog for inclusion at
// synthesis time. See bootloader/bootloader.S for details on each option.
#ifndef PRELOAD_RAM
#define BOOTROM_SPI_FLASH
//#define BOOTROM_GOTO_RESET
//#define BOOTROM_SPI_FLASH
#define BOOTROM_GOTO_RESET
//#define BOOTROM_LOOP_AT_ZERO
//#define BOOTROM_LOOP_IN_ROM
#else
63,8 → 63,11
//
#define TICKS_PER_SEC 100
 
//
// CFI flash controller base
//
#define CFI_CTRL_BASE 0xf0000000
 
 
//
// UART driver configuration
//
/orpsocv2/boards/xilinx/ml501/syn/xst/bin/Makefile
70,7 → 70,7
OPT_LEVEL ?=2
 
XILINX_FLAGS ?=-intstyle silent
XILINX_XST_FLAGS ?= -power NO -glob_opt AllClockNets -write_timing_constraints NO -cross_clock_analysis NO -slice_utilization_ratio 100 -bram_utilization_ratio 100 -dsp_utilization_ratio 100 -safe_implementation No -fsm_style lut -ram_extract Yes -ram_style Auto -rom_extract Yes -rom_style Auto -auto_bram_packing NO -mux_extract YES -mux_style Auto -decoder_extract YES -priority_extract YES -shreg_extract YES -shift_extract YES -xor_collapse YES -resource_sharing YES -async_to_sync NO -use_dsp48 auto -iobuf YES -max_fanout 100000 -bufg 32 -register_duplication YES -equivalent_register_removal YES -register_balancing No -slice_packing YES -optimize_primitives NO -use_clock_enable Auto -use_sync_set Auto -use_sync_reset Auto -iob Auto -slice_utilization_ratio_maxmargin 5
XILINX_XST_FLAGS ?= -power NO -glob_opt AllClockNets -write_timing_constraints NO -cross_clock_analysis NO -slice_utilization_ratio 100 -bram_utilization_ratio 100 -dsp_utilization_ratio 100 -safe_implementation No -fsm_style lut -ram_extract Yes -ram_style Auto -rom_extract Yes -rom_style Auto -auto_bram_packing NO -mux_extract YES -mux_style Auto -decoder_extract YES -priority_extract YES -shreg_extract YES -shift_extract YES -xor_collapse YES -resource_sharing YES -async_to_sync NO -use_dsp48 auto -iobuf YES -max_fanout 100000 -bufg 32 -register_duplication YES -equivalent_register_removal YES -register_balancing No -slice_packing YES -optimize_primitives NO -use_clock_enable Auto -use_sync_set Auto -use_sync_reset Auto -iob yes -slice_utilization_ratio_maxmargin 5
 
XCF_FILE=$(DESIGN_NAME).xcf
XST_FILE=$(DESIGN_NAME).xst

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.