wye11083 发表于 2012-7-4 09:07:52

我也来分享个SDRAM的Verilog垃圾代码

本帖最后由 wye11083 于 2012-7-4 09:09 编辑

如下:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:        08:02:41 04/23/2012
// Design Name:
// Module Name:        SDRController
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module SDRController(
        //input GCLK,
        //input GRST,
        input int_in_GRST,
        input int_in_GCLK,
        input int_in_GCLK2X,
       
        input int_in_Read_AccessAddr,
        input int_in_Write_AccessAddr,
        input int_in_Data_Read_Request,
        input int_in_Data_Write_Request,
        input int_in_Command_Valid,
        input int_in_Data_In,
       
        output int_out_Data_Out,
        output int_out_Data_Valid,
       
        output int_out_CurrentState,                // State -powering -ReadReq:ReadState -WriteReq:WriteState
                                                                // -AutoRefresh -Powered on -State Idle
       
        output int_out_IDLE,
       
        //output port_out_Chip_Select,
       
        output port_out_CS,
        output port_out_RAS,
        output port_out_CAS,
        output port_out_WE,
       
        output port_out_BA,
        output port_out_A,
        inout port_io_Data,
       
        output port_out_CK,                                                // LVDS output
        output port_out_CKS,
       
        output port_out_CKE,
       
        output port_out_DQM
        );
       
        (* keep = 1 *) reg r_port_io_Data_Out_EN /* synthesis keep = 1 */;
        (* keep = 1 *) reg r_port_io_Data_Out /* synthesis keep = 1 */;
        reg r_port_io_Data_Out_output_cache;
        reg r_port_io_Data_Out_EN_output_cache;
       
        (* keep = 1 *) reg r_port_io_Data_Local_GCLK /* synthesis keep = 1 */;

        assign port_io_Data = r_port_io_Data_Out_EN_output_cache ? r_port_io_Data_Out_output_cache : 16'bz;
       
        always @(posedge int_in_GCLK)
                begin
                        r_port_io_Data_Out_output_cache <= r_port_io_Data_Out;
                        r_port_io_Data_Out_EN_output_cache <= r_port_io_Data_Out_EN;
                        r_port_io_Data_Local_GCLK <= port_io_Data;
                end
       
       
        // These are the output level registers. No delay indeed.
        reg r_int_out_Data_Out;
        reg r_int_out_Data_Valid;
       
        assign int_out_Data_Out = r_int_out_Data_Out;
        assign int_out_Data_Valid = r_int_out_Data_Valid;
       
        wire ws_DRAM_State_PowerUp = 0;
        wire ws_DRAM_State_Startup_Sequence = 1;
        wire ws_DRAM_State_CKEValid_Delay = 2;
        wire ws_DRAM_State_Setup_MRS_EMRS = 3;
        wire ws_DRAM_State_Setup_MRS_EMRS_Delay = 4;
       
        wire ws_DRAM_State_IDLE = 5;
       
        wire ws_DRAM_State_Refresh = 6;
        wire ws_DRAM_State_Refresh_Delay = 7;
       
        wire ws_DRAM_State_Bank_Row_Active = 8;
        wire ws_DRAM_State_Bank_Row_Active_Delay = 9;
       
        wire ws_DRAM_State_Write_NAP = 10;
        wire ws_DRAM_State_Write_NAP_Col = 11;
        wire ws_DRAM_State_Write_NAP_WriteData = 12;
       
        wire ws_DRAM_State_Read_NAP = 13;
        wire ws_DRAM_State_Read_NAP_Col = 14;
        wire ws_DRAM_State_Read_NAP_Col_Delay = 15;
        wire ws_DRAM_State_Read_NAP_ReadData = 16;
       
        wire ws_DRAM_State_Precharge_All = 17;
        wire ws_DRAM_State_Precharge_All_Delay = 18;
       

        reg rs_DRAM_State = 0;
        reg rs_DRAM_Next_State = 0;

       
        reg r_CK_Enable = 0;
        reg r_port_out_CKE = 0;
       
       
        // Time Out Counter Value. Set for time out operation.
        reg r_Timeout_Counter_Value = 16'd20000;
        // Reset Time Out Counter. Set to 1 before operation then set 0.
        reg r_Timeout_Counter_Reset = 0;
        // If Timeout_Interrupt is set to 1, the time is out for previous operation.
        wire w_Timeout_Interrupt;
       
       
        // Whenever refresh is required, Request is set 1 until certain refresh cycles occur.
        wire w_Refresh_Request;
        // Validate refresh counter. This signal must be set 1 for each refresh cycle.
        reg r_Refresh_Validate = 0;
       
       
       
       
       
        // Because we use 16-bit sdram, the CAddr is aligned to real ca
        reg r_int_in_AccessAddr = 0;
        wire w_Request_RAddr = r_int_in_AccessAddr;
        wire w_Request_CAddr = {r_int_in_AccessAddr,3'b0};
        wire w_Request_BAddr = r_int_in_AccessAddr;
       
        reg r_Bank0_Address = 0;
        reg r_Bank1_Address = 0;
        reg r_Bank2_Address = 0;
        reg r_Bank3_Address = 0;
       
        wire w_Last_Open_RowAddr = (w_Request_BAddr == 0)?r_Bank0_Address :
                                                                          (w_Request_BAddr == 1)?r_Bank1_Address :
                                                                          (w_Request_BAddr == 2)?r_Bank2_Address :
                                                                          r_Bank3_Address;
        reg r_Bank_Open_Status = 0;
        wire w_Bank_Is_Open = |r_Bank_Open_Status;
        wire w_Current_Bank_Is_Open = (w_Request_BAddr == 0)?r_Bank_Open_Status :
                                                               (w_Request_BAddr == 1)?r_Bank_Open_Status :
                                                               (w_Request_BAddr == 2)?r_Bank_Open_Status :
                                                               r_Bank_Open_Status;
       
       
       
       
       
        reg r_int_in_Data_Read_Request = 0;
        reg r_int_in_Data_Write_Request = 0;
        wire w_Data_Read_Request = ^r_int_in_Data_Read_Request;
        wire w_Data_Write_Request = ^r_int_in_Data_Write_Request;
       
        // Internal Data Cache. Used for Shift Register.
        reg r_int_in_Data_In = 0;

       
        reg r_port_out_CS = 0;
        reg r_port_out_RAS = 0;
        reg r_port_out_CAS = 0;
        reg r_port_out_WE = 0;
        reg r_port_out_BA = 0;
        reg r_port_out_A = 0;
        reg r_port_out_DQM = 0;
       
       
        reg r_int_out_IDLE = 0;
        assign int_out_IDLE = r_int_out_IDLE;
       
        // State -powering -ReadReq:ReadState -WriteReq:WriteState
        // -AutoRefresh -Powered on -State Idle
        assign int_out_CurrentState = r_int_out_IDLE;
        assign int_out_CurrentState = r_port_out_DQM; // 1-powering up, 0-powered up
        assign int_out_CurrentState = ~r_port_out_DQM; // 1-powering up, 0-powered up
        assign int_out_CurrentState = w_Data_Read_Request;
        assign int_out_CurrentState = w_Data_Write_Request;
        reg r_ReadState = 0;
        reg r_WriteState = 0;
        reg r_RefreshState = 0;
        assign int_out_CurrentState = r_ReadState;
        assign int_out_CurrentState = r_WriteState;
        assign int_out_CurrentState = r_RefreshState;
       
       
       
       
        reg rc_DRAM_Latency = 0;
        reg rc_DRAM_Latency_Read = 0;
        reg rc_DRAM_Latency_Write = 0;
        reg rc_DRAM_Precharge_Latency = 0;
        reg rc_DRAM_Setup_MRS_EMRS_Latency = 0;
        reg rc_DRAM_Refresh_Latency = 0;
       
       
        always @(posedge int_in_GCLK or negedge int_in_GRST)
                begin
                        if(~int_in_GRST)
                                begin
                                        r_CK_Enable <= 0;
                                        rs_DRAM_State <= ws_DRAM_State_PowerUp;
                                        r_Timeout_Counter_Value <= 16'd20000;
                                        r_Timeout_Counter_Reset <= 0;
                                        r_port_out_CKE <= 0;
                                        r_port_io_Data_Out_EN <= 0;
                                        r_port_io_Data_Out <= 0;
                                        rc_DRAM_Latency <= 0;
                                        r_port_out_CS <= 0;
                                        r_port_out_RAS <= 0;
                                        r_port_out_CAS <= 0;
                                        r_port_out_WE <= 0;
                                        r_port_out_BA <= 0;
                                        r_port_out_A <= 0;
                                        r_port_out_DQM <= 0;
                                        r_int_in_Data_Read_Request <= 0;
                                        r_int_in_Data_Write_Request <= 0;
                                        r_int_out_IDLE <= 0;
                                        r_int_out_Data_Out <= 0;
                                        r_int_out_Data_Valid <= 0;
                                        r_int_in_Data_In <= 0;
                                        r_Bank_Open_Status <= 0;
                                        r_ReadState <= 0;
                                        r_WriteState <= 0;
                                        r_RefreshState <= 0;
                                end
                        else
                                begin
                                        r_CK_Enable <= 1;        // Enable CK output
                                        r_port_io_Data_Out <= r_int_in_Data_In;
                                       
                                        case (rs_DRAM_State)
                                       
                                       
                                                ws_DRAM_State_IDLE:
                                                        begin
                                                                // Now we are in IDLE mode.
                                                                // Track input request and respond to them.
                                                               
                                                                // Current request mode:
                                                                // Burst-Read (8 byte for one 8-bit device); Burst-Write (8 byte for one 8-bit device);
                                                                // Auto-Refresh (Auto); Command Write;
                                                                r_port_out_DQM <= 0;
                                                                r_int_out_Data_Valid <= 0;
                                                                r_port_io_Data_Out_EN <= 0;
                                                                rs_DRAM_Next_State <= ws_DRAM_State_IDLE;
                                                               
                                                                if(w_Refresh_Request)
                                                                        begin
                                                                                r_int_out_IDLE <= 0;
                                                                                if(w_Bank_Is_Open)
                                                                                        rs_DRAM_State <= ws_DRAM_State_Precharge_All;
                                                                                else
                                                                                        rs_DRAM_State <= ws_DRAM_State_Refresh;
                                                                                r_RefreshState <= 1;
                                                                        end
                                                                else if(w_Data_Write_Request)
                                                                        begin
                                                                                r_int_in_Data_Write_Request <= ~r_int_in_Data_Write_Request;
                                                                                rs_DRAM_State <= ws_DRAM_State_Write_NAP;
                                                                                r_int_out_IDLE <= 0;
                                                                                // Note that address should be latched.
                                                                                r_int_in_AccessAddr <= int_in_Write_AccessAddr;
                                                                                r_int_in_Data_In <= int_in_Data_In;
                                                                                r_WriteState <= 1;
                                                                        end
                                                                else if(w_Data_Read_Request)
                                                                        begin
                                                                                r_int_in_Data_Read_Request <= ~r_int_in_Data_Read_Request;
                                                                                rs_DRAM_State <= ws_DRAM_State_Read_NAP;
                                                                                r_int_out_IDLE <= 0;
                                                                                // Note that address should be latched.
                                                                                r_int_in_AccessAddr <= int_in_Read_AccessAddr;
                                                                                r_ReadState <= 1;
                                                                        end
                                                                else
                                                                        begin
                                                                                rs_DRAM_State <= ws_DRAM_State_IDLE;
                                                                                r_int_out_IDLE <= 1;
                                                                                r_ReadState <= 0;
                                                                                r_WriteState <= 0;
                                                                                r_RefreshState <= 0;
                                                                        end
                                                        end
                                                       
                                                       
                                                       
                                                       
                                                ws_DRAM_State_Write_NAP:
                                                        begin
                                                                // If given bank enable is inactive, then active it
                                                                if(~w_Current_Bank_Is_Open)
                                                                        begin
                                                                                // Open row then goto Read Col
                                                                                rs_DRAM_Next_State <= ws_DRAM_State_Write_NAP_Col;
                                                                                rs_DRAM_State <= ws_DRAM_State_Bank_Row_Active;
                                                                        end
                                                                else
                                                                        begin
                                                                                // Otherwise if row address is not changed, read directly.
                                                                                if(w_Last_Open_RowAddr == w_Request_RAddr)
                                                                                        rs_DRAM_State <= ws_DRAM_State_Write_NAP_Col;
                                                                                else
                                                                                        begin
                                                                                                // Precharge first then goto active
                                                                                                rs_DRAM_State <= ws_DRAM_State_Precharge_All;
                                                                                                rs_DRAM_Next_State <= ws_DRAM_State_Write_NAP;
                                                                                        end
                                                                        end
                                                        end
                                                ws_DRAM_State_Write_NAP_Col:
                                                        begin
                                                                r_port_io_Data_Out_EN <= 1;
                                                                r_port_out_CS <= 0;
                                                                r_port_out_RAS <= 1;
                                                                r_port_out_CAS <= 0;
                                                                r_port_out_WE <= 0;
                                                                r_port_out_BA <= w_Request_BAddr;
                                                                r_port_out_A <= {2'b0,1'b0,1'b0,w_Request_CAddr};
                                                                r_port_out_A <= 0;
                                                                r_int_in_Data_In <= r_int_in_Data_In >> 16;
                                                                rs_DRAM_State <= ws_DRAM_State_Write_NAP_WriteData;
                                                                rc_DRAM_Latency_Write <= 1;
                                                        end
                                                ws_DRAM_State_Write_NAP_WriteData:
                                                        begin
                                                                r_port_out_CS <= 1;
                                                                rc_DRAM_Latency_Write <= rc_DRAM_Latency_Write + 1;
                                                                r_int_in_Data_In <= r_int_in_Data_In >> 16;
                                                                if(rc_DRAM_Latency_Write == 7)
                                                                        begin
                                                                                rs_DRAM_State <= ws_DRAM_State_IDLE;
                                                                                r_int_out_IDLE <= 1;
                                                                        end
                                                                else
                                                                        rs_DRAM_State <= rs_DRAM_State;
                                                        end
                                                       
                                                       
                                                       
                                                       
                                                       
                                                       
                                                       
                                                       
                                                       
                                                ws_DRAM_State_Read_NAP:
                                                        begin
                                                                // If given bank enable is inactive, then active it
                                                                if(~w_Current_Bank_Is_Open)
                                                                        begin
                                                                                // Open row then goto Read Col
                                                                                rs_DRAM_Next_State <= ws_DRAM_State_Read_NAP_Col;
                                                                                rs_DRAM_State <= ws_DRAM_State_Bank_Row_Active;
                                                                        end
                                                                else
                                                                        begin
                                                                                // Otherwise if row address is not changed, read directly.
                                                                                if(w_Last_Open_RowAddr == w_Request_RAddr)
                                                                                        rs_DRAM_State <= ws_DRAM_State_Read_NAP_Col;
                                                                                else
                                                                                        begin
                                                                                                // Precharge first then goto active
                                                                                                rs_DRAM_State <= ws_DRAM_State_Precharge_All;
                                                                                                rs_DRAM_Next_State <= ws_DRAM_State_Read_NAP;
                                                                                        end
                                                                        end
                                                        end
                                                ws_DRAM_State_Read_NAP_Col:
                                                        begin
                                                                // First send BA command then wait for 2 cycles
                                                                // to go to read state.
                                                                rc_DRAM_Latency <= 0;
                                                                r_port_out_CS <= 0;
                                                                r_port_out_RAS <= 1;
                                                                r_port_out_CAS <= 0;
                                                                r_port_out_WE <= 1;
                                                                r_port_out_BA <= w_Request_BAddr;
                                                                r_port_out_A <= {2'b0,1'b0,1'b0,w_Request_CAddr};
                                                                r_port_out_A <= 0;
                                                                rs_DRAM_State <= ws_DRAM_State_Read_NAP_Col_Delay;
                                                        end
                                                ws_DRAM_State_Read_NAP_Col_Delay:
                                                        begin
                                                                // Deassert CS
                                                                r_port_out_CS <= 1;
                                                                rc_DRAM_Latency_Read <= 0;
                                                                rc_DRAM_Latency <= rc_DRAM_Latency + 1;
                                                                // Note the timing. CK is half cycle late than GCLK
                                                                if(rc_DRAM_Latency == 3)
                                                                        rs_DRAM_State <= ws_DRAM_State_Read_NAP_ReadData;
                                                                else
                                                                        rs_DRAM_State <= ws_DRAM_State_Read_NAP_Col_Delay;
                                                        end
                                                ws_DRAM_State_Read_NAP_ReadData:
                                                        begin
                                                                rc_DRAM_Latency_Read <= rc_DRAM_Latency_Read + 1;
                                                                r_int_out_Data_Out <= {r_port_io_Data_Local_GCLK,r_int_out_Data_Out};
                                                                if(rc_DRAM_Latency_Read == 7)
                                                                        begin
                                                                                rs_DRAM_State <= ws_DRAM_State_IDLE;
                                                                                r_int_out_Data_Valid <= 1;
                                                                                r_int_out_IDLE <= 1;
                                                                        end
                                                                else
                                                                        r_int_out_Data_Valid <= 0;
                                                        end
                                                       
                                                       
                                                       
                                                       
                                                       
                                                       
                                                       
                                                ws_DRAM_State_Bank_Row_Active:
                                                        begin
                                                                // First send BA command then wait for 2 cycles
                                                                // to go to read state.
                                                                rc_DRAM_Latency <= 0;
                                                                r_port_out_CS <= 0;
                                                                r_port_out_RAS <= 0;
                                                                r_port_out_CAS <= 1;
                                                                r_port_out_WE <= 1;
                                                                r_port_out_BA <= w_Request_BAddr;
                                                                case (w_Request_BAddr)
                                                                        0:       
                                                                                begin
                                                                                        r_Bank0_Address <= r_int_in_AccessAddr;
                                                                                        r_Bank_Open_Status <= 1;
                                                                                end
                                                                        1:       
                                                                                begin
                                                                                        r_Bank1_Address <= r_int_in_AccessAddr;
                                                                                        r_Bank_Open_Status <= 1;
                                                                                end
                                                                        2:       
                                                                                begin
                                                                                        r_Bank2_Address <= r_int_in_AccessAddr;
                                                                                        r_Bank_Open_Status <= 1;
                                                                                end
                                                                        3:       
                                                                                begin
                                                                                        r_Bank3_Address <= r_int_in_AccessAddr;
                                                                                        r_Bank_Open_Status <= 1;
                                                                                end
                                                                endcase
                                                                r_port_out_A <= w_Request_RAddr;
                                                                r_port_out_A <= 0;
                                                                rs_DRAM_State <= ws_DRAM_State_Bank_Row_Active_Delay;
                                                        end
                                                ws_DRAM_State_Bank_Row_Active_Delay:
                                                        begin
                                                                // Deassert CS
                                                                r_port_out_CS <= 1;
                                                                rc_DRAM_Latency <= rc_DRAM_Latency + 1;
                                                                if(rc_DRAM_Latency == 1)
                                                                        begin
                                                                                if(rs_DRAM_Next_State == ws_DRAM_State_IDLE)
                                                                                        r_int_out_IDLE <= 1;
                                                                                else
                                                                                        r_int_out_IDLE <= 0;
                                                                                rs_DRAM_State <= rs_DRAM_Next_State;
                                                                        end
                                                                else
                                                                        rs_DRAM_State <= ws_DRAM_State_Bank_Row_Active_Delay;
                                                        end
                                                       
                                                       
                                                       
                                                       
                                                       
                                                       
                                                       
                                                       
                                                ws_DRAM_State_PowerUp:
                                                        begin
                                                                r_port_out_DQM <= 1;
                                                                r_port_out_CS <= 1;
                                                                // Time out counter is in reset state until now.
                                                                // Wait for interrupt line.
                                                                if(w_Timeout_Interrupt)
                                                                        begin
                                                                                // After Start up sequence, enter CKE stable state.
                                                                                r_Timeout_Counter_Reset <= 1;
                                                                                r_Timeout_Counter_Value <= 16'd40;
                                                                                rs_DRAM_State <= ws_DRAM_State_CKEValid_Delay;
                                                                                r_port_out_CKE <= 1;
                                                                        end
                                                                else
                                                                        rs_DRAM_State <= ws_DRAM_State_PowerUp;
                                                        end
                                                ws_DRAM_State_CKEValid_Delay:
                                                        begin
                                                                // Wait for some time to assert CKE.
                                                                // Goto precharge and return to ws_DRAM_State_Startup_Sequence for further operation
                                                                r_Timeout_Counter_Reset <= 0;
                                                                rs_DRAM_Next_State <= ws_DRAM_State_Startup_Sequence;
                                                                if(w_Timeout_Interrupt)
                                                                        rs_DRAM_State <= ws_DRAM_State_Precharge_All;
                                                                else
                                                                        rs_DRAM_State <= rs_DRAM_State;
                                                        end
                                                ws_DRAM_State_Startup_Sequence:
                                                        begin
                                                                if(w_Refresh_Request)
                                                                        rs_DRAM_State <= ws_DRAM_State_Refresh;
                                                                else
                                                                        begin
                                                                                rs_DRAM_Next_State <= ws_DRAM_State_IDLE;
                                                                                rs_DRAM_State <= ws_DRAM_State_Setup_MRS_EMRS;
                                                                        end
                                                        end
                                                       
                                                       
                                                       
                                                       
                                                       
                                                       
                                                ws_DRAM_State_Setup_MRS_EMRS:
                                                        begin
                                                                // First send MRS command then wait for 3 cycles
                                                                // to return to prev. state.
                                                                r_port_out_CS <= 0;
                                                                r_port_out_RAS <= 0;
                                                                r_port_out_CAS <= 0;
                                                                r_port_out_WE <= 0;
                                                                r_port_out_BA <= 0;
                                                                // Fixed: CAS=3 BL=8
                                                                // A: CAS Latency, A: BL
                                                                r_port_out_A <= {6'd0,3'd2,1'b0,3'd3};
                                                                r_port_out_A <= 0;
                                                                rs_DRAM_State <= ws_DRAM_State_Setup_MRS_EMRS_Delay;
                                                                rc_DRAM_Setup_MRS_EMRS_Latency <= 0;
                                                        end
                                                ws_DRAM_State_Setup_MRS_EMRS_Delay:
                                                        begin
                                                                // Deassert CS
                                                                r_port_out_CS <= 1;
                                                                rc_DRAM_Setup_MRS_EMRS_Latency <= rc_DRAM_Setup_MRS_EMRS_Latency + 1;
                                                                if(rc_DRAM_Setup_MRS_EMRS_Latency == 1)
                                                                        begin
                                                                                if(rs_DRAM_Next_State == ws_DRAM_State_IDLE)
                                                                                        r_int_out_IDLE <= 1;
                                                                                else
                                                                                        r_int_out_IDLE <= 0;
                                                                                rs_DRAM_State <= rs_DRAM_Next_State;
                                                                        end
                                                                else
                                                                        rs_DRAM_State <= ws_DRAM_State_Setup_MRS_EMRS_Delay;
                                                        end
                                                       
                                                       
                                                       
                                                       
                                                       
                                                       
                                                ws_DRAM_State_Refresh:
                                                        begin
                                                                // First send Refresh command then wait for 9 cycles
                                                                // to return to prev. state.
                                                                r_port_out_CS <= 0;
                                                                r_port_out_RAS <= 0;
                                                                r_port_out_CAS <= 0;
                                                                r_port_out_WE <= 1;
                                                                rs_DRAM_State <= ws_DRAM_State_Refresh_Delay;
                                                                r_Refresh_Validate <= 1;
                                                                rc_DRAM_Refresh_Latency <= 0;
                                                        end
                                                ws_DRAM_State_Refresh_Delay:
                                                        begin
                                                                // Deassert CS
                                                                r_Refresh_Validate <= 0;
                                                                r_port_out_CS <= 1;
                                                                rc_DRAM_Refresh_Latency <= rc_DRAM_Refresh_Latency + 1;
                                                                if(rc_DRAM_Refresh_Latency == 8)
                                                                        begin
                                                                                if(rs_DRAM_Next_State == ws_DRAM_State_IDLE)
                                                                                        r_int_out_IDLE <= 1;
                                                                                else
                                                                                        r_int_out_IDLE <= 0;
                                                                                rs_DRAM_State <= rs_DRAM_Next_State;
                                                                        end
                                                                else
                                                                        rs_DRAM_State <= rs_DRAM_State;
                                                        end
                                                       
                                                       
                                                       
                                                       
                                                       
                                                ws_DRAM_State_Precharge_All:
                                                        begin
                                                                // First send Precharge command then wait for 2 cycles
                                                                // to return to prev. state. Only all bank precharge is
                                                                // supported.
                                                                r_port_out_CS <= 0;
                                                                r_port_out_RAS <= 0;
                                                                r_port_out_CAS <= 1;
                                                                r_port_out_WE <= 0;
                                                                r_port_out_A <= 1;
                                                                r_port_out_A <= 0;
                                                                r_port_out_A <= 0;
                                                                rs_DRAM_State <= ws_DRAM_State_Precharge_All_Delay;
                                                                r_Bank_Open_Status <= 0;
                                                                rc_DRAM_Precharge_Latency <= 0;
                                                        end
                                                ws_DRAM_State_Precharge_All_Delay:
                                                        begin
                                                                // Deassert CS
                                                                r_port_out_CS <= 1;
                                                                rc_DRAM_Precharge_Latency <= rc_DRAM_Precharge_Latency + 1;
                                                                if(rc_DRAM_Precharge_Latency == 1)
                                                                        begin
                                                                                if(rs_DRAM_Next_State == ws_DRAM_State_IDLE)
                                                                                        r_int_out_IDLE <= 1;
                                                                                else
                                                                                        r_int_out_IDLE <= 0;
                                                                                rs_DRAM_State <= rs_DRAM_Next_State;
                                                                        end
                                                                else
                                                                        rs_DRAM_State <= rs_DRAM_State;
                                                        end
                                               
                                                default:
                                                        rs_DRAM_State <= ws_DRAM_State_IDLE;        // Default to IDLE state.
                                        endcase
                                end
                end
       
       
       
       
       
       
       
       
       
       
        // Timer used for Time Out operation.
        TimeOutCounter timeout_counter(
                .int_in_GCLK(int_in_GCLK),
                .int_in_GRST(int_in_GRST),
                .int_in_TimeOut_Value(r_Timeout_Counter_Value),
                .int_in_TimeOut_Hold(1'b1),
                .int_in_Count_Reset(r_Timeout_Counter_Reset),
                .int_out_TimeOut_Interrupt(w_Timeout_Interrupt)
        );       
       
        // Auto-Refresh Counter and Control. Use w_Refresh_Request and w_Refresh_Validate to indicate
        // Auto-Refresh require state and Auto-Refresh process state.
        wire w_Refresh_Interrupt;
        reg rc_Refresh_Count;
        assign w_Refresh_Request = (rc_Refresh_Count != 0);
        always @(posedge int_in_GCLK or negedge int_in_GRST)
                begin
                        if(~int_in_GRST)
                                begin
                                        rc_Refresh_Count <= 0;
                                end
                        else
                                begin
                                        if(r_Refresh_Validate & (rc_Refresh_Count > 8'h00))
                                                // Dec Counter. Min is 8'h00
                                                begin
                                                        if(~w_Refresh_Interrupt)
                                                                rc_Refresh_Count <= rc_Refresh_Count + 8'hFF;
                                                        else
                                                                rc_Refresh_Count <= rc_Refresh_Count;
                                                end
                                        else if(w_Refresh_Interrupt & (rc_Refresh_Count < 8'hFF))
                                                // Inc Counter. Max is 8'hFF.
                                                rc_Refresh_Count <= rc_Refresh_Count + 1;
                                        else
                                                rc_Refresh_Count <= rc_Refresh_Count;
                                end
                end
       
        // Use a counter to indicate how many refresh cycles is to be done.
        TimeOutCounter refresh_counter(
                .int_in_GCLK(int_in_GCLK),
                .int_in_GRST(int_in_GRST),
                .int_in_TimeOut_Value(16'd1560),
                .int_in_TimeOut_Hold(1'b0),
                .int_in_Count_Reset(1'b0),
                .int_out_TimeOut_Interrupt(w_Refresh_Interrupt)
        );       
       
       
       
        // CK Output. Note that it's 1/2 cycle late than original clock.
        // Because CK reg is set to zero at the beginning, we use posedge of GCLK2X
        // is possible to delay output to 1/2 cycle.
        reg r_int_CK_TOG;
        reg r_port_out_CK;
        reg r_port_out_CKS;
        reg r_CK_Enable_Delay;
       
        always @(posedge int_in_GCLK2X)
                begin
                        r_CK_Enable_Delay <= r_CK_Enable;
                        r_port_out_CK <= r_int_CK_TOG;
                        r_port_out_CKS <= ~r_int_CK_TOG;
                        if(~r_CK_Enable_Delay)
                                r_int_CK_TOG <= 0;
                        else
                                r_int_CK_TOG <= ~r_int_CK_TOG;
                end

       
        always @(posedge int_in_GCLK or negedge int_in_GRST)
                begin
                        if(~int_in_GRST)
                                begin
                                        r_int_in_Data_Read_Request <= 0;
                                        r_int_in_Data_Write_Request <= 0;
                                end
                        else
                                begin
                                        if(int_in_Data_Read_Request)
                                                r_int_in_Data_Read_Request <= ~r_int_in_Data_Read_Request;
                                        else
                                                r_int_in_Data_Read_Request <= r_int_in_Data_Read_Request;
                                        if(int_in_Data_Write_Request)
                                                r_int_in_Data_Write_Request <= ~r_int_in_Data_Write_Request;
                                        else
                                                r_int_in_Data_Write_Request <= r_int_in_Data_Write_Request;
                                end
                end

        reg r_port_out_CS_output_cache;
        reg r_port_out_RAS_output_cache;
        reg r_port_out_CAS_output_cache;
        reg r_port_out_WE_output_cache;
        reg r_port_out_BA_output_cache;
        reg r_port_out_A_output_cache;
        reg r_port_out_DQM_output_cache;
        reg r_port_out_CKE_output_cache;
        /*reg r_port_out_CK_output_cache;
        reg r_port_out_CKS_output_cache;*/
       
        // Delay one cycle
        always @(posedge int_in_GCLK)
                begin
                        r_port_out_CS_output_cache <= r_port_out_CS;
                        r_port_out_RAS_output_cache <= r_port_out_RAS;
                        r_port_out_CAS_output_cache <= r_port_out_CAS;
                        r_port_out_WE_output_cache <= r_port_out_WE;
                        r_port_out_BA_output_cache <= r_port_out_BA;
                        r_port_out_A_output_cache <= r_port_out_A;
                        r_port_out_DQM_output_cache <= r_port_out_DQM;
                        r_port_out_CKE_output_cache <= r_port_out_CKE;
                        /*r_port_out_CK_output_cache <= r_port_out_CK;
                        r_port_out_CKS_output_cache <= r_port_out_CKS;*/
                end
               
        assign port_out_CS = r_port_out_CS_output_cache;
        assign port_out_RAS = r_port_out_RAS_output_cache;
        assign port_out_CAS = r_port_out_CAS_output_cache;
        assign port_out_WE = r_port_out_WE_output_cache;
        assign port_out_BA = r_port_out_BA_output_cache;
        assign port_out_A = r_port_out_A_output_cache;
        assign port_out_DQM = r_port_out_DQM_output_cache;
        assign port_out_CKE = r_port_out_CKE_output_cache;
       
       
        /*assign port_out_CK = r_port_out_CK_output_cache;
        assign port_out_CKS = r_port_out_CKS_output_cache;*/
       
       
        /*assign port_out_CS = r_port_out_CS;
        assign port_out_RAS = r_port_out_RAS;
        assign port_out_CAS = r_port_out_CAS;
        assign port_out_WE = r_port_out_WE;
        assign port_out_BA = r_port_out_BA;
        assign port_out_A = r_port_out_A;
        assign port_out_DQM = r_port_out_DQM;
        assign port_out_CKE = r_port_out_CKE;*/
       
        assign port_out_CK = r_port_out_CK;
        assign port_out_CKS = r_port_out_CKS;
       
        //assign port_io_Data = r_port_io_Data_Out_EN ? r_port_io_Data_Out : 'bz;

endmodule

haha,端口都有说明了,自己根据输出延时计算下,然后把CK的延时调调就可以实现在基频上升沿采样数据了。测试尚未出现问题,但是如果供电不稳肯定会出问题。读写采用一个深度的队列,当int_out_CurrentState和int_out_CurrentState为低时就可以发下一条读写指令。
如果要用于不同容量的SDRAM或不同位数的SDRAM,自己修改

        // Because we use 16-bit sdram, the CAddr is aligned to real ca
        reg r_int_in_AccessAddr = 0;
        wire w_Request_RAddr = r_int_in_AccessAddr;
        wire w_Request_CAddr = {r_int_in_AccessAddr,3'b0};
        wire w_Request_BAddr = r_int_in_AccessAddr;
       
        reg r_Bank0_Address = 0;
        reg r_Bank1_Address = 0;
        reg r_Bank2_Address = 0;
        reg r_Bank3_Address = 0;
       
        wire w_Last_Open_RowAddr = (w_Request_BAddr == 0)?r_Bank0_Address :
                                                                          (w_Request_BAddr == 1)?r_Bank1_Address :
                                                                          (w_Request_BAddr == 2)?r_Bank2_Address :
                                                                          r_Bank3_Address;
这里的地址映射。


刚才少发了一个模块,补上来:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:    07:32:44 04/23/2012
// Design Name:
// Module Name:    TimeOutCounter
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module TimeOutCounter(
    input int_in_GCLK,
    input int_in_GRST,
       
    input int_in_TimeOut_Value,
    input int_in_TimeOut_Hold,                                // Active 1
    input int_in_Count_Reset,                                // Active 1
       
    output int_out_TimeOut_Interrupt
    );

        // When counter exceeds int_in_TimeOut_Value, if int_in_TimeOut_Hold
        // then not return to zero until a int_in_Count_Reset event occurs.
        // Else counter will return to zero and int_in_Count_Reset is effective too.
        reg rc_int_in_TimeOut_Counter;
        reg r_int_out_TimeOut_Interrupt;
        assign int_out_TimeOut_Interrupt = r_int_out_TimeOut_Interrupt;
        always @(posedge int_in_GCLK or negedge int_in_GRST)
                begin
                        if(~int_in_GRST)
                                begin
                                        rc_int_in_TimeOut_Counter <= 0;
                                        r_int_out_TimeOut_Interrupt <= 0;
                                end
                        else
                                begin
                                        r_int_out_TimeOut_Interrupt <= (rc_int_in_TimeOut_Counter == int_in_TimeOut_Value);
                                        if(rc_int_in_TimeOut_Counter == int_in_TimeOut_Value)
                                                begin
                                                        if(~int_in_TimeOut_Hold | int_in_Count_Reset)
                                                                rc_int_in_TimeOut_Counter <= 0;
                                                        else
                                                                rc_int_in_TimeOut_Counter <= rc_int_in_TimeOut_Counter;
                                                end
                                        else
                                                begin
                                                        if(int_in_Count_Reset)
                                                                rc_int_in_TimeOut_Counter <= 0;
                                                        else
                                                                rc_int_in_TimeOut_Counter <= rc_int_in_TimeOut_Counter + 1;
                                                end
                                end
                end

endmodule

这个模块用于超时计数,支持异步复位/超时保持/超时自动复位功能,用于启动时序计时。

chadusb 发表于 2012-7-4 09:39:47

又见大哥   
我有个sdram的想法不知道思路对不对
http://www.amobbs.com/thread-5484270-1-1.html
altera的pll功能xilinx dcm能实现吗?

wye11083 发表于 2012-7-4 10:13:39

chadusb 发表于 2012-7-4 09:39 static/image/common/back.gif
又见大哥   
我有个sdram的想法不知道思路对不对
http://www.amobbs.com/thread-5484270-1-1.html


PLL可以用DCM实现,但是也有代价,DCM只能产生固定的时钟,而且步进有限,只能产生(1-32)/(1-32)这么多个时钟,即1/1,1/2,。。,1/32,2/1,。。,32/32。

wye11083 发表于 2012-7-4 11:46:44

补充一个TestBench:

`timescale 1ns / 100ps

////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:   10:48:55 07/03/2012
// Design Name:   SDRController
// Module Name:   D:/USBDevelop/SDRController_tb.v
// Project Name:USBDevelop
// Target Device:
// Tool versions:
// Description:
//
// Verilog Test Fixture created by ISE for module: SDRController
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////

module SDRController_tb;

        // Inputs
        reg int_in_GRST;
        reg int_in_GCLK;
        reg int_in_GCLK2X;
        reg int_in_Read_AccessAddr;
        reg int_in_Write_AccessAddr;
        reg int_in_Data_Read_Request;
        reg int_in_Data_Write_Request;
        reg int_in_Command_Valid;
        reg int_in_Data_In;

        // Outputs
        wire int_out_Data_Out;
        wire int_out_Data_Valid;
        wire int_out_IDLE;
        wire port_out_Chip_Select;
        wire port_out_CS;
        wire port_out_RAS;
        wire port_out_CAS;
        wire port_out_WE;
        wire port_out_BA;
        wire port_out_A;
        wire port_out_CK;
        wire port_out_CKS;
        wire port_out_CKE;
        wire port_out_DQM;

        // Bidirs
        wire port_io_Data;
       
        reg r_port_io_Data;
        reg r_port_io_Data_EN;
       
        assign port_io_Data = r_port_io_Data_EN?r_port_io_Data:'bz;

        // Instantiate the Unit Under Test (UUT)
        SDRController uut (
                .int_in_GRST(int_in_GRST),
                .int_in_GCLK(int_in_GCLK),
                .int_in_GCLK2X(int_in_GCLK2X),
                .int_in_Read_AccessAddr(int_in_Read_AccessAddr),
                .int_in_Write_AccessAddr(int_in_Write_AccessAddr),
                .int_in_Data_Read_Request(int_in_Data_Read_Request),
                .int_in_Data_Write_Request(int_in_Data_Write_Request),
                .int_in_Command_Valid(int_in_Command_Valid),
                .int_in_Data_In(int_in_Data_In),
                .int_out_Data_Out(int_out_Data_Out),
                .int_out_Data_Valid(int_out_Data_Valid),
                .int_out_IDLE(int_out_IDLE),
                .port_out_Chip_Select(port_out_Chip_Select),
                .port_out_CS(port_out_CS),
                .port_out_RAS(port_out_RAS),
                .port_out_CAS(port_out_CAS),
                .port_out_WE(port_out_WE),
                .port_out_BA(port_out_BA),
                .port_out_A(port_out_A),
                .port_io_Data(port_io_Data),
                .port_out_CK(port_out_CK),
                .port_out_CKS(port_out_CKS),
                .port_out_CKE(port_out_CKE),
                .port_out_DQM(port_out_DQM)
        );

        initial begin
                // Initialize Inputs
                r_port_io_Data_EN = 0;
                int_in_GRST = 0;
                int_in_GCLK = 1;
                int_in_GCLK2X = 1;
                int_in_Read_AccessAddr = 0;
                int_in_Write_AccessAddr = 0;
                int_in_Data_Read_Request = 0;
                int_in_Data_Write_Request = 0;
                int_in_Command_Valid = 0;
                int_in_Data_In = 0;

                // Wait 100 ns for global reset to finish
                #100;
      
                // Add stimulus here
               
                int_in_GRST = 1;
               
                #200000;
                r_port_io_Data_EN=1;
                #10;
                while(~int_out_IDLE)#10;
                #100;
                int_in_Read_AccessAddr = 0;
                int_in_Data_Read_Request = 1;
                #10;
                int_in_Data_Read_Request = 0;
                #10;
                while(~int_out_IDLE)#10;
                int_in_Read_AccessAddr = 512;
                int_in_Data_Read_Request = 1;
                #10;
                int_in_Data_Read_Request = 0;
                #10;
                while(~int_out_IDLE)#10;
                int_in_Read_AccessAddr = 32'h00400000;
                int_in_Data_Read_Request = 1;
                #10;
                int_in_Data_Read_Request = 0;
                #10;
                while(~int_out_IDLE)#10;
                r_port_io_Data_EN=0;
                int_in_Data_Write_Request = 1;
                int_in_Write_AccessAddr = 32'h00400100;
                #10;
                int_in_Data_Write_Request = 0;
                #10;
                while(~int_out_IDLE)#10;
                int_in_Data_Write_Request = 1;
                int_in_Write_AccessAddr = 32'h00000000;
                #10;
                int_in_Data_Write_Request = 0;
                #10;
               
                #1200;
                #10;
                while(~int_out_IDLE)#10;
                #100;
                r_port_io_Data_EN=1;
                int_in_Read_AccessAddr = 0;
                int_in_Data_Read_Request = 1;
                #10;
                int_in_Data_Read_Request = 0;
                #10;
                while(~int_out_IDLE)#10;
                int_in_Read_AccessAddr = 512;
                int_in_Data_Read_Request = 1;
                #10;
                int_in_Data_Read_Request = 0;
                #10;
                while(~int_out_IDLE)#10;
                int_in_Read_AccessAddr = 32'h01400000;
                int_in_Data_Read_Request = 1;
                #10;
                int_in_Data_Read_Request = 0;
                #10;
                #18000;
                while(~int_out_IDLE)#10;
                r_port_io_Data_EN=0;
                int_in_Data_Write_Request = 1;
                int_in_Write_AccessAddr = 32'h00400100;
                #10;
                int_in_Data_Write_Request = 0;
                #10;
                while(~int_out_IDLE)#10;
                int_in_Data_Write_Request = 1;
                int_in_Write_AccessAddr = 32'h00000000;
                #10;
                int_in_Data_Write_Request = 0;
                #10;

        end
       
        always #10 r_port_io_Data = $random;
        always #10 int_in_Data_In = {$random,$random,$random,$random};
       
        always #2.5 int_in_GCLK2X = ~int_in_GCLK2X;
        always #5 int_in_GCLK = ~int_in_GCLK;
      
endmodule

另补充一点说明:需要在XST配置属性和MAP配置属性中把IOB Reg Packing全部选中,否则会出现时序异常。GCLK和GCLK2X时钟为同一个DCM或DLL产生的1X和2X时钟,不要移相。经过计算,建立时间可以达到要求,数据正常。另外,到SDRAM的CK端需要调整为Fast Slew。

Nuker 发表于 2012-7-4 15:25:30

花2分钟粗粗看了一下,这个一点也不垃圾,有Bank/Row自动激活/预充功能,非常实用。

chadusb 发表于 2012-7-4 15:52:16

我看了下代码,看惯了3个模块的通用控制器感觉还是不习惯,呵呵,那个ck是什么端口,还要用lvds接?你那个sdram多大的怎么都是32位地址线,自己修改的话是不是这些地址线,以及映射地址都得改,还有setup_MRS_EMRS(应该是LOAD_MODE吧?)那里也要改?队列深度是不是那个128位的reg?如果把那个队列改大,是不是可以不用fifo就能异步了?

wye11083 发表于 2012-7-4 21:54:18

chadusb 发表于 2012-7-4 15:52 static/image/common/back.gif
我看了下代码,看惯了3个模块的通用控制器感觉还是不习惯,呵呵,那个ck是什么端口,还要用lvds接?你那个sd ...

CK是SDRAM的时钟线,不需要LVDS,那个接口是接DDR用的,DDR模块正在开发中。用不同的内存需要改的是地址线的映射,而不是地址线。128b是因为我用的16bit的内存,BL=8,因此一次要读进去16字节的数据。这些都可以根据实际情况调整,状态机不需要动,已经测试正常工作的。这些都可以根据情况在状态机中配置,在外面修改接口和相应的读写计数器的。即状态机框架不动,只修改内外的配置寄存器和wire接线。如果你用的是16Mx16的SDRAM,就不用改任何东西,接上去就可以工作。

M.lee 发表于 2012-7-25 10:45:25

wye11083 发表于 2012-7-4 21:54 static/image/common/back.gif
CK是SDRAM的时钟线,不需要LVDS,那个接口是接DDR用的,DDR模块正在开发中。用不同的内存需要改的是地址 ...


/*******************************************************************
*Project Name:sdram
*ModuleName :sdram
*Target Device :EP1C6Q240C8
*Clkin   :50M
*Desisgner:kang
*Date    :2010-12-01
*Version   :1.00
*Descriprion :sdram controller
*Additional Comments :sdram controller works at 125M HZ.
*******************************************************************/
module sdram_self(
//input signals
        input   clk,
        input   rst,
        input   wr_req,
        input   rd_req,
        input    addr,   //from bus
        input    data_write, //from bus
        //output signals
        output   cs_n,
        output   cas_n,
        output   ras_n,
        output   cke,
        output reg ba,
        output reg add,   //give sdram
        output   we_n,
        output   wr_ack,
        output   rd_ack,
        output   busy,
        output   data_read,
        output   wr_done,
        output   rd_done,
//inout signals
        inout       dq
    );



//Initial state machine parameters   
parameterINIT_NOP =4'd0,
    INIT_PRE =4'd1,
    INIT_AR =4'd2,
    INIT_MRS =4'd3,
    INIT_CNT =4'd4,
    INIT_DONE=4'd5;



//Work state machine parameters
parameter WORK_IDLE =4'd0,
    WORK_ACTIVE =4'd1,
    WORK_READ =4'd2,
    WORK_RD=4'd3,
    WORK_RWAIT =4'd4,
    WORK_WRITE =4'd5,
    WORK_WD=4'd6,
    WORK_TDAL =4'd7,
    WORK_AR=4'd8;



//Command parameters
parameter CMD_INIT   =5'b01111, //Initial after power on
    CMD_NOP   =5'b10111, //NOP command
    CMD_ACTIVE=5'b10011, //ACTIVE command
    CMD_READ   =5'b10101, //READ command
    CMD_WRITE=5'b10100, //WRITE command
    CMD_BURSTSTOP =5'b10110, //BURST stop
    CMD_PRECHARGE =5'b10010, //precharge
    CMD_AUTOREFRESH=5'b10001, //auto refersh
    CMD_LOADMODEREG=5'b10000; //load mode register
   
//timing parameters
parameterTRP_CLK =4'd4,    //precharge
    TRFC_CLK =4'd6,    //refresh
    TMRD_CLK =4'd6,    //load mode register
    TRCD_CLK =4'd2,    //row to column delay
    TCL_CLK =4'd3,    //cas latency
    TREAD_CLK=4'd8,    //read
    TWRITE_CLK=4'd8,    //write
    TDAL_CLK =4'd3;    //after write,wait clock num



/**********************************************************************
******************from here starts the control code********************
***********************************************************************/




/***********************************************************************
//delay 200us after power on
//this counter depends on the work frequency
//default:125M HZ
***********************************************************************/



//counter_200us
        reg counter_200us;
       
        always @(posedge clk or negedge rst)   
                begin
                        if(!rst)
                                counter_200us<=0;
                        else if(counter_200us<15'd25000)//if 80MHZ,16000
                                counter_200us<=counter_200us+1'b1;
                end



//done_200us
        wire done_200us;
       
        assign done_200us=(counter_200us>=15'd25000); //16000,80mhz

/**********************************************************************
//command assignments
//command is made up of cke,cs_n,ras_n,cas_n,we_n
//command's value is produced by the work state machine
**********************************************************************/

        reg command;
       
        assign {cke,cs_n,ras_n,cas_n,we_n}=command;

/**********************************************************************
//Initial state machine
//this state machine is only avaliable after power on,and only runs once
//when this state machine runs over,then the controller runs in the work state machine
//
***********************************************************************/



        reg init_nextstate; //next state
        reg init_state;//current state
        reg init_counter; //this counter is used to make delay in the initial state machine
        reg init_cmd; //cmd in the initial state machine
        reg init_ba; // bank
        reg init_addr;//
        reg refresh_counter;
        always @(posedge clk or negedge rst)
                begin
                if(!rst) begin
                        init_cmd<=CMD_INIT;
                        init_ba<=2'b11;
                        init_addr<=12'hfff;
                        init_state<=INIT_NOP;
                        init_state<=INIT_NOP;
                        init_counter<=0;
                        refresh_counter<=0;
                        end
                else begin
                case(init_state)
                        INIT_NOP :   //wait 200us after power on, and then go the the next state
                                begin
                                        init_cmd<=CMD_NOP;
                                        init_ba<=2'b11;
                                        init_addr<=12'hfff;
                                        if(done_200us) init_state<=INIT_PRE;
                                end
                        INIT_PRE :   //precharge
                                begin
                                        init_cmd<=CMD_PRECHARGE;
                                        init_ba<=2'b11;
                                        init_addr<=12'hfff;
                                        init_counter<=TRP_CLK;
                                        init_state<=INIT_CNT;
                                        init_nextstate<=INIT_AR;
                                end
                        INIT_AR:   //auto refresh, in the initial state,we run auto refresh 3 times
                                begin
                                        init_ba<=2'b11;
                                        init_addr<=12'hfff;
                                        init_counter<=TRFC_CLK;
                                        if(refresh_counter==4'h7)
                                                begin
                                                        init_state<=INIT_MRS;
                                                end
                                        else
                                                begin
                                                        refresh_counter<=refresh_counter+1'b1;
                                                        init_cmd<=CMD_AUTOREFRESH;
                                                        init_state<=INIT_CNT;
                                                end
                                        init_nextstate<=INIT_AR;
                                end
                        INIT_MRS :   //load the mode register
                                begin
                                        init_cmd<=CMD_AUTOREFRESH;
                                        init_ba<=2'b00;
                                        init_addr<={
                                                2'b00,//a11=0,a10=0;
                                                1'b0,   //a9,burst read and write
                                                2'b00,//a8=0;a7=0;
                                                3'b011,//cas latency=3
                                                1'b0,   //burst mode set
                                                3'b011//burst data length set,here we use the length of 8
                                                };
                                        init_counter<=TRFC_CLK;
                                        init_state<=INIT_CNT;
                                        init_nextstate<=INIT_DONE;
                                end
                        INIT_CNT :      //init state machine counter, used to produce delay
                                begin
                                        init_cmd<=CMD_NOP;
                                        init_ba<=2'b11;
                                        init_addr<=12'hfff;
                                        if(init_counter>4'd1) init_counter<=init_counter-1'b1;
                                        else init_state<=init_nextstate;
                                end
                        INIT_DONE:      //initial done
                                        init_state<=INIT_DONE;
                                default:
                                begin
                                        init_state<=INIT_NOP;
                                        init_ba<=2'b11;
                                        init_addr<=12'hfff;
                                end
                endcase
        end
end



        wire sign_init_done;
       
        assign sign_init_done=(init_state==INIT_DONE)?1'b1:1'b0;

/*******************************************************************************
//refresh counter
//sdram need refresh every 64ms,and this chip has 4096 columns
//so we has to fresh every 15.625us
*******************************************************************************/



//counter_15us
        reg counter_15us;
               
        always @(posedge clk or negedge rst)
                begin
                        if(!rst) counter_15us<=0;
                        else if(counter_15us>=11'd1875) counter_15us<=0; //11'd1200
                               
                                        else counter_15us<=counter_15us+1'b1;
                end



//refresh request and answer back
        reg refresh_req;//refresh request
        wire refresh_ack;//refresh answer back
       
        always @(posedge clk or negedge rst)
                begin
                        if(!rst) refresh_req<=0;
                        else if(counter_15us>=1875) refresh_req<=1'b1; //11'd1200
                                        else if(refresh_ack) refresh_req<=0;
                end




/*******************************************************************************
//work state machine
//this state machine works at the normal time, including read, write and refresh
//when initial state machine runs over, this machine begin to run
//
*******************************************************************************/
                reg work_state;    //current state
                reg work_counter;    //work counter, used to make delay
                reg wr_n;      //when write,wr_n=0;when read,wr_n=1;
                reg oe;
               
                always @(posedge clk or negedge rst)
                        begin
                                if(!rst) begin
                                command<=CMD_INIT;
                                ba<=2'b11;
                                add=12'hfff;
                                work_state<=WORK_IDLE;
                                work_counter<=0;
                        end
                                else if(sign_init_done)//when initial state machine done, work state machine begin to run
                                        begin
                                        case(work_state)
                                                WORK_IDLE :   //in the idle state, we will enter autorefresh or active state as the next state
                                                        begin
                                                                command<=CMD_NOP;
                                                                ba<=2'b11;
                                                                add=12'hfff;
                                                                work_counter<=0;
                                                                if(refresh_req)
                                                                        begin
                                                                                work_state<=WORK_AR;
                                                                        end
                                                                else if(wr_req)
                                                                //begin
                                                                //if((prior_rowadd==addr)&&is_prior_wr) work_state<=WORK_WRITE;
                                                                //else
                                                                        begin
                                                                                work_state<=WORK_ACTIVE;   
                                                                                wr_n<=0;   
                                                                        end
                                                                //end
                                                                        else if(rd_req)
                                                                                //begin
                                                                                //if((prior_rowadd==addr)&&is_prior_rd) work_state<=WORK_READ;
                                                                                        //else
                                                                                begin
                                                                                        work_state<=WORK_ACTIVE;
                                                                                        wr_n<=1'b1;
                                                                                end
                                                                                //end
                                                                                        else work_state<=WORK_IDLE;
                                                        end
/*************************************************************************/                                               
                                        WORK_ACTIVE :   //write the row address,and wait TRCD_CLK clks
                                                begin
                                                ba<=addr;
                                                add=addr;
                                                        if(work_counter>=TRCD_CLK)
                                                                begin
                                                                        if(wr_n) work_state<=WORK_READ;
                                                                        else work_state<=WORK_WRITE;
                                                                                  work_counter<=0;
                                                                end
                                                        else begin
                                                                if(work_counter==0) command<=CMD_ACTIVE;
                                                                else command<=CMD_NOP;
                                                                        work_state<=WORK_ACTIVE;
                                                                        work_counter<=work_counter+1'b1;
                                                                end
                                                end
/*************************************************************************/                                                                                               
                                WORK_READ :   //read. wait TCL_CLK clks, then enter WORK_RD
                                begin
                                        ba<=addr;
                                        add<={
                                        4'b0100,    //A10=1;allow precharge after write
                                        addr   //column address
                                        };
                                        if(work_counter>=(TCL_CLK))
                                                begin
                                                work_state<=WORK_RD;
                                                work_counter<=0;
                                                end
                                        else begin
                                                work_state<=WORK_READ;
                                                work_counter<=work_counter+1'b1;
                                                end
                                        if(work_counter==0) command<=CMD_READ;
                                        else command<=CMD_NOP;
                                end
/*************************************************************************/                                               
                                WORK_RD:   //read data
                                begin
                                        command<=CMD_NOP;
                                        if(work_counter>=(TREAD_CLK-1'b1))
                                        begin
                                                work_state<=WORK_RWAIT;
                                                work_counter<=0;
                                        end
                                        else begin
                                                work_state<=WORK_RD;
                                                work_counter<=work_counter+1'b1;
                                                end
                                end
/*************************************************************************/                                                                               
                                WORK_RWAIT :   //read wait
                                begin
                                        command<=CMD_NOP;
                                        if(work_counter>=(TRP_CLK))
                                                begin
                                                work_state<=WORK_IDLE;
                                                work_counter<=0;
                                                end
                                        else begin
                                                work_state<=WORK_RWAIT;
                                                work_counter<=work_counter+1'b1;
                                                end
                                end
/*************************************************************************/                                               
                                WORK_WRITE :   //write
                                begin
                                        command<=CMD_WRITE;
                                        ba<=addr;
                                        add<={
                                                4'b0100,    //A10=1;allow precharge after write
                                                addr   //column address
                                                };
                                        work_state<=WORK_WD;
                                end
/*************************************************************************/                                               
                                WORK_WD:   //write data
                                begin
                                        command<=CMD_NOP;
                                        if(work_counter>=(TWRITE_CLK-1'b1))
                                                begin
                                                work_state<=WORK_TDAL;
                                                work_counter<=0;
                                                end
                                        else begin
                                                work_state<=WORK_WD;
                                                work_counter<=work_counter+1'b1;
                                                end
                                end
/*************************************************************************/                               
                                WORK_TDAL :   //write delay
                                begin
                                        command<=CMD_NOP;
                                        if(work_counter>=TDAL_CLK)
                                                begin
                                                work_state<=WORK_IDLE;
                                                work_counter<=0;
                                                end
                                        else begin
                                                work_state<=WORK_TDAL;
                                                work_counter<=work_counter+1'b1;
                                                end
                                end
/*************************************************************************/                                               
                        WORK_AR:   //auto refresh
                        begin
                                if(work_counter==0) command<=CMD_AUTOREFRESH;
                                else command<=CMD_NOP;
                                        ba<=2'b11;
                                        add<=12'hfff;
                                if(work_counter==TRFC_CLK)
                                        begin
                                        work_state<=WORK_IDLE;
                                        work_counter<=0;
                                        end
                                elsebegin
                                        work_state<=WORK_AR;
                                        work_counter<=work_counter+1'b1;
                                        end
                        end
                       
                        default:
                                begin
                                command<=CMD_NOP;
                                work_state<=WORK_IDLE;
                                work_counter<=0;
                                end
                endcase
        end
        else          //when in initial state, all parameters are equaled to the initial state
                begin
                command<=init_cmd;
                ba<=init_ba;
                add<=init_addr;
                work_counter<=0;
                end
end

/*************************************************************************/                                               

                assign busy=(sign_init_done&&(work_state==WORK_IDLE))?1'b0:1'b1;
                assign refresh_ack=(work_state==WORK_AR);
                assign wr_ack=(work_state==WORK_WD);
                assign rd_ack=(work_state==WORK_RD);
                assign wr_done=(work_state==WORK_TDAL)&&(work_counter==5'd0);
                assign rd_done=(work_state==WORK_RWAIT)&&(work_counter==5'd0);

                assign data_read=dq;

                assign dq=((work_state==WORK_WD)||(work_state==WORK_WRITE)||(work_state==WORK_TDAL))?data_write:16'hzzzz;

               

endmodule

我觉得这个SDRAM读写的还不错的,但是就是不会写testbench,麻烦帮忙给看看,多谢了

fishplj2000 发表于 2012-8-7 17:16:04

单字节写入
8字节写入
全页写入
均支持么?

wye11083 发表于 2012-8-7 23:06:15

fishplj2000 发表于 2012-8-7 17:16 static/image/common/back.gif
单字节写入
8字节写入
全页写入


这个SDRAM模块目前已经不再支持了。考虑到效率,仅支持BL=8。而且延时也需要调整。如果有需要,你可以等待半个月,届时我应该会推出8端口(4读4写)高速DDR控制器(理论最大带宽98%)。

fishplj2000 发表于 2012-8-8 17:50:14

wye11083 发表于 2012-8-7 23:06 static/image/common/back.gif
这个SDRAM模块目前已经不再支持了。考虑到效率,仅支持BL=8。而且延时也需要调整。如果有需要,你可以等 ...

{:victory:} 牛
要顶

代码里面的reg和wire的命名都好长啊!下次能不能精简些?{:lol:}

liurangzhou 发表于 2012-8-8 18:14:10

顶一下,也在弄SDRAM,做TFT显示,我做的是BL=full page的

chuwei6 发表于 2012-8-8 19:00:47

顶一下,{:biggrin:}

lyl520719 发表于 2012-10-18 11:31:12

这个必须要顶。

stdio 发表于 2012-10-18 12:06:33

这个厉害!!

dengterry 发表于 2016-2-28 14:25:36

mark下 最近在学习FPGA

monkey.liu 发表于 2016-2-28 17:37:54

谢谢分享,先收藏
页: [1]
查看完整版本: 我也来分享个SDRAM的Verilog垃圾代码