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

📄 ddr_ctrl.v

📁 DDR RAM控制器的VHDL源码, 实现平台是Lattice FPGA
💻 V
📖 第 1 页 / 共 2 页
字号:
      case (cstate)
        c_idle: begin
           if (!rd_wr_req_during_ref_req)
             if (!sys_adsn_r && latch_ref_req)
               rd_wr_req_during_ref_req <= 1'b1;
             else
               rd_wr_req_during_ref_req <= 1'b0;
        end
        // After completing write (c_tDAL)
        // Durinf c_tDAL, system can make a request and
        // refresh can be pending. 
        c_tRFC,
        c_tDAL,  
        c_AR: begin
           if (!sys_adsn_r)
             rd_wr_req_during_ref_req <= sys_init_done;
        end

        default: begin
           rd_wr_req_during_ref_req <= 1'b0;
        end
        
      endcase
   end
end
//=======================================================================
// CMD_FSM state machine
//=======================================================================

always @(posedge clk or negedge reset_n) begin
   if (reset_n == 1'b0) begin
      cstate <=  c_idle;
      wren   <= 1'b0;
   end else begin
      case (cstate)
        c_idle:   // wait until refresh request or addr strobe asserted
          if (latch_ref_req && sys_init_done) 
            cstate <=  c_AR;
          else if ((!sys_adsn_r && sys_init_done) || rd_wr_req_during_ref_req) 
            cstate <=  c_ACTIVE;
        c_ACTIVE: // assert row/bank addr
          if (NUM_CLK_tRCD == 0)
            cstate <=  (sys_r_wn_r) ? c_READA : c_WRITEA;
          else 
            cstate <=  c_tRCD;
        c_tRCD:   // wait until tRCD satisfied
          if (`endOf_tRCD)
            cstate <=  (sys_r_wn_r) ? c_READA : c_WRITEA;
        c_READA:  // assert col/bank addr for read with auto-precharge
          cstate <=  c_cl;
        c_cl:     // CASn latency
          if (`endOf_Cas_Latency) cstate <=  c_rdata;
        c_rdata:  // read cycle data phase
          if (`endOf_Read_Burst) cstate <=  c_idle;
        c_WRITEA: begin // assert col/bank addr for write with auto-precharge
           cstate <=  c_wdata;
           wren   <= 1'b1;
        end
        c_wdata: begin  // write cycle data phase
           if (`endOf_Write_Burst) begin
              cstate <=  c_tDAL;
              wren   <= 1'b0;
           end
        end
        c_tDAL:   // wait until (tWR + tRP) satisfied before issuing next
          // SDRAM ACTIVE command
          if (`endOf_tDAL) cstate <=  c_idle;
        c_AR:     // auto-refresh
          cstate <=  (NUM_CLK_tRFC == 0) ? c_idle : c_tRFC;
        c_tRFC:   // wait until tRFC satisfied
          if (`endOf_tRFC) cstate <=  c_idle;
        default: begin
           cstate <=  c_idle;
           wren   <= 1'b0;
        end
      endcase
   end
end


//=======================================================================
// Refresh request, generation using LFSR counters
// for better frequency and resource utilisation
// For more information please refer to 
// http://www.fpgacpu.org/usenet/lfsrs.html
// Use the lfsr.exe, if any changes are required.

//lfsr 11 1500
//lfsr 11-bits 1500-cycle=477
//lfsr 11-bits 1500-cycle: d0=xnor(q10,q8, /*477*/and(q10,~q9,~q8,~q7,q6,q5,q4,~q3,q2,q1,q0));

//lfsr 11 750
//lfsr 11-bits 750-cycle=605
//lfsr 11-bits 750-cycle: d0=xnor(q10,q8, /*605*/and(q10,q9,~q8,~q7,~q6,~q5,~q4,~q3,q2,~q1,q0));

//lfsr 11 2000
//lfsr 11-bits 2000-cycle=300
//lfsr 11-bits 2000-cycle: d0=xnor(q10,q8, /*300*/and(~q10,q9,q8,~q7,~q6,~q5,~q4,~q3,~q2,~q1,~q0));

//lfsr 11 1000
//lfsr 11-bits 1000-cycle=350
//lfsr 11-bits 1000-cycle: d0=xnor(q10,q8, /*350*/and(~q10,q9,q8,~q7,q6,~q5,q4,~q3,~q2,~q1,~q0));
//=======================================================================

always @(posedge clk or negedge reset_n) begin
   if (reset_n == 1'b0) begin
      q       <= 0;
      ref_req <= 1'b0;
   end else begin
      q[0]    <= ~(q[10]^q[8]^ref_req_c);
      q[10:1] <= q[9:0];
      ref_req <= ref_req_c;
   end
end

always @ (q) begin
   if (REF_INTERVAL == REF_INT_128MBIT_100MHZ)
      /*477*/ref_req_c =  q[10]&~q[9]&~q[8]&~q[7]&q[6]&q[5]&q[4]&~q[3]&q[2]&q[1]&q[0];
   if (REF_INTERVAL == REF_INT_NON128MBIT_100MHZ)
     /*605*/ref_req_c = q[10]&q[9]&~q[8]&~q[7]&~q[6]&~q[5]&~q[4]&~q[3]&q[2]&~q[1]&q[0];
   if (REF_INTERVAL == REF_INT_128MBIT_133MHZ)
     /*300*/ref_req_c = ~q[10]&q[9]&q[8]&~q[7]&~q[6]&~q[5]&~q[4]&~q[3]&~q[2]&~q[1]&~q[0];
   if (REF_INTERVAL == REF_INT_NON128MBIT_133MHZ)
     /*350*/ref_req_c = ~q[10]&q[9]&q[8]&~q[7]&q[6]&~q[5]&q[4]&~q[3]&~q[2]&~q[1]&~q[0];  
end


always @(posedge clk or negedge reset_n) begin
   if (reset_n == 1'b0) begin
      ref_ack       <= 0;
      latch_ref_req <= 1'b0;
   end else begin
      if (ref_req)
        latch_ref_req <= 1'b1;
      else if (ref_ack)
        latch_ref_req <= 1'b0;
        
      case (cstate)
        c_idle:
          ref_ack    <= sys_init_done && latch_ref_req;
        default:
          ref_ack    <= 1'b0;
      endcase
   end
end


//=======================================================================
// Clock Counter
//=======================================================================
always @(posedge clk or negedge reset_n) begin
   if (reset_n == 1'b0) begin
      cs_clkcnt <= 4'b0;
   end else begin
      if (cs_syncResetClkCNT) 
        cs_clkcnt <=  4'b0;
      else 
        cs_clkcnt <=  cs_clkcnt + 1'b1;
   end
end

always @(posedge clk or negedge reset_n) begin
   if (reset_n == 1'b0) begin
      i_clkcnt <= 4'b0;
   end else begin
      if (i_syncResetClkCNT) 
        i_clkcnt <=  4'b0;
      else 
        i_clkcnt <=  i_clkcnt + 1'b1;
   end
end

//=======================================================================
// istate syncResetClkCNT generation
//=======================================================================
always @(istate or i_clkcnt) begin
  case (istate)
    i_PRE:
      i_syncResetClkCNT =  (NUM_CLK_tRP == 0) ? 1 : 0;
    i_AR1,
    i_AR2:
      i_syncResetClkCNT =  (NUM_CLK_tRFC == 0) ? 1 : 0;
    i_tRP:
      i_syncResetClkCNT =  (`endOf_tRP_i) ? 1 : 0;
    i_tMRD:
      i_syncResetClkCNT =  (`endOf_tMRD_i) ? 1 : 0;
    i_tRFC1,
    i_tRFC2:
      i_syncResetClkCNT =  (`endOf_tRFC_i) ? 1 : 0;
    default:
         i_syncResetClkCNT =  1;
  endcase
end

//=======================================================================
// cstate syncResetClkCNT generation
//=======================================================================
always @(cstate or cs_clkcnt) begin
   case (cstate)
     c_idle:
       cs_syncResetClkCNT =  1;
     c_ACTIVE:
       cs_syncResetClkCNT =  (NUM_CLK_tRCD == 0) ? 1 : 0;
     c_tRCD:
       cs_syncResetClkCNT =  (`endOf_tRCD) ? 1 : 0;
     c_tRFC:
       cs_syncResetClkCNT =  (`endOf_tRFC) ? 1 : 0;
     c_cl:
       cs_syncResetClkCNT =  (`endOf_Cas_Latency) ? 1 : 0;
     c_rdata:
       cs_syncResetClkCNT =  (cs_clkcnt == NUM_CLK_READ) ? 1 : 0;
     c_wdata:
       cs_syncResetClkCNT =  (`endOf_Write_Burst) ? 1 : 0;
     c_tDAL:
       cs_syncResetClkCNT =  (`endOf_tDAL) ? 1 : 0;
     
     default:
       cs_syncResetClkCNT =  1;
   endcase // case(cstate)
end



endmodule
                

                  



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -