URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc
- from Rev 654 to Rev 655
- ↔ Reverse comparison
Rev 654 → Rev 655
/trunk/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 |
|
/trunk/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 |
|
/trunk/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 |
/trunk/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 |
/trunk/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 |
|
|
|
|
/trunk/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 |
|
|
|
/trunk/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 |
/trunk/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 |
|
/trunk/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 |
|
|
|
|
/trunk/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 & |
/trunk/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 |
|
/trunk/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 |
/trunk/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 |
/trunk/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); |
} |
/trunk/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 |
|
/trunk/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); |
} |
/trunk/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); |
} |
/trunk/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 |
|
/trunk/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); |
} |
/trunk/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; |
|
} |
/trunk/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 |
/trunk/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 ] |
} |
} |
/trunk/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 $@ |
/trunk/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) |
/trunk/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); |
/trunk/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)); |
} |
|
|
/trunk/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 |
/trunk/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: |
/trunk/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 |
/trunk/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 |
/trunk/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 |
|
/////////////////////////////// |
// // |
/trunk/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 |
|
// |
/trunk/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] | |
/trunk/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 |
/trunk/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 |
#------------------------------------------------------------------------------ |
/trunk/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) |
/trunk/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 |
// |
/trunk/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 |