⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 command.v

📁 SDRAM控制器Verilog员代码
💻 V
📖 第 1 页 / 共 3 页
字号:
//  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 + -