OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [trunk/] [fpga/] [experiments/] [memctrl/] [sim/] [memctrl-2/] [ramctrl/] [ramctrl.v] - Rev 314

Compare with Previous | Blame | View Log

//
// ramctrl.v -- RAM controller
//
 
 
`include "ramctrl/k4s561632e.v"
 
 
`timescale 1ns/10ps
`default_nettype none
 
 
`define MODE		13'h0032	// CL = 3, sequ. burst length = 4
 
`define CMD_MRSET	3'b000		// mode register set
`define CMD_ARFRS	3'b001		// auto refresh
`define CMD_PRCHG	3'b010		// precharge (deactivate row/rows)
`define CMD_ACTV	3'b011		// select bank, activate row
`define CMD_WRITE	3'b100		// select bank & column, start write
`define CMD_READ	3'b101		// select bank & column, start read
`define CMD_BSTOP	3'b110		// burst stop
`define CMD_NOP		3'b111		// no operation
 
//
// Note: The FSM is a registered Mealy machine. Its actions, which
//       are noted here for a specific state, take place in the next
//       clock cycle. This is only a notational problem: the actions
//       should in fact be associated with state transitions.
//
// ST_RESET				// NOP, CKE=0, CS_N=1, wait 100 us
`define ST_INIT0	5'd0		// NOP, CKE=1, CS_N=0, wait 100 us
`define ST_INIT1	5'd1		// PRECHARGE ALL
`define ST_INIT2	5'd2		// NOP, wait tRP - 1 cycle
`define ST_INIT3	5'd3		// AUTO REFRESH
`define ST_INIT4	5'd4		// NOP, wait tRFC - 1 cycle
`define ST_INIT5	5'd5		// AUTO REFRESH
`define ST_INIT6	5'd6		// NOP, wait tRFC - 1 cycle
`define ST_INIT7	5'd7		// MODE REGISTER SET
`define ST_INIT8	5'd8		// NOP, wait tMRD - 1 cycle
`define ST_IDLE		5'd9		// AUTO REFRESH, ACTIVE, or NOP
`define ST_RFRSH	5'd10		// NOP, wait tRFC - 1 cycle
`define ST_WRDATA0	5'd11		// NOP, wait tRCD - 1 cycle
`define ST_WRDATA1	5'd12		// WRITE, de=1
`define ST_WRDATA2	5'd13		// NOP, wait 3 cycles
`define ST_WRDATA3	5'd14		// NOP, ack=1, de=0, wait 2 cycles
`define ST_WRDATA4	5'd15		// NOP, ack=0, wait 2 cycles
`define ST_RDDATA0	5'd16		// NOP, wait tRCD - 1 cycle
`define ST_RDDATA1	5'd17		// READ
`define ST_RDDATA2	5'd18		// NOP, wait 2 cycles
`define ST_RDDATA3	5'd19		// NOP, ld=1, wait 4 cycles
`define ST_RDDATA4	5'd20		// NOP, ack=1, ld=0, wait 2 cycles
`define ST_RDDATA5	5'd21		// NOP, ack=0, wait 3 cycles
`define ST_RDINST0	5'd22		// NOP, wait tRCD - 1 cycle
`define ST_RDINST1	5'd23		// READ
`define ST_RDINST2	5'd24		// NOP, wait 2 cycles
`define ST_RDINST3	5'd25		// NOP, ld=1, wait 4 cycles
`define ST_RDINST4	5'd26		// NOP, ack=1, ld=0, wait 2 cycles
`define ST_RDINST5	5'd27		// NOP, ack=0, wait 3 cycles
`define ST_ILLDA0	5'd28		// NOP, data_timeout=1, wait 2 cycles
`define ST_ILLDA1	5'd29		// NOP, data_timeout=0
`define ST_ILLIA0	5'd30		// NOP, inst_timeout=1, wait 2 cycles
`define ST_ILLIA1	5'd31		// NOP, inst_timeout=0
 
`define T_INIT0		14'd10000	// min 100 usec with CKE = 0
`define T_INIT1		14'd10000	// min 100 usec with CKE = 1
`define T_RP		14'd3		// min 20 ns row precharge time
`define T_RFC		14'd9		// min 66 ns auto refresh period
`define T_MRD		14'd3		// min load mode register delay
`define T_RCD		14'd3		// min 20 ns active-to-rw delay
 
`define REFCNT		10'd780		// 8192 refresh cycles per 64 ms
 
 
module ramctrl(clk_ok, clk,
               inst_stb, inst_addr,
               inst_dout, inst_ack,
               inst_timeout,
               data_stb, data_we,
               data_addr, data_din,
               data_dout, data_ack,
               data_timeout);
    input clk_ok;
    input clk;
    input inst_stb;
    input [25:0] inst_addr;
    output [63:0] inst_dout;
    output reg inst_ack;
    output reg inst_timeout;
    input data_stb;
    input data_we;
    input [25:0] data_addr;
    input [63:0] data_din;
    output [63:0] data_dout;
    output reg data_ack;
    output reg data_timeout;
 
  wire sdram_clk;
  wire sdram_clk_aux;
  reg sdram_cke;
  reg sdram_cs_n;
  wire sdram_ras_n;
  wire sdram_cas_n;
  wire sdram_we_n;
  reg [1:0] sdram_ba;
  reg [12:0] sdram_a;
  wire [1:0] sdram_dqm;
  wire [15:0] sdram_dq;
 
  reg [1:0] ram_cnt;
  wire [15:0] ram_dout;
  reg ram_de;
  reg [63:0] data;
  reg data_ld;
 
  wire inst_addr_out_of_range;
  wire data_addr_out_of_range;
 
  reg [2:0] ram_cmd;
  reg [1:0] ram_dqm;
  reg [13:0] count;
  reg [4:0] state;
 
  reg [9:0] refcnt;
  reg refflg;
  reg refrst;
 
  //
  // create ram instance
  //
 
  sdram sdram_1(
    .clk(sdram_clk),
    .cke(sdram_cke),
    .csb(sdram_cs_n),
    .rasb(sdram_ras_n),
    .casb(sdram_cas_n),
    .web(sdram_we_n),
    .ba(sdram_ba[1:0]),
    .ad(sdram_a[12:0]),
    .dqm(sdram_dqm[1:0]),
    .dqi(sdram_dq[15:0])
  );
 
  //
  // clock output to ram
  // the necessary phase shift will be accomplished by
  // a DLL if the controller is implemented on an FPGA
  //
 
  not #4 not_1(sdram_clk_aux, clk);
  not #5 not_2(sdram_clk, sdram_clk_aux);
 
  //
  // data output to ram
  //
 
  assign ram_dout[15:0] =
    ~ram_cnt[1] ? (~ram_cnt[0] ? data_din[63:48] : data_din[47:32]) :
                  (~ram_cnt[0] ? data_din[31:16] : data_din[15: 0]);
  assign sdram_dq[15:0] = ram_de ? ram_dout[15:0] : 16'hzzzz;
 
  //
  // data output to cache
  //
 
  always @(posedge clk) begin
    if (data_ld & (ram_cnt[1:0] == 2'b00)) begin
      data[63:48] <= sdram_dq[15:0];
    end
    if (data_ld & (ram_cnt[1:0] == 2'b01)) begin
      data[47:32] <= sdram_dq[15:0];
    end
    if (data_ld & (ram_cnt[1:0] == 2'b10)) begin
      data[31:16] <= sdram_dq[15:0];
    end
    if (data_ld & (ram_cnt[1:0] == 2'b11)) begin
      data[15: 0] <= sdram_dq[15:0];
    end
  end
 
  assign inst_dout[63:0] = data[63:0];
  assign data_dout[63:0] = data[63:0];
 
  //
  // address range check
  //
 
  assign inst_addr_out_of_range = | inst_addr[25:22];
  assign data_addr_out_of_range = | data_addr[25:22];
 
  //
  // ramctrl state machine
  //
 
  assign sdram_ras_n = ram_cmd[2];
  assign sdram_cas_n = ram_cmd[1];
  assign sdram_we_n = ram_cmd[0];
 
  assign sdram_dqm[1] = ram_dqm[1];
  assign sdram_dqm[0] = ram_dqm[0];
 
  always @(posedge clk or negedge clk_ok) begin
    // asynchronous reset
    if (~clk_ok) begin
      inst_ack <= 0;
      inst_timeout <= 0;
      data_ack <= 0;
      data_timeout <= 0;
      sdram_cke <= 0;
      sdram_cs_n <= 1;
      ram_cnt <= 0;
      ram_de <= 0;
      data_ld <= 0;
      ram_cmd <= `CMD_NOP;
      ram_dqm <= 2'b11;
      count <= `T_INIT0 - 1;
      state <= `ST_INIT0;
      refrst <= 0;
    end else begin
      if (|count[13:0]) begin
        // wait until count = 0
        // if count is loaded with N on a state transition, the
        // new state will last for (N+1)/fclk cycles before (!)
        // any action specified in the new state will take place
        count <= count - 1;
        // ram_cnt cycles through the 16-bit half-words in SDRAM
        // during burst read/writes while the main state machine
        // waits, thus it must be incremented here
        ram_cnt <= ram_cnt + 1;
      end else begin
        case (state)
          //----------------------------
          // init
          //----------------------------
          `ST_INIT0:
            begin
              sdram_cke <= 1;
              sdram_cs_n <= 0;
              ram_cmd <= `CMD_NOP;
              count <= `T_INIT1 - 1;
              state <= `ST_INIT1;
            end
          `ST_INIT1:
            begin
              ram_cmd <= `CMD_PRCHG;
              sdram_ba <= 2'b00;	// don't care
              sdram_a <= 13'h0400;	// precharge all
              state <= `ST_INIT2;
            end
          `ST_INIT2:
            begin
              ram_cmd <= `CMD_NOP;
              count <= `T_RP - 2;
              state <= `ST_INIT3;
            end
          `ST_INIT3:
            begin
              ram_cmd <= `CMD_ARFRS;
              state <= `ST_INIT4;
            end
          `ST_INIT4:
            begin
              ram_cmd <= `CMD_NOP;
              count <= `T_RFC - 2;
              state <= `ST_INIT5;
            end
          `ST_INIT5:
            begin
              ram_cmd <= `CMD_ARFRS;
              state <= `ST_INIT6;
            end
          `ST_INIT6:
            begin
              ram_cmd <= `CMD_NOP;
              count <= `T_RFC - 2;
              state <= `ST_INIT7;
            end
          `ST_INIT7:
            begin
              ram_cmd <= `CMD_MRSET;
              sdram_ba <= 2'b00;
              sdram_a <= `MODE;
              state <= `ST_INIT8;
            end
          `ST_INIT8:
            begin
              ram_cmd <= `CMD_NOP;
              ram_dqm <= 2'b00;
              count <= `T_MRD - 2;
              state <= `ST_IDLE;
            end
          //----------------------------
          // idle
          //----------------------------
          `ST_IDLE:
            begin
              if (refflg) begin
                // refresh request
                ram_cmd <= `CMD_ARFRS;
                state <= `ST_RFRSH;
                refrst <= 1;
              end else begin
                if (data_stb) begin
                  if (data_addr_out_of_range) begin
                    // illegal data address
                    ram_cmd <= `CMD_NOP;
                    state <= `ST_ILLDA0;
                  end else begin
                    // data address is ok
                    if (data_we) begin
                      // data write request
                      ram_cmd <= `CMD_ACTV;
                      sdram_ba <= data_addr[21:20];
                      sdram_a <= data_addr[19:7];
                      state <= `ST_WRDATA0;
                    end else begin
                      // data read request
                      ram_cmd <= `CMD_ACTV;
                      sdram_ba <= data_addr[21:20];
                      sdram_a <= data_addr[19:7];
                      state <= `ST_RDDATA0;
                    end
                  end
                end else begin
                  if (inst_stb) begin
                    if (inst_addr_out_of_range) begin
                      // illegal inst address
                      ram_cmd <= `CMD_NOP;
                      state <= `ST_ILLIA0;
                    end else begin
                      // inst address is ok
                      // inst read request
                      ram_cmd <= `CMD_ACTV;
                      sdram_ba <= inst_addr[21:20];
                      sdram_a <= inst_addr[19:7];
                      state <= `ST_RDINST0;
                    end
                  end else begin
                    // no request
                    ram_cmd <= `CMD_NOP;
                    state <= `ST_IDLE;
                  end
                end
              end
            end
          //----------------------------
          // refresh
          //----------------------------
          `ST_RFRSH:
            begin
              ram_cmd <= `CMD_NOP;
              count <= `T_RFC - 2;
              state <= `ST_IDLE;
              refrst <= 0;
            end
          //----------------------------
          // write data
          //----------------------------
          `ST_WRDATA0:
            begin
              ram_cmd <= `CMD_NOP;
              count <= `T_RCD - 2;
              state <= `ST_WRDATA1;
            end
          `ST_WRDATA1:
            begin
              ram_cnt <= 0;
              ram_de <= 1;
              ram_cmd <= `CMD_WRITE;
              sdram_ba <= data_addr[21:20];
              sdram_a <= { 6'b0010, data_addr[6:0], 2'b00 };
              state <= `ST_WRDATA2;
            end
          `ST_WRDATA2:
            begin
              ram_cnt <= ram_cnt + 1;
              ram_cmd <= `CMD_NOP;
              count <= 2;
              state <= `ST_WRDATA3;
            end
          `ST_WRDATA3:
            begin
              data_ack <= 1;
              ram_de <= 0;
              ram_cmd <= `CMD_NOP;
              count <= 1;
              state <= `ST_WRDATA4;
            end
          `ST_WRDATA4:
            begin
              data_ack <= 0;
              ram_cmd <= `CMD_NOP;
              count <= 1;
              state <= `ST_IDLE;
            end
          //----------------------------
          // read data
          //----------------------------
          `ST_RDDATA0:
            begin
              ram_cmd <= `CMD_NOP;
              count <= `T_RCD - 2;
              state <= `ST_RDDATA1;
            end
          `ST_RDDATA1:
            begin
              ram_cmd <= `CMD_READ;
              sdram_ba <= data_addr[21:20];
              sdram_a <= { 6'b0010, data_addr[6:0], 2'b00 };
              state <= `ST_RDDATA2;
            end
          `ST_RDDATA2:
            begin
              ram_cmd <= `CMD_NOP;
              count <= 1;
              state <= `ST_RDDATA3;
            end
          `ST_RDDATA3:
            begin
              ram_cnt <= 0;
              data_ld <= 1;
              ram_cmd <= `CMD_NOP;
              count <= 3;
              state <= `ST_RDDATA4;
            end
          `ST_RDDATA4:
            begin
              data_ack <= 1;
              data_ld <= 0;
              ram_cmd <= `CMD_NOP;
              count <= 1;
              state <= `ST_RDDATA5;
            end
          `ST_RDDATA5:
            begin
              data_ack <= 0;
              ram_cmd <= `CMD_NOP;
              count <= 2;
              state <= `ST_IDLE;
            end
          //----------------------------
          // read inst
          //----------------------------
          `ST_RDINST0:
            begin
              ram_cmd <= `CMD_NOP;
              count <= `T_RCD - 2;
              state <= `ST_RDINST1;
            end
          `ST_RDINST1:
            begin
              ram_cmd <= `CMD_READ;
              sdram_ba <= inst_addr[21:20];
              sdram_a <= { 6'b0010, inst_addr[6:0], 2'b00 };
              state <= `ST_RDINST2;
            end
          `ST_RDINST2:
            begin
              ram_cmd <= `CMD_NOP;
              count <= 1;
              state <= `ST_RDINST3;
            end
          `ST_RDINST3:
            begin
              ram_cnt <= 0;
              data_ld <= 1;
              ram_cmd <= `CMD_NOP;
              count <= 3;
              state <= `ST_RDINST4;
            end
          `ST_RDINST4:
            begin
              inst_ack <= 1;
              data_ld <= 0;
              ram_cmd <= `CMD_NOP;
              count <= 1;
              state <= `ST_RDINST5;
            end
          `ST_RDINST5:
            begin
              inst_ack <= 0;
              ram_cmd <= `CMD_NOP;
              count <= 2;
              state <= `ST_IDLE;
            end
          //----------------------------
          // illegal data address
          //----------------------------
          `ST_ILLDA0:
            begin
              data_timeout <= 1;
              ram_cmd <= `CMD_NOP;
              count <= 1;
              state <= `ST_ILLDA1;
            end
          `ST_ILLDA1:
            begin
              data_timeout <= 0;
              ram_cmd <= `CMD_NOP;
              state <= `ST_IDLE;
            end
          //----------------------------
          // illegal inst address
          //----------------------------
          `ST_ILLIA0:
            begin
              inst_timeout <= 1;
              ram_cmd <= `CMD_NOP;
              count <= 1;
              state <= `ST_ILLIA1;
            end
          `ST_ILLIA1:
            begin
              inst_timeout <= 0;
              ram_cmd <= `CMD_NOP;
              state <= `ST_IDLE;
            end
          //----------------------------
          // not used
          //----------------------------
          default:
            begin
              inst_ack <= 0;
              inst_timeout <= 0;
              data_ack <= 0;
              data_timeout <= 0;
              sdram_cke <= 0;
              sdram_cs_n <= 1;
              ram_cnt <= 0;
              ram_de <= 0;
              data_ld <= 0;
              ram_cmd <= `CMD_NOP;
              ram_dqm <= 2'b11;
              count <= `T_INIT0 - 1;
              state <= `ST_INIT0;
              refrst <= 0;
            end
        endcase
      end
    end
  end
 
  //
  // refresh counter
  //
 
  always @(posedge clk or negedge clk_ok) begin
    if (~clk_ok) begin
      refcnt <= 10'd0;
    end else begin
      if (refcnt == 10'd0) begin
        refcnt <= `REFCNT;
        refflg <= 1;
      end else begin
        refcnt <= refcnt - 1;
        if (refrst) begin
          refflg <= 0;
        end
      end
    end
  end
 
endmodule
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.