📄 adv_bb.v
字号:
endcase
end //default
endcase
end //if
end //always (predecode)
//
// Command Decode
//
always @(DataPtr) begin : command
integer BlockUsed;
// When DataPtr hits zero it means that all the
// additional data has been given to the current command
if (!Reset && (DataPtr == 0) && (WriteToPtr != `NewCmd)) begin
if (CmdValid && (WriteToPtr == `CmdField)) begin
WriteToPtr = `NewCmd;
// Just finish a multi-cycle command. Determine which block the command uses
BlockUsed = -1;
for (LoopCntr = `NumberOfBlocks-1; LoopCntr >= 0; LoopCntr = LoopCntr - 1) begin
if (Cmd[`CmdAdd_1] <= BlocksEnd[LoopCntr])
BlockUsed = LoopCntr;
end
if (BlockUsed == -1)
$display("FLASH: Error: Invalid Command Address");
else
Cmd [`OpBlock] = BlockUsed;
if (Cmd [`OpType] == `Erase ) begin
if (BlocksType[BlockUsed] == `MainBlock)
Cmd[`Time] = Main_Erase_Time;
else
Cmd[`Time] = Param_Erase_Time;
end
else if (Cmd [`OpType] == `Program)
Cmd[`Time] = Program_Time_Word;
else
Cmd[`Time] = 0;
// If this command needs a confirm
// (flaged at predecode) then check if confirm was received
if (Cmd [`Confirm]) begin
if (Cmd[`CmdData1Fx8] == `ConfirmCmd) begin
// If the command is still valid put it in the queue and deactivate the array
Algorithm = Cmd;
AlgTime = Cmd [`Time] ;
CmdValid <= `FALSE;
if (!VppError)
ReadyBusy <= #1 `Busy;
ReadMode <= `rdCSR;
end
else begin
ReadMode <= `rdCSR ;
ProgramError <= `TRUE;
EraseError <= `TRUE;
CmdValid <= `FALSE;
end
end
else begin
Algorithm = Cmd;
AlgTime = Cmd [`Time] ;
CmdValid <= `FALSE;
if (!VppError)
ReadyBusy <= #1 `Busy ;
ReadMode <= `rdCSR;
end
end
end
end //always (command)
//////////////
// Execution //
//////////////
always @(posedge AlgDone) begin : execution
if (!Reset) begin
if (AlgDone) begin // When the algorithm finishes
// if chips is executing during an erase interrupt
// then execute out of queue slot 2
if (Algorithm [`OpType] == `Erase) begin
// ERASE COMMAND //
if (VppFlag) begin
VppError <= `TRUE ;
EraseError <= `TRUE;
end
else begin
// Do ERASE to OpBlock
if ((BlocksType[Algorithm[`OpBlock]] == `LockBlock) && !InternalBoot_WE) begin
$display("FLASH: Error: Attempted to erase locked block.");
EraseError <= `TRUE;
BlockLockStatus <= `TRUE;
end
else begin
for (LoopCntr = BlocksBegin[Algorithm[`OpBlock]];
LoopCntr <= BlocksEnd[Algorithm[`OpBlock]]; LoopCntr = LoopCntr + 1)
MainArray [LoopCntr] = 'hFFFF;
BlocksEraseCount[Algorithm[`OpBlock]] = BlocksEraseCount[Algorithm[`OpBlock]] + 1;
$display("FLASH: Block %d Erase Count: %d",Algorithm[`OpBlock],BlocksEraseCount[Algorithm[`OpBlock]]);
end
end
end
else begin
// PROGRAM COMMAND //
if (VppFlag) begin
ProgramError <= `TRUE;
VppError <= `TRUE ;
end
else begin
if ((BlocksType[Algorithm[`OpBlock]] == `LockBlock) && !InternalBoot_WE) begin
$display("FLASH: Error: Attempted to program locked boot block.");
ProgramError <= `TRUE;
BlockLockStatus <= `TRUE;
end
else begin
Program (MainArray[Algorithm [`CmdAdd_1]], Algorithm [`CmdData_1]);
if (EraseSuspended == `TRUE) begin
AlgTime = TimeLeft;
ToBeSuspended = `Erase;
Algorithm = SuspendedAlg;
end
end
end
end
end //if (AlgDone)
ReadyBusy <= `Ready;
end //if (!Reset)
end //always (execution)
always @(ReadyBusy) begin
if ((!Reset) && (ReadyBusy == `Busy)) begin // If the algorithm engine
// just started, start the clock
ClearVppFlag <= #1 `TRUE ;
ClearVppFlag <= #3 `FALSE ;
TimerClk <= #1 1'b1 ;
TimerClk <= #TimerPeriod 1'b0 ;
end
end
// record the time for addr changes .
always @(addr) begin
if ($time != 0 & !ceb) begin
if (((curr_addr_time + TAVAV) > $time) & !ceb) //Read/Write Cycle Time --- Added "& !ceb" RU 9/9/99 9pm
$display("FLASH: [",$time,"] Timing Violation: Read/Write Cycle Time (TAVAV), Last addr change: %d",curr_addr_time) ;
curr_addr_time = $time ;
end
end
// record the time for oe changes .
always @(oeb) begin
if ($time != 0) begin
curr_oe_time = $time ;
end
end
// record the time for ce changes .
always @(ceb) begin
if ($time != 0) begin
curr_ce_time = $time ;
end
end
reg rpb_r;
initial rpb_r = rpb;
// record the time for rp changes .
always @(rpb) begin
if ((rpb_r != rpb) & ($time != 0) ) begin
curr_rp_time = $time ;
rpb_r = rpb;
end
end
// record the time for ReadMode changes .
always @(ReadMode) begin
if ($time != 0) begin
curr_ReadMode_time = $time ;
end
end
// record the time for Internal_RE changes .
always @(Internal_RE) begin
if ($time != 0) begin
curr_Internal_RE_time = $time ;
end
end
always @(InternalBoot) begin
InternalBoot_WE <= #TVPWH InternalBoot;
end
always @(TimerClk) begin
if ((!Reset) && (ReadyBusy == `Busy) && (TimerClk == 1'b0)) begin // Reschedule clock and
// decrement algorithm count
TimerClk <= #1 1'b1 ;
TimerClk <= #TimerPeriod 1'b0 ;
if (Suspend) begin // Is the chip pending suspend? If so do it
Suspend = `FALSE;
if (ToBeSuspended == `Program) begin
WriteSuspended <= #Program_Suspend_Time `TRUE;
ReadyBusy <= #Program_Suspend_Time `Ready;
end
else begin
EraseSuspended <= #Erase_Suspend_Time `TRUE;
ReadyBusy <= #Erase_Suspend_Time `Ready;
end
end
if (ReadyBusy == `Busy) begin
AlgTime = AlgTime - 1;
if (AlgTime <= 0) begin // Check if the algorithm is done
AlgDone <= #1 `TRUE ;
AlgDone <= #10 `FALSE ;
end
end
end
end
//------------------------------------------------------------------------
// Reset Controller
//------------------------------------------------------------------------
always @(rpb or vcc) begin : ResetPowerdownMonitor
// Go into reset if reset powerdown pin is active or
// the vcc is too low
if ((rpb != `VIH) || (vcc < 2500)) begin // Low Vcc protection
Reset <= `TRUE ;
if (!((vcc >= 2500) || StartUpFlag))
$display ("FLASH: Low Vcc: Chip Resetting") ;
end
else
// Coming out of reset takes time
Reset <= #TPHWL `FALSE ;
end
//------------------------------------------------------------------------
// VccMonitor
//------------------------------------------------------------------------
always @(Reset or vcc) begin : VccMonitor
// Save the array when chip is powered off
if ($time > 0) begin
if (vcc == 0 && SaveOnPowerdown)
StoreToFile;
if (vcc < 2700)
$display("FLASH: Vcc is below minimum operating specs");
else if ((vcc >= 2700) && (vcc <= 3600) && (`VccLevels & `Vcc2700)) begin
//$display ("Vcc is in operating range for 2.7 volt mode") ; // Commented out RU 9/11/99
/*
TAVAV = `TAVAV_27;
TAVQV = `TAVQV_27;
TELQV = `TELQV_27;
TPHQV = `TPHQV_27;
TGLQV = `TGLQV_27;
TELQX = `TELQX_27;
TEHQZ = `TEHQZ_27;
TGLQX = `TGLQX_27;
TGHQZ = `TGHQZ_27;
TOH = `TOH_27 ;
TPHWL = `TPHWL_27;
TWLWH = `TWLWH_27;
TDVWH = `TDVWH_27;
TAVWH = `TAVWH_27;
TWHDX = `TWHDX_27;
TWHAX = `TWHAX_27;
TWHWL = `TWHWL_27;
TVPWH = `TVPWH_27;
*/
if ((vpp <= 3600) && (vpp >= 2700)) begin
Param_Erase_Time = `AC_EraseTime_Param_27_27;
Main_Erase_Time = `AC_EraseTime_Main_27_27;
Program_Time_Word = `AC_ProgramTime_Word_27_27;
end
else begin
Param_Erase_Time = `AC_EraseTime_Param_27_12;
Main_Erase_Time = `AC_EraseTime_Main_27_12;
Program_Time_Word = `AC_ProgramTime_Word_27_12;
end
end
else
$display ("FLASH: Vcc is out of operating range") ;
end //$time
end
//------------------------------------------------------------------------
// VppMonitor
//------------------------------------------------------------------------
always @(VppFlag or ClearVppFlag or vpp) begin : VppMonitor
if (ClearVppFlag) begin
VppErrFlag = `FALSE ;
end
else
if (!(((vpp <= 12600) && (vpp >= 11400)) || ((vpp <= 3600) && (vpp >= 2700)))) begin
VppErrFlag = `TRUE ;
end
if ((vpp <= 3600) && (vpp >= 2700)) begin
if ((vcc >= 2700) && (vcc <= 3600)) begin
Param_Erase_Time = `AC_EraseTime_Param_27_27;
Main_Erase_Time = `AC_EraseTime_Main_27_27;
Program_Time_Word = `AC_ProgramTime_Word_27_27;
end
else begin
$display("FLASH: Invalid Vcc level at Vpp change");
VppErrFlag = `TRUE;
end
end
else begin
if ((vcc >= 2700) && (vcc <= 3600)) begin
Param_Erase_Time = `AC_EraseTime_Param_27_12;
Main_Erase_Time = `AC_EraseTime_Main_27_12;
Program_Time_Word = `AC_ProgramTime_Word_27_12;
end
else begin
$display("FLASH: Invalid Vcc level at Vpp change");
VppErrFlag = `TRUE;
end
end
VppFlag <= VppErrFlag;
end
always @(StartUpFlag or Internal_OE3) begin : OEMonitor
// This section generated DriveOutputs which is the main signal that
// controls the state of the output drivers
if (!StartUpFlag) begin
WriteRecovery = 0 ;
last_Internal_WE_time = $time - curr_Internal_WE_time;
if (Internal_OE) begin
TempTime = WriteRecovery + TGLQX ;
DriveOutputs = `FALSE ;
WriteRecovery = WriteRecovery + TGLQV - TempTime;
DriveOutputs <= #WriteRecovery `TRUE ;
end
else begin
InternalOutput <= #TOH `MaxOutputs'hx;
if (oeb == `VIH)
WriteRecovery = WriteRecovery + TGHQZ;
else
WriteRecovery = WriteRecovery + TEHQZ;
DriveOutputs <= #WriteRecovery `FALSE ;
end
end
else
DriveOutputs <= `FALSE ;
end
/////// Timing Checks /////////////
always @(Internal_WE) begin : Timing_chk
if ($time > 0) begin
// pulse chk
if (Internal_WE) begin
if ((($time - curr_Internal_WE_time) < TWHWL) && (TWHWL > 0 )) begin
$display("FLASH: [",$time,"] Timing Violation: Internal Write Enable Insufficient High Time") ;
end
end
else if ((($time - curr_Internal_WE_time) < TWLWH) && (TWLWH > 0 ))
$display("FLASH: [",$time,"] Timing Violation: Internal Write Enable Insufficient Low Time") ;
curr_Internal_WE_time = $time ;
// timing_chk - addr
last_dq_time = $time - curr_dq_time;
last_rpb_time = $time - curr_rpb_time;
last_addr_time = $time - curr_addr_time;
if (Internal_WE == 0) begin
if ((last_addr_time < TAVWH) && (last_addr_time > 0))
$display("FLASH: [",$time,"] Timing Violation: Address setup time during write, Last Event %d",last_addr_time) ;
if ((last_rpb_time < TPHWL) && (last_rpb_time > 0))
$display("FLASH: [",$time,"] Timing Violation: Writing while coming out of powerdown, Last Event %d",last_rpb_time) ;
if ((last_dq_time < TDVWH) && (last_dq_time > 0))
$display("FLASH: [",$time,"] Timing Violation: Data setup time during write, Last Event %d",last_dq_time) ;
end
end
end
always @(addr) begin
last_Internal_WE_time = $time - curr_Internal_WE_time;
if (($time > 0) && !Internal_WE) begin //timing chk
if ((last_Internal_WE_time < TWHAX) && (last_Internal_WE_time > 0))
$display("FLASH: [",$time,"] Timing Violation:Address hold time after write, Last Event %d",last_Internal_WE_time) ;
end
end
always @(rpb) begin
if ((rpb_r != rpb) & ($time > 0)) begin
curr_rpb_time = $time ;
end
end
always @(dq) begin
curr_dq_time = $time ;
last_Internal_WE_time = $time - curr_Internal_WE_time;
if (($time > 0) && !Internal_WE) begin
if ((last_Internal_WE_time < TWHDX) && (last_Internal_WE_time > 0))
$display("FLASH: [",$time,"] Timing Violation:Data hold time after write, Last Event %d",last_Internal_WE_time) ;
end
end
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -