From: Sebastien Bourdeauducq Date: Sun, 19 Feb 2012 17:43:42 +0000 (+0100) Subject: Prepare for new DDR PHY X-Git-Tag: 24jan2021_ls180~3227 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f35cd4a85bec00f364779314f7d7a8ed277cc628;p=litex.git Prepare for new DDR PHY --- diff --git a/.gitignore b/.gitignore index 15832e33..9d2acfa3 100644 --- a/.gitignore +++ b/.gitignore @@ -6,5 +6,3 @@ build/* tools/bin2hex tools/flterm tools/mkmmimg -verilog/s6ddrphy/*.v -verilog/s6ddrphy/.pc diff --git a/Makefile b/Makefile index 9ebc7067..f1696a3b 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ build/soc-routed.ncd: build/soc.ncd cd build && par -ol high -w soc.ncd soc-routed.ncd build/soc.bit build/soc.bin: build/soc-routed.ncd - cd build && bitgen -g Binary:Yes -g INIT_9K:Yes -w soc-routed.ncd soc.bit + cd build && bitgen -g LCK_cycle:6 -g Binary:Yes -g INIT_9K:Yes -w soc-routed.ncd soc.bit load: build/soc.bit jtag -n load.jtag diff --git a/README b/README index 5dc6b642..1cc3abf5 100644 --- a/README +++ b/README @@ -19,22 +19,6 @@ production version of Milkymist SoC, visit: First, download and install Migen from: https://github.com/milkymist/migen -Then, you will need to fetch the "Spartan-6 FPGA DDR/DDR2 SDRAM PHY core" -(PHY only solution, we do not need the NWL memory controller) from: - http://www.xilinx.com/products/intellectual-property/1-1MFEDB.htm -Downloading it is free of charge, but it cannot be redistributed in -source form due to copyright restrictions. - -Place the Verilog source code of the PHY (contents of -phy_rtl/spartan6_soft_phy) into the verilog/s6ddrphy folder. -Then run (from verilog/s6ddrphy): - quilt push -a -in order to apply patches that make the PHY more compliant with the DFI -specification in general, and in particular with the capability to send -multiple SDRAM commands in one system clock cycle, which our new SDRAM -controller is capable of doing. -The patches are against version 1.04 of the PHY. - Once this is done, build the bitstream with: python3 build.py This will generate the build/soc.bit programming file. @@ -67,8 +51,7 @@ without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. The authors grant the additional permissions that the code can be used in -conjunction with the LatticeMico32 CPU core from Lattice and the -Spartan-6 FPGA DDR/DDR2 SDRAM PHY core from Xilinx and Northwest Logic. +conjunction with the LatticeMico32 CPU core from Lattice. Unless otherwise noted, Milkymist-NG's source code is copyright (C) 2011-2012 Sebastien Bourdeauducq. Other authors retain ownership of their diff --git a/constraints.py b/constraints.py index 4867ae5b..f68e5bb3 100644 --- a/constraints.py +++ b/constraints.py @@ -13,7 +13,6 @@ def get(ns, crg0, norflash0, uart0, ddrphy0): add(crg0.ac97_rst_n, "D6") add(crg0.videoin_rst_n, "W17") add(crg0.flash_rst_n, "P22", extra="SLEW = FAST | DRIVE = 8") - add(crg0.rd_clk_lb, "K5", extra="IOSTANDARD = SSTL2_I") add(crg0.trigger_reset, "AA4") add_vec(norflash0.adr, ["L22", "L20", "K22", "K21", "J19", "H20", "F22", @@ -61,15 +60,8 @@ def get(ns, crg0, norflash0, uart0, ddrphy0): r += """ TIMESPEC "TSclk50" = PERIOD "GRPclk50" 20 ns HIGH 50%; -INST "spartan6_soft_phy/datapath_s6_inst/dq_idelay_cal_inst/max_tap_drp" LOC = "IODELAY_X0Y79"; # use sd_dm[0] at E1 -INST "m1crg/wr_bufpll_left" LOC = "BUFPLL_X0Y2"; -INST "m1crg/wr_bufpll_right" LOC = "BUFPLL_X2Y2"; -INST "m1crg/rd_bufpll_left" LOC = "BUFPLL_X0Y3"; -INST "m1crg/rd_bufpll_right" LOC = "BUFPLL_X2Y3"; - -# MAP (13.4) hallucinates that this placement is unroutable. Tell it to STFU. -PIN "m1crg/rd_bufpll_left.IOCLK" CLOCK_DEDICATED_ROUTE = FALSE; -PIN "spartan6_soft_phy/datapath_s6_inst/dq_idelay_cal_inst/max_tap_drp.IOCLK0" CLOCK_DEDICATED_ROUTE = FALSE; +INST "m1crg/wr_bufpll" LOC = "BUFPLL_X0Y2"; +INST "m1crg/rd_bufpll" LOC = "BUFPLL_X0Y3"; """ return r diff --git a/milkymist/m1crg/__init__.py b/milkymist/m1crg/__init__.py index 37b19e5a..a0b49b61 100644 --- a/milkymist/m1crg/__init__.py +++ b/milkymist/m1crg/__init__.py @@ -15,21 +15,15 @@ class M1CRG: "videoin_rst_n", "flash_rst_n", "clk2x_90", - "clk4x_wr_left", - "clk4x_wr_strb_left", - "clk4x_wr_right", - "clk4x_wr_strb_right", - "clk4x_rd_left", - "clk4x_rd_strb_left", - "clk4x_rd_right", - "clk4x_rd_strb_right" + "clk4x_wr", + "clk4x_wr_strb", + "clk4x_rd", + "clk4x_rd_strb" ]: s = Signal(name=name) setattr(self, name, s) generated.append((name, s)) - self.rd_clk_lb = Signal() - ratio = Fraction(outfreq1x)/Fraction(infreq) in_period = float(Fraction(1000000000)/Fraction(infreq)) @@ -38,9 +32,8 @@ class M1CRG: [ ("clkin", self.clkin), ("trigger_reset", self.trigger_reset) - ], [ - ("rd_clk_lb", self.rd_clk_lb) - ], [ + ], + parameters=[ ("in_period", in_period), ("f_mult", ratio.numerator), ("f_div", ratio.denominator) @@ -49,4 +42,4 @@ class M1CRG: def get_fragment(self): return Fragment(instances=[self._inst], - pads={self.clkin, self.ac97_rst_n, self.videoin_rst_n, self.flash_rst_n, self.rd_clk_lb}) + pads={self.clkin, self.ac97_rst_n, self.videoin_rst_n, self.flash_rst_n}) diff --git a/milkymist/s6ddrphy/__init__.py b/milkymist/s6ddrphy/__init__.py index 6b269703..4129f089 100644 --- a/milkymist/s6ddrphy/__init__.py +++ b/milkymist/s6ddrphy/__init__.py @@ -1,31 +1,24 @@ from migen.fhdl.structure import * from migen.bus import dfi -from migen.bank.description import * -from migen.bank import csrgen class S6DDRPHY: - def __init__(self, csr_address, a, ba, d): + def __init__(self, a, ba, d): ins = [] outs = [] inouts = [] for name in [ "clk2x_90", - "clk4x_wr_left", - "clk4x_wr_strb_left", - "clk4x_wr_right", - "clk4x_wr_strb_right", - "clk4x_rd_left", - "clk4x_rd_strb_left", - "clk4x_rd_right", - "clk4x_rd_strb_right" + "clk4x_wr", + "clk4x_wr_strb", + "clk4x_rd", + "clk4x_rd_strb" ]: s = Signal(name=name) setattr(self, name, s) ins.append((name, s)) self._sd_pins = [] - sd_d = d//4 for name, width, l in [ ("sd_clk_out_p", 1, outs), ("sd_clk_out_n", 1, outs), @@ -36,9 +29,9 @@ class S6DDRPHY: ("sd_ras_n", 1, outs), ("sd_cas_n", 1, outs), ("sd_we_n", 1, outs), - ("sd_dq", sd_d, inouts), - ("sd_dm", sd_d//8, outs), - ("sd_dqs", sd_d//8, inouts) + ("sd_dq", d//2, inouts), + ("sd_dm", d//16, outs), + ("sd_dqs", d//16, inouts) ]: s = Signal(BV(width), name=name) @@ -46,93 +39,20 @@ class S6DDRPHY: l.append((name, s)) self._sd_pins.append(s) - self.dfi = dfi.Interface(a, ba, d) + self.dfi = dfi.Interface(a, ba, d, 2) ins += self.dfi.get_standard_names(True, False) outs += self.dfi.get_standard_names(False, True) - ins += [ - ("reset_n", BV(1)), - - ("cfg_al", BV(3)), - ("cfg_cl", BV(3)), - ("cfg_bl", BV(2)), - ("cfg_regdimm", BV(1)), - - ("init_done", BV(1)), - - ("cpg_busy", BV(1)), - - ("diag_dq_recal", BV(1)), - ("diag_io_sel", BV(9)), - ("diag_disable_cal_on_startup", BV(1)), - ("diag_cal_bits", BV(2)), - ("diag_short_cal", BV(1)) - ] - outs += [ - ("phy_cal_done", BV(1)), - - ("cpg_r_req", BV(1)), - ("cpg_w_req", BV(1)), - ("cpg_addr", BV(a)), - ("cpg_b_size", BV(4)) - ] - - self._inst = Instance("spartan6_soft_phy", + self._inst = Instance("s6ddrphy", outs, ins, inouts, [ - ("DSIZE", d), ("NUM_AD", a), ("NUM_BA", ba), - ("ADDR_WIDTH", 31), - ("DQ_IO_LOC", Constant(2**32-1, BV(32))), - ("DM_IO_LOC", Constant(2**4-1, BV(4))) + ("NUM_D", d) ], - clkport="clk") - - self._reset_n = Field("reset_n") - self._init_done = Field("init_done") - self._phy_cal_done = Field("phy_cal_done", 1, READ_ONLY, WRITE_ONLY) - self._status = RegisterFields("status", - [self._reset_n, self._init_done, self._phy_cal_done]) - self._req = RegisterRaw("req", 2) - self._req_addr = RegisterField("req_addr", 8, READ_ONLY, WRITE_ONLY) - - self.bank = csrgen.Bank([self._status, self._req, self._req_addr], - address=csr_address) + clkport="sys_clk") def get_fragment(self): - pending_r = Signal() - pending_w = Signal() - cpg_busy = Signal() - - comb = [ - self._inst.ins["cfg_al"].eq(0), - self._inst.ins["cfg_cl"].eq(3), - self._inst.ins["cfg_bl"].eq(1), - self._inst.ins["cfg_regdimm"].eq(0), - - self._inst.ins["diag_dq_recal"].eq(0), - self._inst.ins["diag_io_sel"].eq(0), - self._inst.ins["diag_disable_cal_on_startup"].eq(0), - self._inst.ins["diag_cal_bits"].eq(0), - self._inst.ins["diag_short_cal"].eq(0), - - self._inst.ins["reset_n"].eq(self._reset_n.r), - self._inst.ins["init_done"].eq(self._init_done.r), - self._phy_cal_done.w.eq(self._inst.outs["phy_cal_done"]), - self._req_addr.field.w.eq(self._inst.outs["cpg_addr"][2:10]), - - self._req.w.eq(Cat(pending_r, pending_w)), - cpg_busy.eq(pending_r | pending_w), - self._inst.ins["cpg_busy"].eq(cpg_busy) - ] - sync = [ - If(self._inst.outs["cpg_r_req"], pending_r.eq(1)), - If(self._inst.outs["cpg_w_req"], pending_w.eq(1)), - If(self._req.re & self._req.r[0], pending_r.eq(0)), - If(self._req.re & self._req.r[1], pending_w.eq(0)) - ] - return Fragment(comb, sync, instances=[self._inst], pads=set(self._sd_pins)) \ - + self.bank.get_fragment() + return Fragment(instances=[self._inst], pads=set(self._sd_pins)) diff --git a/software/bios/ddrinit.c b/software/bios/ddrinit.c index 5edce234..6e18e16b 100644 --- a/software/bios/ddrinit.c +++ b/software/bios/ddrinit.c @@ -17,7 +17,6 @@ #include -#include #include #include "ddrinit.h" @@ -79,54 +78,11 @@ static void init_sequence(void) cdelay(200); } -static void calibrate_phy(void) -{ - int requests; - int addr; - - printf("Calibrating PHY...\n"); - - CSR_DFII_WRDELAY = 4; - CSR_DFII_WRDURATION = 1; - CSR_DFII_RDDELAY = 7; - CSR_DFII_RDDURATION = 1; - - /* Use bank 0, activate row 0 */ - CSR_DFII_BA = 0; - setaddr(0x0000); - CSR_DFII_COMMAND = DFII_COMMAND_RAS|DFII_COMMAND_CS; - - while(!(CSR_DDRPHY_STATUS & DDRPHY_STATUS_PHY_CAL_DONE)) { - cdelay(20); - requests = CSR_DDRPHY_REQUESTS; - addr = CSR_DDRPHY_REQADDR; - - setaddr(addr << 2); - if(requests & DDRPHY_REQUEST_READ) { - printf("R %d\n", addr); - CSR_DFII_COMMAND = DFII_COMMAND_RDDATA|DFII_COMMAND_CAS|DFII_COMMAND_CS; - } - if(requests & DDRPHY_REQUEST_WRITE) { - printf("W %d\n", addr); - CSR_DFII_COMMAND = DFII_COMMAND_WRDATA|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS; - } - - CSR_DDRPHY_REQUESTS = requests; - } - - /* Precharge All */ - setaddr(0x0400); - CSR_DFII_COMMAND = DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS; -} - int ddrinit(void) { printf("Initializing DDR SDRAM...\n"); - CSR_DDRPHY_STATUS = DDRPHY_STATUS_RESETN; init_sequence(); - CSR_DDRPHY_STATUS = DDRPHY_STATUS_RESETN|DDRPHY_STATUS_INIT_DONE; - calibrate_phy(); return 1; } diff --git a/software/include/hw/dfii.h b/software/include/hw/dfii.h index 9a58faac..045e25ae 100644 --- a/software/include/hw/dfii.h +++ b/software/include/hw/dfii.h @@ -20,7 +20,7 @@ #include -#define CSR_DFII_CONTROL MMPTR(0xe0001000) +#define CSR_DFII_CONTROL MMPTR(0xe0000800) #define DFII_CONTROL_SEL (0x01) #define DFII_CONTROL_CKE (0x02) @@ -34,13 +34,13 @@ #define DFII_COMMAND_RDDATA (0x10) #define DFII_COMMAND_WRDATA (0x20) -#define CSR_DFII_AH MMPTR(0xe0001008) -#define CSR_DFII_AL MMPTR(0xe000100C) -#define CSR_DFII_BA MMPTR(0xe0001010) +#define CSR_DFII_AH MMPTR(0xe0000808) +#define CSR_DFII_AL MMPTR(0xe000080C) +#define CSR_DFII_BA MMPTR(0xe0000810) -#define CSR_DFII_RDDELAY MMPTR(0xe0001014) -#define CSR_DFII_RDDURATION MMPTR(0xe0001018) -#define CSR_DFII_WRDELAY MMPTR(0xe000101C) -#define CSR_DFII_WRDURATION MMPTR(0xe0001020) +#define CSR_DFII_RDDELAY MMPTR(0xe0000814) +#define CSR_DFII_RDDURATION MMPTR(0xe0000818) +#define CSR_DFII_WRDELAY MMPTR(0xe000081C) +#define CSR_DFII_WRDURATION MMPTR(0xe0000820) #endif /* __HW_DFII_H */ diff --git a/software/include/hw/s6ddrphy.h b/software/include/hw/s6ddrphy.h deleted file mode 100644 index a139c4c8..00000000 --- a/software/include/hw/s6ddrphy.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Milkymist SoC (Software) - * Copyright (C) 2012 Sebastien Bourdeauducq - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __HW_S6DDRPHY_H -#define __HW_S6DDRPHY_H - -#include - -#define CSR_DDRPHY_STATUS MMPTR(0xe0000800) - -#define DDRPHY_STATUS_RESETN (0x1) -#define DDRPHY_STATUS_INIT_DONE (0x2) -#define DDRPHY_STATUS_PHY_CAL_DONE (0x4) - -#define CSR_DDRPHY_REQUESTS MMPTR(0xe0000804) - -#define DDRPHY_REQUEST_READ (0x1) -#define DDRPHY_REQUEST_WRITE (0x2) - -#define CSR_DDRPHY_REQADDR MMPTR(0xe0000808) - -#endif /* __HW_S6DDRPHY_H */ diff --git a/top.py b/top.py index 47367406..a4d89886 100644 --- a/top.py +++ b/top.py @@ -14,19 +14,15 @@ l2_size = 8192 # in bytes dfi_a = 13 dfi_ba = 2 -dfi_d = 128 # TODO -> 64 +dfi_d = 64 def ddrphy_clocking(crg, phy): names = [ "clk2x_90", - "clk4x_wr_left", - "clk4x_wr_strb_left", - "clk4x_wr_right", - "clk4x_wr_strb_right", - "clk4x_rd_left", - "clk4x_rd_strb_left", - "clk4x_rd_right", - "clk4x_rd_strb_right", + "clk4x_wr", + "clk4x_wr_strb", + "clk4x_rd", + "clk4x_rd_strb" ] comb = [getattr(phy, name).eq(getattr(crg, name)) for name in names] return Fragment(comb) @@ -42,8 +38,8 @@ def get(): # # DFI # - ddrphy0 = s6ddrphy.S6DDRPHY(1, dfi_a, dfi_ba, dfi_d) - dfii0 = dfii.DFIInjector(2, dfi_a, dfi_ba, dfi_d, 1) + ddrphy0 = s6ddrphy.S6DDRPHY(dfi_a, dfi_ba, dfi_d) + dfii0 = dfii.DFIInjector(1, dfi_a, dfi_ba, dfi_d, 2) dficon0 = dfi.Interconnect(dfii0.master, ddrphy0.dfi) # @@ -80,7 +76,6 @@ def get(): uart0 = uart.UART(0, clk_freq, baud=115200) csrcon0 = csr.Interconnect(wishbone2csr0.csr, [ uart0.bank.interface, - ddrphy0.bank.interface, dfii0.bank.interface ]) diff --git a/verilog/m1crg/m1crg.v b/verilog/m1crg/m1crg.v index e885a0c0..0ab04410 100644 --- a/verilog/m1crg/m1crg.v +++ b/verilog/m1crg/m1crg.v @@ -32,37 +32,25 @@ module m1crg #( output videoin_rst_n, output flash_rst_n, - /* DDR PHY clocks and reset */ + /* DDR PHY clocks */ output clk2x_90, - output clk4x_wr_left, - output clk4x_wr_strb_left, - output clk4x_wr_right, - output clk4x_wr_strb_right, - output clk4x_rd_left, - output clk4x_rd_strb_left, - output clk4x_rd_right, - output clk4x_rd_strb_right, - inout rd_clk_lb /* < unconnected clock pin for read clock PLL loopback */ + output clk4x_wr, + output clk4x_wr_strb, + output clk4x_rd, + output clk4x_rd_strb ); /* * Reset */ -wire reset_n; - reg [19:0] rst_debounce; -always @(posedge sys_clk, negedge reset_n) begin - if(~reset_n) begin +always @(posedge sys_clk) begin + if(trigger_reset) rst_debounce <= 20'hFFFFF; - sys_rst <= 1'b1; - end else begin - if(trigger_reset) - rst_debounce <= 20'hFFFFF; - else if(rst_debounce != 20'd0) - rst_debounce <= rst_debounce - 20'd1; - sys_rst <= rst_debounce != 20'd0; - end + else if(rst_debounce != 20'd0) + rst_debounce <= rst_debounce - 20'd1; + sys_rst <= rst_debounce != 20'd0; end assign ac97_rst_n = ~sys_rst; @@ -79,23 +67,19 @@ assign videoin_rst_n = ~sys_rst; reg [7:0] flash_rstcounter; -always @(posedge sys_clk, negedge reset_n) begin - if(~reset_n) begin +always @(posedge sys_clk) begin + if(trigger_reset) flash_rstcounter <= 8'd0; - end else begin - if(trigger_reset) - flash_rstcounter <= 8'd0; - else if(~flash_rstcounter[7]) - flash_rstcounter <= flash_rstcounter + 8'd1; - end + else if(~flash_rstcounter[7]) + flash_rstcounter <= flash_rstcounter + 8'd1; end assign flash_rst_n = flash_rstcounter[7]; /* - * Clock management. Largely taken from the NWL reference design. + * Clock management. Inspired by the NWL reference design. */ - + wire sdr_clkin; wire clkdiv; @@ -117,12 +101,12 @@ BUFIO2 #( .SERDESSTROBE() ); -wire pll1_lckd; -wire buf_pll1_fb_out; -wire pll1out0; -wire pll1out1; -wire pll1out2; -wire pll1out3; +wire pll_lckd; +wire buf_pll_fb_out; +wire pllout0; +wire pllout1; +wire pllout2; +wire pllout3; PLL_ADV #( .BANDWIDTH("OPTIMIZED"), @@ -136,12 +120,12 @@ PLL_ADV #( .CLKOUT1_DIVIDE(f_div), .CLKOUT1_DUTY_CYCLE(0.5), .CLKOUT1_PHASE(0), - .CLKOUT2_DIVIDE(4*f_div), + .CLKOUT2_DIVIDE(2*f_div), .CLKOUT2_DUTY_CYCLE(0.5), - .CLKOUT2_PHASE(0.0), - .CLKOUT3_DIVIDE(2*f_div), + .CLKOUT2_PHASE(90.0), + .CLKOUT3_DIVIDE(4*f_div), .CLKOUT3_DUTY_CYCLE(0.5), - .CLKOUT3_PHASE(90), + .CLKOUT3_PHASE(0.0), .CLKOUT4_DIVIDE(7), .CLKOUT4_DUTY_CYCLE(0.5), .CLKOUT4_PHASE(0), @@ -153,13 +137,13 @@ PLL_ADV #( .REF_JITTER(0.100), .CLK_FEEDBACK("CLKFBOUT"), .SIM_DEVICE("SPARTAN6") -) pll1 ( +) pll ( .CLKFBDCM(), - .CLKFBOUT(buf_pll1_fb_out), - .CLKOUT0(pll1out0), /* < x4 180 clock for transmitter */ - .CLKOUT1(pll1out1), /* < x4 180 clock for transmitter */ - .CLKOUT2(pll1out2), /* < x1 clock for memory controller */ - .CLKOUT3(pll1out3), /* < x2 90 clock to generate memory clock, clock DQS and memory address and control signals. */ + .CLKFBOUT(buf_pll_fb_out), + .CLKOUT0(pllout0), /* < x4 clock for writes */ + .CLKOUT1(pllout1), /* < x4 clock for reads */ + .CLKOUT2(pllout2), /* < x2 90 clock to generate memory clock, clock DQS and memory address and control signals. */ + .CLKOUT3(pllout3), /* < x1 clock for system and memory controller */ .CLKOUT4(), .CLKOUT5(), .CLKOUTDCM0(), @@ -170,8 +154,8 @@ PLL_ADV #( .CLKOUTDCM5(), .DO(), .DRDY(), - .LOCKED(pll1_lckd), - .CLKFBIN(buf_pll1_fb_out), + .LOCKED(pll_lckd), + .CLKFBIN(buf_pll_fb_out), .CLKIN1(clkdiv), .CLKIN2(1'b0), .CLKINSEL(1'b1), @@ -186,239 +170,34 @@ PLL_ADV #( BUFPLL #( .DIVIDE(4) -) wr_bufpll_left ( - .PLLIN(pll1out0), +) wr_bufpll ( + .PLLIN(pllout0), .GCLK(sys_clk), - .LOCKED(pll1_lckd), - .IOCLK(clk4x_wr_left), + .LOCKED(pll_lckd), + .IOCLK(clk4x_wr), .LOCK(), - .SERDESSTROBE(clk4x_wr_strb_left) + .SERDESSTROBE(clk4x_wr_strb) ); BUFPLL #( .DIVIDE(4) -) wr_bufpll_right ( - .PLLIN(pll1out1), +) rd_bufpll ( + .PLLIN(pllout1), .GCLK(sys_clk), - .LOCKED(pll1_lckd), - .IOCLK(clk4x_wr_right), + .LOCKED(pll_lckd), + .IOCLK(clk4x_rd), .LOCK(), - .SERDESSTROBE(clk4x_wr_strb_right) -); - -BUFG bufg_x1( - .I(pll1out2), - .O(sys_clk) + .SERDESSTROBE(clk4x_rd_strb) ); BUFG bufg_x2_2( - .I(pll1out3), + .I(pllout2), .O(clk2x_90) ); -/* - * Generate clk4x_rd. This clock is sourced from clk2x_90. - * An IODELAY2 element is included in the path of this clock so that - * any variation in IDELAY element's base delay is compensated when this clock - * is used to capture read data which also goes through IDELAY element. - */ - -wire rd_clk_out; - -ODDR2 #( - .DDR_ALIGNMENT("C0"), - .INIT(1'b0), - .SRTYPE("ASYNC") -) rd_clk_out_inst ( - .Q(rd_clk_out), - .C0(clk2x_90), - .C1(~clk2x_90), - .CE(1'b1), - .D0(1'b1), - .D1(1'b0), - .R(1'b0), - .S(1'b0) -); - -wire rd_clk_out_oe_n; - -ODDR2 #( - .DDR_ALIGNMENT("C0"), - .INIT(1'b0), - .SRTYPE("ASYNC") -) rd_clk_out_oe_inst ( - .Q(rd_clk_out_oe_n), - .C0(clk2x_90), - .C1(~clk2x_90), - .CE(1'b1), - .D0(1'b0), - .D1(1'b0), - .R(1'b0), - .S(1'b0) -); - -wire rd_clk_fb; - -/* Dummy pin used for calibration */ -IOBUF rd_clk_loop_back_inst( - .O(rd_clk_fb), - .IO(rd_clk_lb), - .I(rd_clk_out), - .T(rd_clk_out_oe_n) -); - -wire rd_clk_fb_dly; - -IODELAY2 #( - .DATA_RATE("DDR"), - .IDELAY_VALUE(0), - .IDELAY2_VALUE(0), - .IDELAY_MODE("NORMAL"), - .ODELAY_VALUE(0), - .IDELAY_TYPE("FIXED"), - .COUNTER_WRAPAROUND("STAY_AT_LIMIT"), - .DELAY_SRC("IDATAIN"), - .SERDES_MODE("NONE"), - .SIM_TAPDELAY_VALUE(49) -) iodelay_cm ( - .IDATAIN(rd_clk_fb), - .TOUT(), - .DOUT(), - .T(1'b1), - .ODATAIN(1'b0), - .DATAOUT(rd_clk_fb_dly), - .DATAOUT2(), - .IOCLK0(1'b0), - .IOCLK1(1'b0), - .CLK(1'b0), - .CAL(1'b0), - .INC(1'b0), - .CE(1'b0), - .RST(1'b0), - .BUSY() -); - -wire rd_clk_fb_dly_bufio; - -BUFIO2 #( - .DIVIDE(1), - .DIVIDE_BYPASS("FALSE"), - .I_INVERT("FALSE") -) bufio2_inst ( - .I(rd_clk_fb_dly), - .IOCLK(), - .DIVCLK(rd_clk_fb_dly_bufio), - .SERDESSTROBE() -); - -wire pll2_lckd; -wire buf_pll2_fb_out; -wire pll2out0; -wire pll2out1; - -PLL_ADV #( - .BANDWIDTH("OPTIMIZED"), - .CLKFBOUT_MULT(4), - .CLKFBOUT_PHASE(0.0), - .CLKIN1_PERIOD(clk2x_period), - .CLKIN2_PERIOD(clk2x_period), - .CLKOUT0_DIVIDE(2), - .CLKOUT0_DUTY_CYCLE(0.5), - .CLKOUT0_PHASE(0.0), - .CLKOUT1_DIVIDE(2), - .CLKOUT1_DUTY_CYCLE(0.5), - .CLKOUT1_PHASE(0.0), - .CLKOUT2_DIVIDE(7), - .CLKOUT2_DUTY_CYCLE(0.5), - .CLKOUT2_PHASE(0.0), - .CLKOUT3_DIVIDE(7), - .CLKOUT3_DUTY_CYCLE(0.5), - .CLKOUT3_PHASE(0.0), - .CLKOUT4_DIVIDE(7), - .CLKOUT4_DUTY_CYCLE(0.5), - .CLKOUT4_PHASE(0.0), - .CLKOUT5_DIVIDE(7), - .CLKOUT5_DUTY_CYCLE (0.5), - .CLKOUT5_PHASE(0.0), - .COMPENSATION("INTERNAL"), - .DIVCLK_DIVIDE(1), - .REF_JITTER(0.100), - .CLK_FEEDBACK("CLKFBOUT"), - .SIM_DEVICE("SPARTAN6") -) pll2 ( - .CLKFBDCM(), - .CLKFBOUT(buf_pll2_fb_out), - .CLKOUT0(pll2out0), /* < x4 clock to capture read data */ - .CLKOUT1(pll2out1), /* < x4 clock to capture read data */ - .CLKOUT2(), - .CLKOUT3(), - .CLKOUT4(), - .CLKOUT5(), - .CLKOUTDCM0(), - .CLKOUTDCM1(), - .CLKOUTDCM2(), - .CLKOUTDCM3(), - .CLKOUTDCM4(), - .CLKOUTDCM5(), - .DO(), - .DRDY(), - .LOCKED(pll2_lckd), - .CLKFBIN(buf_pll2_fb_out), - .CLKIN1(rd_clk_fb_dly_bufio), - .CLKIN2(1'b0), - .CLKINSEL(1'b1), - .DADDR(5'b00000), - .DCLK(1'b0), - .DEN(1'b0), - .DI(16'h0000), - .DWE(1'b0), - .RST(~pll1_lckd), - .REL(1'b0) -); - -BUFPLL #( - .DIVIDE(4) -) rd_bufpll_left ( - .PLLIN(pll2out0), - .GCLK(sys_clk), - .LOCKED(pll2_lckd), - .IOCLK(clk4x_rd_left), - .LOCK(), - .SERDESSTROBE(clk4x_rd_strb_left) -); - -BUFPLL #( - .DIVIDE(4) -) rd_bufpll_right ( - .PLLIN(pll2out1), - .GCLK(sys_clk), - .LOCKED(pll2_lckd), - .IOCLK(clk4x_rd_right), - .LOCK(), - .SERDESSTROBE(clk4x_rd_strb_right) -); - -wire sdram_sys_clk_lock_d16; -reg sdram_sys_clk_lock_d17; - -/* - * Async reset generation - * The reset is de-asserted 16 clocks after both internal clocks are locked. - */ - -SRL16 reset_delay_sr( - .CLK(sys_clk), - .D(pll1_lckd & pll2_lckd), - .A0(1'b1), - .A1(1'b1), - .A2(1'b1), - .A3(1'b1), - .Q(sdram_sys_clk_lock_d16) +BUFG bufg_x1( + .I(pllout3), + .O(sys_clk) ); - -always @(posedge sys_clk) - sdram_sys_clk_lock_d17 <= sdram_sys_clk_lock_d16; - -assign reset_n = sdram_sys_clk_lock_d17; endmodule diff --git a/verilog/s6ddrphy/README b/verilog/s6ddrphy/README deleted file mode 100644 index eddbdd07..00000000 --- a/verilog/s6ddrphy/README +++ /dev/null @@ -1 +0,0 @@ -The Verilog files of the Spartan-6 DDR PHY from Xilinx/Northwest Logic go here. diff --git a/verilog/s6ddrphy/patches/s6ddrphy.diff b/verilog/s6ddrphy/patches/s6ddrphy.diff deleted file mode 100644 index 4ae6a549..00000000 --- a/verilog/s6ddrphy/patches/s6ddrphy.diff +++ /dev/null @@ -1,27 +0,0 @@ -Index: s6ddrphy/spartan6_soft_phy.v -=================================================================== ---- s6ddrphy.orig/spartan6_soft_phy.v -+++ s6ddrphy/spartan6_soft_phy.v -@@ -116,7 +116,6 @@ module spartan6_soft_phy # ( - inout [NUM_DQ-1:0] sd_dq, // Data in from SDRAM device - output [NUM_DQS-1:0] sd_dm, // Data mask to SDRAM devices - inout [NUM_DQS-1:0] sd_dqs, // DQS -- inout [NUM_DQS-1:0] sd_dqs_n, // complimentary DQS - - // configuration ports - input [2:0] cfg_al, // Posted CAS additive latency -@@ -300,12 +299,11 @@ genvar j; - generate - for (j = 0; j < NUM_DQ/8*(NIBBLE_DEVICES+1) ; j = j + 1) - begin:dqs_iob -- IOBUFDS iobufds ( -+ IOBUF iobufds ( - .O (sd_dqs_in[j]), - .I (sd_dqs_out[j]), - .T (sd_dqs_oe_n[j]), -- .IO (sd_dqs[j]), -- .IOB (sd_dqs_n[j]) -+ .IO (sd_dqs[j]) - ); - end - endgenerate diff --git a/verilog/s6ddrphy/patches/series b/verilog/s6ddrphy/patches/series deleted file mode 100644 index dd08e5b7..00000000 --- a/verilog/s6ddrphy/patches/series +++ /dev/null @@ -1 +0,0 @@ -s6ddrphy.diff diff --git a/verilog/s6ddrphy/s6ddrphy.v b/verilog/s6ddrphy/s6ddrphy.v new file mode 100644 index 00000000..f7cd05fa --- /dev/null +++ b/verilog/s6ddrphy/s6ddrphy.v @@ -0,0 +1,59 @@ +module s6ddrphy #( + parameter NUM_AD = 0, + parameter NUM_BA = 0, + parameter NUM_D = 0 /* < number of data lines per DFI phase */ +) ( + /* Clocks */ + input sys_clk, + input clk2x_90, + input clk4x_wr, + input clk4x_wr_strb, + input clk4x_rd, + input clk4x_rd_strb, + + /* DFI phase 0 */ + input [NUM_AD-1:0] dfi_address_p0, + input [NUM_BA-1:0] dfi_bank_p0, + input dfi_cs_n_p0, + input dfi_cke_p0, + input dfi_ras_n_p0, + input dfi_cas_n_p0, + input dfi_we_n_p0, + input dfi_wrdata_en_p0, + input [NUM_D/8-1:0] dfi_wrdata_mask_p0, + input [NUM_D-1:0] dfi_wrdata_p0, + input dfi_rddata_en_p0, + output [NUM_D-1:0] dfi_rddata_w0, + output dfi_rddata_valid_w0, + + /* DFI phase 1 */ + input [NUM_AD-1:0] dfi_address_p1, + input [NUM_BA-1:0] dfi_bank_p1, + input dfi_cs_n_p1, + input dfi_cke_p1, + input dfi_ras_n_p1, + input dfi_cas_n_p1, + input dfi_we_n_p1, + input dfi_wrdata_en_p1, + input [NUM_D/8-1:0] dfi_wrdata_mask_p1, + input [NUM_D-1:0] dfi_wrdata_p1, + input dfi_rddata_en_p1, + output [NUM_D-1:0] dfi_rddata_w1, + output dfi_rddata_valid_w1, + + /* DDR SDRAM pads */ + output sd_clk_out_p, + output sd_clk_out_n, + output [NUM_AD-1:0] sd_a, + output [NUM_BA-1:0] sd_ba, + output sd_cs_n, + output sd_cke, + output sd_ras_n, + output sd_cas_n, + output sd_we_n, + inout [NUM_D/2-1:0] sd_dq, + output [NUM_D/16-1:0] sd_dm, + inout [NUM_D/16-1:0] sd_dqs +); + +endmodule