123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- /*
- * SDRAM controller
- */
- module SDRAMcontroller(
- input clk,
- // read
- output busy, // high if controller is busy
- input [23:0] addr, // addr to read or write 2*24 * 16 = 32MiBytes
- input [31:0] d, // data to write
- input we, // high if write, low if read
- input start, // high when controller should start reading/writing
- output [31:0] q, // read data output
- //output reg q_ready_reg_delay, // read data ready
- output q_ready, // read data ready
- output initDone, // high when initialization done
- // SDRAM
- output SDRAM_CSn, SDRAM_WEn, SDRAM_CASn, SDRAM_RASn,
- output reg SDRAM_CKE,
- output reg [12:0] SDRAM_A,
- output reg [1:0] SDRAM_BA,
- output reg [1:0] SDRAM_DQM,
- inout [15:0] SDRAM_DQ
- );
- reg q_ready_reg;
- assign q_ready = (start && q_ready_reg);
- assign busy = (state != s_idle);
- assign initDone = (state != s_init);
- reg [3:0] SDRAM_CMD;
- parameter [3:0] SDRAM_CMD_UNSELECTED= 4'b1000;
- parameter [3:0] SDRAM_CMD_NOP = 4'b0111;
- parameter [3:0] SDRAM_CMD_ACTIVE = 4'b0011;
- parameter [3:0] SDRAM_CMD_READ = 4'b0101;
- parameter [3:0] SDRAM_CMD_WRITE = 4'b0100;
- parameter [3:0] SDRAM_CMD_TERMINATE = 4'b0110;
- parameter [3:0] SDRAM_CMD_PRECHARGE = 4'b0010;
- parameter [3:0] SDRAM_CMD_REFRESH = 4'b0001;
- parameter [3:0] SDRAM_CMD_LOADMODE = 4'b0000;
- assign {SDRAM_CSn, SDRAM_RASn, SDRAM_CASn, SDRAM_WEn} = SDRAM_CMD;
- // 48LC16M16A2-7E specs
- parameter sdram_column_bits = 10;
- parameter sdram_address_width = 25;
- parameter sdram_startup_cycles = 10100; // -- 100us, plus a little more, @ 100MHz
- parameter cycles_per_refresh = 780; // 25MHz -> 195; // (64000*100)/8192-1 Cycled as (64ms @100MHz)/8192 rows (780 for 100mhz)
- // bit indexes used when splitting the address into row/colum/bank.
- parameter start_of_col = 0;
- parameter end_of_col = sdram_column_bits-2;
- parameter start_of_bank = sdram_column_bits-1;
- parameter end_of_bank = sdram_column_bits;
- parameter START_OF_ROW = sdram_column_bits+1;
- parameter END_OF_ROW = sdram_address_width-2;
- parameter prefresh_cmd = 10;
- parameter ROW_PAD_BITS = 12 + START_OF_ROW - END_OF_ROW;
- wire [12:0] addr_row;
- wire [12:0] addr_col;
- wire [1:0] addr_bank;
- //--------------------------------------------------------------------------
- // Seperate the address into row / bank / address
- //--------------------------------------------------------------------------
- //11111111110 111010100
- wire [24:0] bigaddr;
- assign bigaddr = addr << 1;
- assign addr_col = bigaddr[8:0];
- assign addr_row = bigaddr[21:9];
- assign addr_bank = bigaddr[23:22];
- //DQ write port
- reg [15:0] WrData;
- reg SDRAM_DQ_OE;
- assign SDRAM_DQ = SDRAM_DQ_OE ? WrData : 16'hZZZZ;
- wire [15:0] SDRAM_Q;
- assign SDRAM_Q = SDRAM_DQ;
- //Input data
- wire [15:0] data_low, data_high;
- assign data_low = d[15:0];
- assign data_high = d[31:16];
- //Output data
- reg [15:0] q_low, q_high;
- assign q = {q_high, q_low};
- // state of controller
- reg [6:0] state;
- parameter s_init = 0;
- parameter s_idle = 1;
- parameter s_open_in_2 = 2;
- parameter s_open_in_1 = 3;
- parameter s_write_1 = 4;
- parameter s_write_2 = 5;
- parameter s_write_3 = 6;
- parameter s_read_1 = 7;
- parameter s_read_2 = 8;
- parameter s_read_3 = 9;
- parameter s_read_4 = 10;
- parameter s_precharge = 11;
- parameter s_idle_in_6 = 12;
- parameter s_idle_in_5 = 13;
- parameter s_idle_in_4 = 14;
- parameter s_idle_in_3 = 15;
- parameter s_idle_in_2 = 16;
- parameter s_idle_in_1 = 17;
- parameter s_read_precharge = 18;
- reg [9:0] startup_refresh_count = 0;
- wire refresh;
- assign refresh = (SDRAM_CMD == SDRAM_CMD_REFRESH);
- //140ns = 1clk
- //63980 - 42820 = 21160
- // 21160 / 40 = 529 cycles
- // 25MHz -> 25.000.000 cycles per sec
- // 25.000.000*0.064 -> 1.600.000 cycles per 64ms
- // 1.600.000 / 8192 auto refreshes -> refresh after 196 cycles
- // for 50mhz this should be 196*2 cycles and for 100mhz this should be 196*4 cycles
- reg [31:0] InitCounter = 0;
- reg isRefreshing = 1'b0;
- always @(posedge clk)
- begin
- /*if (reset)
- begin
- SDRAM_BA <= 2'b00;
- SDRAM_DQM <= 2'b11;
- SDRAM_A <= 0;
- SDRAM_CMD <= SDRAM_CMD_UNSELECTED;
- SDRAM_CKE <= 0;
- SDRAM_DQ_OE <= 0;
- state <= 0;
- WrData <= 0;
- q_ready_reg <= 0;
- q_low <= 0;
- q_high <= 0;
- startup_refresh_count <= 0;
- end
- else */
- begin
-
- startup_refresh_count <= startup_refresh_count+1;
- case(state)
- s_init:
- begin
- q_ready_reg <= 1'b0;
- SDRAM_CKE <= 1'b1;
- SDRAM_DQM <= 2'b00;
- case(InitCounter)
- 1010: begin
- SDRAM_CMD <= SDRAM_CMD_PRECHARGE;
- SDRAM_A <= 1024;
- end
- 1015: begin
- SDRAM_CMD <= SDRAM_CMD_REFRESH;
- end
- 1025: begin
- SDRAM_CMD <= SDRAM_CMD_REFRESH;
- end
- 1035: begin
- SDRAM_CMD <= SDRAM_CMD_LOADMODE;
- SDRAM_A <= 6'b100001; //cas = 2, and burst length = 2, burst type = sequenctial
- end
- 1036: begin
- SDRAM_CMD <= SDRAM_CMD_NOP;
- SDRAM_A <= 0;
- state <= s_idle;
- end
- default: begin
- SDRAM_CMD <= SDRAM_CMD_NOP;
- end
- endcase
- InitCounter <= InitCounter + 1'b1;
- end
- s_idle:
- begin
- q_ready_reg <= 1'b0;
- if (startup_refresh_count > cycles_per_refresh) //refresh has priority!
- begin
- state <= s_idle_in_6;
- isRefreshing <= 1'b1;
- SDRAM_CMD <= SDRAM_CMD_REFRESH;
- startup_refresh_count <= 0;
- end
- else
- begin
- if (start)
- begin
- //--------------------------------
- //-- Start the read or write cycle.
- //-- First task is to open the row
- //--------------------------------
- state <= s_open_in_2;
- SDRAM_CMD <= SDRAM_CMD_ACTIVE;
- SDRAM_A <= addr_row;
- SDRAM_BA <= addr_bank;
- end
- else //if nothing happens, just nop
- begin
- SDRAM_DQM <= 2'b00;
- SDRAM_CMD <= SDRAM_CMD_NOP;
- SDRAM_A <= 0;
- end
- end
-
- end
- s_open_in_2:
- begin
- state <= s_open_in_1;
- SDRAM_CMD <= SDRAM_CMD_NOP;
- end
- s_open_in_1:
- begin
- // if write command
- if (we)
- begin
- state <= s_write_1;
- WrData <= data_low;
- SDRAM_DQ_OE <= 1'b1;
- end
- else // if read command
- begin
- state <= s_read_1;
- SDRAM_DQ_OE <= 1'b0;
- end
- end
- s_write_1:
- begin
- state <= s_write_2;
- SDRAM_CMD <= SDRAM_CMD_WRITE;
- SDRAM_A <= addr_col;
- SDRAM_A[prefresh_cmd] <= 1'b0; // A10 actually matters - it selects auto precharge
- SDRAM_BA <= addr_bank;
- SDRAM_DQM <= 2'b00;
- WrData <= data_low;
- end
- s_write_2:
- begin
- WrData <= data_high;
- SDRAM_CMD <= SDRAM_CMD_NOP;
- state <= s_write_3;
- end
- s_write_3:
- begin
- state <= s_precharge;
- SDRAM_DQ_OE <= 1'b0;
- end
- s_precharge:
- begin
- q_ready_reg <= 1'b1;
- state <= s_idle_in_3;
- SDRAM_CMD <= SDRAM_CMD_PRECHARGE;
- SDRAM_A[prefresh_cmd] <= 1'b1; // A10 actually matters - it selects all banks or just one
- end
- s_idle_in_6:
- begin
- state <= s_idle_in_5;
- SDRAM_CMD <= SDRAM_CMD_NOP;
- end
- s_idle_in_5: state <= s_idle_in_4;
- s_idle_in_4: state <= s_idle_in_3;
- s_idle_in_3:
- begin
- if (!start) q_ready_reg <= 1'b0;
- state <= s_idle_in_2;
- SDRAM_CMD <= SDRAM_CMD_NOP;
- end
- s_idle_in_2:
- begin
- state <= s_idle_in_1;
- if (!start) q_ready_reg <= 1'b0;
- end
- s_idle_in_1:
- begin
- if (!start || isRefreshing || !q_ready_reg)
- begin
- q_ready_reg <= 1'b0;
- state <= s_idle;
- isRefreshing <= 1'b0;
- end
- end
- s_read_1:
- begin
- state <= s_read_2;
- SDRAM_CMD <= SDRAM_CMD_READ;
- SDRAM_A <= addr_col;
- SDRAM_BA <= addr_bank;
- SDRAM_A[prefresh_cmd] <= 1'b0; // A10 actually matters - it selects auto precharge
- SDRAM_DQM <= 2'b00;
- end
- s_read_2: begin
- SDRAM_CMD <= SDRAM_CMD_NOP;
- state <= s_read_3;
- end
- s_read_3: begin
- state <= s_read_4;
-
- end
- s_read_4:
- begin
- state <= s_read_precharge;
- q_low <= SDRAM_Q;
-
-
- end
- s_read_precharge:
- begin
- q_high <= SDRAM_Q;
- q_ready_reg <= 1'b1;
- state <= s_idle_in_3;
- SDRAM_CMD <= SDRAM_CMD_PRECHARGE;
- SDRAM_A[prefresh_cmd] <= 1'b1; // A10 actually matters - it selects all banks or just one
- end
- endcase
- end
-
- end
- /*
- reg q_ready_reg;
- always @(posedge clk)
- begin
- if (reset)
- begin
- q_ready_reg_delay <= 0;
- end
- else
- begin
- q_ready_reg_delay <= q_ready_reg;
-
- //if (state == s_read_4)
- // q_low <= SDRAM_Q;
- //if (state == s_read_precharge)
- // q_high <= SDRAM_Q;
- end
- end
- */
- initial
- begin
- SDRAM_BA <= 2'b00;
- SDRAM_DQM <= 2'b11;
- SDRAM_A <= 0;
- SDRAM_CMD <= SDRAM_CMD_UNSELECTED;
- SDRAM_CKE <= 0;
- SDRAM_DQ_OE <= 0;
- state <= 0;
- WrData <= 0;
- q_ready_reg <= 0;
- q_low <= 0;
- q_high <= 0;
- startup_refresh_count <= 0;
- //q_ready_reg_delay <= 0;
- end
- endmodule
|