📄 command.v
字号:
// Issue the appropriate command if the sdram is not currently busy 如果SDRAM空闲,则发出适当的内部命令
//包含一个用户命令与刷新请求的仲裁器。如何仲裁请看本模块开头的介绍
if ((REF_REQ == 1 | REFRESH == 1) & command_done == 0 & do_refresh == 0 & rp_done == 0 // Refresh若隐藏的刷新请求信号有效或REFRESH命令有效,且SDRAM空闲,rp_done指示没有正在进行的读写及刷新命令,当前没有do_reada、do_writea内部命令发出,同时do_refresh未发出,则发出do_refresh(赋1)
& do_reada == 0 & do_writea == 0)
do_refresh <= 1;
else
do_refresh <= 0; //否则为0
if ((READA == 1) & (command_done == 0) & (do_reada == 0) & (rp_done == 0) & (REF_REQ == 0)) // READA若READA命令有效,且SDRAM空闲,rp_done指示没有正在进行的读写及刷新命令,刷新请求信号无效,同时do_reada未发出,则发出do_reada(赋1)。
do_reada <= 1;
else
do_reada <= 0; //否则为0
if ((WRITEA == 1) & (command_done == 0) & (do_writea == 0) & (rp_done == 0) & (REF_REQ == 0)) // WRITEA若WRITEA命令有效,且SDRAM空闲,rp_done指示没有正在进行的读写及刷新命令,刷新请求信号无效,同时do_writea未发出,则发出do_writea(赋1),do_writea和do_writea1用在不同always块中
begin
do_writea <= 1;
do_writea1 <= 1;
end
else
begin
do_writea <= 0;
do_writea1 <= 0; //否则为0
end
if ((PRECHARGE == 1) & (command_done == 0) & (do_precharge == 0)) // PRECHARGE若PRECHARGE命令有效,且SDRAM空闲,同时do_precharge未发出,则发出do_precharge,即do_precharge赋1,
do_precharge <= 1;
else
do_precharge <= 0; //否则为0
if ((LOAD_MODE == 1) & (command_done == 0) & (do_load_mode == 0)) // LOADMODE若LOAD_MODE命令有效,且SDRAM空闲,同时do_load_mode未发出,则发出do_load_mode,即do_load_mode赋1,
do_load_mode <= 1;
else
do_load_mode <= 0; //否则为0
// set command_delay shift register and command_done flag
// The command delay shift register is a timer that is used to ensure that
// the SDRAM devices have had sufficient time to finish the last command.
//设置命令延迟移位寄存器和SDRAM忙标志,命令延迟移位寄存器确保SDRAM有足够时间完成上一个命令操作
//对读写及刷新命令,最大突发长度为8个字,因此需要8个时钟周期完成读写操作,同时由于在读写命令之前,控制器首先要给出ACTIVATE命令,而ACTIVATE命令与读写命令之间延迟最大为3个时钟周期,这样就要求控制器至少在(8+1)+(3+2)=14个时钟周期内不能对用户给出的新的读写刷新命令作出反应;但在9个时钟周期后,控制器可对其他命令作出响应如precharge命令,从而可以终止读写操作。
//对其他命令设置为8+1=9个时钟周期内控制器不能响应新的命令。
if ((do_refresh == 1) | (do_reada == 1) | (do_writea == 1) | (do_precharge == 1)
| (do_load_mode)) //如果有任何一个内部命令被发出,则command_delay赋全1,command_done置位(表示SDRAM忙),rw_flag赋值为do_reada(若do_reada为1即读操作命令有效,则rw_flag赋1;否则若do_reada为0,则rw_flag赋0,表明不是读操作命令)
begin
command_delay <= 8'b11111111;
command_done <= 1;
rw_flag <= do_reada;
end
else //否则,命令延迟移位寄存器进行向右移位操作,最低位移出给command_done,最高位补0。在移位期间只要命令延迟移位寄存器不为0,command_done就始终为1(可保持9个时钟周期为1),因此不会有新的内部命令被发出,保证SDRAM有足够时间完成上一个命令操作
begin
command_done <= command_delay[0]; // the command_delay shift operation
command_delay[6:0] <= command_delay[7:1];
command_delay[7] <= 0;
end
// start additional timer that is used for the refresh, writea, reada commands
//用于refresh, writea, reada命令的附加的移位寄存器rp_shift,保证SDRAM有足够时间完成上一次读写及刷新命令,因为这三个命令的执行需要更多的时间,还须隐含执行ACTIVATE命令
if (command_delay[0] == 0 & command_done == 1) //若命令延迟移位寄存器最低位为0且command_done == 1,则附加的移位寄存器rp_shift赋全1,rp_done 置位(表示读写忙)
begin
rp_shift <= 4'b1111;
rp_done <= 1;
end
else //否则,附加的移位寄存器rp_shift进行右移位操作,最低位移出给rp_done,最高位补0。在移位期间只要附加的移位寄存器不为0,rp_done就始终为1(可保持5个时钟周期为1),因此不会有新的读、写、刷新内部命令被发出(但别的内部命令可以发出,比如do_precharge命令,这条命令可以终止正在进行的读写及刷新命令)
begin
rp_done <= rp_shift[0];
rp_shift[2:0] <= rp_shift[3:1];
rp_shift[3] <= 0;
end
end
end
// logic that generates the OE signal for the data path module该always块产生输出使能信号OE,输出给data path module
// For normal burst write the duration of OE is dependent on the configured burst length.在正常的突发写入操作中,OE的持续时间取决于配置的REG1的burst length位段
// For page mode accesses(SC_PM=1) the OE signal is turned on at the start of the write command在页写入访问模式中,OE在write命令开始时有效并且保持到检测到PRECHARGE命令
// and is left on until a PRECHARGE(page burst terminate) is detected.
//(时钟信号CLK上升沿)
always @(posedge CLK or negedge RESET_N)
begin
if (RESET_N == 0) //复位,清除oe_shift、oe1、oe2、OE
begin
oe_shift <= 0;
oe1 <= 0;
oe2 <= 0;
OE <= 0;
end
else
begin
if (SC_PM == 0) //若SC_PM == 0,说明是正常的突发写入操作,则
begin
if (do_writea1 == 1) //若do_writea1 == 1,即内部写命令有效(首先会执行ACTIVATE命令),则
begin // Set the shift register to the appropriate value based on burst length.根据SC_BL(burst length)的值设置输出移位寄存器oe_shift
if (SC_BL == 1) //若burst length==1(突发写入长度为1个字),则oe_shift取值为0,进行一次移位操作后会使oe1清0,即输出使能信号能持续一个时钟周期
oe_shift <= 0;
else if (SC_BL == 2) //若burst length==2(突发写入长度为2个字),则oe_shift取值为1,进行两次移位操作后会使oe1清0,即输出使能信号能持续两个时钟周期
oe_shift <= 1;
else if (SC_BL == 4) //若burst length==4(突发写入长度为4个字),则oe_shift取值为7,进行四次移位操作后会使oe1清0,即输出使能信号能持续四个时钟周期
oe_shift <= 7;
else if (SC_BL == 8) //若burst length==8(突发写入长度为8个字),则oe_shift取值为127,进行八次移位操作后会使oe1清0,即输出使能信号能持续八个时钟周期
oe_shift <= 127;
oe1 <= 1; //oe1置位
end
else //否则若do_writea1 != 1,即执行完ACTIVATE命令,则
begin
oe_shift[6:0] <= oe_shift[7:1]; // Do the shift operation输出移位寄存器oe_shift进行向右移位操作,最高位补0,最低位移进oe1,oe1移进oe2,oe2移进oe3,oe3移进oe4
oe_shift[7] <= 0;
oe1 <= oe_shift[0];
oe2 <= oe1;
oe3 <= oe2;
oe4 <= oe3;
if (SC_RC == 2) //若SC_RC == 2,即RAS to CAS Delay为2个时钟周期,则oe3(oe1延迟2个时钟周期的结果)赋给OE,否则必有SC_RC == 3(因为根据SDRAM资料,RAS to CAS Delay即tRCD只能取3CLKs或2CLKs),即RAS to CAS Delay为3个时钟周期,则oe4(oe1延迟3个时钟周期的结果)赋给OE
OE <= oe3;
else
OE <= oe4;
end
end
else //否则若SC_PM == 1,说明是页写入访问模式,则
begin
if (do_writea1 == 1) // OE generation for page mode accesses 若do_writea1 == 1,即内部写命令有效,则oe4置位
oe4 <= 1;
else if (do_precharge == 1 | do_reada == 1 | do_refresh)// 否则若内部写命令无效,而内部命令do_precharge或do_reada或do_refresh有效,则oe4清除
oe4 <= 0;
OE <= oe4; // oe4赋给OE
end
end
end
// This always block tracks the time between the activate command and the
// subsequent WRITEA or READA command, RC. The shift register is set using
// the configuration register setting SC_RC. The shift register is loaded with
// a single '1' with the position within the register dependent on SC_RC.
// When the '1' is shifted out of the register it sets so_rw which triggers
// a writea or reada command
//这个always块监测控制SDRAM执行ACTIVATE命令和接下来的WRITEA or READA命令之间的时间间隔。当用户输入WRITEA or READA命令后,command module发出内部命令do_reada == 1 | do_writea == 1,此时触发SDRAM执行ACTIVATE命令,然后等到do_rw==1时才触发SDRAM执行WRITEA or READA命令,等待的时间由SC_RC决定(必须保证CAS有效时才触发SDRAM执行WRITEA or READA命令),由本always块监测控制。
//读写移位寄存器用配置寄存器REG1中的SC_RC位段加载。读写移位寄存器中1加载的位置取决于SC_RC位段,当1移出读写移位寄存器时,do_rw被置位,该信号将触发一个writea or reada命令
//(时钟信号CLK上升沿)
always @(posedge CLK or negedge RESET_N)
begin
if (RESET_N == 0) //复位,清除rw_shift、do_rw
begin
rw_shift <= 0;
do_rw <= 0;
end
else
begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -