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

Subversion Repositories eco32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /eco32
    from Rev 322 to Rev 323
    Reverse comparison

Rev 322 → Rev 323

/trunk/fpga/experiments/memspeed/build/memspeed.bit Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
trunk/fpga/experiments/memspeed/build/memspeed.bit Property changes : Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: trunk/fpga/experiments/memspeed/src/memspeed.ucf =================================================================== --- trunk/fpga/experiments/memspeed/src/memspeed.ucf (revision 322) +++ trunk/fpga/experiments/memspeed/src/memspeed.ucf (nonexistent) @@ -1,65 +0,0 @@ -# -# memspeed.ucf -- user constraints for XSA-3S1000 + XST-3 board -# - -# -# clock and reset -# -NET "clk_in" PERIOD = 20.0ns HIGH 40%; -NET "clk_in" LOC = "p8"; -NET "rst_inout_n" LOC = "d15"; - -# -# SDRAM -# -NET "sdram_clk" LOC = "e10"; -NET "sdram_fb" LOC = "n8"; -NET "sdram_cke" LOC = "d7"; -NET "sdram_cs_n" LOC = "b8"; -NET "sdram_ras_n" LOC = "a9"; -NET "sdram_cas_n" LOC = "a10"; -NET "sdram_we_n" LOC = "b10"; -NET "sdram_ba<1>" LOC = "c7"; -NET "sdram_ba<0>" LOC = "a7"; -NET "sdram_a<12>" LOC = "c6"; -NET "sdram_a<11>" LOC = "c5"; -NET "sdram_a<10>" LOC = "b6"; -NET "sdram_a<9>" LOC = "a3"; -NET "sdram_a<8>" LOC = "c2"; -NET "sdram_a<7>" LOC = "d3"; -NET "sdram_a<6>" LOC = "e4"; -NET "sdram_a<5>" LOC = "c1"; -NET "sdram_a<4>" LOC = "e3"; -NET "sdram_a<3>" LOC = "e6"; -NET "sdram_a<2>" LOC = "b4"; -NET "sdram_a<1>" LOC = "a4"; -NET "sdram_a<0>" LOC = "b5"; -NET "sdram_udqm" LOC = "d9"; -NET "sdram_ldqm" LOC = "c10"; -NET "sdram_dq<15>" LOC = "f13"; -NET "sdram_dq<14>" LOC = "f12"; -NET "sdram_dq<13>" LOC = "c16"; -NET "sdram_dq<12>" LOC = "d14"; -NET "sdram_dq<11>" LOC = "b14"; -NET "sdram_dq<10>" LOC = "c12"; -NET "sdram_dq<9>" LOC = "b12"; -NET "sdram_dq<8>" LOC = "b11"; -NET "sdram_dq<7>" LOC = "d10"; -NET "sdram_dq<6>" LOC = "c11"; -NET "sdram_dq<5>" LOC = "a12"; -NET "sdram_dq<4>" LOC = "d11"; -NET "sdram_dq<3>" LOC = "b13"; -NET "sdram_dq<2>" LOC = "a14"; -NET "sdram_dq<1>" LOC = "d12"; -NET "sdram_dq<0>" LOC = "c15"; - -# -# 7 segment LED -# -NET "ssl<6>" LOC = "r10"; -NET "ssl<5>" LOC = "t7"; -NET "ssl<4>" LOC = "p10"; -NET "ssl<3>" LOC = "r7"; -NET "ssl<2>" LOC = "n6"; -NET "ssl<1>" LOC = "m11"; -NET "ssl<0>" LOC = "m6"; Index: trunk/fpga/experiments/memspeed/src/memspeed.v =================================================================== --- trunk/fpga/experiments/memspeed/src/memspeed.v (revision 322) +++ trunk/fpga/experiments/memspeed/src/memspeed.v (nonexistent) @@ -1,161 +0,0 @@ -// -// memspeed.v -- toplevel for memory speedometer -// - - -`timescale 1ns/10ps -`default_nettype none - - -module memspeed(clk_in, - rst_inout_n, - sdram_clk, - sdram_fb, - sdram_cke, - sdram_cs_n, - sdram_ras_n, - sdram_cas_n, - sdram_we_n, - sdram_ba, - sdram_a, - sdram_udqm, - sdram_ldqm, - sdram_dq, - ssl - ); - // clock and reset - input clk_in; - inout rst_inout_n; - // SDRAM - output sdram_clk; - input sdram_fb; - output sdram_cke; - output sdram_cs_n; - output sdram_ras_n; - output sdram_cas_n; - output sdram_we_n; - output [1:0] sdram_ba; - output [12:0] sdram_a; - output sdram_udqm; - output sdram_ldqm; - inout [15:0] sdram_dq; - // 7 segment LED output - output [6:0] ssl; - - // clk_rst - wire clk; - wire clk_ok; - wire rst; - // ram - reg stb; - wire we; - wire [22:0] addr; - wire [31:0] data_in; - wire [31:0] data_out; - wire ack; - // control - reg [27:0] count; - reg next_count; - reg [1:0] state; - reg [1:0] next_state; - - clk_rst clk_rst_1( - .clk_in(clk_in), - .rst_inout_n(rst_inout_n), - .sdram_clk(sdram_clk), - .sdram_fb(sdram_fb), - .clk(clk), - .clk_ok(clk_ok), - .rst(rst) - ); - - ram ram_1( - .clk(clk), - .clk_ok(clk_ok), - .rst(rst), - .stb(stb), - .we(we), - .addr(addr[22:0]), - .data_in(data_in[31:0]), - .data_out(data_out[31:0]), - .ack(ack), - .sdram_cke(sdram_cke), - .sdram_cs_n(sdram_cs_n), - .sdram_ras_n(sdram_ras_n), - .sdram_cas_n(sdram_cas_n), - .sdram_we_n(sdram_we_n), - .sdram_ba(sdram_ba), - .sdram_a(sdram_a), - .sdram_udqm(sdram_udqm), - .sdram_ldqm(sdram_ldqm), - .sdram_dq(sdram_dq) - ); - - assign we = count[1] & count[0]; - assign addr[22:0] = count[22:0]; - assign data_in[31:0] = { count[15:0], count[15:0] }; - - always @(posedge clk) begin - if (rst) begin - count <= 0; - end else begin - if (next_count) begin - count <= count + 1; - end - end - end - - always @(posedge clk) begin - if (rst) begin - state <= 0; - end else begin - state <= next_state; - end - end - - always @(*) begin - case (state) - 2'd0: - begin - stb = 0; - next_count = 0; - next_state = 1; - end - 2'd1: - begin - stb = 1; - next_count = 0; - if (ack) begin - next_state = 2; - end else begin - next_state = 1; - end - end - 2'd2: - begin - stb = 0; - next_count = 1; - if (count[27]) begin - next_state = 3; - end else begin - next_state = 1; - end - end - 2'd3: - begin - stb = 0; - next_count = 0; - next_state = 3; - end - endcase - end - - assign ssl[0] = 0; - assign ssl[1] = | state[1:0]; - assign ssl[2] = & state[1:0]; - assign ssl[3] = 0; - assign ssl[4] = 0; - assign ssl[5] = 0; - assign ssl[6] = ^ data_out[31:0]; - -endmodule Index: trunk/fpga/experiments/memspeed/src/ram.v =================================================================== --- trunk/fpga/experiments/memspeed/src/ram.v (revision 322) +++ trunk/fpga/experiments/memspeed/src/ram.v (nonexistent) @@ -1,220 +0,0 @@ -// -// ram.v -- external RAM interface, using SDRAM -// 8M x 32 bit = 32 MB -// - - -`timescale 1ns/10ps -`default_nettype none - - -module ram(clk, clk_ok, rst, - stb, we, addr, - data_in, data_out, ack, - sdram_cke, sdram_cs_n, - sdram_ras_n, sdram_cas_n, - sdram_we_n, sdram_ba, sdram_a, - sdram_udqm, sdram_ldqm, sdram_dq); - // internal interface signals - input clk; - input clk_ok; - input rst; - input stb; - input we; - input [24:2] addr; - input [31:0] data_in; - output reg [31:0] data_out; - output reg ack; - // SDRAM interface signals - output sdram_cke; - output sdram_cs_n; - output sdram_ras_n; - output sdram_cas_n; - output sdram_we_n; - output [1:0] sdram_ba; - output [12:0] sdram_a; - output sdram_udqm; - output sdram_ldqm; - inout [15:0] sdram_dq; - - reg [2:0] state; - reg a0; - reg cntl_read; - reg cntl_write; - wire cntl_done; - wire [23:0] cntl_addr; - reg [15:0] cntl_din; - wire [15:0] cntl_dout; - - wire sd_out_en; - wire [15:0] sd_out; - -//-------------------------------------------------------------- - - sdramCntl sdramCntl_1( - // clock - .clk(clk), - .clk_ok(clk_ok), - // host side - .rd(cntl_read & ~cntl_done), - .wr(cntl_write & ~cntl_done), - .done(cntl_done), - .hAddr(cntl_addr), - .hDIn(cntl_din), - .hDOut(cntl_dout), - // SDRAM side - .cke(sdram_cke), - .ce_n(sdram_cs_n), - .ras_n(sdram_ras_n), - .cas_n(sdram_cas_n), - .we_n(sdram_we_n), - .ba(sdram_ba), - .sAddr(sdram_a), - .sDIn(sdram_dq), - .sDOut(sd_out), - .sDOutEn(sd_out_en), - .dqmh(sdram_udqm), - .dqml(sdram_ldqm) - ); - - assign sdram_dq = (sd_out_en == 1) ? sd_out : 16'hzzzz; - -//-------------------------------------------------------------- - - // the SDRAM is organized in 16-bit halfwords - // address line 0 is controlled by the state machine - assign cntl_addr[23:1] = addr[24:2]; - assign cntl_addr[0] = a0; - - // state machine for SDRAM access - always @(posedge clk) begin - if (rst) begin - state <= 3'b000; - ack <= 0; - end else begin - case (state) - 3'b000: - // wait for access - begin - if (stb) begin - // access - if (we) begin - // write - state <= 3'b001; - end else begin - // read - state <= 3'b011; - end - end - end - 3'b001: - // write word, upper 16 bits - begin - if (cntl_done) begin - state <= 3'b010; - end - end - 3'b010: - // write word, lower 16 bits - begin - if (cntl_done) begin - state <= 3'b111; - ack <= 1; - end - end - 3'b011: - // read word, upper 16 bits - begin - if (cntl_done) begin - state <= 3'b100; - data_out[31:16] <= cntl_dout; - end - end - 3'b100: - // read word, lower 16 bits - begin - if (cntl_done) begin - state <= 3'b111; - data_out[15:0] <= cntl_dout; - ack <= 1; - end - end - 3'b111: - // end of bus cycle - begin - state <= 3'b000; - ack <= 0; - end - default: - // all other states: reset - begin - state <= 3'b000; - ack <= 0; - end - endcase - end - end - - // output of state machine - always @(*) begin - case (state) - 3'b000: - // wait for access - begin - a0 = 1'bx; - cntl_read = 0; - cntl_write = 0; - cntl_din = 16'hxxxx; - end - 3'b001: - // write word, upper 16 bits - begin - a0 = 1'b0; - cntl_read = 0; - cntl_write = 1; - cntl_din = data_in[31:16]; - end - 3'b010: - // write word, lower 16 bits - begin - a0 = 1'b1; - cntl_read = 0; - cntl_write = 1; - cntl_din = data_in[15:0]; - end - 3'b011: - // read word, upper 16 bits - begin - a0 = 1'b0; - cntl_read = 1; - cntl_write = 0; - cntl_din = 16'hxxxx; - end - 3'b100: - // read word, lower 16 bits - begin - a0 = 1'b1; - cntl_read = 1; - cntl_write = 0; - cntl_din = 16'hxxxx; - end - 3'b111: - // end of bus cycle - begin - a0 = 1'bx; - cntl_read = 0; - cntl_write = 0; - cntl_din = 16'hxxxx; - end - default: - // all other states: reset - begin - a0 = 1'bx; - cntl_read = 0; - cntl_write = 0; - cntl_din = 16'hxxxx; - end - endcase - end - -endmodule Index: trunk/fpga/experiments/memspeed/src/clk_rst.v =================================================================== --- trunk/fpga/experiments/memspeed/src/clk_rst.v (revision 322) +++ trunk/fpga/experiments/memspeed/src/clk_rst.v (nonexistent) @@ -1,103 +0,0 @@ -// -// clk_rst.v -- clock and reset generator -// - - -`timescale 1ns/10ps -`default_nettype none - - -module clk_rst(clk_in, rst_inout_n, - sdram_clk, sdram_fb, - clk, clk_ok, rst); - input clk_in; - inout rst_inout_n; - output sdram_clk; - input sdram_fb; - output clk; - output clk_ok; - output rst; - - wire clk_in_buf; - wire int_clk; - wire int_locked; - wire ext_rst_n; - wire ext_fb; - wire ext_locked; - - reg rst_p_n; - reg rst_s_n; - reg [23:0] rst_counter; - wire rst_counting; - - //------------------------------------------------------------ - - IBUFG clk_in_buffer( - .I(clk_in), - .O(clk_in_buf) - ); - - DCM int_dcm( - .CLKIN(clk_in_buf), - .CLKFB(clk), - .RST(1'b0), - .CLK0(int_clk), - .LOCKED(int_locked) - ); - - BUFG int_clk_buffer( - .I(int_clk), - .O(clk) - ); - - //------------------------------------------------------------ - - SRL16 ext_dll_rst_gen( - .CLK(clk_in_buf), - .D(int_locked), - .Q(ext_rst_n), - .A0(1'b1), - .A1(1'b1), - .A2(1'b1), - .A3(1'b1) - ); - - defparam ext_dll_rst_gen.INIT = 16'h0000; - - //------------------------------------------------------------ - - IBUFG ext_fb_buffer( - .I(sdram_fb), - .O(ext_fb) - ); - - DCM ext_dcm( - .CLKIN(clk_in_buf), - .CLKFB(ext_fb), - .RST(~ext_rst_n), - .CLK0(sdram_clk), - .LOCKED(ext_locked) - ); - - assign clk_ok = int_locked & ext_locked; - - //------------------------------------------------------------ - - assign rst_counting = (rst_counter == 24'hFFFFFF) ? 0 : 1; - assign rst_inout_n = (rst_counter[23] == 0) ? 1'b0 : 1'bz; - - always @(posedge clk_in_buf) begin - rst_p_n <= rst_inout_n; - rst_s_n <= rst_p_n; - if (rst_counting) begin - rst_counter <= rst_counter + 1; - end else begin - if (~rst_s_n | ~clk_ok) begin - rst_counter <= 24'h000000; - end - end - end - - assign rst = rst_counting; - -endmodule Index: trunk/fpga/experiments/memspeed/src/sdramcntl.vhd =================================================================== --- trunk/fpga/experiments/memspeed/src/sdramcntl.vhd (revision 322) +++ trunk/fpga/experiments/memspeed/src/sdramcntl.vhd (nonexistent) @@ -1,596 +0,0 @@ --------------------------------------------------------------------- --- Company : XESS Corp. --- Engineer : Dave Vanden Bout --- Creation Date : 05/17/2005 --- Copyright : 2005, XESS Corp --- Tool Versions : WebPACK 6.3.03i --- --- Description: --- SDRAM controller --- --- Revision: --- n.a. (because of hacking by Hellwig Geisse) --- --- Additional Comments: --- 1.4.0: --- Added generic parameter to enable/disable independent active rows in each bank. --- 1.3.0: --- Modified to allow independently active rows in each bank. --- 1.2.0: --- Modified to allow pipelining of read/write operations. --- 1.1.0: --- Initial release. --- --- License: --- This code can be freely distributed and modified as long as --- this header is not removed. --------------------------------------------------------------------- - -library IEEE, UNISIM; -use IEEE.std_logic_1164.all; -use IEEE.std_logic_unsigned.all; -use IEEE.numeric_std.all; - -entity sdramCntl is - port( - -- host side - clk : in std_logic; -- master clock - clk_ok : in std_logic; -- true if clock is stable - rd : in std_logic; -- initiate read operation - wr : in std_logic; -- initiate write operation - done : out std_logic; -- read or write operation is done - hAddr : in std_logic_vector(23 downto 0); -- address from host to SDRAM - hDIn : in std_logic_vector(15 downto 0); -- data from host to SDRAM - hDOut : out std_logic_vector(15 downto 0); -- data from SDRAM to host - - -- SDRAM side - cke : out std_logic; -- clock-enable to SDRAM - ce_n : out std_logic; -- chip-select to SDRAM - ras_n : out std_logic; -- SDRAM row address strobe - cas_n : out std_logic; -- SDRAM column address strobe - we_n : out std_logic; -- SDRAM write enable - ba : out std_logic_vector(1 downto 0); -- SDRAM bank address - sAddr : out std_logic_vector(12 downto 0); -- SDRAM row/column address - sDIn : in std_logic_vector(15 downto 0); -- data from SDRAM - sDOut : out std_logic_vector(15 downto 0); -- data to SDRAM - sDOutEn : out std_logic; -- true if data is output to SDRAM on sDOut - dqmh : out std_logic; -- enable upper-byte of SDRAM databus if true - dqml : out std_logic -- enable lower-byte of SDRAM databus if true - ); -end sdramCntl; - - -architecture arch of sdramCntl is - - constant YES : std_logic := '1'; - constant NO : std_logic := '0'; - - -- select one of two integers based on a Boolean - function int_select(s : in boolean; a : in integer; b : in integer) return integer is - begin - if s then - return a; - else - return b; - end if; - return a; - end function int_select; - - constant OUTPUT : std_logic := '1'; -- direction of dataflow w.r.t. this controller - constant INPUT : std_logic := '0'; - constant NOP : std_logic := '0'; -- no operation - constant READ : std_logic := '1'; -- read operation - constant WRITE : std_logic := '1'; -- write operation - - -- SDRAM timing parameters - constant Tinit : natural := 200; -- min initialization interval (us) - constant Tras : natural := 45; -- min interval between active to precharge commands (ns) - constant Trcd : natural := 20; -- min interval between active and R/W commands (ns) - constant Tref : natural := 64_000_000; -- maximum refresh interval (ns) - constant Trfc : natural := 66; -- duration of refresh operation (ns) - constant Trp : natural := 20; -- min precharge command duration (ns) - constant Twr : natural := 15; -- write recovery time (ns) - constant Txsr : natural := 75; -- exit self-refresh time (ns) - - -- SDRAM timing parameters converted into clock cycles (based on FREQ = 50_000) - constant NORM : natural := 1_000_000; -- normalize ns * KHz - constant INIT_CYCLES : natural := 1+((Tinit*50_000)/1000); -- SDRAM power-on initialization interval - constant RAS_CYCLES : natural := 1+((Tras*50_000)/NORM); -- active-to-precharge interval - constant RCD_CYCLES : natural := 1+((Trcd*50_000)/NORM); -- active-to-R/W interval - constant REF_CYCLES : natural := 1+(((Tref/8192)*50_000)/NORM); -- interval between row refreshes - constant RFC_CYCLES : natural := 1+((Trfc*50_000)/NORM); -- refresh operation interval - constant RP_CYCLES : natural := 1+((Trp*50_000)/NORM); -- precharge operation interval - constant WR_CYCLES : natural := 1+((Twr*50_000)/NORM); -- write recovery time - constant XSR_CYCLES : natural := 1+((Txsr*50_000)/NORM); -- exit self-refresh time - constant MODE_CYCLES : natural := 2; -- mode register setup time - constant CAS_CYCLES : natural := 3; -- CAS latency - constant RFSH_OPS : natural := 8; -- number of refresh operations needed to init SDRAM - - -- timer registers that count down times for various SDRAM operations - signal timer_r, timer_x : natural range 0 to INIT_CYCLES; -- current SDRAM op time - signal rasTimer_r, rasTimer_x : natural range 0 to RAS_CYCLES; -- active-to-precharge time - signal wrTimer_r, wrTimer_x : natural range 0 to WR_CYCLES; -- write-to-precharge time - signal refTimer_r, refTimer_x : natural range 0 to REF_CYCLES; -- time between row refreshes - signal rfshCntr_r, rfshCntr_x : natural range 0 to 8192; -- counts refreshes that are neede - signal nopCntr_r, nopCntr_x : natural range 0 to 10000; -- counts consecutive NOP operations - - signal doSelfRfsh : std_logic; -- active when the NOP counter hits zero and self-refresh can start - - -- states of the SDRAM controller state machine - type cntlState is ( - INITWAIT, -- initialization - waiting for power-on initialization to complete - INITPCHG, -- initialization - initial precharge of SDRAM banks - INITSETMODE, -- initialization - set SDRAM mode - INITRFSH, -- initialization - do initial refreshes - RW, -- read/write/refresh the SDRAM - ACTIVATE, -- open a row of the SDRAM for reading/writing - REFRESHROW, -- refresh a row of the SDRAM - SELFREFRESH -- keep SDRAM in self-refresh mode with CKE low - ); - signal state_r, state_x : cntlState; -- state register and next state - - -- commands that are sent to the SDRAM to make it perform certain operations - -- commands use these SDRAM input pins (ce_n,ras_n,cas_n,we_n,dqmh,dqml) - subtype sdramCmd is unsigned(5 downto 0); - constant NOP_CMD : sdramCmd := "011100"; - constant ACTIVE_CMD : sdramCmd := "001100"; - constant READ_CMD : sdramCmd := "010100"; - constant WRITE_CMD : sdramCmd := "010000"; - constant PCHG_CMD : sdramCmd := "001011"; - constant MODE_CMD : sdramCmd := "000011"; - constant RFSH_CMD : sdramCmd := "000111"; - - -- SDRAM mode register - -- the SDRAM is placed in a non-burst mode (burst length = 1) with a 3-cycle CAS - subtype sdramMode is std_logic_vector(12 downto 0); - constant MODE : sdramMode := "000" & "0" & "00" & "011" & "0" & "000"; - - -- the host address is decomposed into these sets of SDRAM address components - constant ROW_LEN : natural := 13; -- number of row address bits - constant COL_LEN : natural := 9; -- number of column address bits - signal bank : std_logic_vector(ba'range); -- bank address bits - signal row : std_logic_vector(ROW_LEN - 1 downto 0); -- row address within bank - signal col : std_logic_vector(sAddr'range); -- column address within row - - -- registers that store the currently active row in each bank of the SDRAM - constant NUM_ACTIVE_ROWS : integer := 1; - type activeRowType is array(0 to NUM_ACTIVE_ROWS-1) of std_logic_vector(row'range); - signal activeRow_r, activeRow_x : activeRowType; - signal activeFlag_r, activeFlag_x : std_logic_vector(0 to NUM_ACTIVE_ROWS-1); -- indicates that some row in a bank is active - signal bankIndex : natural range 0 to NUM_ACTIVE_ROWS-1; -- bank address bits - signal activeBank_r, activeBank_x : std_logic_vector(ba'range); -- indicates the bank with the active row - signal doActivate : std_logic; -- indicates when a new row in a bank needs to be activated - - -- there is a command bit embedded within the SDRAM column address - constant CMDBIT_POS : natural := 10; -- position of command bit - constant AUTO_PCHG_ON : std_logic := '1'; -- CMDBIT value to auto-precharge the bank - constant AUTO_PCHG_OFF : std_logic := '0'; -- CMDBIT value to disable auto-precharge - constant ONE_BANK : std_logic := '0'; -- CMDBIT value to select one bank - constant ALL_BANKS : std_logic := '1'; -- CMDBIT value to select all banks - - -- status signals that indicate when certain operations are in progress - signal wrInProgress : std_logic; -- write operation in progress - signal rdInProgress : std_logic; -- read operation in progress - signal activateInProgress : std_logic; -- row activation is in progress - - -- these registers track the progress of read and write operations - signal rdPipeline_r, rdPipeline_x : std_logic_vector(CAS_CYCLES+1 downto 0); -- pipeline of read ops in progress - signal wrPipeline_r, wrPipeline_x : std_logic_vector(0 downto 0); -- pipeline of write ops (only need 1 cycle) - - -- registered outputs to host - signal hDOut_r, hDOut_x : std_logic_vector(hDOut'range); -- holds data read from SDRAM and sent to the host - - -- registered outputs to SDRAM - signal cke_r, cke_x : std_logic; -- clock enable - signal cmd_r, cmd_x : sdramCmd; -- SDRAM command bits - signal ba_r, ba_x : std_logic_vector(ba'range); -- SDRAM bank address bits - signal sAddr_r, sAddr_x : std_logic_vector(sAddr'range); -- SDRAM row/column address - signal sData_r, sData_x : std_logic_vector(sDOut'range); -- SDRAM out databus - signal sDataDir_r, sDataDir_x : std_logic; -- SDRAM databus direction control bit - -begin - - ----------------------------------------------------------- - -- attach some internal signals to the I/O ports - ----------------------------------------------------------- - - -- attach registered SDRAM control signals to SDRAM input pins - (ce_n, ras_n, cas_n, we_n, dqmh, dqml) <= cmd_r; -- SDRAM operation control bits - cke <= cke_r; -- SDRAM clock enable - ba <= ba_r; -- SDRAM bank address - sAddr <= sAddr_r; -- SDRAM address - sDOut <= sData_r; -- SDRAM output data bus - sDOutEn <= YES when sDataDir_r = OUTPUT else NO; -- output databus enable - - -- attach some port signals - hDOut <= hDOut_r; -- data back to host - - - ----------------------------------------------------------- - -- compute the next state and outputs - ----------------------------------------------------------- - - combinatorial : process(rd, wr, hAddr, hDIn, hDOut_r, sDIn, state_r, - activeFlag_r, activeRow_r, activeBank_r, - rdPipeline_r, wrPipeline_r, - nopCntr_r, rfshCntr_r, timer_r, rasTimer_r, - wrTimer_r, refTimer_r, cmd_r, cke_r) - begin - - ----------------------------------------------------------- - -- setup default values for signals - ----------------------------------------------------------- - - cke_x <= YES; -- enable SDRAM clock - cmd_x <= NOP_CMD; -- set SDRAM command to no-operation - sDataDir_x <= INPUT; -- accept data from the SDRAM - sData_x <= hDIn(sData_x'range); -- output data from host to SDRAM - state_x <= state_r; -- reload these registers and flags - activeFlag_x <= activeFlag_r; -- with their existing values - activeRow_x <= activeRow_r; - activeBank_x <= activeBank_r; - rfshCntr_x <= rfshCntr_r; - - ----------------------------------------------------------- - -- setup default value for the SDRAM address - ----------------------------------------------------------- - - -- extract bank field from host address - ba_x <= hAddr(ba'length + ROW_LEN + COL_LEN - 1 downto ROW_LEN + COL_LEN); - bank <= ba_x; - bankIndex <= 0; - -- extract row, column fields from host address - row <= hAddr(ROW_LEN + COL_LEN - 1 downto COL_LEN); - -- extend column (if needed) until it is as large as the (SDRAM address bus - 1) - col <= (others => '0'); -- set it to all zeroes - col(COL_LEN-1 downto 0) <= hAddr(COL_LEN-1 downto 0); - -- by default, set SDRAM address to the column address with interspersed - -- command bit set to disable auto-precharge - sAddr_x <= col(col'high-1 downto CMDBIT_POS) & AUTO_PCHG_OFF - & col(CMDBIT_POS-1 downto 0); - - ----------------------------------------------------------- - -- manage the read and write operation pipelines - ----------------------------------------------------------- - - -- determine if read operations are in progress by the presence of - -- READ flags in the read pipeline - if rdPipeline_r(rdPipeline_r'high downto 1) /= 0 then - rdInProgress <= YES; - else - rdInProgress <= NO; - end if; - - -- enter NOPs into the read and write pipeline shift registers by default - rdPipeline_x <= NOP & rdPipeline_r(rdPipeline_r'high downto 1); - wrPipeline_x(0) <= NOP; - - -- transfer data from SDRAM to the host data register if a read flag has exited the pipeline - -- (the transfer occurs 1 cycle before we tell the host the read operation is done) - if rdPipeline_r(1) = READ then - -- get the SDRAM data for the host directly from the SDRAM if the controller and SDRAM are in-phase - hDOut_x <= sDIn(hDOut'range); - else - -- retain contents of host data registers if no data from the SDRAM has arrived yet - hDOut_x <= hDOut_r; - end if; - - done <= rdPipeline_r(0) or wrPipeline_r(0); -- a read or write operation is done - - ----------------------------------------------------------- - -- manage row activation - ----------------------------------------------------------- - - -- request a row activation operation if the row of the current address - -- does not match the currently active row in the bank, or if no row - -- in the bank is currently active - if (bank /= activeBank_r) or (row /= activeRow_r(bankIndex)) or (activeFlag_r(bankIndex) = NO) then - doActivate <= YES; - else - doActivate <= NO; - end if; - - ----------------------------------------------------------- - -- manage self-refresh - ----------------------------------------------------------- - - -- enter self-refresh if neither a read or write is requested for 10000 consecutive cycles. - if (rd = YES) or (wr = YES) then - -- any read or write resets NOP counter and exits self-refresh state - nopCntr_x <= 0; - doSelfRfsh <= NO; - elsif nopCntr_r /= 10000 then - -- increment NOP counter whenever there is no read or write operation - nopCntr_x <= nopCntr_r + 1; - doSelfRfsh <= NO; - else - -- start self-refresh when counter hits maximum NOP count and leave counter unchanged - nopCntr_x <= nopCntr_r; - doSelfRfsh <= YES; - end if; - - ----------------------------------------------------------- - -- update the timers - ----------------------------------------------------------- - - -- row activation timer - if rasTimer_r /= 0 then - -- decrement a non-zero timer and set the flag - -- to indicate the row activation is still inprogress - rasTimer_x <= rasTimer_r - 1; - activateInProgress <= YES; - else - -- on timeout, keep the timer at zero and reset the flag - -- to indicate the row activation operation is done - rasTimer_x <= rasTimer_r; - activateInProgress <= NO; - end if; - - -- write operation timer - if wrTimer_r /= 0 then - -- decrement a non-zero timer and set the flag - -- to indicate the write operation is still inprogress - wrTimer_x <= wrTimer_r - 1; - wrInPRogress <= YES; - else - -- on timeout, keep the timer at zero and reset the flag that - -- indicates a write operation is in progress - wrTimer_x <= wrTimer_r; - wrInPRogress <= NO; - end if; - - -- refresh timer - if refTimer_r /= 0 then - refTimer_x <= refTimer_r - 1; - else - -- on timeout, reload the timer with the interval between row refreshes - -- and increment the counter for the number of row refreshes that are needed - refTimer_x <= REF_CYCLES; - rfshCntr_x <= rfshCntr_r + 1; - end if; - - -- main timer for sequencing SDRAM operations - if timer_r /= 0 then - -- decrement the timer and do nothing else since the previous operation has not completed yet. - timer_x <= timer_r - 1; - else - -- the previous operation has completed once the timer hits zero - timer_x <= timer_r; -- by default, leave the timer at zero - - ----------------------------------------------------------- - -- compute the next state and outputs - ----------------------------------------------------------- - case state_r is - - ----------------------------------------------------------- - -- let clock stabilize and then wait for the SDRAM to initialize - ----------------------------------------------------------- - when INITWAIT => - -- wait for SDRAM power-on initialization once the clock is stable - timer_x <= INIT_CYCLES; -- set timer for initialization duration - state_x <= INITPCHG; - - ----------------------------------------------------------- - -- precharge all SDRAM banks after power-on initialization - ----------------------------------------------------------- - when INITPCHG => - cmd_x <= PCHG_CMD; - sAddr_x(CMDBIT_POS) <= ALL_BANKS; -- precharge all banks - timer_x <= RP_CYCLES; -- set timer for precharge operation duration - rfshCntr_x <= RFSH_OPS; -- set counter for refresh ops needed after precharge - state_x <= INITRFSH; - - ----------------------------------------------------------- - -- refresh the SDRAM a number of times after initial precharge - ----------------------------------------------------------- - when INITRFSH => - cmd_x <= RFSH_CMD; - timer_x <= RFC_CYCLES; -- set timer to refresh operation duration - rfshCntr_x <= rfshCntr_r - 1; -- decrement refresh operation counter - if rfshCntr_r = 1 then - state_x <= INITSETMODE; -- set the SDRAM mode once all refresh ops are done - end if; - - ----------------------------------------------------------- - -- set the mode register of the SDRAM - ----------------------------------------------------------- - when INITSETMODE => - cmd_x <= MODE_CMD; - sAddr_x <= MODE; -- output mode register bits on the SDRAM address bits - timer_x <= MODE_CYCLES; -- set timer for mode setting operation duration - state_x <= RW; - - ----------------------------------------------------------- - -- process read/write/refresh operations after initialization is done - ----------------------------------------------------------- - when RW => - ----------------------------------------------------------- - -- highest priority operation: row refresh - -- do a refresh operation if the refresh counter is non-zero - ----------------------------------------------------------- - if rfshCntr_r /= 0 then - -- wait for any row activations, writes or reads to finish before doing a precharge - if (activateInProgress = NO) and (wrInProgress = NO) and (rdInProgress = NO) then - cmd_x <= PCHG_CMD; -- initiate precharge of the SDRAM - sAddr_x(CMDBIT_POS) <= ALL_BANKS; -- precharge all banks - timer_x <= RP_CYCLES; -- set timer for this operation - activeFlag_x <= (others => NO); -- all rows are inactive after a precharge operation - state_x <= REFRESHROW; -- refresh the SDRAM after the precharge - end if; - ----------------------------------------------------------- - -- do a host-initiated read operation - ----------------------------------------------------------- - elsif rd = YES then - -- Wait one clock cycle if the bank address has just changed and each bank has its own active row. - -- This gives extra time for the row activation circuitry. - if (true) then - -- activate a new row if the current read is outside the active row or bank - if doActivate = YES then - -- activate new row only if all previous activations, writes, reads are done - if (activateInProgress = NO) and (wrInProgress = NO) and (rdInProgress = NO) then - cmd_x <= PCHG_CMD; -- initiate precharge of the SDRAM - sAddr_x(CMDBIT_POS) <= ONE_BANK; -- precharge this bank - timer_x <= RP_CYCLES; -- set timer for this operation - activeFlag_x(bankIndex) <= NO; -- rows in this bank are inactive after a precharge operation - state_x <= ACTIVATE; -- activate the new row after the precharge is done - end if; - -- read from the currently active row if no previous read operation - -- is in progress or if pipeline reads are enabled - -- we can always initiate a read even if a write is already in progress - elsif (rdInProgress = NO) then - cmd_x <= READ_CMD; -- initiate a read of the SDRAM - -- insert a flag into the pipeline shift register that will exit the end - -- of the shift register when the data from the SDRAM is available - rdPipeline_x <= READ & rdPipeline_r(rdPipeline_r'high downto 1); - end if; - end if; - ----------------------------------------------------------- - -- do a host-initiated write operation - ----------------------------------------------------------- - elsif wr = YES then - -- Wait one clock cycle if the bank address has just changed and each bank has its own active row. - -- This gives extra time for the row activation circuitry. - if (true) then - -- activate a new row if the current write is outside the active row or bank - if doActivate = YES then - -- activate new row only if all previous activations, writes, reads are done - if (activateInProgress = NO) and (wrInProgress = NO) and (rdInProgress = NO) then - cmd_x <= PCHG_CMD; -- initiate precharge of the SDRAM - sAddr_x(CMDBIT_POS) <= ONE_BANK; -- precharge this bank - timer_x <= RP_CYCLES; -- set timer for this operation - activeFlag_x(bankIndex) <= NO; -- rows in this bank are inactive after a precharge operation - state_x <= ACTIVATE; -- activate the new row after the precharge is done - end if; - -- write to the currently active row if no previous read operations are in progress - elsif rdInProgress = NO then - cmd_x <= WRITE_CMD; -- initiate the write operation - sDataDir_x <= OUTPUT; -- turn on drivers to send data to SDRAM - -- set timer so precharge doesn't occur too soon after write operation - wrTimer_x <= WR_CYCLES; - -- insert a flag into the 1-bit pipeline shift register that will exit on the - -- next cycle. The write into SDRAM is not actually done by that time, but - -- this doesn't matter to the host - wrPipeline_x(0) <= WRITE; - end if; - end if; - ----------------------------------------------------------- - -- do a host-initiated self-refresh operation - ----------------------------------------------------------- - elsif doSelfRfsh = YES then - -- wait until all previous activations, writes, reads are done - if (activateInProgress = NO) and (wrInProgress = NO) and (rdInProgress = NO) then - cmd_x <= PCHG_CMD; -- initiate precharge of the SDRAM - sAddr_x(CMDBIT_POS) <= ALL_BANKS; -- precharge all banks - timer_x <= RP_CYCLES; -- set timer for this operation - activeFlag_x <= (others => NO); -- all rows are inactive after a precharge operation - state_x <= SELFREFRESH; -- self-refresh the SDRAM after the precharge - end if; - ----------------------------------------------------------- - -- no operation - ----------------------------------------------------------- - else - state_x <= RW; -- continue to look for SDRAM operations to execute - end if; - - ----------------------------------------------------------- - -- activate a row of the SDRAM - ----------------------------------------------------------- - when ACTIVATE => - cmd_x <= ACTIVE_CMD; - sAddr_x <= (others => '0'); -- output the address for the row to be activated - sAddr_x(row'range) <= row; - activeBank_x <= bank; - activeRow_x(bankIndex) <= row; -- store the new active SDRAM row address - activeFlag_x(bankIndex) <= YES; -- the SDRAM is now active - rasTimer_x <= RAS_CYCLES; -- minimum time before another precharge can occur - timer_x <= RCD_CYCLES; -- minimum time before a read/write operation can occur - state_x <= RW; -- return to do read/write operation that initiated this activation - - ----------------------------------------------------------- - -- refresh a row of the SDRAM - ----------------------------------------------------------- - when REFRESHROW => - cmd_x <= RFSH_CMD; - timer_x <= RFC_CYCLES; -- refresh operation interval - rfshCntr_x <= rfshCntr_r - 1; -- decrement the number of needed row refreshes - state_x <= RW; -- process more SDRAM operations after refresh is done - - ----------------------------------------------------------- - -- place the SDRAM into self-refresh and keep it there until further notice - ----------------------------------------------------------- - when SELFREFRESH => - if (doSelfRfsh = YES) then - -- keep the SDRAM in self-refresh mode as long as requested and until there is a stable clock - cmd_x <= RFSH_CMD; -- output the refresh command; this is only needed on the first clock cycle - cke_x <= NO; -- disable the SDRAM clock - else - -- else exit self-refresh mode and start processing read and write operations - cke_x <= YES; -- restart the SDRAM clock - rfshCntr_x <= 0; -- no refreshes are needed immediately after leaving self-refresh - activeFlag_x <= (others => NO); -- self-refresh deactivates all rows - timer_x <= XSR_CYCLES; -- wait this long until read and write operations can resume - state_x <= RW; - end if; - - ----------------------------------------------------------- - -- unknown state - ----------------------------------------------------------- - when others => - state_x <= INITWAIT; -- reset state if in erroneous state - - end case; - end if; - end process combinatorial; - - - ----------------------------------------------------------- - -- update registers on the appropriate clock edge - ----------------------------------------------------------- - - update : process(clk_ok, clk) - begin - - if clk_ok = NO then - -- asynchronous reset - state_r <= INITWAIT; - activeFlag_r <= (others => NO); - rfshCntr_r <= 0; - timer_r <= 0; - refTimer_r <= REF_CYCLES; - rasTimer_r <= 0; - wrTimer_r <= 0; - nopCntr_r <= 0; - rdPipeline_r <= (others => '0'); - wrPipeline_r <= (others => '0'); - cke_r <= NO; - cmd_r <= NOP_CMD; - ba_r <= (others => '0'); - sAddr_r <= (others => '0'); - sData_r <= (others => '0'); - sDataDir_r <= INPUT; - hDOut_r <= (others => '0'); - elsif rising_edge(clk) then - state_r <= state_x; - activeBank_r <= activeBank_x; - activeRow_r <= activeRow_x; - activeFlag_r <= activeFlag_x; - rfshCntr_r <= rfshCntr_x; - timer_r <= timer_x; - refTimer_r <= refTimer_x; - rasTimer_r <= rasTimer_x; - wrTimer_r <= wrTimer_x; - nopCntr_r <= nopCntr_x; - rdPipeline_r <= rdPipeline_x; - wrPipeline_r <= wrPipeline_x; - cke_r <= cke_x; - cmd_r <= cmd_x; - ba_r <= ba_x; - sAddr_r <= sAddr_x; - sData_r <= sData_x; - sDataDir_r <= sDataDir_x; - hDOut_r <= hDOut_x; - end if; - - end process update; - -end arch; Index: trunk/fpga/experiments/memspeed-1/README =================================================================== --- trunk/fpga/experiments/memspeed-1/README (nonexistent) +++ trunk/fpga/experiments/memspeed-1/README (revision 323) @@ -0,0 +1,69 @@ +Purpose +------- + +This test circuit allows speed measurements of the old +memory controller (written by Dave Vanden Bout), driving +the on-board SDRAM of the XESS board. To do timing +measurements of reads or writes, wire the "we" signal +to 0 or 1, respectively. It is also possible to get a +mix of reads and writes if the "we" signal is a function +of (some bits of) the counter "count". Note that only +32-bit accesses are performed. The clock rate is 50 MHz. + + +Read +---- + +41.8 s +41.9 s +41.7 s + +average: +41.8 s / 2^27 read cycles = 311.4 ns / read cycle +which means 15.6 clock cycles per read +(the corresponding data rate is 12.8 MB/s) + + +Write +----- + +19.6 s +19.7 s +19.6 s + +average: +19.6 s / 2^27 write cycles = 146.0 ns / write cycle +which means 7.3 clock cycles per write +(the corresponding data rate is 27.4 MB/s) + + +Mix (75% read, 25% write) +------------------------- + +36.2 s +36.1 s +36.2 s + +average: +36.2 s / 2^27 operations = 269.7 ns / operation +which means 13.5 clock cycles per operation + + +Conclusions +----------- + +1) The weighted average from read and write operations + (0.75*15.6 + 0.25*7.3) is a very good approximation + for the value measured in the "mixed" case. This + confirms the different values for the "read" and + "write" cases. + +2) The test circuit needs one clock cycle to recover + from a read or write operation before the next one + is started. The recommended number of clock cycles + for a memory simulation are therefore + read : 14 clock cycles + write : 6 clock cycles + measured from start of the operation (leading edge + of signal stb) to end of the operation (trailing + edge of signal ack). Index: trunk/fpga/experiments/memspeed-1/Makefile =================================================================== --- trunk/fpga/experiments/memspeed-1/Makefile (nonexistent) +++ trunk/fpga/experiments/memspeed-1/Makefile (revision 323) @@ -0,0 +1,19 @@ +# +# Makefile for memory speedometer on XESS XSA-XST-3 board +# + +BUILD = ../../../build + +.PHONY: all install clean + +all: build/memspeed.bit + +install: build/memspeed.bit + +clean: + mv build/memspeed.xise . + mv build/memspeed.bit . + rm -rf build/* + mv memspeed.xise build + mv memspeed.bit build + rm -f *~ Index: trunk/fpga/experiments/memspeed-1/build/memspeed.xise =================================================================== --- trunk/fpga/experiments/memspeed-1/build/memspeed.xise (nonexistent) +++ trunk/fpga/experiments/memspeed-1/build/memspeed.xise (revision 323) @@ -0,0 +1,355 @@ + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Index: trunk/fpga/experiments/memspeed-1/build/memspeed.bit =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/fpga/experiments/memspeed-1/build/memspeed.bit =================================================================== --- trunk/fpga/experiments/memspeed-1/build/memspeed.bit (nonexistent) +++ trunk/fpga/experiments/memspeed-1/build/memspeed.bit (revision 323)
trunk/fpga/experiments/memspeed-1/build/memspeed.bit Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/fpga/experiments/memspeed-1/src/memspeed.v =================================================================== --- trunk/fpga/experiments/memspeed-1/src/memspeed.v (nonexistent) +++ trunk/fpga/experiments/memspeed-1/src/memspeed.v (revision 323) @@ -0,0 +1,161 @@ +// +// memspeed.v -- toplevel for memory speedometer +// + + +`timescale 1ns/10ps +`default_nettype none + + +module memspeed(clk_in, + rst_inout_n, + sdram_clk, + sdram_fb, + sdram_cke, + sdram_cs_n, + sdram_ras_n, + sdram_cas_n, + sdram_we_n, + sdram_ba, + sdram_a, + sdram_udqm, + sdram_ldqm, + sdram_dq, + ssl + ); + // clock and reset + input clk_in; + inout rst_inout_n; + // SDRAM + output sdram_clk; + input sdram_fb; + output sdram_cke; + output sdram_cs_n; + output sdram_ras_n; + output sdram_cas_n; + output sdram_we_n; + output [1:0] sdram_ba; + output [12:0] sdram_a; + output sdram_udqm; + output sdram_ldqm; + inout [15:0] sdram_dq; + // 7 segment LED output + output [6:0] ssl; + + // clk_rst + wire clk; + wire clk_ok; + wire rst; + // ram + reg stb; + wire we; + wire [22:0] addr; + wire [31:0] data_in; + wire [31:0] data_out; + wire ack; + // control + reg [27:0] count; + reg next_count; + reg [1:0] state; + reg [1:0] next_state; + + clk_rst clk_rst_1( + .clk_in(clk_in), + .rst_inout_n(rst_inout_n), + .sdram_clk(sdram_clk), + .sdram_fb(sdram_fb), + .clk(clk), + .clk_ok(clk_ok), + .rst(rst) + ); + + ram ram_1( + .clk(clk), + .clk_ok(clk_ok), + .rst(rst), + .stb(stb), + .we(we), + .addr(addr[22:0]), + .data_in(data_in[31:0]), + .data_out(data_out[31:0]), + .ack(ack), + .sdram_cke(sdram_cke), + .sdram_cs_n(sdram_cs_n), + .sdram_ras_n(sdram_ras_n), + .sdram_cas_n(sdram_cas_n), + .sdram_we_n(sdram_we_n), + .sdram_ba(sdram_ba), + .sdram_a(sdram_a), + .sdram_udqm(sdram_udqm), + .sdram_ldqm(sdram_ldqm), + .sdram_dq(sdram_dq) + ); + + assign we = count[1] & count[0]; + assign addr[22:0] = count[22:0]; + assign data_in[31:0] = { count[15:0], count[15:0] }; + + always @(posedge clk) begin + if (rst) begin + count <= 0; + end else begin + if (next_count) begin + count <= count + 1; + end + end + end + + always @(posedge clk) begin + if (rst) begin + state <= 0; + end else begin + state <= next_state; + end + end + + always @(*) begin + case (state) + 2'd0: + begin + stb = 0; + next_count = 0; + next_state = 1; + end + 2'd1: + begin + stb = 1; + next_count = 0; + if (ack) begin + next_state = 2; + end else begin + next_state = 1; + end + end + 2'd2: + begin + stb = 0; + next_count = 1; + if (count[27]) begin + next_state = 3; + end else begin + next_state = 1; + end + end + 2'd3: + begin + stb = 0; + next_count = 0; + next_state = 3; + end + endcase + end + + assign ssl[0] = 0; + assign ssl[1] = | state[1:0]; + assign ssl[2] = & state[1:0]; + assign ssl[3] = 0; + assign ssl[4] = 0; + assign ssl[5] = 0; + assign ssl[6] = ^ data_out[31:0]; + +endmodule Index: trunk/fpga/experiments/memspeed-1/src/ram.v =================================================================== --- trunk/fpga/experiments/memspeed-1/src/ram.v (nonexistent) +++ trunk/fpga/experiments/memspeed-1/src/ram.v (revision 323) @@ -0,0 +1,220 @@ +// +// ram.v -- external RAM interface, using SDRAM +// 8M x 32 bit = 32 MB +// + + +`timescale 1ns/10ps +`default_nettype none + + +module ram(clk, clk_ok, rst, + stb, we, addr, + data_in, data_out, ack, + sdram_cke, sdram_cs_n, + sdram_ras_n, sdram_cas_n, + sdram_we_n, sdram_ba, sdram_a, + sdram_udqm, sdram_ldqm, sdram_dq); + // internal interface signals + input clk; + input clk_ok; + input rst; + input stb; + input we; + input [24:2] addr; + input [31:0] data_in; + output reg [31:0] data_out; + output reg ack; + // SDRAM interface signals + output sdram_cke; + output sdram_cs_n; + output sdram_ras_n; + output sdram_cas_n; + output sdram_we_n; + output [1:0] sdram_ba; + output [12:0] sdram_a; + output sdram_udqm; + output sdram_ldqm; + inout [15:0] sdram_dq; + + reg [2:0] state; + reg a0; + reg cntl_read; + reg cntl_write; + wire cntl_done; + wire [23:0] cntl_addr; + reg [15:0] cntl_din; + wire [15:0] cntl_dout; + + wire sd_out_en; + wire [15:0] sd_out; + +//-------------------------------------------------------------- + + sdramCntl sdramCntl_1( + // clock + .clk(clk), + .clk_ok(clk_ok), + // host side + .rd(cntl_read & ~cntl_done), + .wr(cntl_write & ~cntl_done), + .done(cntl_done), + .hAddr(cntl_addr), + .hDIn(cntl_din), + .hDOut(cntl_dout), + // SDRAM side + .cke(sdram_cke), + .ce_n(sdram_cs_n), + .ras_n(sdram_ras_n), + .cas_n(sdram_cas_n), + .we_n(sdram_we_n), + .ba(sdram_ba), + .sAddr(sdram_a), + .sDIn(sdram_dq), + .sDOut(sd_out), + .sDOutEn(sd_out_en), + .dqmh(sdram_udqm), + .dqml(sdram_ldqm) + ); + + assign sdram_dq = (sd_out_en == 1) ? sd_out : 16'hzzzz; + +//-------------------------------------------------------------- + + // the SDRAM is organized in 16-bit halfwords + // address line 0 is controlled by the state machine + assign cntl_addr[23:1] = addr[24:2]; + assign cntl_addr[0] = a0; + + // state machine for SDRAM access + always @(posedge clk) begin + if (rst) begin + state <= 3'b000; + ack <= 0; + end else begin + case (state) + 3'b000: + // wait for access + begin + if (stb) begin + // access + if (we) begin + // write + state <= 3'b001; + end else begin + // read + state <= 3'b011; + end + end + end + 3'b001: + // write word, upper 16 bits + begin + if (cntl_done) begin + state <= 3'b010; + end + end + 3'b010: + // write word, lower 16 bits + begin + if (cntl_done) begin + state <= 3'b111; + ack <= 1; + end + end + 3'b011: + // read word, upper 16 bits + begin + if (cntl_done) begin + state <= 3'b100; + data_out[31:16] <= cntl_dout; + end + end + 3'b100: + // read word, lower 16 bits + begin + if (cntl_done) begin + state <= 3'b111; + data_out[15:0] <= cntl_dout; + ack <= 1; + end + end + 3'b111: + // end of bus cycle + begin + state <= 3'b000; + ack <= 0; + end + default: + // all other states: reset + begin + state <= 3'b000; + ack <= 0; + end + endcase + end + end + + // output of state machine + always @(*) begin + case (state) + 3'b000: + // wait for access + begin + a0 = 1'bx; + cntl_read = 0; + cntl_write = 0; + cntl_din = 16'hxxxx; + end + 3'b001: + // write word, upper 16 bits + begin + a0 = 1'b0; + cntl_read = 0; + cntl_write = 1; + cntl_din = data_in[31:16]; + end + 3'b010: + // write word, lower 16 bits + begin + a0 = 1'b1; + cntl_read = 0; + cntl_write = 1; + cntl_din = data_in[15:0]; + end + 3'b011: + // read word, upper 16 bits + begin + a0 = 1'b0; + cntl_read = 1; + cntl_write = 0; + cntl_din = 16'hxxxx; + end + 3'b100: + // read word, lower 16 bits + begin + a0 = 1'b1; + cntl_read = 1; + cntl_write = 0; + cntl_din = 16'hxxxx; + end + 3'b111: + // end of bus cycle + begin + a0 = 1'bx; + cntl_read = 0; + cntl_write = 0; + cntl_din = 16'hxxxx; + end + default: + // all other states: reset + begin + a0 = 1'bx; + cntl_read = 0; + cntl_write = 0; + cntl_din = 16'hxxxx; + end + endcase + end + +endmodule Index: trunk/fpga/experiments/memspeed-1/src/clk_rst.v =================================================================== --- trunk/fpga/experiments/memspeed-1/src/clk_rst.v (nonexistent) +++ trunk/fpga/experiments/memspeed-1/src/clk_rst.v (revision 323) @@ -0,0 +1,103 @@ +// +// clk_rst.v -- clock and reset generator +// + + +`timescale 1ns/10ps +`default_nettype none + + +module clk_rst(clk_in, rst_inout_n, + sdram_clk, sdram_fb, + clk, clk_ok, rst); + input clk_in; + inout rst_inout_n; + output sdram_clk; + input sdram_fb; + output clk; + output clk_ok; + output rst; + + wire clk_in_buf; + wire int_clk; + wire int_locked; + wire ext_rst_n; + wire ext_fb; + wire ext_locked; + + reg rst_p_n; + reg rst_s_n; + reg [23:0] rst_counter; + wire rst_counting; + + //------------------------------------------------------------ + + IBUFG clk_in_buffer( + .I(clk_in), + .O(clk_in_buf) + ); + + DCM int_dcm( + .CLKIN(clk_in_buf), + .CLKFB(clk), + .RST(1'b0), + .CLK0(int_clk), + .LOCKED(int_locked) + ); + + BUFG int_clk_buffer( + .I(int_clk), + .O(clk) + ); + + //------------------------------------------------------------ + + SRL16 ext_dll_rst_gen( + .CLK(clk_in_buf), + .D(int_locked), + .Q(ext_rst_n), + .A0(1'b1), + .A1(1'b1), + .A2(1'b1), + .A3(1'b1) + ); + + defparam ext_dll_rst_gen.INIT = 16'h0000; + + //------------------------------------------------------------ + + IBUFG ext_fb_buffer( + .I(sdram_fb), + .O(ext_fb) + ); + + DCM ext_dcm( + .CLKIN(clk_in_buf), + .CLKFB(ext_fb), + .RST(~ext_rst_n), + .CLK0(sdram_clk), + .LOCKED(ext_locked) + ); + + assign clk_ok = int_locked & ext_locked; + + //------------------------------------------------------------ + + assign rst_counting = (rst_counter == 24'hFFFFFF) ? 0 : 1; + assign rst_inout_n = (rst_counter[23] == 0) ? 1'b0 : 1'bz; + + always @(posedge clk_in_buf) begin + rst_p_n <= rst_inout_n; + rst_s_n <= rst_p_n; + if (rst_counting) begin + rst_counter <= rst_counter + 1; + end else begin + if (~rst_s_n | ~clk_ok) begin + rst_counter <= 24'h000000; + end + end + end + + assign rst = rst_counting; + +endmodule Index: trunk/fpga/experiments/memspeed-1/src/sdramcntl.vhd =================================================================== --- trunk/fpga/experiments/memspeed-1/src/sdramcntl.vhd (nonexistent) +++ trunk/fpga/experiments/memspeed-1/src/sdramcntl.vhd (revision 323) @@ -0,0 +1,596 @@ +-------------------------------------------------------------------- +-- Company : XESS Corp. +-- Engineer : Dave Vanden Bout +-- Creation Date : 05/17/2005 +-- Copyright : 2005, XESS Corp +-- Tool Versions : WebPACK 6.3.03i +-- +-- Description: +-- SDRAM controller +-- +-- Revision: +-- n.a. (because of hacking by Hellwig Geisse) +-- +-- Additional Comments: +-- 1.4.0: +-- Added generic parameter to enable/disable independent active rows in each bank. +-- 1.3.0: +-- Modified to allow independently active rows in each bank. +-- 1.2.0: +-- Modified to allow pipelining of read/write operations. +-- 1.1.0: +-- Initial release. +-- +-- License: +-- This code can be freely distributed and modified as long as +-- this header is not removed. +-------------------------------------------------------------------- + +library IEEE, UNISIM; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_unsigned.all; +use IEEE.numeric_std.all; + +entity sdramCntl is + port( + -- host side + clk : in std_logic; -- master clock + clk_ok : in std_logic; -- true if clock is stable + rd : in std_logic; -- initiate read operation + wr : in std_logic; -- initiate write operation + done : out std_logic; -- read or write operation is done + hAddr : in std_logic_vector(23 downto 0); -- address from host to SDRAM + hDIn : in std_logic_vector(15 downto 0); -- data from host to SDRAM + hDOut : out std_logic_vector(15 downto 0); -- data from SDRAM to host + + -- SDRAM side + cke : out std_logic; -- clock-enable to SDRAM + ce_n : out std_logic; -- chip-select to SDRAM + ras_n : out std_logic; -- SDRAM row address strobe + cas_n : out std_logic; -- SDRAM column address strobe + we_n : out std_logic; -- SDRAM write enable + ba : out std_logic_vector(1 downto 0); -- SDRAM bank address + sAddr : out std_logic_vector(12 downto 0); -- SDRAM row/column address + sDIn : in std_logic_vector(15 downto 0); -- data from SDRAM + sDOut : out std_logic_vector(15 downto 0); -- data to SDRAM + sDOutEn : out std_logic; -- true if data is output to SDRAM on sDOut + dqmh : out std_logic; -- enable upper-byte of SDRAM databus if true + dqml : out std_logic -- enable lower-byte of SDRAM databus if true + ); +end sdramCntl; + + +architecture arch of sdramCntl is + + constant YES : std_logic := '1'; + constant NO : std_logic := '0'; + + -- select one of two integers based on a Boolean + function int_select(s : in boolean; a : in integer; b : in integer) return integer is + begin + if s then + return a; + else + return b; + end if; + return a; + end function int_select; + + constant OUTPUT : std_logic := '1'; -- direction of dataflow w.r.t. this controller + constant INPUT : std_logic := '0'; + constant NOP : std_logic := '0'; -- no operation + constant READ : std_logic := '1'; -- read operation + constant WRITE : std_logic := '1'; -- write operation + + -- SDRAM timing parameters + constant Tinit : natural := 200; -- min initialization interval (us) + constant Tras : natural := 45; -- min interval between active to precharge commands (ns) + constant Trcd : natural := 20; -- min interval between active and R/W commands (ns) + constant Tref : natural := 64_000_000; -- maximum refresh interval (ns) + constant Trfc : natural := 66; -- duration of refresh operation (ns) + constant Trp : natural := 20; -- min precharge command duration (ns) + constant Twr : natural := 15; -- write recovery time (ns) + constant Txsr : natural := 75; -- exit self-refresh time (ns) + + -- SDRAM timing parameters converted into clock cycles (based on FREQ = 50_000) + constant NORM : natural := 1_000_000; -- normalize ns * KHz + constant INIT_CYCLES : natural := 1+((Tinit*50_000)/1000); -- SDRAM power-on initialization interval + constant RAS_CYCLES : natural := 1+((Tras*50_000)/NORM); -- active-to-precharge interval + constant RCD_CYCLES : natural := 1+((Trcd*50_000)/NORM); -- active-to-R/W interval + constant REF_CYCLES : natural := 1+(((Tref/8192)*50_000)/NORM); -- interval between row refreshes + constant RFC_CYCLES : natural := 1+((Trfc*50_000)/NORM); -- refresh operation interval + constant RP_CYCLES : natural := 1+((Trp*50_000)/NORM); -- precharge operation interval + constant WR_CYCLES : natural := 1+((Twr*50_000)/NORM); -- write recovery time + constant XSR_CYCLES : natural := 1+((Txsr*50_000)/NORM); -- exit self-refresh time + constant MODE_CYCLES : natural := 2; -- mode register setup time + constant CAS_CYCLES : natural := 3; -- CAS latency + constant RFSH_OPS : natural := 8; -- number of refresh operations needed to init SDRAM + + -- timer registers that count down times for various SDRAM operations + signal timer_r, timer_x : natural range 0 to INIT_CYCLES; -- current SDRAM op time + signal rasTimer_r, rasTimer_x : natural range 0 to RAS_CYCLES; -- active-to-precharge time + signal wrTimer_r, wrTimer_x : natural range 0 to WR_CYCLES; -- write-to-precharge time + signal refTimer_r, refTimer_x : natural range 0 to REF_CYCLES; -- time between row refreshes + signal rfshCntr_r, rfshCntr_x : natural range 0 to 8192; -- counts refreshes that are neede + signal nopCntr_r, nopCntr_x : natural range 0 to 10000; -- counts consecutive NOP operations + + signal doSelfRfsh : std_logic; -- active when the NOP counter hits zero and self-refresh can start + + -- states of the SDRAM controller state machine + type cntlState is ( + INITWAIT, -- initialization - waiting for power-on initialization to complete + INITPCHG, -- initialization - initial precharge of SDRAM banks + INITSETMODE, -- initialization - set SDRAM mode + INITRFSH, -- initialization - do initial refreshes + RW, -- read/write/refresh the SDRAM + ACTIVATE, -- open a row of the SDRAM for reading/writing + REFRESHROW, -- refresh a row of the SDRAM + SELFREFRESH -- keep SDRAM in self-refresh mode with CKE low + ); + signal state_r, state_x : cntlState; -- state register and next state + + -- commands that are sent to the SDRAM to make it perform certain operations + -- commands use these SDRAM input pins (ce_n,ras_n,cas_n,we_n,dqmh,dqml) + subtype sdramCmd is unsigned(5 downto 0); + constant NOP_CMD : sdramCmd := "011100"; + constant ACTIVE_CMD : sdramCmd := "001100"; + constant READ_CMD : sdramCmd := "010100"; + constant WRITE_CMD : sdramCmd := "010000"; + constant PCHG_CMD : sdramCmd := "001011"; + constant MODE_CMD : sdramCmd := "000011"; + constant RFSH_CMD : sdramCmd := "000111"; + + -- SDRAM mode register + -- the SDRAM is placed in a non-burst mode (burst length = 1) with a 3-cycle CAS + subtype sdramMode is std_logic_vector(12 downto 0); + constant MODE : sdramMode := "000" & "0" & "00" & "011" & "0" & "000"; + + -- the host address is decomposed into these sets of SDRAM address components + constant ROW_LEN : natural := 13; -- number of row address bits + constant COL_LEN : natural := 9; -- number of column address bits + signal bank : std_logic_vector(ba'range); -- bank address bits + signal row : std_logic_vector(ROW_LEN - 1 downto 0); -- row address within bank + signal col : std_logic_vector(sAddr'range); -- column address within row + + -- registers that store the currently active row in each bank of the SDRAM + constant NUM_ACTIVE_ROWS : integer := 1; + type activeRowType is array(0 to NUM_ACTIVE_ROWS-1) of std_logic_vector(row'range); + signal activeRow_r, activeRow_x : activeRowType; + signal activeFlag_r, activeFlag_x : std_logic_vector(0 to NUM_ACTIVE_ROWS-1); -- indicates that some row in a bank is active + signal bankIndex : natural range 0 to NUM_ACTIVE_ROWS-1; -- bank address bits + signal activeBank_r, activeBank_x : std_logic_vector(ba'range); -- indicates the bank with the active row + signal doActivate : std_logic; -- indicates when a new row in a bank needs to be activated + + -- there is a command bit embedded within the SDRAM column address + constant CMDBIT_POS : natural := 10; -- position of command bit + constant AUTO_PCHG_ON : std_logic := '1'; -- CMDBIT value to auto-precharge the bank + constant AUTO_PCHG_OFF : std_logic := '0'; -- CMDBIT value to disable auto-precharge + constant ONE_BANK : std_logic := '0'; -- CMDBIT value to select one bank + constant ALL_BANKS : std_logic := '1'; -- CMDBIT value to select all banks + + -- status signals that indicate when certain operations are in progress + signal wrInProgress : std_logic; -- write operation in progress + signal rdInProgress : std_logic; -- read operation in progress + signal activateInProgress : std_logic; -- row activation is in progress + + -- these registers track the progress of read and write operations + signal rdPipeline_r, rdPipeline_x : std_logic_vector(CAS_CYCLES+1 downto 0); -- pipeline of read ops in progress + signal wrPipeline_r, wrPipeline_x : std_logic_vector(0 downto 0); -- pipeline of write ops (only need 1 cycle) + + -- registered outputs to host + signal hDOut_r, hDOut_x : std_logic_vector(hDOut'range); -- holds data read from SDRAM and sent to the host + + -- registered outputs to SDRAM + signal cke_r, cke_x : std_logic; -- clock enable + signal cmd_r, cmd_x : sdramCmd; -- SDRAM command bits + signal ba_r, ba_x : std_logic_vector(ba'range); -- SDRAM bank address bits + signal sAddr_r, sAddr_x : std_logic_vector(sAddr'range); -- SDRAM row/column address + signal sData_r, sData_x : std_logic_vector(sDOut'range); -- SDRAM out databus + signal sDataDir_r, sDataDir_x : std_logic; -- SDRAM databus direction control bit + +begin + + ----------------------------------------------------------- + -- attach some internal signals to the I/O ports + ----------------------------------------------------------- + + -- attach registered SDRAM control signals to SDRAM input pins + (ce_n, ras_n, cas_n, we_n, dqmh, dqml) <= cmd_r; -- SDRAM operation control bits + cke <= cke_r; -- SDRAM clock enable + ba <= ba_r; -- SDRAM bank address + sAddr <= sAddr_r; -- SDRAM address + sDOut <= sData_r; -- SDRAM output data bus + sDOutEn <= YES when sDataDir_r = OUTPUT else NO; -- output databus enable + + -- attach some port signals + hDOut <= hDOut_r; -- data back to host + + + ----------------------------------------------------------- + -- compute the next state and outputs + ----------------------------------------------------------- + + combinatorial : process(rd, wr, hAddr, hDIn, hDOut_r, sDIn, state_r, + activeFlag_r, activeRow_r, activeBank_r, + rdPipeline_r, wrPipeline_r, + nopCntr_r, rfshCntr_r, timer_r, rasTimer_r, + wrTimer_r, refTimer_r, cmd_r, cke_r) + begin + + ----------------------------------------------------------- + -- setup default values for signals + ----------------------------------------------------------- + + cke_x <= YES; -- enable SDRAM clock + cmd_x <= NOP_CMD; -- set SDRAM command to no-operation + sDataDir_x <= INPUT; -- accept data from the SDRAM + sData_x <= hDIn(sData_x'range); -- output data from host to SDRAM + state_x <= state_r; -- reload these registers and flags + activeFlag_x <= activeFlag_r; -- with their existing values + activeRow_x <= activeRow_r; + activeBank_x <= activeBank_r; + rfshCntr_x <= rfshCntr_r; + + ----------------------------------------------------------- + -- setup default value for the SDRAM address + ----------------------------------------------------------- + + -- extract bank field from host address + ba_x <= hAddr(ba'length + ROW_LEN + COL_LEN - 1 downto ROW_LEN + COL_LEN); + bank <= ba_x; + bankIndex <= 0; + -- extract row, column fields from host address + row <= hAddr(ROW_LEN + COL_LEN - 1 downto COL_LEN); + -- extend column (if needed) until it is as large as the (SDRAM address bus - 1) + col <= (others => '0'); -- set it to all zeroes + col(COL_LEN-1 downto 0) <= hAddr(COL_LEN-1 downto 0); + -- by default, set SDRAM address to the column address with interspersed + -- command bit set to disable auto-precharge + sAddr_x <= col(col'high-1 downto CMDBIT_POS) & AUTO_PCHG_OFF + & col(CMDBIT_POS-1 downto 0); + + ----------------------------------------------------------- + -- manage the read and write operation pipelines + ----------------------------------------------------------- + + -- determine if read operations are in progress by the presence of + -- READ flags in the read pipeline + if rdPipeline_r(rdPipeline_r'high downto 1) /= 0 then + rdInProgress <= YES; + else + rdInProgress <= NO; + end if; + + -- enter NOPs into the read and write pipeline shift registers by default + rdPipeline_x <= NOP & rdPipeline_r(rdPipeline_r'high downto 1); + wrPipeline_x(0) <= NOP; + + -- transfer data from SDRAM to the host data register if a read flag has exited the pipeline + -- (the transfer occurs 1 cycle before we tell the host the read operation is done) + if rdPipeline_r(1) = READ then + -- get the SDRAM data for the host directly from the SDRAM if the controller and SDRAM are in-phase + hDOut_x <= sDIn(hDOut'range); + else + -- retain contents of host data registers if no data from the SDRAM has arrived yet + hDOut_x <= hDOut_r; + end if; + + done <= rdPipeline_r(0) or wrPipeline_r(0); -- a read or write operation is done + + ----------------------------------------------------------- + -- manage row activation + ----------------------------------------------------------- + + -- request a row activation operation if the row of the current address + -- does not match the currently active row in the bank, or if no row + -- in the bank is currently active + if (bank /= activeBank_r) or (row /= activeRow_r(bankIndex)) or (activeFlag_r(bankIndex) = NO) then + doActivate <= YES; + else + doActivate <= NO; + end if; + + ----------------------------------------------------------- + -- manage self-refresh + ----------------------------------------------------------- + + -- enter self-refresh if neither a read or write is requested for 10000 consecutive cycles. + if (rd = YES) or (wr = YES) then + -- any read or write resets NOP counter and exits self-refresh state + nopCntr_x <= 0; + doSelfRfsh <= NO; + elsif nopCntr_r /= 10000 then + -- increment NOP counter whenever there is no read or write operation + nopCntr_x <= nopCntr_r + 1; + doSelfRfsh <= NO; + else + -- start self-refresh when counter hits maximum NOP count and leave counter unchanged + nopCntr_x <= nopCntr_r; + doSelfRfsh <= YES; + end if; + + ----------------------------------------------------------- + -- update the timers + ----------------------------------------------------------- + + -- row activation timer + if rasTimer_r /= 0 then + -- decrement a non-zero timer and set the flag + -- to indicate the row activation is still inprogress + rasTimer_x <= rasTimer_r - 1; + activateInProgress <= YES; + else + -- on timeout, keep the timer at zero and reset the flag + -- to indicate the row activation operation is done + rasTimer_x <= rasTimer_r; + activateInProgress <= NO; + end if; + + -- write operation timer + if wrTimer_r /= 0 then + -- decrement a non-zero timer and set the flag + -- to indicate the write operation is still inprogress + wrTimer_x <= wrTimer_r - 1; + wrInPRogress <= YES; + else + -- on timeout, keep the timer at zero and reset the flag that + -- indicates a write operation is in progress + wrTimer_x <= wrTimer_r; + wrInPRogress <= NO; + end if; + + -- refresh timer + if refTimer_r /= 0 then + refTimer_x <= refTimer_r - 1; + else + -- on timeout, reload the timer with the interval between row refreshes + -- and increment the counter for the number of row refreshes that are needed + refTimer_x <= REF_CYCLES; + rfshCntr_x <= rfshCntr_r + 1; + end if; + + -- main timer for sequencing SDRAM operations + if timer_r /= 0 then + -- decrement the timer and do nothing else since the previous operation has not completed yet. + timer_x <= timer_r - 1; + else + -- the previous operation has completed once the timer hits zero + timer_x <= timer_r; -- by default, leave the timer at zero + + ----------------------------------------------------------- + -- compute the next state and outputs + ----------------------------------------------------------- + case state_r is + + ----------------------------------------------------------- + -- let clock stabilize and then wait for the SDRAM to initialize + ----------------------------------------------------------- + when INITWAIT => + -- wait for SDRAM power-on initialization once the clock is stable + timer_x <= INIT_CYCLES; -- set timer for initialization duration + state_x <= INITPCHG; + + ----------------------------------------------------------- + -- precharge all SDRAM banks after power-on initialization + ----------------------------------------------------------- + when INITPCHG => + cmd_x <= PCHG_CMD; + sAddr_x(CMDBIT_POS) <= ALL_BANKS; -- precharge all banks + timer_x <= RP_CYCLES; -- set timer for precharge operation duration + rfshCntr_x <= RFSH_OPS; -- set counter for refresh ops needed after precharge + state_x <= INITRFSH; + + ----------------------------------------------------------- + -- refresh the SDRAM a number of times after initial precharge + ----------------------------------------------------------- + when INITRFSH => + cmd_x <= RFSH_CMD; + timer_x <= RFC_CYCLES; -- set timer to refresh operation duration + rfshCntr_x <= rfshCntr_r - 1; -- decrement refresh operation counter + if rfshCntr_r = 1 then + state_x <= INITSETMODE; -- set the SDRAM mode once all refresh ops are done + end if; + + ----------------------------------------------------------- + -- set the mode register of the SDRAM + ----------------------------------------------------------- + when INITSETMODE => + cmd_x <= MODE_CMD; + sAddr_x <= MODE; -- output mode register bits on the SDRAM address bits + timer_x <= MODE_CYCLES; -- set timer for mode setting operation duration + state_x <= RW; + + ----------------------------------------------------------- + -- process read/write/refresh operations after initialization is done + ----------------------------------------------------------- + when RW => + ----------------------------------------------------------- + -- highest priority operation: row refresh + -- do a refresh operation if the refresh counter is non-zero + ----------------------------------------------------------- + if rfshCntr_r /= 0 then + -- wait for any row activations, writes or reads to finish before doing a precharge + if (activateInProgress = NO) and (wrInProgress = NO) and (rdInProgress = NO) then + cmd_x <= PCHG_CMD; -- initiate precharge of the SDRAM + sAddr_x(CMDBIT_POS) <= ALL_BANKS; -- precharge all banks + timer_x <= RP_CYCLES; -- set timer for this operation + activeFlag_x <= (others => NO); -- all rows are inactive after a precharge operation + state_x <= REFRESHROW; -- refresh the SDRAM after the precharge + end if; + ----------------------------------------------------------- + -- do a host-initiated read operation + ----------------------------------------------------------- + elsif rd = YES then + -- Wait one clock cycle if the bank address has just changed and each bank has its own active row. + -- This gives extra time for the row activation circuitry. + if (true) then + -- activate a new row if the current read is outside the active row or bank + if doActivate = YES then + -- activate new row only if all previous activations, writes, reads are done + if (activateInProgress = NO) and (wrInProgress = NO) and (rdInProgress = NO) then + cmd_x <= PCHG_CMD; -- initiate precharge of the SDRAM + sAddr_x(CMDBIT_POS) <= ONE_BANK; -- precharge this bank + timer_x <= RP_CYCLES; -- set timer for this operation + activeFlag_x(bankIndex) <= NO; -- rows in this bank are inactive after a precharge operation + state_x <= ACTIVATE; -- activate the new row after the precharge is done + end if; + -- read from the currently active row if no previous read operation + -- is in progress or if pipeline reads are enabled + -- we can always initiate a read even if a write is already in progress + elsif (rdInProgress = NO) then + cmd_x <= READ_CMD; -- initiate a read of the SDRAM + -- insert a flag into the pipeline shift register that will exit the end + -- of the shift register when the data from the SDRAM is available + rdPipeline_x <= READ & rdPipeline_r(rdPipeline_r'high downto 1); + end if; + end if; + ----------------------------------------------------------- + -- do a host-initiated write operation + ----------------------------------------------------------- + elsif wr = YES then + -- Wait one clock cycle if the bank address has just changed and each bank has its own active row. + -- This gives extra time for the row activation circuitry. + if (true) then + -- activate a new row if the current write is outside the active row or bank + if doActivate = YES then + -- activate new row only if all previous activations, writes, reads are done + if (activateInProgress = NO) and (wrInProgress = NO) and (rdInProgress = NO) then + cmd_x <= PCHG_CMD; -- initiate precharge of the SDRAM + sAddr_x(CMDBIT_POS) <= ONE_BANK; -- precharge this bank + timer_x <= RP_CYCLES; -- set timer for this operation + activeFlag_x(bankIndex) <= NO; -- rows in this bank are inactive after a precharge operation + state_x <= ACTIVATE; -- activate the new row after the precharge is done + end if; + -- write to the currently active row if no previous read operations are in progress + elsif rdInProgress = NO then + cmd_x <= WRITE_CMD; -- initiate the write operation + sDataDir_x <= OUTPUT; -- turn on drivers to send data to SDRAM + -- set timer so precharge doesn't occur too soon after write operation + wrTimer_x <= WR_CYCLES; + -- insert a flag into the 1-bit pipeline shift register that will exit on the + -- next cycle. The write into SDRAM is not actually done by that time, but + -- this doesn't matter to the host + wrPipeline_x(0) <= WRITE; + end if; + end if; + ----------------------------------------------------------- + -- do a host-initiated self-refresh operation + ----------------------------------------------------------- + elsif doSelfRfsh = YES then + -- wait until all previous activations, writes, reads are done + if (activateInProgress = NO) and (wrInProgress = NO) and (rdInProgress = NO) then + cmd_x <= PCHG_CMD; -- initiate precharge of the SDRAM + sAddr_x(CMDBIT_POS) <= ALL_BANKS; -- precharge all banks + timer_x <= RP_CYCLES; -- set timer for this operation + activeFlag_x <= (others => NO); -- all rows are inactive after a precharge operation + state_x <= SELFREFRESH; -- self-refresh the SDRAM after the precharge + end if; + ----------------------------------------------------------- + -- no operation + ----------------------------------------------------------- + else + state_x <= RW; -- continue to look for SDRAM operations to execute + end if; + + ----------------------------------------------------------- + -- activate a row of the SDRAM + ----------------------------------------------------------- + when ACTIVATE => + cmd_x <= ACTIVE_CMD; + sAddr_x <= (others => '0'); -- output the address for the row to be activated + sAddr_x(row'range) <= row; + activeBank_x <= bank; + activeRow_x(bankIndex) <= row; -- store the new active SDRAM row address + activeFlag_x(bankIndex) <= YES; -- the SDRAM is now active + rasTimer_x <= RAS_CYCLES; -- minimum time before another precharge can occur + timer_x <= RCD_CYCLES; -- minimum time before a read/write operation can occur + state_x <= RW; -- return to do read/write operation that initiated this activation + + ----------------------------------------------------------- + -- refresh a row of the SDRAM + ----------------------------------------------------------- + when REFRESHROW => + cmd_x <= RFSH_CMD; + timer_x <= RFC_CYCLES; -- refresh operation interval + rfshCntr_x <= rfshCntr_r - 1; -- decrement the number of needed row refreshes + state_x <= RW; -- process more SDRAM operations after refresh is done + + ----------------------------------------------------------- + -- place the SDRAM into self-refresh and keep it there until further notice + ----------------------------------------------------------- + when SELFREFRESH => + if (doSelfRfsh = YES) then + -- keep the SDRAM in self-refresh mode as long as requested and until there is a stable clock + cmd_x <= RFSH_CMD; -- output the refresh command; this is only needed on the first clock cycle + cke_x <= NO; -- disable the SDRAM clock + else + -- else exit self-refresh mode and start processing read and write operations + cke_x <= YES; -- restart the SDRAM clock + rfshCntr_x <= 0; -- no refreshes are needed immediately after leaving self-refresh + activeFlag_x <= (others => NO); -- self-refresh deactivates all rows + timer_x <= XSR_CYCLES; -- wait this long until read and write operations can resume + state_x <= RW; + end if; + + ----------------------------------------------------------- + -- unknown state + ----------------------------------------------------------- + when others => + state_x <= INITWAIT; -- reset state if in erroneous state + + end case; + end if; + end process combinatorial; + + + ----------------------------------------------------------- + -- update registers on the appropriate clock edge + ----------------------------------------------------------- + + update : process(clk_ok, clk) + begin + + if clk_ok = NO then + -- asynchronous reset + state_r <= INITWAIT; + activeFlag_r <= (others => NO); + rfshCntr_r <= 0; + timer_r <= 0; + refTimer_r <= REF_CYCLES; + rasTimer_r <= 0; + wrTimer_r <= 0; + nopCntr_r <= 0; + rdPipeline_r <= (others => '0'); + wrPipeline_r <= (others => '0'); + cke_r <= NO; + cmd_r <= NOP_CMD; + ba_r <= (others => '0'); + sAddr_r <= (others => '0'); + sData_r <= (others => '0'); + sDataDir_r <= INPUT; + hDOut_r <= (others => '0'); + elsif rising_edge(clk) then + state_r <= state_x; + activeBank_r <= activeBank_x; + activeRow_r <= activeRow_x; + activeFlag_r <= activeFlag_x; + rfshCntr_r <= rfshCntr_x; + timer_r <= timer_x; + refTimer_r <= refTimer_x; + rasTimer_r <= rasTimer_x; + wrTimer_r <= wrTimer_x; + nopCntr_r <= nopCntr_x; + rdPipeline_r <= rdPipeline_x; + wrPipeline_r <= wrPipeline_x; + cke_r <= cke_x; + cmd_r <= cmd_x; + ba_r <= ba_x; + sAddr_r <= sAddr_x; + sData_r <= sData_x; + sDataDir_r <= sDataDir_x; + hDOut_r <= hDOut_x; + end if; + + end process update; + +end arch; Index: trunk/fpga/experiments/memspeed-1/src/memspeed.ucf =================================================================== --- trunk/fpga/experiments/memspeed-1/src/memspeed.ucf (nonexistent) +++ trunk/fpga/experiments/memspeed-1/src/memspeed.ucf (revision 323) @@ -0,0 +1,65 @@ +# +# memspeed.ucf -- user constraints for XSA-3S1000 + XST-3 board +# + +# +# clock and reset +# +NET "clk_in" PERIOD = 20.0ns HIGH 40%; +NET "clk_in" LOC = "p8"; +NET "rst_inout_n" LOC = "d15"; + +# +# SDRAM +# +NET "sdram_clk" LOC = "e10"; +NET "sdram_fb" LOC = "n8"; +NET "sdram_cke" LOC = "d7"; +NET "sdram_cs_n" LOC = "b8"; +NET "sdram_ras_n" LOC = "a9"; +NET "sdram_cas_n" LOC = "a10"; +NET "sdram_we_n" LOC = "b10"; +NET "sdram_ba<1>" LOC = "c7"; +NET "sdram_ba<0>" LOC = "a7"; +NET "sdram_a<12>" LOC = "c6"; +NET "sdram_a<11>" LOC = "c5"; +NET "sdram_a<10>" LOC = "b6"; +NET "sdram_a<9>" LOC = "a3"; +NET "sdram_a<8>" LOC = "c2"; +NET "sdram_a<7>" LOC = "d3"; +NET "sdram_a<6>" LOC = "e4"; +NET "sdram_a<5>" LOC = "c1"; +NET "sdram_a<4>" LOC = "e3"; +NET "sdram_a<3>" LOC = "e6"; +NET "sdram_a<2>" LOC = "b4"; +NET "sdram_a<1>" LOC = "a4"; +NET "sdram_a<0>" LOC = "b5"; +NET "sdram_udqm" LOC = "d9"; +NET "sdram_ldqm" LOC = "c10"; +NET "sdram_dq<15>" LOC = "f13"; +NET "sdram_dq<14>" LOC = "f12"; +NET "sdram_dq<13>" LOC = "c16"; +NET "sdram_dq<12>" LOC = "d14"; +NET "sdram_dq<11>" LOC = "b14"; +NET "sdram_dq<10>" LOC = "c12"; +NET "sdram_dq<9>" LOC = "b12"; +NET "sdram_dq<8>" LOC = "b11"; +NET "sdram_dq<7>" LOC = "d10"; +NET "sdram_dq<6>" LOC = "c11"; +NET "sdram_dq<5>" LOC = "a12"; +NET "sdram_dq<4>" LOC = "d11"; +NET "sdram_dq<3>" LOC = "b13"; +NET "sdram_dq<2>" LOC = "a14"; +NET "sdram_dq<1>" LOC = "d12"; +NET "sdram_dq<0>" LOC = "c15"; + +# +# 7 segment LED +# +NET "ssl<6>" LOC = "r10"; +NET "ssl<5>" LOC = "t7"; +NET "ssl<4>" LOC = "p10"; +NET "ssl<3>" LOC = "r7"; +NET "ssl<2>" LOC = "n6"; +NET "ssl<1>" LOC = "m11"; +NET "ssl<0>" LOC = "m6";

powered by: WebSVN 2.1.0

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