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/README
File deleted
/trunk/fpga/experiments/memspeed/Makefile
File deleted
/trunk/fpga/experiments/memspeed/build/memspeed.xise
File deleted
/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/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/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-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";