Loading phy/ddr3c16.v +191 −24 Original line number Original line Diff line number Diff line Loading @@ -43,11 +43,8 @@ module ddr3c16 #( parameter SS_EN = "FALSE", parameter SS_EN = "FALSE", parameter SS_MODE = "CENTER_HIGH", parameter SS_MODE = "CENTER_HIGH", parameter SS_MOD_PERIOD = 10000, parameter SS_MOD_PERIOD = 10000, parameter DQSTRI_FIRST= 4'h3, // DQS tri-state control word, first when enabling output parameter CMD_PAUSE_BITS= 6, parameter DQSTRI_LAST= 4'hc, // DQS tri-state control word, first after disabling output parameter CMD_DONE_BIT= 6 parameter DQTRI_FIRST= 4'h7, // DQ tri-state control word, first when enabling output parameter DQTRI_LAST= 4'he // DQ tri-state control word, first after disabling output )( )( // DDR3 interface // DDR3 interface output SDCLK, // DDR3 clock differential output, positive output SDCLK, // DDR3 clock differential output, positive Loading @@ -71,16 +68,18 @@ module ddr3c16 #( input clk_in, input clk_in, input rst_in, input rst_in, output mclk, // global clock, half DDR3 clock, synchronizes all I/O thorough the command port output mclk, // global clock, half DDR3 clock, synchronizes all I/O thorough the command port // command port 0 (filled by software - 32w->64r) - used for mode set, refresh, write levelling, ... // command port 0 (filled by software - 32w->32r) - used for mode set, refresh, write levelling, ... input cmd0_clk, input cmd0_we, input cmd0_we, input [9:0] cmd0_addr, input [9:0] cmd0_addr, input [31:0] cmd0_data, input [31:0] cmd0_data, // TODO: add automatic command port1 , filled by the PL, 36w 36r, used for actual page R/W // automatic command port1 , filled by the PL, 32w 32r, used for actual page R/W input cmd1_clk, input cmd1_we, input cmd1_we, input [9:0] cmd1_addr, input [9:0] cmd1_addr, input [35:0] cmd1_data, input [31:0] cmd1_data, // Controller run interface, posedge mclk // Controller run interface, posedge mclk input [10:0] run_addr, // controller sequencer start address (0..11'h1ff - cmd0, 11'h400..11'h7ff - cmd1) input [10:0] run_addr, // controller sequencer start address (0..11'h3ff - cmd0, 11'h400..11'h7ff - cmd1) input [3:0] run_chn, // data channel to use input [3:0] run_chn, // data channel to use input run_seq, // start controller sequence input run_seq, // start controller sequence output run_done, // controller sequence finished output run_done, // controller sequence finished Loading Loading @@ -116,12 +115,174 @@ module ddr3c16 #( ); ); localparam ADDRESS_NUMBER = 15; localparam ADDRESS_NUMBER = 15; wire [35:0] phy_cmd; // input[35:0] wire [6:0] buf_addr; // output[6:0] // wire [35:0] phy_cmd; // input[35:0] wire [31:0] phy_cmd_word; // selected output from eithe cmd0 buffer or cmd1 buffer wire [31:0] phy_cmd0_word; // cmd0 buffer output wire [31:0] phy_cmd1_word; // cmd1 buffer output reg [ 8:0] buf_raddr; reg [ 8:0] buf_waddr_negedge; reg buf_wr_negedge; wire [63:0] buf_wdata; // output[63:0] wire [63:0] buf_wdata; // output[63:0] wire [63:0] buf_rdata; // input[63:0] reg [63:0] buf_wdata_negedge; // output[63:0] wire [63:0] buf_rdata; // multiplexed input from one of the write channels buffer wire [63:0] buf1_rdata; wire buf_wr; // output wire buf_wr; // output wire buf_rd; // output wire buf_rd; // read next 64 bytes from the buffer, need one extra pre-read wire rst=rst_in; // wire [ 9:0] next_cmd_addr; reg [ 9:0] cmd_addr; // command word adderss reg cmd_sel; reg [ 2:0] cmd_busy; // bit 0 - immediately, wire phy_cmd_nop; // decoded command (ras, cas, we) was NOP wire sequence_done; wire [CMD_PAUSE_BITS-1:0] pause_len; reg cmd_fetch; // previous cycle command was read from the command memory, current: command valid wire pause; // do not register new data from the command memory reg [CMD_PAUSE_BITS-1:0] pause_cntr; reg [1:0] buf_page; // one of 4 pages in the channel buffer to use for R/W reg [15:0] buf_sel_1hot; // 1 hot channel buffer select reg [3:0] run_chn_d; reg run_seq_d; assign run_done=sequence_done; assign pause=cmd_fetch? (phy_cmd_nop && (pause_len != 0)): (cmd_busy[2] && (pause_cntr[CMD_PAUSE_BITS-1:1]!=0)); assign phy_cmd_word = phy_cmd_word?phy_cmd1_word:phy_cmd0_word; assign buf_rdata[63:0] = ({64{buf_sel_1hot[1]}} & buf1_rdata[63:0]); // ORR with other read channels terms always @ (posedge mclk or posedge rst) begin if (rst) cmd_busy <= 0; else if (sequence_done) cmd_busy <= 0; else cmd_busy <= {cmd_busy[1:0],run_seq}; // Pause counter if (rst) pause_cntr <= 0; else if (!cmd_busy[1]) pause_cntr <= 0; // not needed? else if (cmd_fetch && phy_cmd_nop) pause_cntr <= pause_len; else if (pause_cntr!=0) pause_cntr <= pause_cntr-1; // Fetch - command data valid if (rst) cmd_fetch <= 0; else cmd_fetch <= cmd_busy[0] && !pause; // Command read adderss if (rst) cmd_addr <= 0; else if (run_seq) cmd_addr <= run_addr[9:0]; else if (cmd_busy[0] && !pause) cmd_addr <= cmd_addr + 1; // command bank select (0 - "manual" (software programmed sequences), 1 - "auto" (normal block r/w) if (rst) cmd_sel <= 0; else if (run_seq) cmd_sel <= run_addr[10]; if (rst) buf_page <= 0; else if (run_seq) case (run_chn) 4'h0: buf_page <= port0_int_page; 4'h1: buf_page <= port1_int_page; // Add other channles later default: buf_page <= 2'bxx; endcase if (rst) buf_sel_1hot <= 0; else buf_sel_1hot <= { (run_chn_d==4'hf)?1'b1:1'b0, (run_chn_d==4'he)?1'b1:1'b0, (run_chn_d==4'hd)?1'b1:1'b0, (run_chn_d==4'hc)?1'b1:1'b0, (run_chn_d==4'hb)?1'b1:1'b0, (run_chn_d==4'ha)?1'b1:1'b0, (run_chn_d==4'h9)?1'b1:1'b0, (run_chn_d==4'h8)?1'b1:1'b0, (run_chn_d==4'h7)?1'b1:1'b0, (run_chn_d==4'h6)?1'b1:1'b0, (run_chn_d==4'h5)?1'b1:1'b0, (run_chn_d==4'h4)?1'b1:1'b0, (run_chn_d==4'h3)?1'b1:1'b0, (run_chn_d==4'h2)?1'b1:1'b0, (run_chn_d==4'h1)?1'b1:1'b0, (run_chn_d==4'h0)?1'b1:1'b0 }; if (rst) buf_raddr <= 9'h0; else if (run_seq_d) buf_raddr <= {buf_page,7'h0}; else if (buf_wr || buf_rd) buf_raddr <= buf_raddr +1; // Separate read/write address? read address re-registered @ negedge end // re-register buffer write address to match DDR3 data always @ (negedge mclk) begin buf_waddr_negedge <= buf_raddr; buf_wr_negedge <= buf_wr; buf_wdata_negedge <= buf_wdata; end always @ (posedge mclk) begin run_chn_d <= run_chn; run_seq_d <= run_seq; end // Command sequence memories: // Command sequence memory 0 ("manual"): ram_1kx32_1kx32 #( .REGISTERS(1) // register output ) cmd0_buf_i ( .rclk (mclk), // input .raddr (cmd_addr), // input[9:0] .ren (!cmd_sel && cmd_busy && !pause), // input .regen (!cmd_sel && cmd_busy && !pause), // input .data_out (phy_cmd0_word), // output[31:0] .wclk (cmd0_clk), // input .waddr (cmd0_addr), // input[9:0] .we (cmd0_we), // input .web (4'hf), // input[3:0] .data_in (cmd0_data) // input[31:0] ); // Command sequence memory 0 ("manual"): ram_1kx32_1kx32 #( .REGISTERS(1) // register output ) cmd1_buf_i ( .rclk (mclk), // input .raddr (cmd_addr), // input[9:0] .ren ( cmd_sel && cmd_busy && !pause), // input .regen ( cmd_sel && cmd_busy && !pause), // input .data_out (phy_cmd1_word), // output[31:0] .wclk (cmd1_clk), // input .waddr (cmd1_addr), // input[9:0] .we (cmd1_we), // input .web (4'hf), // input[3:0] .data_in (cmd1_data) // input[31:0] ); // Port memory buffer (4 pages each, R/W fixed, port 0 - AXI read from DDR, port 1 - AXI write to DDR // Port 0 (read DDR to AXI) buffer ram_512x64w_1kx32r #( .REGISTERS(1) ) port0_buf_i ( .rclk (port0_clk), // input .raddr ({port0_page,port0_addr}), // input[9:0] .ren (port0_re), // input .regen (port0_regen), // input .data_out (port0_data), // output[31:0] .wclk (!mclk), // input .waddr (buf_waddr_negedge), // input[8:0] .we (buf_sel_1hot[0] && buf_wr_negedge), // input .web (8'hff), // input[7:0] .data_in (buf_wdata_negedge) // input[63:0] ); // Port 1 (write DDR from AXI) buffer ram_1kx32w_512x64r #( .REGISTERS(1) ) port1_buf_i ( .rclk(mclk), // input .raddr(buf_raddr), // input[8:0] .ren(buf_sel_1hot[1] && buf_rd), // input .regen(buf_sel_1hot[1] && buf_rd), // input .data_out(buf1_rdata), // output[63:0] .wclk(port1_clk), // input .waddr({port1_page,port1_addr}), // input[9:0] .we(port1_we), // input .web(4'hf), // input[3:0] .data_in(port1_data) // input[31:0] ); phy_cmd #( phy_cmd #( Loading @@ -147,7 +308,10 @@ module ddr3c16 #( .REF_JITTER1 (REF_JITTER1), .REF_JITTER1 (REF_JITTER1), .SS_EN (SS_EN), .SS_EN (SS_EN), .SS_MODE (SS_MODE), .SS_MODE (SS_MODE), .SS_MOD_PERIOD (SS_MOD_PERIOD) .SS_MOD_PERIOD (SS_MOD_PERIOD), .CMD_PAUSE_BITS (CMD_PAUSE_BITS), // numer of (address) bits to encode pause .CMD_DONE_BIT (CMD_DONE_BIT) // bit number (address) to signal sequence done ) phy_cmd_i ( ) phy_cmd_i ( .SDCLK (SDCLK), // output .SDCLK (SDCLK), // output .SDNCLK (SDNCLK), // output .SDNCLK (SDNCLK), // output Loading Loading @@ -175,8 +339,11 @@ module ddr3c16 #( .locked (locked), // output .locked (locked), // output .ps_rdy (ps_rdy), // output .ps_rdy (ps_rdy), // output .ps_out (ps_out[7:0]), // output[7:0] .ps_out (ps_out[7:0]), // output[7:0] .phy_cmd (phy_cmd[35:0]), // input[35:0] .phy_cmd_word (phy_cmd_word[31:0]), // input[35:0] .buf_addr (buf_addr[6:0]), // output[6:0] .phy_cmd_nop (phy_cmd_nop), // output .pause_len (pause_len), // output [CMD_PAUSE_BITS-1:0] .sequence_done (sequence_done), // output // .buf_addr (buf_addr[6:0]), // output[6:0] .buf_wdata (buf_wdata[63:0]), // output[63:0] .buf_wdata (buf_wdata[63:0]), // output[63:0] .buf_rdata (buf_rdata[63:0]), // input[63:0] .buf_rdata (buf_rdata[63:0]), // input[63:0] .buf_wr (buf_wr), // output .buf_wr (buf_wr), // output Loading phy/phy_cmd.v +21 −12 Original line number Original line Diff line number Diff line Loading @@ -44,8 +44,9 @@ module phy_cmd#( parameter REF_JITTER1 = 0.010, parameter REF_JITTER1 = 0.010, parameter SS_EN = "FALSE", parameter SS_EN = "FALSE", parameter SS_MODE = "CENTER_HIGH", parameter SS_MODE = "CENTER_HIGH", parameter SS_MOD_PERIOD = 10000 parameter SS_MOD_PERIOD = 10000, parameter CMD_PAUSE_BITS= 6, // numer of (address) bits to encode pause parameter CMD_DONE_BIT= 6 // bit number (address) to signal sequence done )( )( // DDR3 interface // DDR3 interface output SDCLK, // DDR3 clock differential output, positive output SDCLK, // DDR3 clock differential output, positive Loading Loading @@ -78,9 +79,13 @@ module phy_cmd#( output ps_rdy, output ps_rdy, output [PHASE_WIDTH-1:0] ps_out, output [PHASE_WIDTH-1:0] ps_out, // command port // command port input [35:0] phy_cmd, // input [35:0] phy_cmd, input [31:0] phy_cmd_word, output phy_cmd_nop, output [CMD_PAUSE_BITS-1:0] pause_len, output sequence_done, // external memory buffer (cs- channel select, high addresses- page addresses are decoded externally) // external memory buffer (cs- channel select, high addresses- page addresses are decoded externally) output [ 6:0] buf_addr, // output [ 6:0] buf_addr, output [63:0] buf_wdata, // data to be written to the buffer (from DDR3), valid @ negedge mclk output [63:0] buf_wdata, // data to be written to the buffer (from DDR3), valid @ negedge mclk input [63:0] buf_rdata, // data read from the buffer (to DDR3) input [63:0] buf_rdata, // data read from the buffer (to DDR3) output buf_wr, // write buffer (next cycle!) output buf_wr, // write buffer (next cycle!) Loading @@ -106,7 +111,7 @@ module phy_cmd#( wire phy_dq_tri_in; // tristate DQ lines (internal timing sequencer for 0->1 and 1->0) wire phy_dq_tri_in; // tristate DQ lines (internal timing sequencer for 0->1 and 1->0) wire phy_dqs_tri_in; // tristate DQS lines (internal timing sequencer for 0->1 and 1->0) wire phy_dqs_tri_in; // tristate DQS lines (internal timing sequencer for 0->1 and 1->0) wire phy_dci_in; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0) wire phy_dci_in; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0) wire [ 6:0] phy_buf_addr; // connect to extrenal buffer // wire [ 6:0] phy_buf_addr; // connect to extrenal buffer wire phy_buf_wr; // connect to extrenal buffer wire phy_buf_wr; // connect to extrenal buffer wire phy_buf_rd; // connect to extrenal buffer wire phy_buf_rd; // connect to extrenal buffer Loading Loading @@ -138,8 +143,8 @@ module phy_cmd#( wire [63:0] phy_rdata; // data read from ddr3 iserdese2 at posedge clk_div wire [63:0] phy_rdata; // data read from ddr3 iserdese2 at posedge clk_div reg [63:0] phy_rdata_r; // registered @ posedge mclk reg [63:0] phy_rdata_r; // registered @ posedge mclk // output [63:0] buf_wdata, // data to be written to the buffer (from DDR3) // output [63:0] buf_wdata, // data to be written to the buffer (from DDR3) // SuppressWarnings VEditor (* keep = "true" *) wire [2:0] phy_spare; assign { assign { phy_addr_in, phy_addr_in, phy_bank_in, phy_bank_in, Loading @@ -150,12 +155,16 @@ module phy_cmd#( phy_dq_tri_in, // tristate DQ lines (internal timing sequencer for 0->1 and 1->0) phy_dq_tri_in, // tristate DQ lines (internal timing sequencer for 0->1 and 1->0) phy_dqs_tri_in, // tristate DQS lines (internal timing sequencer for 0->1 and 1->0) phy_dqs_tri_in, // tristate DQS lines (internal timing sequencer for 0->1 and 1->0) phy_dci_in, // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0) phy_dci_in, // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0) phy_buf_addr, // connect to extrenal buffer // phy_buf_addr, // connect to external buffer (is it needed? maybe just autoincrement?) phy_buf_wr, // connect to extrenal buffer phy_buf_wr, // connect to external buffer (but only if not paused) phy_buf_rd // connect to extrenal buffer phy_buf_rd, // connect to external buffer (but only if not paused) } = phy_cmd; phy_spare // Reserved for future use } = phy_cmd_word; assign phy_cmd_nop= (phy_rcw_in==0); assign sequence_done= (phy_rcw_in==0) && phy_addr_in[CMD_DONE_BIT]; assign pause_len= phy_addr_in[CMD_PAUSE_BITS-1:0]; assign buf_addr = phy_buf_addr; // assign buf_addr = phy_buf_addr; assign buf_wr = phy_buf_wr; assign buf_wr = phy_buf_wr; assign buf_rd = phy_buf_rd; assign buf_rd = phy_buf_rd; Loading wrap/ram_1kx32_1kx32.v +3 −3 Original line number Original line Diff line number Diff line Loading @@ -70,7 +70,7 @@ */ */ module ram_1kx32_1kx32 module ram_1kx32_1kx32 #( #( parameter integer registers = 0 // 1 - registered output parameter integer REGISTERS = 0 // 1 - registered output ) ) ( ( input rclk, // clock for read port input rclk, // clock for read port Loading @@ -89,8 +89,8 @@ module ram_1kx32_1kx32 #( #( .RSTREG_PRIORITY_A("RSTREG"), // Valid: "RSTREG" or "REGCE" .RSTREG_PRIORITY_A("RSTREG"), // Valid: "RSTREG" or "REGCE" .RSTREG_PRIORITY_B("RSTREG"), // Valid: "RSTREG" or "REGCE" .RSTREG_PRIORITY_B("RSTREG"), // Valid: "RSTREG" or "REGCE" .DOA_REG(registers), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .DOA_REG(REGISTERS), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .DOB_REG(registers), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .DOB_REG(REGISTERS), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .RAM_EXTENSION_A("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .RAM_EXTENSION_A("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .RAM_EXTENSION_B("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .RAM_EXTENSION_B("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .READ_WIDTH_A(36), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used) .READ_WIDTH_A(36), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used) Loading wrap/ram_1kx32w_512x64r.v +3 −3 Original line number Original line Diff line number Diff line Loading @@ -70,7 +70,7 @@ */ */ module ram_1kx32w_512x64r module ram_1kx32w_512x64r #( #( parameter integer registers = 0 // 1 - registered output parameter integer REGISTERS = 0 // 1 - registered output ) ) ( ( input rclk, // clock for read port input rclk, // clock for read port Loading @@ -89,8 +89,8 @@ module ram_1kx32w_512x64r #( #( .RSTREG_PRIORITY_A("RSTREG"), // Valid: "RSTREG" or "REGCE" .RSTREG_PRIORITY_A("RSTREG"), // Valid: "RSTREG" or "REGCE" .RSTREG_PRIORITY_B("RSTREG"), // Valid: "RSTREG" or "REGCE" .RSTREG_PRIORITY_B("RSTREG"), // Valid: "RSTREG" or "REGCE" .DOA_REG(registers), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .DOA_REG(REGISTERS), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .DOB_REG(registers), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .DOB_REG(REGISTERS), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .RAM_EXTENSION_A("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .RAM_EXTENSION_A("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .RAM_EXTENSION_B("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .RAM_EXTENSION_B("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .READ_WIDTH_A(72), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used) .READ_WIDTH_A(72), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used) Loading wrap/ram_512x64w_1kx32r.v +3 −3 Original line number Original line Diff line number Diff line Loading @@ -70,7 +70,7 @@ */ */ module ram_512x64w_1kx32r module ram_512x64w_1kx32r #( #( parameter integer registers = 0 // 1 - registered output parameter integer REGISTERS = 0 // 1 - registered output ) ) ( ( input rclk, // clock for read port input rclk, // clock for read port Loading @@ -89,8 +89,8 @@ module ram_512x64w_1kx32r #( #( .RSTREG_PRIORITY_A("RSTREG"), // Valid: "RSTREG" or "REGCE" .RSTREG_PRIORITY_A("RSTREG"), // Valid: "RSTREG" or "REGCE" .RSTREG_PRIORITY_B("RSTREG"), // Valid: "RSTREG" or "REGCE" .RSTREG_PRIORITY_B("RSTREG"), // Valid: "RSTREG" or "REGCE" .DOA_REG(registers), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .DOA_REG(REGISTERS), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .DOB_REG(registers), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .DOB_REG(REGISTERS), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .RAM_EXTENSION_A("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .RAM_EXTENSION_A("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .RAM_EXTENSION_B("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .RAM_EXTENSION_B("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .READ_WIDTH_A(36), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used) .READ_WIDTH_A(36), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used) Loading Loading
phy/ddr3c16.v +191 −24 Original line number Original line Diff line number Diff line Loading @@ -43,11 +43,8 @@ module ddr3c16 #( parameter SS_EN = "FALSE", parameter SS_EN = "FALSE", parameter SS_MODE = "CENTER_HIGH", parameter SS_MODE = "CENTER_HIGH", parameter SS_MOD_PERIOD = 10000, parameter SS_MOD_PERIOD = 10000, parameter DQSTRI_FIRST= 4'h3, // DQS tri-state control word, first when enabling output parameter CMD_PAUSE_BITS= 6, parameter DQSTRI_LAST= 4'hc, // DQS tri-state control word, first after disabling output parameter CMD_DONE_BIT= 6 parameter DQTRI_FIRST= 4'h7, // DQ tri-state control word, first when enabling output parameter DQTRI_LAST= 4'he // DQ tri-state control word, first after disabling output )( )( // DDR3 interface // DDR3 interface output SDCLK, // DDR3 clock differential output, positive output SDCLK, // DDR3 clock differential output, positive Loading @@ -71,16 +68,18 @@ module ddr3c16 #( input clk_in, input clk_in, input rst_in, input rst_in, output mclk, // global clock, half DDR3 clock, synchronizes all I/O thorough the command port output mclk, // global clock, half DDR3 clock, synchronizes all I/O thorough the command port // command port 0 (filled by software - 32w->64r) - used for mode set, refresh, write levelling, ... // command port 0 (filled by software - 32w->32r) - used for mode set, refresh, write levelling, ... input cmd0_clk, input cmd0_we, input cmd0_we, input [9:0] cmd0_addr, input [9:0] cmd0_addr, input [31:0] cmd0_data, input [31:0] cmd0_data, // TODO: add automatic command port1 , filled by the PL, 36w 36r, used for actual page R/W // automatic command port1 , filled by the PL, 32w 32r, used for actual page R/W input cmd1_clk, input cmd1_we, input cmd1_we, input [9:0] cmd1_addr, input [9:0] cmd1_addr, input [35:0] cmd1_data, input [31:0] cmd1_data, // Controller run interface, posedge mclk // Controller run interface, posedge mclk input [10:0] run_addr, // controller sequencer start address (0..11'h1ff - cmd0, 11'h400..11'h7ff - cmd1) input [10:0] run_addr, // controller sequencer start address (0..11'h3ff - cmd0, 11'h400..11'h7ff - cmd1) input [3:0] run_chn, // data channel to use input [3:0] run_chn, // data channel to use input run_seq, // start controller sequence input run_seq, // start controller sequence output run_done, // controller sequence finished output run_done, // controller sequence finished Loading Loading @@ -116,12 +115,174 @@ module ddr3c16 #( ); ); localparam ADDRESS_NUMBER = 15; localparam ADDRESS_NUMBER = 15; wire [35:0] phy_cmd; // input[35:0] wire [6:0] buf_addr; // output[6:0] // wire [35:0] phy_cmd; // input[35:0] wire [31:0] phy_cmd_word; // selected output from eithe cmd0 buffer or cmd1 buffer wire [31:0] phy_cmd0_word; // cmd0 buffer output wire [31:0] phy_cmd1_word; // cmd1 buffer output reg [ 8:0] buf_raddr; reg [ 8:0] buf_waddr_negedge; reg buf_wr_negedge; wire [63:0] buf_wdata; // output[63:0] wire [63:0] buf_wdata; // output[63:0] wire [63:0] buf_rdata; // input[63:0] reg [63:0] buf_wdata_negedge; // output[63:0] wire [63:0] buf_rdata; // multiplexed input from one of the write channels buffer wire [63:0] buf1_rdata; wire buf_wr; // output wire buf_wr; // output wire buf_rd; // output wire buf_rd; // read next 64 bytes from the buffer, need one extra pre-read wire rst=rst_in; // wire [ 9:0] next_cmd_addr; reg [ 9:0] cmd_addr; // command word adderss reg cmd_sel; reg [ 2:0] cmd_busy; // bit 0 - immediately, wire phy_cmd_nop; // decoded command (ras, cas, we) was NOP wire sequence_done; wire [CMD_PAUSE_BITS-1:0] pause_len; reg cmd_fetch; // previous cycle command was read from the command memory, current: command valid wire pause; // do not register new data from the command memory reg [CMD_PAUSE_BITS-1:0] pause_cntr; reg [1:0] buf_page; // one of 4 pages in the channel buffer to use for R/W reg [15:0] buf_sel_1hot; // 1 hot channel buffer select reg [3:0] run_chn_d; reg run_seq_d; assign run_done=sequence_done; assign pause=cmd_fetch? (phy_cmd_nop && (pause_len != 0)): (cmd_busy[2] && (pause_cntr[CMD_PAUSE_BITS-1:1]!=0)); assign phy_cmd_word = phy_cmd_word?phy_cmd1_word:phy_cmd0_word; assign buf_rdata[63:0] = ({64{buf_sel_1hot[1]}} & buf1_rdata[63:0]); // ORR with other read channels terms always @ (posedge mclk or posedge rst) begin if (rst) cmd_busy <= 0; else if (sequence_done) cmd_busy <= 0; else cmd_busy <= {cmd_busy[1:0],run_seq}; // Pause counter if (rst) pause_cntr <= 0; else if (!cmd_busy[1]) pause_cntr <= 0; // not needed? else if (cmd_fetch && phy_cmd_nop) pause_cntr <= pause_len; else if (pause_cntr!=0) pause_cntr <= pause_cntr-1; // Fetch - command data valid if (rst) cmd_fetch <= 0; else cmd_fetch <= cmd_busy[0] && !pause; // Command read adderss if (rst) cmd_addr <= 0; else if (run_seq) cmd_addr <= run_addr[9:0]; else if (cmd_busy[0] && !pause) cmd_addr <= cmd_addr + 1; // command bank select (0 - "manual" (software programmed sequences), 1 - "auto" (normal block r/w) if (rst) cmd_sel <= 0; else if (run_seq) cmd_sel <= run_addr[10]; if (rst) buf_page <= 0; else if (run_seq) case (run_chn) 4'h0: buf_page <= port0_int_page; 4'h1: buf_page <= port1_int_page; // Add other channles later default: buf_page <= 2'bxx; endcase if (rst) buf_sel_1hot <= 0; else buf_sel_1hot <= { (run_chn_d==4'hf)?1'b1:1'b0, (run_chn_d==4'he)?1'b1:1'b0, (run_chn_d==4'hd)?1'b1:1'b0, (run_chn_d==4'hc)?1'b1:1'b0, (run_chn_d==4'hb)?1'b1:1'b0, (run_chn_d==4'ha)?1'b1:1'b0, (run_chn_d==4'h9)?1'b1:1'b0, (run_chn_d==4'h8)?1'b1:1'b0, (run_chn_d==4'h7)?1'b1:1'b0, (run_chn_d==4'h6)?1'b1:1'b0, (run_chn_d==4'h5)?1'b1:1'b0, (run_chn_d==4'h4)?1'b1:1'b0, (run_chn_d==4'h3)?1'b1:1'b0, (run_chn_d==4'h2)?1'b1:1'b0, (run_chn_d==4'h1)?1'b1:1'b0, (run_chn_d==4'h0)?1'b1:1'b0 }; if (rst) buf_raddr <= 9'h0; else if (run_seq_d) buf_raddr <= {buf_page,7'h0}; else if (buf_wr || buf_rd) buf_raddr <= buf_raddr +1; // Separate read/write address? read address re-registered @ negedge end // re-register buffer write address to match DDR3 data always @ (negedge mclk) begin buf_waddr_negedge <= buf_raddr; buf_wr_negedge <= buf_wr; buf_wdata_negedge <= buf_wdata; end always @ (posedge mclk) begin run_chn_d <= run_chn; run_seq_d <= run_seq; end // Command sequence memories: // Command sequence memory 0 ("manual"): ram_1kx32_1kx32 #( .REGISTERS(1) // register output ) cmd0_buf_i ( .rclk (mclk), // input .raddr (cmd_addr), // input[9:0] .ren (!cmd_sel && cmd_busy && !pause), // input .regen (!cmd_sel && cmd_busy && !pause), // input .data_out (phy_cmd0_word), // output[31:0] .wclk (cmd0_clk), // input .waddr (cmd0_addr), // input[9:0] .we (cmd0_we), // input .web (4'hf), // input[3:0] .data_in (cmd0_data) // input[31:0] ); // Command sequence memory 0 ("manual"): ram_1kx32_1kx32 #( .REGISTERS(1) // register output ) cmd1_buf_i ( .rclk (mclk), // input .raddr (cmd_addr), // input[9:0] .ren ( cmd_sel && cmd_busy && !pause), // input .regen ( cmd_sel && cmd_busy && !pause), // input .data_out (phy_cmd1_word), // output[31:0] .wclk (cmd1_clk), // input .waddr (cmd1_addr), // input[9:0] .we (cmd1_we), // input .web (4'hf), // input[3:0] .data_in (cmd1_data) // input[31:0] ); // Port memory buffer (4 pages each, R/W fixed, port 0 - AXI read from DDR, port 1 - AXI write to DDR // Port 0 (read DDR to AXI) buffer ram_512x64w_1kx32r #( .REGISTERS(1) ) port0_buf_i ( .rclk (port0_clk), // input .raddr ({port0_page,port0_addr}), // input[9:0] .ren (port0_re), // input .regen (port0_regen), // input .data_out (port0_data), // output[31:0] .wclk (!mclk), // input .waddr (buf_waddr_negedge), // input[8:0] .we (buf_sel_1hot[0] && buf_wr_negedge), // input .web (8'hff), // input[7:0] .data_in (buf_wdata_negedge) // input[63:0] ); // Port 1 (write DDR from AXI) buffer ram_1kx32w_512x64r #( .REGISTERS(1) ) port1_buf_i ( .rclk(mclk), // input .raddr(buf_raddr), // input[8:0] .ren(buf_sel_1hot[1] && buf_rd), // input .regen(buf_sel_1hot[1] && buf_rd), // input .data_out(buf1_rdata), // output[63:0] .wclk(port1_clk), // input .waddr({port1_page,port1_addr}), // input[9:0] .we(port1_we), // input .web(4'hf), // input[3:0] .data_in(port1_data) // input[31:0] ); phy_cmd #( phy_cmd #( Loading @@ -147,7 +308,10 @@ module ddr3c16 #( .REF_JITTER1 (REF_JITTER1), .REF_JITTER1 (REF_JITTER1), .SS_EN (SS_EN), .SS_EN (SS_EN), .SS_MODE (SS_MODE), .SS_MODE (SS_MODE), .SS_MOD_PERIOD (SS_MOD_PERIOD) .SS_MOD_PERIOD (SS_MOD_PERIOD), .CMD_PAUSE_BITS (CMD_PAUSE_BITS), // numer of (address) bits to encode pause .CMD_DONE_BIT (CMD_DONE_BIT) // bit number (address) to signal sequence done ) phy_cmd_i ( ) phy_cmd_i ( .SDCLK (SDCLK), // output .SDCLK (SDCLK), // output .SDNCLK (SDNCLK), // output .SDNCLK (SDNCLK), // output Loading Loading @@ -175,8 +339,11 @@ module ddr3c16 #( .locked (locked), // output .locked (locked), // output .ps_rdy (ps_rdy), // output .ps_rdy (ps_rdy), // output .ps_out (ps_out[7:0]), // output[7:0] .ps_out (ps_out[7:0]), // output[7:0] .phy_cmd (phy_cmd[35:0]), // input[35:0] .phy_cmd_word (phy_cmd_word[31:0]), // input[35:0] .buf_addr (buf_addr[6:0]), // output[6:0] .phy_cmd_nop (phy_cmd_nop), // output .pause_len (pause_len), // output [CMD_PAUSE_BITS-1:0] .sequence_done (sequence_done), // output // .buf_addr (buf_addr[6:0]), // output[6:0] .buf_wdata (buf_wdata[63:0]), // output[63:0] .buf_wdata (buf_wdata[63:0]), // output[63:0] .buf_rdata (buf_rdata[63:0]), // input[63:0] .buf_rdata (buf_rdata[63:0]), // input[63:0] .buf_wr (buf_wr), // output .buf_wr (buf_wr), // output Loading
phy/phy_cmd.v +21 −12 Original line number Original line Diff line number Diff line Loading @@ -44,8 +44,9 @@ module phy_cmd#( parameter REF_JITTER1 = 0.010, parameter REF_JITTER1 = 0.010, parameter SS_EN = "FALSE", parameter SS_EN = "FALSE", parameter SS_MODE = "CENTER_HIGH", parameter SS_MODE = "CENTER_HIGH", parameter SS_MOD_PERIOD = 10000 parameter SS_MOD_PERIOD = 10000, parameter CMD_PAUSE_BITS= 6, // numer of (address) bits to encode pause parameter CMD_DONE_BIT= 6 // bit number (address) to signal sequence done )( )( // DDR3 interface // DDR3 interface output SDCLK, // DDR3 clock differential output, positive output SDCLK, // DDR3 clock differential output, positive Loading Loading @@ -78,9 +79,13 @@ module phy_cmd#( output ps_rdy, output ps_rdy, output [PHASE_WIDTH-1:0] ps_out, output [PHASE_WIDTH-1:0] ps_out, // command port // command port input [35:0] phy_cmd, // input [35:0] phy_cmd, input [31:0] phy_cmd_word, output phy_cmd_nop, output [CMD_PAUSE_BITS-1:0] pause_len, output sequence_done, // external memory buffer (cs- channel select, high addresses- page addresses are decoded externally) // external memory buffer (cs- channel select, high addresses- page addresses are decoded externally) output [ 6:0] buf_addr, // output [ 6:0] buf_addr, output [63:0] buf_wdata, // data to be written to the buffer (from DDR3), valid @ negedge mclk output [63:0] buf_wdata, // data to be written to the buffer (from DDR3), valid @ negedge mclk input [63:0] buf_rdata, // data read from the buffer (to DDR3) input [63:0] buf_rdata, // data read from the buffer (to DDR3) output buf_wr, // write buffer (next cycle!) output buf_wr, // write buffer (next cycle!) Loading @@ -106,7 +111,7 @@ module phy_cmd#( wire phy_dq_tri_in; // tristate DQ lines (internal timing sequencer for 0->1 and 1->0) wire phy_dq_tri_in; // tristate DQ lines (internal timing sequencer for 0->1 and 1->0) wire phy_dqs_tri_in; // tristate DQS lines (internal timing sequencer for 0->1 and 1->0) wire phy_dqs_tri_in; // tristate DQS lines (internal timing sequencer for 0->1 and 1->0) wire phy_dci_in; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0) wire phy_dci_in; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0) wire [ 6:0] phy_buf_addr; // connect to extrenal buffer // wire [ 6:0] phy_buf_addr; // connect to extrenal buffer wire phy_buf_wr; // connect to extrenal buffer wire phy_buf_wr; // connect to extrenal buffer wire phy_buf_rd; // connect to extrenal buffer wire phy_buf_rd; // connect to extrenal buffer Loading Loading @@ -138,8 +143,8 @@ module phy_cmd#( wire [63:0] phy_rdata; // data read from ddr3 iserdese2 at posedge clk_div wire [63:0] phy_rdata; // data read from ddr3 iserdese2 at posedge clk_div reg [63:0] phy_rdata_r; // registered @ posedge mclk reg [63:0] phy_rdata_r; // registered @ posedge mclk // output [63:0] buf_wdata, // data to be written to the buffer (from DDR3) // output [63:0] buf_wdata, // data to be written to the buffer (from DDR3) // SuppressWarnings VEditor (* keep = "true" *) wire [2:0] phy_spare; assign { assign { phy_addr_in, phy_addr_in, phy_bank_in, phy_bank_in, Loading @@ -150,12 +155,16 @@ module phy_cmd#( phy_dq_tri_in, // tristate DQ lines (internal timing sequencer for 0->1 and 1->0) phy_dq_tri_in, // tristate DQ lines (internal timing sequencer for 0->1 and 1->0) phy_dqs_tri_in, // tristate DQS lines (internal timing sequencer for 0->1 and 1->0) phy_dqs_tri_in, // tristate DQS lines (internal timing sequencer for 0->1 and 1->0) phy_dci_in, // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0) phy_dci_in, // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0) phy_buf_addr, // connect to extrenal buffer // phy_buf_addr, // connect to external buffer (is it needed? maybe just autoincrement?) phy_buf_wr, // connect to extrenal buffer phy_buf_wr, // connect to external buffer (but only if not paused) phy_buf_rd // connect to extrenal buffer phy_buf_rd, // connect to external buffer (but only if not paused) } = phy_cmd; phy_spare // Reserved for future use } = phy_cmd_word; assign phy_cmd_nop= (phy_rcw_in==0); assign sequence_done= (phy_rcw_in==0) && phy_addr_in[CMD_DONE_BIT]; assign pause_len= phy_addr_in[CMD_PAUSE_BITS-1:0]; assign buf_addr = phy_buf_addr; // assign buf_addr = phy_buf_addr; assign buf_wr = phy_buf_wr; assign buf_wr = phy_buf_wr; assign buf_rd = phy_buf_rd; assign buf_rd = phy_buf_rd; Loading
wrap/ram_1kx32_1kx32.v +3 −3 Original line number Original line Diff line number Diff line Loading @@ -70,7 +70,7 @@ */ */ module ram_1kx32_1kx32 module ram_1kx32_1kx32 #( #( parameter integer registers = 0 // 1 - registered output parameter integer REGISTERS = 0 // 1 - registered output ) ) ( ( input rclk, // clock for read port input rclk, // clock for read port Loading @@ -89,8 +89,8 @@ module ram_1kx32_1kx32 #( #( .RSTREG_PRIORITY_A("RSTREG"), // Valid: "RSTREG" or "REGCE" .RSTREG_PRIORITY_A("RSTREG"), // Valid: "RSTREG" or "REGCE" .RSTREG_PRIORITY_B("RSTREG"), // Valid: "RSTREG" or "REGCE" .RSTREG_PRIORITY_B("RSTREG"), // Valid: "RSTREG" or "REGCE" .DOA_REG(registers), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .DOA_REG(REGISTERS), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .DOB_REG(registers), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .DOB_REG(REGISTERS), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .RAM_EXTENSION_A("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .RAM_EXTENSION_A("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .RAM_EXTENSION_B("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .RAM_EXTENSION_B("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .READ_WIDTH_A(36), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used) .READ_WIDTH_A(36), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used) Loading
wrap/ram_1kx32w_512x64r.v +3 −3 Original line number Original line Diff line number Diff line Loading @@ -70,7 +70,7 @@ */ */ module ram_1kx32w_512x64r module ram_1kx32w_512x64r #( #( parameter integer registers = 0 // 1 - registered output parameter integer REGISTERS = 0 // 1 - registered output ) ) ( ( input rclk, // clock for read port input rclk, // clock for read port Loading @@ -89,8 +89,8 @@ module ram_1kx32w_512x64r #( #( .RSTREG_PRIORITY_A("RSTREG"), // Valid: "RSTREG" or "REGCE" .RSTREG_PRIORITY_A("RSTREG"), // Valid: "RSTREG" or "REGCE" .RSTREG_PRIORITY_B("RSTREG"), // Valid: "RSTREG" or "REGCE" .RSTREG_PRIORITY_B("RSTREG"), // Valid: "RSTREG" or "REGCE" .DOA_REG(registers), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .DOA_REG(REGISTERS), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .DOB_REG(registers), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .DOB_REG(REGISTERS), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .RAM_EXTENSION_A("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .RAM_EXTENSION_A("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .RAM_EXTENSION_B("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .RAM_EXTENSION_B("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .READ_WIDTH_A(72), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used) .READ_WIDTH_A(72), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used) Loading
wrap/ram_512x64w_1kx32r.v +3 −3 Original line number Original line Diff line number Diff line Loading @@ -70,7 +70,7 @@ */ */ module ram_512x64w_1kx32r module ram_512x64w_1kx32r #( #( parameter integer registers = 0 // 1 - registered output parameter integer REGISTERS = 0 // 1 - registered output ) ) ( ( input rclk, // clock for read port input rclk, // clock for read port Loading @@ -89,8 +89,8 @@ module ram_512x64w_1kx32r #( #( .RSTREG_PRIORITY_A("RSTREG"), // Valid: "RSTREG" or "REGCE" .RSTREG_PRIORITY_A("RSTREG"), // Valid: "RSTREG" or "REGCE" .RSTREG_PRIORITY_B("RSTREG"), // Valid: "RSTREG" or "REGCE" .RSTREG_PRIORITY_B("RSTREG"), // Valid: "RSTREG" or "REGCE" .DOA_REG(registers), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .DOA_REG(REGISTERS), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .DOB_REG(registers), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .DOB_REG(REGISTERS), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36) .RAM_EXTENSION_A("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .RAM_EXTENSION_A("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .RAM_EXTENSION_B("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .RAM_EXTENSION_B("NONE"), // Cascading, valid: "NONE","UPPER", LOWER" .READ_WIDTH_A(36), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used) .READ_WIDTH_A(36), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used) Loading