Loading axi/axibram_write.v +3 −2 Original line number Diff line number Diff line Loading @@ -89,7 +89,7 @@ module axibram_write #( reg [ 1:0] wburst; // registered burst type reg [ 3:0] wlen; // registered awlen type (for wrapped over transfers) wire [ADDRESS_BITS-1:0] next_wr_address_w; // next transfer address; wire bram_we_w; // write BRAM memory wire bram_we_w; //,bram_we_nonmasked; // write BRAM memory non-masked - should be combined with wire start_write_burst_w; wire write_in_progress_w; reg dev_ready_r; // device, selected at start burst Loading @@ -99,6 +99,7 @@ module axibram_write #( (wburst[0]? (write_address[ADDRESS_BITS-1:0]+1):(write_address[ADDRESS_BITS-1:0])); assign bram_we_w= w_nempty && write_in_progress && dev_ready_r; // assign bram_we_nonmasked= w_nempty && write_in_progress; assign start_write_burst_w=aw_nempty && (!write_in_progress || (w_nempty && (write_left[3:0]==4'b0))); assign write_in_progress_w=aw_nempty || (write_in_progress && !(w_nempty && (write_left[3:0]==4'b0))); Loading ddrc_control.v 0 → 100644 +69 −0 Original line number Diff line number Diff line /******************************************************************************* * Module: ddrc_control * Date:2014-05-19 * Author: Andrey Filippov * Description: Temporary module with DDRC control / command registers * * Copyright (c) 2014 Elphel, Inc. * ddrc_control.v 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, either version 3 of the License, or * (at your option) any later version. * * ddrc_control.v 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 <http://www.gnu.org/licenses/> . *******************************************************************************/ `timescale 1ns/1ps module ddrc_control #( parameter AXI_WR_ADDR_BITS= 12, parameter SELECT_ADDR = 'h800, // address to select this module parameter SELECT_ADDR_MASK = 'h800, // address mask to select this module parameter BUSY_ADDR = 'hc00, // address to generate busy parameter BUSY_ADDR_MASK = 'hc00 // address mask to generate busy )( input clk, input mclk, input rst, input [AXI_WR_ADDR_BITS-1:0] pre_waddr, // AXI write address, before actual writes (to generate busy), valid@start_burst input start_wburst, // burst start - should generate ~ready (should be AND-ed with !busy internally) input [AXI_WR_ADDR_BITS-1:0] waddr, // write address, valid with wr_en input wr_en, // write enable input [31:0] wdata, // write data, valid with waddr and wr_en output busy, // interface busy (combinatorial delay from start_wburst and pre_addr // control signals // control: sequencer run output [10:0] run_addr, // Start address of the physical sequencer (MSB = 0 - "manual", 1 -"auto") output [ 3:0] run_chn, // channel number to use for I/O buffers output run_seq, // single mclk pulse to start sequencer // input run_done; // output - will go through other channel - sequencer done (add busy?) // control: delays and mmcm setup output [ 7:0] dly_data, // 8-bit IDELAY/ODELAY (fine) and MMCM phase shift output [ 6:0] dly_addr, // address to select delay register output ld_delay, // write dly_data to dly_address, one mclk active pulse output set, // transfer (activate) all delays simultaneosly, 1 mclk pulse // control: additional signals output cmda_tri, // tri-state all command and address lines to DDR chip output inv_clk_div, // invert clk_div to ISERDES output [ 7:0] dqs_pattern, // DQS pattern during write (normally 8'h55) output [ 7:0] dqm_pattern, // DQM pattern (just for testing, should be 8'h0) // control: buffers pages output [ 1:0] port0_page, // port 0 buffer read page (to be controlled by arbiter later, set to 2'b0) output [ 1:0] port0_int_page, // port 0 PHY-side write to buffer page (to be controlled by arbiter later, set to 2'b0) output [ 1:0] port1_page, // port 1 buffer write page (to be controlled by arbiter later, set to 2'b0) output [ 1:0] port1_int_page // port 1 PHY-side buffer read page (to be controlled by arbiter later, set to 2'b0) ); reg busy_r=0; reg selected_r=0; // assign busy=busy_r && start_wburst?(((pre_addr ^ SELECT_ADDR) & SELECT_ADDR_MASK)==0): selected_r; assign busy=busy_r && start_wburst?(((pre_waddr ^ BUSY_ADDR) & BUSY_ADDR_MASK)==0): selected_r; endmodule ddrc_status.v 0 → 100644 +50 −0 Original line number Diff line number Diff line /******************************************************************************* * Module: ddrc_status * Date:2014-05-19 * Author: Andrey Filippov * Description: Read status/radback information from the DDR controller * * Copyright (c) 2014 Elphel, Inc. * ddrc_status.v 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, either version 3 of the License, or * (at your option) any later version. * * ddrc_status.v 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 <http://www.gnu.org/licenses/> . *******************************************************************************/ `timescale 1ns/1ps module ddrc_status#( parameter AXI_RD_ADDR_BITS= 12, parameter SELECT_ADDR = 'h800, // address to select this module parameter SELECT_ADDR_MASK = 'h800, // address mask to select this module parameter BUSY_ADDR = 'hc00, // address to generate busy parameter BUSY_ADDR_MASK = 'hc00 // address mask to generate busy )( input clk, input mclk, input rst, input [AXI_RD_ADDR_BITS-1:0] pre_raddr, // AXI reade address, before actual reads (to generate busy), valid@start_burst input start_rburst, // burst start - should generate ~ready (should be AND-ed with !busy internally) input [AXI_RD_ADDR_BITS-1:0] raddr, // read address, valid with rd_en input rd_en, // read enable output [31:0] rdata, // read data, should valid with raddr and rd_en output busy, // interface busy (combinatorial delay from start_wburst and pre_addr // status/readback signals input run_done, // sequencer done (add busy?) input run_busy, // sequencer busy input locked, // MMCM and PLL locked input ps_rdy, // MMCM phase shift control ready input [ 7:0] ps_out // MMCM phase shift value (in 1/56 of the Fvco period) ); endmodule ddrc_test01.v +151 −58 Original line number Diff line number Diff line Loading @@ -46,7 +46,16 @@ module ddrc_test01 #( parameter CMD_PAUSE_BITS= 6, parameter CMD_DONE_BIT= 6, parameter AXI_WR_ADDR_BITS = 12, parameter AXI_RD_ADDR_BITS = 12 parameter AXI_RD_ADDR_BITS = 12, parameter SELECT_WR_ADDR = 'h800, // AXI write address to select this module parameter SELECT_WR_ADDR_MASK = 'h800, // AXI write address mask to select this module parameter BUSY_WR_ADDR = 'hc00, // AXI write address to generate busy parameter BUSY_WR_ADDR_MASK = 'hc00, // AXI write address mask to generate busy parameter SELECT_RD_ADDR = 'h800, // AXI read address to select this module parameter SELECT_RD_ADDR_MASK = 'h800, // AXI read address mask to select this module parameter BUSY_RD_ADDR = 'hc00, // AXI read address to generate busy parameter BUSY_RD_ADDR_MASK = 'hc00 // AXI read address mask to generate busy )( // DDR3 interface output SDCLK, // DDR3 clock differential output, positive Loading @@ -68,6 +77,7 @@ module ddrc_test01 #( inout NDQSU // ~UDQS I/O pad // AXI write (ps -> pl) ); localparam ADDRESS_NUMBER=15; // Source for reset and clock wire [3:0] fclk; // PL Clocks [3:0], output wire [3:0] frst; // PL Clocks [3:0], output Loading Loading @@ -109,7 +119,8 @@ module ddrc_test01 #( wire axiwr_dev_ready; // extrernal combinatorial ready signal, multiplexed from different sources according to pre_awaddr@start_burst wire axiwr_bram_wclk; wire [AXI_WR_ADDR_BITS-1:0] axiwr_bram_waddr; wire axiwr_bram_wen; // external memory wreite enable, (internally combined with registered dev_ready wire axiwr_bram_wen; // external memory write enable, (internally combined with registered dev_ready // SuppressWarnings VEditor unused (yet?) wire [3:0] axiwr_bram_wstb; wire [31:0] axiwr_bram_wdata; Loading Loading @@ -138,6 +149,7 @@ module ddrc_test01 #( wire axird_start_burst; // start of read burst, valid pre_araddr, save externally to control ext. dev_ready multiplexer wire axird_dev_ready; // extrernal combinatorial ready signal, multiplexed from different sources according to pre_araddr@start_burst // External memory interface // SuppressWarnings VEditor unused (yet?) - use mclk wire axird_bram_rclk; // .rclk(aclk), // clock for read port wire [AXI_RD_ADDR_BITS-1:0] axird_bram_raddr; // .raddr(read_in_progress?read_address[9:0]:10'h3ff), // read address wire axird_bram_ren; // .ren(bram_reg_re_w) , // read port enable Loading Loading @@ -214,6 +226,7 @@ wire [10:0] run_addr; // input[10:0] wire [ 3:0] run_chn; // input[3:0] wire run_seq; // input wire run_done; // output wire run_busy; // TODO: add to ddrc_sequencer wire [ 7:0] dly_data; // input[7:0] wire [ 6:0] dly_addr; // input[6:0] wire ld_delay; // input Loading @@ -223,9 +236,87 @@ wire locked; // output wire ps_rdy; // output wire [ 7:0] ps_out; // output[7:0] wire en_port0_rd; wire en_port0_regen; wire en_port1_wr; wire [ 1:0] port0_page; // input[1:0] wire [ 1:0] port0_int_page; // input[1:0] wire [ 1:0] port1_page; // input[1:0] wire [ 1:0] port1_int_page;// input[1:0] // additional control signals wire cmda_tri; // input wire inv_clk_div; // input wire [ 7:0] dqs_pattern; // input[7:0] 8'h55 wire [ 7:0] dqm_pattern; // input[7:0] 8'h00 assign en_cmd0_wr= axiwr_bram_wen && (axiwr_bram_waddr[11:10]==3); assign en_cmd0_wr= axiwr_bram_wen && (axiwr_bram_waddr[11:10]==2'h1); assign en_port0_rd= axird_bram_ren && (axird_bram_raddr[11:10]==2'h0); assign en_port0_regen= axird_bram_regen && (axird_bram_raddr[11:10]==2'h0); assign en_port1_wr= axiwr_bram_wen && (axiwr_bram_waddr[11:10]==2'h0); wire axiwr_dev_busy; assign axiwr_dev_ready = ~axiwr_dev_busy; //may combine (AND) multiple sources if needed wire axird_dev_busy; assign axird_dev_ready = ~axird_dev_busy; //may combine (AND) multiple sources if needed ddrc_control #( .AXI_WR_ADDR_BITS (AXI_WR_ADDR_BITS), .SELECT_ADDR (SELECT_WR_ADDR), .SELECT_ADDR_MASK (SELECT_WR_ADDR_MASK), .BUSY_ADDR (BUSY_WR_ADDR), .BUSY_ADDR_MASK (BUSY_WR_ADDR_MASK) ) ddrc_control_i ( .clk (axi_aclk), // input .mclk (axiwr_bram_wclk), // input .rst (axi_rst), // input .pre_waddr (axiwr_pre_awaddr[AXI_WR_ADDR_BITS-1:0]), // input[11:0] .start_wburst (axiwr_start_burst), // input .waddr (axiwr_bram_waddr[AXI_WR_ADDR_BITS-1:0]), // input[11:0] .wr_en (axiwr_bram_wen), // input .wdata (axiwr_bram_wdata[31:0]), // input[31:0] (no input for wstb here) .busy (axiwr_dev_busy), // output .run_addr (run_addr[10:0]), // output[10:0] .run_chn (run_chn[3:0]), // output[3:0] .run_seq (run_seq), // output .dly_data (dly_data[7:0]), // output[7:0] .dly_addr (dly_addr[6:0]), // output[6:0] .ld_delay (ld_delay), // output .set (set), // output .cmda_tri (cmda_tri), // output .inv_clk_div (inv_clk_div), // output .dqs_pattern (dqs_pattern[7:0]), // output[7:0] .dqm_pattern (dqm_pattern[7:0]), // output[7:0] .port0_page (port0_page[1:0]), // output[1:0] .port0_int_page (port0_int_page[1:0]), // output[1:0] .port1_page (port1_page[1:0]), // output[1:0] .port1_int_page (port1_int_page[1:0]) // output[1:0] ); ddrc_status #( .AXI_RD_ADDR_BITS (AXI_RD_ADDR_BITS), .SELECT_ADDR (SELECT_RD_ADDR), .SELECT_ADDR_MASK (SELECT_RD_ADDR_MASK), .BUSY_ADDR (BUSY_RD_ADDR), .BUSY_ADDR_MASK (BUSY_RD_ADDR_MASK) ) ddrc_status_i ( .clk (axi_aclk), // input .mclk (mclk), // input .rst (axi_rst), // input .pre_raddr (axird_pre_araddr[AXI_RD_ADDR_BITS-1:0]), // input[11:0] .start_rburst (axird_start_burst), // input .raddr (axird_bram_raddr[AXI_RD_ADDR_BITS-1:0]), // input[11:0] .rd_en (axird_bram_regen), // input .rdata (axird_bram_rdata[31:0]), // output[31:0] .busy (axird_dev_busy), // output .run_done (run_done), // input .run_busy (run_busy), // input .locked (locked), // input .ps_rdy (ps_rdy), // input .ps_out (ps_out[7:0]) // input[7:0] ); ddrc_sequencer #( Loading Loading @@ -256,14 +347,14 @@ assign en_cmd0_wr= axiwr_bram_wen && (axiwr_bram_waddr[11:10]==3); ) ddrc_sequencer_i ( .SDCLK (SDCLK), // output .SDNCLK (SDNCLK), // output .SDA (SDA), // output[14:0] .SDBA (SDBA), // output[2:0] .SDA (SDA[14:0]), // output[14:0] // BUG with localparam - fixed .SDBA (SDBA[2:0]), // output[2:0] .SDWE (SDWE), // output .SDRAS (SDRAS), // output .SDCAS (SDCAS), // output .SDCKE (SDCKE), // output .SDODT (SDODT), // output .SDD (SDD), // inout[15:0] .SDD (SDD[15:0]), // inout[15:0] .SDDML (SDDML), // inout .DQSL (DQSL), // inout .NDQSL (NDQSL), // inout Loading @@ -278,6 +369,7 @@ assign en_cmd0_wr= axiwr_bram_wen && (axiwr_bram_waddr[11:10]==3); .cmd0_addr (axiwr_bram_waddr[9:0]), // input[9:0] .cmd0_data (axiwr_bram_wdata[31:0]), // input[31:0] .cmd1_clk (mclk), // input // TODO: add - from PL generation of the command sequences .cmd1_we (1'b0), // input .cmd1_addr (10'b0), // input[9:0] .cmd1_data (32'b0), // input[31:0] Loading @@ -286,6 +378,7 @@ assign en_cmd0_wr= axiwr_bram_wen && (axiwr_bram_waddr[11:10]==3); .run_chn (run_chn[3:0]), // input[3:0] .run_seq (run_seq), // input .run_done (run_done), // output .run_busy (run_busy), // output .dly_data (dly_data[7:0]), // input[7:0] .dly_addr (dly_addr[6:0]), // input[6:0] .ld_delay (ld_delay), // input Loading @@ -294,23 +387,23 @@ assign en_cmd0_wr= axiwr_bram_wen && (axiwr_bram_waddr[11:10]==3); .ps_rdy (ps_rdy), // output .ps_out (ps_out[7:0]), // output[7:0] .port0_clk(), // input .port0_re(), // input .port0_regen(), // input .port0_page(), // input[1:0] .port0_int_page(), // input[1:0] .port0_addr(), // input[7:0] .port0_data(), // output[31:0] .port1_clk(), // input .port1_we(), // input .port1_page(), // input[1:0] .port1_int_page(), // input[1:0] .port1_addr(), // input[7:0] .port1_data(), // input[31:0] .cmda_tri(), // input .inv_clk_div(), // input .dqs_pattern(), // input[7:0] .dqm_pattern() // input[7:0] .port0_clk (axi_aclk), // input .port0_re (en_port0_rd), // input .port0_regen (en_port0_regen), // input .port0_page (port0_page[1:0]), // input[1:0] .port0_int_page (port0_int_page[1:0]), // input[1:0] .port0_addr (axird_bram_raddr[7:0]), // input[7:0] .port0_data (axird_bram_rdata[31:0]), // output[31:0] .port1_clk (axi_aclk), // input .port1_we (en_port1_wr), // input .port1_page (port1_page[1:0]), // input[1:0] .port1_int_page (port1_int_page[1:0]), // input[1:0] .port1_addr (axiwr_bram_waddr[7:0]), // input[7:0] .port1_data (axiwr_bram_wdata[31:0]), // input[31:0] .cmda_tri (cmda_tri), // input .inv_clk_div (inv_clk_div), // input .dqs_pattern (dqs_pattern), // input[7:0] .dqm_pattern (dqm_pattern) // input[7:0] ); Loading phy/ddrc_sequencer.v +3 −2 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ module ddrc_sequencer #( input [3:0] run_chn, // data channel to use input run_seq, // start controller sequence output run_done, // controller sequence finished output run_busy, // controller sequence in progress // inteface to control I/O delays and mmcm input [7:0] dly_data, // delay value (3 LSB - fine delay) input [6:0] dly_addr, // select which delay to program Loading Loading @@ -150,7 +151,7 @@ module ddrc_sequencer #( reg run_seq_d; assign run_done=sequence_done; assign run_busy=cmd_busy[0]; //earliest 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; Loading Loading
axi/axibram_write.v +3 −2 Original line number Diff line number Diff line Loading @@ -89,7 +89,7 @@ module axibram_write #( reg [ 1:0] wburst; // registered burst type reg [ 3:0] wlen; // registered awlen type (for wrapped over transfers) wire [ADDRESS_BITS-1:0] next_wr_address_w; // next transfer address; wire bram_we_w; // write BRAM memory wire bram_we_w; //,bram_we_nonmasked; // write BRAM memory non-masked - should be combined with wire start_write_burst_w; wire write_in_progress_w; reg dev_ready_r; // device, selected at start burst Loading @@ -99,6 +99,7 @@ module axibram_write #( (wburst[0]? (write_address[ADDRESS_BITS-1:0]+1):(write_address[ADDRESS_BITS-1:0])); assign bram_we_w= w_nempty && write_in_progress && dev_ready_r; // assign bram_we_nonmasked= w_nempty && write_in_progress; assign start_write_burst_w=aw_nempty && (!write_in_progress || (w_nempty && (write_left[3:0]==4'b0))); assign write_in_progress_w=aw_nempty || (write_in_progress && !(w_nempty && (write_left[3:0]==4'b0))); Loading
ddrc_control.v 0 → 100644 +69 −0 Original line number Diff line number Diff line /******************************************************************************* * Module: ddrc_control * Date:2014-05-19 * Author: Andrey Filippov * Description: Temporary module with DDRC control / command registers * * Copyright (c) 2014 Elphel, Inc. * ddrc_control.v 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, either version 3 of the License, or * (at your option) any later version. * * ddrc_control.v 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 <http://www.gnu.org/licenses/> . *******************************************************************************/ `timescale 1ns/1ps module ddrc_control #( parameter AXI_WR_ADDR_BITS= 12, parameter SELECT_ADDR = 'h800, // address to select this module parameter SELECT_ADDR_MASK = 'h800, // address mask to select this module parameter BUSY_ADDR = 'hc00, // address to generate busy parameter BUSY_ADDR_MASK = 'hc00 // address mask to generate busy )( input clk, input mclk, input rst, input [AXI_WR_ADDR_BITS-1:0] pre_waddr, // AXI write address, before actual writes (to generate busy), valid@start_burst input start_wburst, // burst start - should generate ~ready (should be AND-ed with !busy internally) input [AXI_WR_ADDR_BITS-1:0] waddr, // write address, valid with wr_en input wr_en, // write enable input [31:0] wdata, // write data, valid with waddr and wr_en output busy, // interface busy (combinatorial delay from start_wburst and pre_addr // control signals // control: sequencer run output [10:0] run_addr, // Start address of the physical sequencer (MSB = 0 - "manual", 1 -"auto") output [ 3:0] run_chn, // channel number to use for I/O buffers output run_seq, // single mclk pulse to start sequencer // input run_done; // output - will go through other channel - sequencer done (add busy?) // control: delays and mmcm setup output [ 7:0] dly_data, // 8-bit IDELAY/ODELAY (fine) and MMCM phase shift output [ 6:0] dly_addr, // address to select delay register output ld_delay, // write dly_data to dly_address, one mclk active pulse output set, // transfer (activate) all delays simultaneosly, 1 mclk pulse // control: additional signals output cmda_tri, // tri-state all command and address lines to DDR chip output inv_clk_div, // invert clk_div to ISERDES output [ 7:0] dqs_pattern, // DQS pattern during write (normally 8'h55) output [ 7:0] dqm_pattern, // DQM pattern (just for testing, should be 8'h0) // control: buffers pages output [ 1:0] port0_page, // port 0 buffer read page (to be controlled by arbiter later, set to 2'b0) output [ 1:0] port0_int_page, // port 0 PHY-side write to buffer page (to be controlled by arbiter later, set to 2'b0) output [ 1:0] port1_page, // port 1 buffer write page (to be controlled by arbiter later, set to 2'b0) output [ 1:0] port1_int_page // port 1 PHY-side buffer read page (to be controlled by arbiter later, set to 2'b0) ); reg busy_r=0; reg selected_r=0; // assign busy=busy_r && start_wburst?(((pre_addr ^ SELECT_ADDR) & SELECT_ADDR_MASK)==0): selected_r; assign busy=busy_r && start_wburst?(((pre_waddr ^ BUSY_ADDR) & BUSY_ADDR_MASK)==0): selected_r; endmodule
ddrc_status.v 0 → 100644 +50 −0 Original line number Diff line number Diff line /******************************************************************************* * Module: ddrc_status * Date:2014-05-19 * Author: Andrey Filippov * Description: Read status/radback information from the DDR controller * * Copyright (c) 2014 Elphel, Inc. * ddrc_status.v 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, either version 3 of the License, or * (at your option) any later version. * * ddrc_status.v 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 <http://www.gnu.org/licenses/> . *******************************************************************************/ `timescale 1ns/1ps module ddrc_status#( parameter AXI_RD_ADDR_BITS= 12, parameter SELECT_ADDR = 'h800, // address to select this module parameter SELECT_ADDR_MASK = 'h800, // address mask to select this module parameter BUSY_ADDR = 'hc00, // address to generate busy parameter BUSY_ADDR_MASK = 'hc00 // address mask to generate busy )( input clk, input mclk, input rst, input [AXI_RD_ADDR_BITS-1:0] pre_raddr, // AXI reade address, before actual reads (to generate busy), valid@start_burst input start_rburst, // burst start - should generate ~ready (should be AND-ed with !busy internally) input [AXI_RD_ADDR_BITS-1:0] raddr, // read address, valid with rd_en input rd_en, // read enable output [31:0] rdata, // read data, should valid with raddr and rd_en output busy, // interface busy (combinatorial delay from start_wburst and pre_addr // status/readback signals input run_done, // sequencer done (add busy?) input run_busy, // sequencer busy input locked, // MMCM and PLL locked input ps_rdy, // MMCM phase shift control ready input [ 7:0] ps_out // MMCM phase shift value (in 1/56 of the Fvco period) ); endmodule
ddrc_test01.v +151 −58 Original line number Diff line number Diff line Loading @@ -46,7 +46,16 @@ module ddrc_test01 #( parameter CMD_PAUSE_BITS= 6, parameter CMD_DONE_BIT= 6, parameter AXI_WR_ADDR_BITS = 12, parameter AXI_RD_ADDR_BITS = 12 parameter AXI_RD_ADDR_BITS = 12, parameter SELECT_WR_ADDR = 'h800, // AXI write address to select this module parameter SELECT_WR_ADDR_MASK = 'h800, // AXI write address mask to select this module parameter BUSY_WR_ADDR = 'hc00, // AXI write address to generate busy parameter BUSY_WR_ADDR_MASK = 'hc00, // AXI write address mask to generate busy parameter SELECT_RD_ADDR = 'h800, // AXI read address to select this module parameter SELECT_RD_ADDR_MASK = 'h800, // AXI read address mask to select this module parameter BUSY_RD_ADDR = 'hc00, // AXI read address to generate busy parameter BUSY_RD_ADDR_MASK = 'hc00 // AXI read address mask to generate busy )( // DDR3 interface output SDCLK, // DDR3 clock differential output, positive Loading @@ -68,6 +77,7 @@ module ddrc_test01 #( inout NDQSU // ~UDQS I/O pad // AXI write (ps -> pl) ); localparam ADDRESS_NUMBER=15; // Source for reset and clock wire [3:0] fclk; // PL Clocks [3:0], output wire [3:0] frst; // PL Clocks [3:0], output Loading Loading @@ -109,7 +119,8 @@ module ddrc_test01 #( wire axiwr_dev_ready; // extrernal combinatorial ready signal, multiplexed from different sources according to pre_awaddr@start_burst wire axiwr_bram_wclk; wire [AXI_WR_ADDR_BITS-1:0] axiwr_bram_waddr; wire axiwr_bram_wen; // external memory wreite enable, (internally combined with registered dev_ready wire axiwr_bram_wen; // external memory write enable, (internally combined with registered dev_ready // SuppressWarnings VEditor unused (yet?) wire [3:0] axiwr_bram_wstb; wire [31:0] axiwr_bram_wdata; Loading Loading @@ -138,6 +149,7 @@ module ddrc_test01 #( wire axird_start_burst; // start of read burst, valid pre_araddr, save externally to control ext. dev_ready multiplexer wire axird_dev_ready; // extrernal combinatorial ready signal, multiplexed from different sources according to pre_araddr@start_burst // External memory interface // SuppressWarnings VEditor unused (yet?) - use mclk wire axird_bram_rclk; // .rclk(aclk), // clock for read port wire [AXI_RD_ADDR_BITS-1:0] axird_bram_raddr; // .raddr(read_in_progress?read_address[9:0]:10'h3ff), // read address wire axird_bram_ren; // .ren(bram_reg_re_w) , // read port enable Loading Loading @@ -214,6 +226,7 @@ wire [10:0] run_addr; // input[10:0] wire [ 3:0] run_chn; // input[3:0] wire run_seq; // input wire run_done; // output wire run_busy; // TODO: add to ddrc_sequencer wire [ 7:0] dly_data; // input[7:0] wire [ 6:0] dly_addr; // input[6:0] wire ld_delay; // input Loading @@ -223,9 +236,87 @@ wire locked; // output wire ps_rdy; // output wire [ 7:0] ps_out; // output[7:0] wire en_port0_rd; wire en_port0_regen; wire en_port1_wr; wire [ 1:0] port0_page; // input[1:0] wire [ 1:0] port0_int_page; // input[1:0] wire [ 1:0] port1_page; // input[1:0] wire [ 1:0] port1_int_page;// input[1:0] // additional control signals wire cmda_tri; // input wire inv_clk_div; // input wire [ 7:0] dqs_pattern; // input[7:0] 8'h55 wire [ 7:0] dqm_pattern; // input[7:0] 8'h00 assign en_cmd0_wr= axiwr_bram_wen && (axiwr_bram_waddr[11:10]==3); assign en_cmd0_wr= axiwr_bram_wen && (axiwr_bram_waddr[11:10]==2'h1); assign en_port0_rd= axird_bram_ren && (axird_bram_raddr[11:10]==2'h0); assign en_port0_regen= axird_bram_regen && (axird_bram_raddr[11:10]==2'h0); assign en_port1_wr= axiwr_bram_wen && (axiwr_bram_waddr[11:10]==2'h0); wire axiwr_dev_busy; assign axiwr_dev_ready = ~axiwr_dev_busy; //may combine (AND) multiple sources if needed wire axird_dev_busy; assign axird_dev_ready = ~axird_dev_busy; //may combine (AND) multiple sources if needed ddrc_control #( .AXI_WR_ADDR_BITS (AXI_WR_ADDR_BITS), .SELECT_ADDR (SELECT_WR_ADDR), .SELECT_ADDR_MASK (SELECT_WR_ADDR_MASK), .BUSY_ADDR (BUSY_WR_ADDR), .BUSY_ADDR_MASK (BUSY_WR_ADDR_MASK) ) ddrc_control_i ( .clk (axi_aclk), // input .mclk (axiwr_bram_wclk), // input .rst (axi_rst), // input .pre_waddr (axiwr_pre_awaddr[AXI_WR_ADDR_BITS-1:0]), // input[11:0] .start_wburst (axiwr_start_burst), // input .waddr (axiwr_bram_waddr[AXI_WR_ADDR_BITS-1:0]), // input[11:0] .wr_en (axiwr_bram_wen), // input .wdata (axiwr_bram_wdata[31:0]), // input[31:0] (no input for wstb here) .busy (axiwr_dev_busy), // output .run_addr (run_addr[10:0]), // output[10:0] .run_chn (run_chn[3:0]), // output[3:0] .run_seq (run_seq), // output .dly_data (dly_data[7:0]), // output[7:0] .dly_addr (dly_addr[6:0]), // output[6:0] .ld_delay (ld_delay), // output .set (set), // output .cmda_tri (cmda_tri), // output .inv_clk_div (inv_clk_div), // output .dqs_pattern (dqs_pattern[7:0]), // output[7:0] .dqm_pattern (dqm_pattern[7:0]), // output[7:0] .port0_page (port0_page[1:0]), // output[1:0] .port0_int_page (port0_int_page[1:0]), // output[1:0] .port1_page (port1_page[1:0]), // output[1:0] .port1_int_page (port1_int_page[1:0]) // output[1:0] ); ddrc_status #( .AXI_RD_ADDR_BITS (AXI_RD_ADDR_BITS), .SELECT_ADDR (SELECT_RD_ADDR), .SELECT_ADDR_MASK (SELECT_RD_ADDR_MASK), .BUSY_ADDR (BUSY_RD_ADDR), .BUSY_ADDR_MASK (BUSY_RD_ADDR_MASK) ) ddrc_status_i ( .clk (axi_aclk), // input .mclk (mclk), // input .rst (axi_rst), // input .pre_raddr (axird_pre_araddr[AXI_RD_ADDR_BITS-1:0]), // input[11:0] .start_rburst (axird_start_burst), // input .raddr (axird_bram_raddr[AXI_RD_ADDR_BITS-1:0]), // input[11:0] .rd_en (axird_bram_regen), // input .rdata (axird_bram_rdata[31:0]), // output[31:0] .busy (axird_dev_busy), // output .run_done (run_done), // input .run_busy (run_busy), // input .locked (locked), // input .ps_rdy (ps_rdy), // input .ps_out (ps_out[7:0]) // input[7:0] ); ddrc_sequencer #( Loading Loading @@ -256,14 +347,14 @@ assign en_cmd0_wr= axiwr_bram_wen && (axiwr_bram_waddr[11:10]==3); ) ddrc_sequencer_i ( .SDCLK (SDCLK), // output .SDNCLK (SDNCLK), // output .SDA (SDA), // output[14:0] .SDBA (SDBA), // output[2:0] .SDA (SDA[14:0]), // output[14:0] // BUG with localparam - fixed .SDBA (SDBA[2:0]), // output[2:0] .SDWE (SDWE), // output .SDRAS (SDRAS), // output .SDCAS (SDCAS), // output .SDCKE (SDCKE), // output .SDODT (SDODT), // output .SDD (SDD), // inout[15:0] .SDD (SDD[15:0]), // inout[15:0] .SDDML (SDDML), // inout .DQSL (DQSL), // inout .NDQSL (NDQSL), // inout Loading @@ -278,6 +369,7 @@ assign en_cmd0_wr= axiwr_bram_wen && (axiwr_bram_waddr[11:10]==3); .cmd0_addr (axiwr_bram_waddr[9:0]), // input[9:0] .cmd0_data (axiwr_bram_wdata[31:0]), // input[31:0] .cmd1_clk (mclk), // input // TODO: add - from PL generation of the command sequences .cmd1_we (1'b0), // input .cmd1_addr (10'b0), // input[9:0] .cmd1_data (32'b0), // input[31:0] Loading @@ -286,6 +378,7 @@ assign en_cmd0_wr= axiwr_bram_wen && (axiwr_bram_waddr[11:10]==3); .run_chn (run_chn[3:0]), // input[3:0] .run_seq (run_seq), // input .run_done (run_done), // output .run_busy (run_busy), // output .dly_data (dly_data[7:0]), // input[7:0] .dly_addr (dly_addr[6:0]), // input[6:0] .ld_delay (ld_delay), // input Loading @@ -294,23 +387,23 @@ assign en_cmd0_wr= axiwr_bram_wen && (axiwr_bram_waddr[11:10]==3); .ps_rdy (ps_rdy), // output .ps_out (ps_out[7:0]), // output[7:0] .port0_clk(), // input .port0_re(), // input .port0_regen(), // input .port0_page(), // input[1:0] .port0_int_page(), // input[1:0] .port0_addr(), // input[7:0] .port0_data(), // output[31:0] .port1_clk(), // input .port1_we(), // input .port1_page(), // input[1:0] .port1_int_page(), // input[1:0] .port1_addr(), // input[7:0] .port1_data(), // input[31:0] .cmda_tri(), // input .inv_clk_div(), // input .dqs_pattern(), // input[7:0] .dqm_pattern() // input[7:0] .port0_clk (axi_aclk), // input .port0_re (en_port0_rd), // input .port0_regen (en_port0_regen), // input .port0_page (port0_page[1:0]), // input[1:0] .port0_int_page (port0_int_page[1:0]), // input[1:0] .port0_addr (axird_bram_raddr[7:0]), // input[7:0] .port0_data (axird_bram_rdata[31:0]), // output[31:0] .port1_clk (axi_aclk), // input .port1_we (en_port1_wr), // input .port1_page (port1_page[1:0]), // input[1:0] .port1_int_page (port1_int_page[1:0]), // input[1:0] .port1_addr (axiwr_bram_waddr[7:0]), // input[7:0] .port1_data (axiwr_bram_wdata[31:0]), // input[31:0] .cmda_tri (cmda_tri), // input .inv_clk_div (inv_clk_div), // input .dqs_pattern (dqs_pattern), // input[7:0] .dqm_pattern (dqm_pattern) // input[7:0] ); Loading
phy/ddrc_sequencer.v +3 −2 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ module ddrc_sequencer #( input [3:0] run_chn, // data channel to use input run_seq, // start controller sequence output run_done, // controller sequence finished output run_busy, // controller sequence in progress // inteface to control I/O delays and mmcm input [7:0] dly_data, // delay value (3 LSB - fine delay) input [6:0] dly_addr, // select which delay to program Loading Loading @@ -150,7 +151,7 @@ module ddrc_sequencer #( reg run_seq_d; assign run_done=sequence_done; assign run_busy=cmd_busy[0]; //earliest 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; Loading