Commit 943fc4a1 authored by Andrey Filippov's avatar Andrey Filippov

before adding extra register layer between channel buffers outputs and memory controller

parent d2db8c14
parameter MCONTR_WR_MASK = 'h3c00, // AXI write address mask for the 1Kx32 buffers command sequence memory
parameter MCONTR_RD_MASK = 'h3c00, // AXI read address mask to generate busy
parameter MCONTR_CMD_WR_ADDR = 'h0000, // AXI write to command sequence memory
parameter MCONTR_BUF0_RD_ADDR = 'h0400, // AXI read address from buffer 0 (PS sequence, memory read)
parameter MCONTR_BUF0_WR_ADDR = 'h0400, // AXI write address to buffer 0 (PS sequence, memory write)
parameter MCONTR_BUF1_RD_ADDR = 'h0800, // AXI read address from buffer 1 (PL sequence, scanline, memory read)
parameter MCONTR_BUF1_WR_ADDR = 'h0800, // AXI write address to buffer 1 (PL sequence, scanline, memory write)
parameter MCONTR_BUF2_RD_ADDR = 'h0c00, // AXI read address from buffer 2 (PL sequence, tiles, memory read)
parameter MCONTR_BUF2_WR_ADDR = 'h0c00, // AXI write address to buffer 2 (PL sequence, tiles, memory write)
parameter MCONTR_BUF3_RD_ADDR = 'h1000, // AXI read address from buffer 3 (PL sequence, scanline, memory read)
parameter MCONTR_BUF3_WR_ADDR = 'h1000, // AXI write address to buffer 3 (PL sequence, scanline, memory write)
parameter MCONTR_BUF4_RD_ADDR = 'h1400, // AXI read address from buffer 4 (PL sequence, tiles, memory read)
parameter MCONTR_BUF4_WR_ADDR = 'h1400, // AXI write address to buffer 4 (PL sequence, tiles, memory write)
parameter CONTROL_ADDR = 'h2000, // AXI write address of control write registers
parameter CONTROL_ADDR_MASK = 'h3800, // AXI write address of control registers
// so 'h2000..'h23ff (CONTROL_ADDR) - no busy when writing, 'h2400..'h27ff (CONTROL_ADDR | BUSY_WR_ADDR) generates busy if fifo half full
parameter BUSY_WR_ADDR = 'h1400, // AXI write address to generate busy
parameter BUSY_WR_ADDR_MASK = 'h3c00, // AXI write address mask to generate busy during memory controller register write
parameter STATUS_ADDR = 'h2800, // AXI write address of status read registers
parameter STATUS_ADDR_MASK = 'h3c00, // AXI write address of status registers
parameter AXI_WR_ADDR_BITS = 14,
parameter AXI_RD_ADDR_BITS = 14,
parameter STATUS_DEPTH= 8, // 256 cells, maybe just 16..64 are enough?
--------------
.MCONTR_WR_MASK (MCONTR_WR_MASK),
.MCONTR_RD_MASK (MCONTR_RD_MASK),
.MCONTR_CMD_WR_ADDR (MCONTR_CMD_WR_ADDR),
.MCONTR_BUF0_RD_ADDR (MCONTR_BUF0_RD_ADDR),
.MCONTR_BUF0_WR_ADDR (MCONTR_BUF0_WR_ADDR),
.MCONTR_BUF1_RD_ADDR (MCONTR_BUF1_RD_ADDR),
.MCONTR_BUF1_WR_ADDR (MCONTR_BUF1_WR_ADDR),
.MCONTR_BUF2_RD_ADDR (MCONTR_BUF2_RD_ADDR),
.MCONTR_BUF2_WR_ADDR (MCONTR_BUF2_WR_ADDR),
.MCONTR_BUF3_RD_ADDR (MCONTR_BUF3_RD_ADDR),
.MCONTR_BUF3_WR_ADDR (MCONTR_BUF3_WR_ADDR),
.MCONTR_BUF4_RD_ADDR (MCONTR_BUF4_RD_ADDR),
.MCONTR_BUF4_WR_ADDR (MCONTR_BUF4_WR_ADDR),
.CONTROL_ADDR (CONTROL_ADDR),
.CONTROL_ADDR_MASK (CONTROL_ADDR_MASK),
.BUSY_WR_ADDR (BUSY_WR_ADDR),
.BUSY_WR_ADDR_MASK (BUSY_WR_ADDR_MASK),
.STATUS_ADDR (STATUS_ADDR),
.STATUS_ADDR_MASK (STATUS_ADDR_MASK),
.AXI_WR_ADDR_BITS (AXI_WR_ADDR_BITS),
.AXI_RD_ADDR_BITS (AXI_RD_ADDR_BITS),
.STATUS_DEPTH (STATUS_DEPTH),
ddrc_control
parameter BUSY_WR_ADDR = 'h1800, // AXI write address to generate busy
parameter BUSY_WR_ADDR_MASK = 'h1c00, // AXI write address mask to generate busy
//0x1080..10ff - 8- bit data - to set various delay values
parameter DLY_LD = 'h080, // address to generate delay load
parameter DLY_LD_MASK = 'h380, // address mask to generate delay load
......
......@@ -21,9 +21,9 @@
`timescale 1ns/1ps
module cmd_mux #(
parameter AXI_WR_ADDR_BITS= 13,
parameter CONTROL_ADDR = 'h1000, // AXI write address of control write registers
parameter CONTROL_ADDR_MASK = 'h1400, // AXI write address of control registers
parameter AXI_WR_ADDR_BITS= 14,
parameter CONTROL_ADDR = 'h2000, // AXI write address of control write registers
parameter CONTROL_ADDR_MASK = 'h3c00, // AXI write address of control registers
parameter NUM_CYCLES_LOW_BIT= 6, // decode addresses [NUM_CYCLES_LOW_BIT+:4] into command a/d length
parameter NUM_CYCLES_00 = 9, // single-cycle
parameter NUM_CYCLES_01 = 2, // 2-cycle
......
......@@ -18,17 +18,11 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
parameter MCONTR_WR_MASK = 'h1c00, // AXI write address mask for the 1Kx32 buffers command sequence memory
parameter MCONTR_RD_MASK = 'h1c00, // AXI read address mask to generate busy
parameter MCONTR_WR_MASK = 'h3c00, // AXI write address mask for the 1Kx32 buffers command sequence memory
parameter MCONTR_RD_MASK = 'h3c00, // AXI read address mask to generate busy
parameter MCONTR_CMD_WR_ADDR = 'h0000, // AXI write to command sequence memory
parameter MCONTR_BUF0_RD_ADDR = 'h0400, // AXI read address from buffer 0 (PS sequence, memory read)
parameter MCONTR_BUF0_WR_ADDR = 'h0400, // AXI write address to buffer 0 (PS sequence, memory write)
// parameter MCONTR_BUF0_WR_ADDR = 'h0400, // AXI write address to buffer 1 (PS sequence, memory write)
// parameter MCONTR_BUF2_RD_ADDR = 'h0800, // AXI read address from buffer 2 (PL sequence, scanline, memory read)
// parameter MCONTR_BUF3_WR_ADDR = 'h0800, // AXI write address to buffer 3 (PL sequence, scanline, memory write)
// parameter MCONTR_BUF4_RD_ADDR = 'h0c00, // AXI read address from buffer 4 (PL sequence, tiles, memory read)
// parameter MCONTR_BUF5_WR_ADDR = 'h0c00, // AXI write address to buffer 5 (PL sequence, scanline, memory write)
parameter MCONTR_BUF1_RD_ADDR = 'h0800, // AXI read address from buffer 1 (PL sequence, scanline, memory read)
parameter MCONTR_BUF1_WR_ADDR = 'h0800, // AXI write address to buffer 1 (PL sequence, scanline, memory write)
parameter MCONTR_BUF2_RD_ADDR = 'h0c00, // AXI read address from buffer 2 (PL sequence, tiles, memory read)
......@@ -37,6 +31,14 @@
parameter MCONTR_BUF3_WR_ADDR = 'h1000, // AXI write address to buffer 3 (PL sequence, scanline, memory write)
parameter MCONTR_BUF4_RD_ADDR = 'h1400, // AXI read address from buffer 4 (PL sequence, tiles, memory read)
parameter MCONTR_BUF4_WR_ADDR = 'h1400, // AXI write address to buffer 4 (PL sequence, tiles, memory write)
parameter CONTROL_ADDR = 'h2000, // AXI write address of control write registers
parameter CONTROL_ADDR_MASK = 'h3c00, // AXI write address of control registers
parameter STATUS_ADDR = 'h2400, // AXI write address of status read registers
parameter STATUS_ADDR_MASK = 'h3c00, // AXI write address of status registers
parameter AXI_WR_ADDR_BITS = 14,
parameter AXI_RD_ADDR_BITS = 14,
parameter STATUS_DEPTH= 8, // 256 cells, maybe just 16..64 are enough?
//command interface parameters
parameter DLY_LD = 'h080, // address to generate delay load
parameter DLY_LD_MASK = 'h380, // address mask to generate delay load
......@@ -151,14 +153,6 @@
parameter CMD_PAUSE_BITS= 10,
parameter CMD_DONE_BIT= 10,
parameter STATUS_ADDR = 'h1400, // AXI write address of status read registers
parameter STATUS_ADDR_MASK = 'h1400, // AXI write address of status registers
parameter STATUS_DEPTH= 8, // 256 cells, maybe just 16..64 are enough?
parameter AXI_WR_ADDR_BITS = 13,
parameter AXI_RD_ADDR_BITS = 13,
parameter CONTROL_ADDR = 'h1000, // AXI write address of control write registers
parameter CONTROL_ADDR_MASK = 'h1400, // AXI write address of control registers
parameter NUM_CYCLES_LOW_BIT= 'h6, // decode addresses [NUM_CYCLES_LOW_BIT+:4] into command a/d length
// TODO: put actual data
parameter NUM_CYCLES_00 = 2, // 2-cycle 000.003f
......
/*******************************************************************************
* 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 CONTROL_ADDR = 'h1000, // AXI write address of control write registers
parameter CONTROL_ADDR_MASK = 'h1400, // AXI write address of control registers
parameter BUSY_WR_ADDR = 'h1800, // AXI write address to generate busy
parameter BUSY_WR_ADDR_MASK = 'h1c00, // AXI write address mask to generate busy
parameter DLY_LD_REL = 'h080, // address to generate delay load
parameter DLY_LD_REL_MASK = 'h380, // address mask to generate delay load
parameter DLY_SET_REL = 'h070, // address to generate delay set
parameter DLY_SET_REL_MASK = 'h3ff, // address mask to generate delay set
parameter RUN_CHN_REL = 'h000, // address to set sequnecer channel and run (4 LSB-s - channel)
parameter RUN_CHN_REL_MASK = 'h3f0, // address mask to generate sequencer channel/run
parameter PATTERNS_REL = 'h020, // address to set DQM and DQS patterns (16'h0055)
parameter PATTERNS_REL_MASK = 'h3ff, // address mask to set DQM and DQS patterns
parameter PATTERNS_TRI_REL = 'h021, // address to set DQM and DQS tristate on/off patterns {dqs_off,dqs_on, dq_off,dq_on} - 4 bits each
parameter PATTERNS_TRI_REL_MASK = 'h3ff, // address mask to set DQM and DQS tristate patterns
parameter WBUF_DELAY_REL = 'h022, // extra delay (in mclk cycles) to add to write buffer enable (DDR3 read data)
parameter WBUF_DELAY_REL_MASK = 'h3ff, // address mask to set extra delay
parameter PAGES_REL = 'h023, // address to set buffer pages {port1_page[1:0],port1_int_page[1:0],port0_page[1:0],port0_int_page[1:0]}
parameter PAGES_REL_MASK = 'h3ff, // address mask to set DQM and DQS patterns
parameter CMDA_EN_REL = 'h024, // address to enable('h825)/disable('h824) command/address outputs
parameter CMDA_EN_REL_MASK = 'h3fe, // address mask for command/address outputs
parameter SDRST_ACT_REL = 'h026, // address to activate('h827)/deactivate('h826) active-low reset signal to DDR3 memory
parameter SDRST_ACT_REL_MASK = 'h3fe, // address mask for reset DDR3
parameter CKE_EN_REL = 'h028, // address to enable('h829)/disable('h828) CKE signal to memory
parameter CKE_EN_REL_MASK = 'h3fe, // address mask for command/address outputs
parameter DCI_RST_REL = 'h02a, // address to activate('h82b)/deactivate('h82a) Zynq DCI calibrate circuitry
parameter DCI_RST_REL_MASK = 'h3fe, // address mask for DCI calibrate circuitry
parameter DLY_RST_REL = 'h02c, // address to activate('h82d)/deactivate('h82c) delay calibration circuitry
parameter DLY_RST_REL_MASK = 'h3fe, // address mask for delay calibration circuitry
parameter EXTRA_REL = 'h02e, // address to set extra parameters (currently just inv_clk_div)
parameter EXTRA_REL_MASK = 'h3ff, // address mask for extra parameters
parameter REFRESH_EN_REL = 'h030, // address to enable('h31) and disable ('h30) DDR refresh
parameter REFRESH_EN_REL_MASK = 'h3fe, // address mask to enable/disable DDR refresh
parameter REFRESH_PER_REL = 'h032, // address to set refresh period in 32 x tCK
parameter REFRESH_PER_REL_MASK = 'h3ff, // address mask set refresh period
parameter REFRESH_ADDR_REL = 'h033, // address to set sequencer start address for DDR refresh
parameter REFRESH_ADDR_REL_MASK = 'h3ff // address mask set refresh sequencer address
)(
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
// simple arbitration (should not start if higher priority, busy or run_seq)
input run_seq_rq_in, // higher priority request to run sequence
output run_seq_rq_gen,// this wants to run sequencer
input run_seq_busy, // sequencer is busy or access granted to other master (should be on staring nearest cycle)
output [10:0] refresh_address,
output [ 7:0] refresh_period,
output refresh_set,
output refresh_en,
// output run_seq_granted, // this module got sequencer access granted
// 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 dly_set, // transfer (activate) all delays simultaneosly, 1 mclk pulse
// control: additional signals
output cmda_en, // tri-state all command and address lines to DDR chip
output ddr_rst, // generate DDR3 memory reset signal
output dci_rst, // active high - reset DCI circuitry
output dly_rst, // active high - delay calibration circuitry
output ddr_cke, // control DDR3 memory CKE signal
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)
output [ 3:0] dq_tri_on_pattern,
output [ 3:0] dq_tri_off_pattern,
output [ 3:0] dqs_tri_on_pattern,
output [ 3:0] dqs_tri_off_pattern,
output [ 3:0] wbuf_delay,
// 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)
);
localparam DQSTRI_FIRST= 4'h3; // DQS tri-state control word, first when enabling output
localparam DQSTRI_LAST= 4'hc; // DQS tri-state control word, first after disabling output
localparam DQTRI_FIRST= 4'h7; // DQ tri-state control word, first when enabling output
localparam DQTRI_LAST= 4'he; // DQ tri-state control word, first after disabling output
localparam WBUF_DLY_DFLT= 4'h6; // extra delay (in mclk cycles) to add to write buffer enable (DDR3 read data)
localparam DLY_LD_ADDR = CONTROL_ADDR | DLY_LD_REL; // address to generate delay load
localparam DLY_LD_ADDR_MASK = CONTROL_ADDR_MASK | DLY_LD_REL_MASK; // address mask to generate delay load
localparam DLY_SET_ADDR = CONTROL_ADDR | DLY_SET_REL; // address to generate delay set
localparam DLY_SET_ADDR_MASK = CONTROL_ADDR_MASK | DLY_SET_REL_MASK; // address mask to generate delay set
localparam RUN_CHN_ADDR = CONTROL_ADDR | RUN_CHN_REL; // address to set sequnecer channel and run (4 LSB-s - channel)
localparam RUN_CHN_ADDR_MASK = CONTROL_ADDR_MASK | RUN_CHN_REL_MASK; // address mask to generate sequencer channel/run
localparam PATTERNS_ADDR = CONTROL_ADDR | PATTERNS_REL; // address to set DQM and DQS patterns (16'h0055)
localparam PATTERNS_ADDR_MASK = CONTROL_ADDR_MASK | PATTERNS_REL_MASK;// address mask to set DQM and DQS patterns
localparam PATTERNS_TRI_ADDR = CONTROL_ADDR | PATTERNS_TRI_REL; //address to set DQM and DQS tristate on/off patterns {dqs_off,dqs_on, dq_off,dq_on} - 4 bits each
localparam PATTERNS_TRI_ADDR_MASK = CONTROL_ADDR_MASK | PATTERNS_TRI_REL_MASK;// address mask to set DQM and DQS tristate patterns
localparam WBUF_DELAY_ADDR = CONTROL_ADDR | WBUF_DELAY_REL; // extra delay (in mclk cycles) to add to write buffer enable (DDR3 read data)
localparam WBUF_DELAY_ADDR_MASK = CONTROL_ADDR_MASK | WBUF_DELAY_REL_MASK; // address mask to set extra delay
localparam PAGES_ADDR = CONTROL_ADDR | PAGES_REL; // address to set buffer pages {port1_page[1:0],port1_int_page[1:0],port0_page[1:0],port0_int_page[1:0]}
localparam PAGES_ADDR_MASK = CONTROL_ADDR_MASK | PAGES_REL_MASK; // address mask to set DQM and DQS patterns
localparam CMDA_EN_ADDR = CONTROL_ADDR | CMDA_EN_REL; // address to enable('h823)/disable('h822) command/address outputs
localparam CMDA_EN_ADDR_MASK = CONTROL_ADDR_MASK | CMDA_EN_REL_MASK; // address mask for command/address outputs
localparam SDRST_ACT_ADDR = CONTROL_ADDR | SDRST_ACT_REL; // address to activate('h825)/deactivate('h8242) active-low reset signal to DDR3 memory
localparam SDRST_ACT_ADDR_MASK =CONTROL_ADDR_MASK | SDRST_ACT_REL_MASK; // address mask for reset DDR3
localparam DCI_RST_ADDR = CONTROL_ADDR | DCI_RST_REL; // address to activate/deactivate Zynq DCI calibrate circuitry
localparam DCI_RST_ADDR_MASK = CONTROL_ADDR_MASK | DCI_RST_REL_MASK; // address mask for DCI calibrate circuitry
localparam DLY_RST_ADDR = CONTROL_ADDR | DLY_RST_REL; // address to activate/deactivate delay calibration circuitry
localparam DLY_RST_ADDR_MASK = CONTROL_ADDR_MASK | DLY_RST_REL_MASK; // address mask for delay calibration circuitry
localparam CKE_EN_ADDR = CONTROL_ADDR | CKE_EN_REL; // address to enable('h827)/disable('h826) CKE signal to memory
localparam CKE_EN_ADDR_MASK = CONTROL_ADDR_MASK | CKE_EN_REL_MASK; // address mask for CKE
localparam EXTRA_ADDR = CONTROL_ADDR | EXTRA_REL; // address to set extra parameters (currently just inv_clk_div)
localparam EXTRA_ADDR_MASK = CONTROL_ADDR_MASK | EXTRA_REL_MASK; // address mask for extra parameters
localparam REFRESH_EN_ADDR = CONTROL_ADDR | REFRESH_EN_REL; // address to enable('h31) and disable ('h30) DDR refresh
localparam REFRESH_EN_ADDR_MASK = CONTROL_ADDR_MASK | REFRESH_EN_REL_MASK; // address mask to enable/disable DDR refresh
localparam REFRESH_PER_ADDR = CONTROL_ADDR | REFRESH_PER_REL; // address to set refresh period in 32 x tCK
localparam REFRESH_PER_ADDR_MASK = CONTROL_ADDR_MASK | REFRESH_PER_REL_MASK; // address mask set refresh period
localparam REFRESH_ADDR_ADDR = CONTROL_ADDR | REFRESH_ADDR_REL; // address to set sequencer start address for DDR refresh
localparam REFRESH_ADDR_ADDR_MASK = CONTROL_ADDR_MASK | REFRESH_ADDR_REL_MASK; // address mask set refresh sequencer address
reg [10:0] refresh_address_r;
reg [ 7:0] refresh_period_r;
reg refresh_set_r, refresh_set_r0;
reg refresh_ld_addr;
reg refresh_en_r;
wire refresh_set_w; // just decoded
assign refresh_address = refresh_address_r;
assign refresh_period = refresh_period_r;
assign refresh_set = refresh_set_r;
assign refresh_en = refresh_en_r;
reg busy_r=0;
reg selected=0;
reg selected_busy=0; // decoded from address, if false - busy_r is ignored (always ready)
wire fifo_half_empty; // just debugging with (* keep = "true" *)
wire [AXI_WR_ADDR_BITS-1:0] waddr_fifo_out;
wire [31:0] wdata_fifo_out;
// reg fifo_re; // wrong, need to have (fifo!=1) || !re
wire fifo_nempty;
wire fifo_re;
reg [AXI_WR_ADDR_BITS-1:0] waddr_fifo_out_r;
reg [31:0] wdata_fifo_out_r;
reg dly_ld_r=0;
reg dly_set_r=0;
reg run_seq_r=0;
reg [ 7:0] dqs_pattern_r; // DQS pattern during write (normally 8'h55)
reg [ 7:0] dqm_pattern_r; // DQM pattern (just for testing, should be 8'h0)
reg [ 1:0] port0_page_r; // port 0 buffer read page (to be controlled by arbiter later, set to 2'b0)
reg [ 1:0] port0_int_page_r; // port 0 PHY-side write to buffer page (to be controlled by arbiter later, set to 2'b0)
reg [ 1:0] port1_page_r; // port 1 buffer write page (to be controlled by arbiter later, set to 2'b0)
reg [ 1:0] port1_int_page_r; // port 1 PHY-side buffer read page (to be controlled by arbiter later, set to 2'b0)
reg cmda_en_r; // enable (tri-state off) all command and address lines to DDR chip
reg ddr_rst_r; // generate DDR3 memory reset
reg dci_rst_r; // active high - reset DCI circuitry
reg dly_rst_r; // active high - reset delay calibration circuitry
reg ddr_cke_r; // enable CKE to memory
reg inv_clk_div_r; // invert clk_div to ISERDES
reg [15:0] dqs_tri_pattern_r;
reg [ 3:0] wbuf_delay_r;
wire decoded_run_seq;
assign refresh_set_w= fifo_re && (((waddr_fifo_out ^ REFRESH_PER_ADDR) & REFRESH_PER_ADDR_MASK)==0);
// reg this_granted;
// assign run_seq_granted=this_granted;
assign decoded_run_seq= (((waddr_fifo_out ^ RUN_CHN_ADDR) & RUN_CHN_ADDR_MASK)==0) && !ddr_rst; // without ddr_rst 'bx
assign run_seq_rq_gen=decoded_run_seq && fifo_nempty ; //
// assign fifo_re=fifo_nempty; // try simpler
// need a way to reset if run_seq_busy is forever busy? Will it work to just repeat the same command w/o busy to overrun fifo?
// ddr_rst_r should reset seqencer?
// watch higher priority and busy for run_seq command, always ready - for others
assign fifo_re= fifo_nempty && (decoded_run_seq? (!run_seq_rq_in && !run_seq_busy && !run_seq_r): 1'b1);
assign wbuf_delay= wbuf_delay_r;
assign {
dqs_tri_off_pattern[3:0],
dqs_tri_on_pattern[3:0],
dq_tri_off_pattern[3:0],
dq_tri_on_pattern[3:0]
} = dqs_tri_pattern_r;
assign ld_delay = dly_ld_r;
assign dly_set = dly_set_r;
assign dly_data = wdata_fifo_out_r[ 7:0]; // IgnoreThisWarning VivadoSynthesis WARNING: [Synth 8-3936] Found unconnected internal register 'wdata_fifo_out_r_reg' and it is trimmed from '32' to '11' bits. [ddrc_control.v:100]
assign dly_addr = waddr_fifo_out_r[ 6:0]; // IgnoreThisWarning VivadoSynthesis WARNING: [Synth 8-3936] Found unconnected internal register 'waddr_fifo_out_r_reg' and it is trimmed from '12' to '7' bits. [ddrc_control.v:101]
assign run_addr = wdata_fifo_out_r[10:0];
assign run_chn = waddr_fifo_out_r[3:0];
assign run_seq = run_seq_r && !ddr_rst;
assign busy=busy_r && (start_wburst?(((pre_waddr ^ BUSY_WR_ADDR) & BUSY_WR_ADDR_MASK)==0): selected_busy);
assign dqs_pattern = dqs_pattern_r[7:0];
assign dqm_pattern = dqm_pattern_r[7:0];
assign port0_page = port0_page_r[1:0];
assign port0_int_page = port0_int_page_r[1:0];
assign port1_page = port1_page_r[1:0];
assign port1_int_page = port1_int_page_r[1:0];
assign cmda_en = cmda_en_r;
assign ddr_rst = ddr_rst_r;
assign dci_rst = dci_rst_r;
assign dly_rst = dly_rst_r;
assign ddr_cke= ddr_cke_r;
assign inv_clk_div = inv_clk_div_r;
always @ (posedge clk or posedge rst) begin
if (rst) selected <= 1'b0;
else if (start_wburst) selected <= ((pre_waddr ^ CONTROL_ADDR) & CONTROL_ADDR_MASK)==0;
if (rst) selected_busy <= 1'b0;
else if (start_wburst) selected_busy <= ((pre_waddr ^ BUSY_WR_ADDR) & BUSY_WR_ADDR_MASK)==0;
if (rst) busy_r <= 1'b0;
// else if (start_wburst) busy_r <= !fifo_half_empty;
else busy_r <= !fifo_half_empty;
end
/* FIFO to cross clock boundary */
fifo_cross_clocks #(
.DATA_WIDTH (AXI_WR_ADDR_BITS+32),
.DATA_DEPTH (4)
) fifo_cross_clocks_i (
.rst (rst), // input
.rclk (mclk), // input
.wclk (clk), // input
.we (wr_en && selected), // input
.re (fifo_re), // input
.data_in ({waddr[AXI_WR_ADDR_BITS-1:0],wdata[31:0]}), // input[15:0]
.data_out ({waddr_fifo_out[AXI_WR_ADDR_BITS-1:0],wdata_fifo_out[31:0]}), // output[15:0]
.nempty (fifo_nempty), // output
.half_empty (fifo_half_empty) // output
);
always @ (posedge rst or posedge mclk) begin
// if (rst) fifo_re <= 1'b0;
// else fifo_re <= fifo_nempty;
if (rst) dly_ld_r <= 1'b0;
else dly_ld_r <= fifo_re && (((waddr_fifo_out ^ DLY_LD_ADDR) & DLY_LD_ADDR_MASK)==0);
if (rst) dly_set_r <= 1'b0;
else dly_set_r <= fifo_re && (((waddr_fifo_out ^ DLY_SET_ADDR) & DLY_SET_ADDR_MASK)==0);
if (rst) run_seq_r <= 1'b0;
// else run_seq_r <= fifo_re && (((waddr_fifo_out ^ RUN_CHN_ADDR) & RUN_CHN_ADDR_MASK)==0);
else run_seq_r <= fifo_nempty && decoded_run_seq && !run_seq_rq_in && !run_seq_busy && !run_seq_r;
if (rst) {dqm_pattern_r,dqs_pattern_r} <= 16'h0055;
else if (fifo_re && (((waddr_fifo_out ^ PATTERNS_ADDR) & PATTERNS_ADDR_MASK)==0))
{dqm_pattern_r,dqs_pattern_r} <= wdata_fifo_out[15:0];
if (rst) {port1_page_r[1:0],port1_int_page_r[1:0],port0_page_r[1:0],port0_int_page_r[1:0]} <= 8'h00;
else if (fifo_re && (((waddr_fifo_out ^ PAGES_ADDR) & PAGES_ADDR_MASK)==0))
{port1_page_r[1:0],port1_int_page_r[1:0],port0_page_r[1:0],port0_int_page_r[1:0]} <= wdata_fifo_out[7:0];
if (rst) cmda_en_r <= 1'b0;
else if (fifo_re && (((waddr_fifo_out ^ CMDA_EN_ADDR) & CMDA_EN_ADDR_MASK)==0))
cmda_en_r <= waddr_fifo_out[0];
if (rst) ddr_rst_r <= 1'b1; // enable DDR3 reset at system reset
else if (fifo_re && (((waddr_fifo_out ^ SDRST_ACT_ADDR) & SDRST_ACT_ADDR_MASK)==0))
ddr_rst_r <= waddr_fifo_out[0];
if (rst) dci_rst_r <= 1'b0; // reset DCI circuitry off (it is ORed with rst later)
else if (fifo_re && (((waddr_fifo_out ^ DCI_RST_ADDR) & DCI_RST_ADDR_MASK)==0))
dci_rst_r <= waddr_fifo_out[0];
if (rst) dly_rst_r <= 1'b0; // reset DCI circuitry off (it is ORed with rst later)
else if (fifo_re && (((waddr_fifo_out ^ DLY_RST_ADDR) & DLY_RST_ADDR_MASK)==0))
dly_rst_r <= waddr_fifo_out[0];
if (rst) ddr_cke_r <= 1'b0;
else if (fifo_re && (((waddr_fifo_out ^ CKE_EN_ADDR) & CKE_EN_ADDR_MASK)==0))
ddr_cke_r <= waddr_fifo_out[0];
if (rst) inv_clk_div_r <= 1'b0;
else if (fifo_re && (((waddr_fifo_out ^ EXTRA_ADDR) & EXTRA_ADDR_MASK)==0))
inv_clk_div_r <= wdata_fifo_out[0];
if (rst) dqs_tri_pattern_r <= {DQSTRI_LAST,DQSTRI_FIRST,DQTRI_LAST,DQTRI_FIRST};
else if (fifo_re && (((waddr_fifo_out ^ PATTERNS_TRI_ADDR) & PATTERNS_TRI_ADDR_MASK)==0))
dqs_tri_pattern_r <= wdata_fifo_out[15:0];
if (rst) wbuf_delay_r <= WBUF_DLY_DFLT;
else if (fifo_re && (((waddr_fifo_out ^ WBUF_DELAY_ADDR) & WBUF_DELAY_ADDR_MASK)==0))
wbuf_delay_r <= wdata_fifo_out[3:0];
if (rst) refresh_en_r <= 1'b0;
else if (fifo_re && (((waddr_fifo_out ^ REFRESH_EN_ADDR) & REFRESH_EN_ADDR_MASK)==0))
refresh_en_r <= waddr_fifo_out[0];
if (rst) refresh_address_r <= 0;
else if (refresh_ld_addr) refresh_address_r <= wdata_fifo_out_r[10:0];
if (rst) refresh_period_r <= 0;
else if (refresh_set_r0) refresh_period_r <= wdata_fifo_out_r[7:0];
if (rst) refresh_set_r0 <= 0;
else refresh_set_r0 <= refresh_set_w;
if (rst) refresh_set_r <= 0;
else refresh_set_r <= refresh_set_r0;
if (rst) refresh_ld_addr <= 0;
else refresh_ld_addr <= fifo_re && (((waddr_fifo_out ^ REFRESH_ADDR_ADDR) & REFRESH_ADDR_ADDR_MASK)==0);
end
always @ (posedge mclk) begin
waddr_fifo_out_r <= waddr_fifo_out;
wdata_fifo_out_r <= wdata_fifo_out;
end
endmodule
/*******************************************************************************
* 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 locked_mmcm,
input locked_pll,
input dly_ready,
input dci_ready,
input ps_rdy, // MMCM phase shift control ready
input [ 7:0] ps_out // MMCM phase shift value (in 1/56 of the Fvco period)
);
assign busy=0;
assign rdata={17'b0,dly_ready,dci_ready, locked_mmcm, locked_pll, run_busy,locked,ps_rdy,ps_out[7:0]};
endmodule
......@@ -22,20 +22,11 @@
module mcntrl393 #(
// AXI
parameter AXI_WR_ADDR_BITS = 13,
parameter AXI_RD_ADDR_BITS = 13,
// buffers (1k='h400 each) map, addresses and masks are in 32-bit words, not bytes
parameter MCONTR_WR_MASK = 'h1c00, // AXI write address mask for the 1Kx32 buffers command sequence memory
parameter MCONTR_RD_MASK = 'h1c00, // AXI read address mask to generate busy
parameter MCONTR_WR_MASK = 'h3c00, // AXI write address mask for the 1Kx32 buffers command sequence memory
parameter MCONTR_RD_MASK = 'h3c00, // AXI read address mask to generate busy
parameter MCONTR_CMD_WR_ADDR = 'h0000, // AXI write to command sequence memory
parameter MCONTR_BUF0_RD_ADDR = 'h0400, // AXI read address from buffer 0 (PS sequence, memory read)
parameter MCONTR_BUF0_WR_ADDR = 'h0400, // AXI write address to buffer 0 (PS sequence, memory write)
// parameter MCONTR_BUF0_WR_ADDR = 'h0400, // AXI write address to buffer 1 (PS sequence, memory write)
// parameter MCONTR_BUF2_RD_ADDR = 'h0800, // AXI read address from buffer 2 (PL sequence, scanline, memory read)
// parameter MCONTR_BUF3_WR_ADDR = 'h0800, // AXI write address to buffer 3 (PL sequence, scanline, memory write)
// parameter MCONTR_BUF4_RD_ADDR = 'h0c00, // AXI read address from buffer 4 (PL sequence, tiles, memory read)
// parameter MCONTR_BUF5_WR_ADDR = 'h0c00, // AXI write address to buffer 5 (PL sequence, scanline, memory write)
parameter MCONTR_BUF1_RD_ADDR = 'h0800, // AXI read address from buffer 1 (PL sequence, scanline, memory read)
parameter MCONTR_BUF1_WR_ADDR = 'h0800, // AXI write address to buffer 1 (PL sequence, scanline, memory write)
parameter MCONTR_BUF2_RD_ADDR = 'h0c00, // AXI read address from buffer 2 (PL sequence, tiles, memory read)
......@@ -44,6 +35,8 @@ module mcntrl393 #(
parameter MCONTR_BUF3_WR_ADDR = 'h1000, // AXI write address to buffer 3 (PL sequence, scanline, memory write)
parameter MCONTR_BUF4_RD_ADDR = 'h1400, // AXI read address from buffer 4 (PL sequence, tiles, memory read)
parameter MCONTR_BUF4_WR_ADDR = 'h1400, // AXI write address to buffer 4 (PL sequence, tiles, memory write)
parameter AXI_WR_ADDR_BITS = 14,
parameter AXI_RD_ADDR_BITS = 14,
//command interface parameters
......
......@@ -361,9 +361,9 @@ wire start_not_partial= xfer_start_r[0] && !xfer_limited_by_mem_page_r;
if (rst) xfer_start_wr_r <= 0;
else xfer_start_wr_r <= xfer_grant && !chn_rst && cmd_wrmem;
if (rst) need_r <= 0;
else if (chn_rst || xfer_grant) need_r <= 0;
else if (pre_want && (page_cntr>=3)) need_r <= 1;
if (rst) need_r <= 0;
else if (chn_rst || xfer_grant) need_r <= 0;
else if ((pre_want || want_r) && (page_cntr>=3)) need_r <= 1; // may raise need if want was already set
if (rst) want_r <= 0;
else if (chn_rst || xfer_grant) want_r <= 0;
......
......@@ -391,9 +391,9 @@ wire start_not_partial= xfer_start_r[0] && !xfer_limited_by_mem_page_r;
else if (frame_start) continued_tile <= 1'b0;
else if (xfer_start_r[0]) continued_tile <= xfer_limited_by_mem_page_r; // only set after actual start if it was partial, not after parameter change
if (rst) need_r <= 0;
else if (chn_rst || xfer_grant) need_r <= 0;
else if (pre_want && (page_cntr>=3)) need_r <= 1;
if (rst) need_r <= 0;
else if (chn_rst || xfer_grant) need_r <= 0;
else if ((pre_want || want_r) && (page_cntr>=3)) need_r <= 1; // may raise need if want was already set
if (rst) want_r <= 0;
else if (chn_rst || xfer_grant) want_r <= 0;
......
......@@ -29,9 +29,9 @@
`timescale 1ns/1ps
module status_read#(
parameter STATUS_ADDR = 'h1400, // AXI write address of status read registers
parameter STATUS_ADDR_MASK = 'h1400, // AXI write address of status registers
parameter AXI_RD_ADDR_BITS = 13,
parameter STATUS_ADDR = 'h2400, // AXI write address of status read registers
parameter STATUS_ADDR_MASK = 'h3c00, // AXI write address of status registers
parameter AXI_RD_ADDR_BITS = 14,
parameter integer STATUS_DEPTH= 8 // 256 cells, maybe just 16..64 are enough?
)(
input rst,
......
......@@ -23,17 +23,11 @@
//`define DEBUG_FIFO 1
`include ".editor_defines.vh"
module x393 #(
parameter MCONTR_WR_MASK = 'h1c00, // AXI write address mask for the 1Kx32 buffers command sequence memory
parameter MCONTR_RD_MASK = 'h1c00, // AXI read address mask to generate busy
parameter MCONTR_WR_MASK = 'h3c00, // AXI write address mask for the 1Kx32 buffers command sequence memory
parameter MCONTR_RD_MASK = 'h3c00, // AXI read address mask to generate busy
parameter MCONTR_CMD_WR_ADDR = 'h0000, // AXI write to command sequence memory
parameter MCONTR_BUF0_RD_ADDR = 'h0400, // AXI read address from buffer 0 (PS sequence, memory read)
parameter MCONTR_BUF0_WR_ADDR = 'h0400, // AXI write address to buffer 0 (PS sequence, memory write)
// parameter MCONTR_BUF0_WR_ADDR = 'h0400, // AXI write address to buffer 1 (PS sequence, memory write)
// parameter MCONTR_BUF2_RD_ADDR = 'h0800, // AXI read address from buffer 2 (PL sequence, scanline, memory read)
// parameter MCONTR_BUF3_WR_ADDR = 'h0800, // AXI write address to buffer 3 (PL sequence, scanline, memory write)
// parameter MCONTR_BUF4_RD_ADDR = 'h0c00, // AXI read address from buffer 4 (PL sequence, tiles, memory read)
// parameter MCONTR_BUF5_WR_ADDR = 'h0c00, // AXI write address to buffer 5 (PL sequence, scanline, memory write)
parameter MCONTR_BUF1_RD_ADDR = 'h0800, // AXI read address from buffer 1 (PL sequence, scanline, memory read)
parameter MCONTR_BUF1_WR_ADDR = 'h0800, // AXI write address to buffer 1 (PL sequence, scanline, memory write)
parameter MCONTR_BUF2_RD_ADDR = 'h0c00, // AXI read address from buffer 2 (PL sequence, tiles, memory read)
......@@ -42,6 +36,14 @@ module x393 #(
parameter MCONTR_BUF3_WR_ADDR = 'h1000, // AXI write address to buffer 3 (PL sequence, scanline, memory write)
parameter MCONTR_BUF4_RD_ADDR = 'h1400, // AXI read address from buffer 4 (PL sequence, tiles, memory read)
parameter MCONTR_BUF4_WR_ADDR = 'h1400, // AXI write address to buffer 4 (PL sequence, tiles, memory write)
parameter CONTROL_ADDR = 'h2000, // AXI write address of control write registers
parameter CONTROL_ADDR_MASK = 'h3c00, // AXI write address of control registers
parameter STATUS_ADDR = 'h2400, // AXI write address of status read registers
parameter STATUS_ADDR_MASK = 'h3c00, // AXI write address of status registers
parameter AXI_WR_ADDR_BITS = 14,
parameter AXI_RD_ADDR_BITS = 14,
parameter STATUS_DEPTH= 8, // 256 cells, maybe just 16..64 are enough?
//command interface parameters
parameter DLY_LD = 'h080, // address to generate delay load
parameter DLY_LD_MASK = 'h380, // address mask to generate delay load
......@@ -155,15 +157,6 @@ module x393 #(
parameter SS_MOD_PERIOD = 10000,
parameter CMD_PAUSE_BITS= 10,
parameter CMD_DONE_BIT= 10,
parameter STATUS_ADDR = 'h1400, // AXI write address of status read registers
parameter STATUS_ADDR_MASK = 'h1400, // AXI write address of status registers
parameter STATUS_DEPTH= 8, // 256 cells, maybe just 16..64 are enough?
parameter AXI_WR_ADDR_BITS = 13,
parameter AXI_RD_ADDR_BITS = 13,
parameter CONTROL_ADDR = 'h1000, // AXI write address of control write registers
parameter CONTROL_ADDR_MASK = 'h1400, // AXI write address of control registers
parameter NUM_CYCLES_LOW_BIT= 'h6, // decode addresses [NUM_CYCLES_LOW_BIT+:4] into command a/d length
// TODO: put actual data
parameter NUM_CYCLES_00 = 2, // 2-cycle 000.003f
......@@ -610,10 +603,10 @@ BUFG bufg_axi_aclk_i (.O(axi_aclk),.I(fclk[0]));
);
status_read #(
.STATUS_ADDR(STATUS_ADDR),
.STATUS_ADDR_MASK(STATUS_ADDR_MASK),
.AXI_RD_ADDR_BITS(AXI_RD_ADDR_BITS),
.STATUS_DEPTH(STATUS_DEPTH)
.STATUS_ADDR (STATUS_ADDR),
.STATUS_ADDR_MASK (STATUS_ADDR_MASK),
.AXI_RD_ADDR_BITS (AXI_RD_ADDR_BITS),
.STATUS_DEPTH (STATUS_DEPTH)
) status_read_i (
.rst (axi_rst), // input
.clk (mclk), // input
......@@ -647,8 +640,6 @@ BUFG bufg_axi_aclk_i (.O(axi_aclk),.I(fclk[0]));
/* Instance template for module mcntrl393 */
mcntrl393 #(
.AXI_WR_ADDR_BITS (AXI_WR_ADDR_BITS),
.AXI_RD_ADDR_BITS (AXI_RD_ADDR_BITS),
.MCONTR_WR_MASK (MCONTR_WR_MASK),
.MCONTR_RD_MASK (MCONTR_RD_MASK),
.MCONTR_CMD_WR_ADDR (MCONTR_CMD_WR_ADDR),
......@@ -662,6 +653,8 @@ BUFG bufg_axi_aclk_i (.O(axi_aclk),.I(fclk[0]));
.MCONTR_BUF3_WR_ADDR (MCONTR_BUF3_WR_ADDR),
.MCONTR_BUF4_RD_ADDR (MCONTR_BUF4_RD_ADDR),
.MCONTR_BUF4_WR_ADDR (MCONTR_BUF4_WR_ADDR),
.AXI_WR_ADDR_BITS (AXI_WR_ADDR_BITS),
.AXI_RD_ADDR_BITS (AXI_RD_ADDR_BITS),
.DLY_LD (DLY_LD),
.DLY_LD_MASK (DLY_LD_MASK),
......
[*]
[*] GTKWave Analyzer v3.3.64 (w)1999-2014 BSI
[*] Sun Feb 22 21:43:30 2015
[*] Mon Feb 23 20:32:53 2015
[*]
[dumpfile] "/home/andrey/git/x393/simulation/x393_testbench01-20150222141943750.lxt"
[dumpfile_mtime] "Sun Feb 22 21:34:12 2015"
[dumpfile_size] 804533571
[dumpfile] "/home/andrey/git/x393/simulation/x393_testbench01-20150223124353972.lxt"
[dumpfile_mtime] "Mon Feb 23 20:02:26 2015"
[dumpfile_size] 1073748834
[savefile] "/home/andrey/git/x393/x393_testbench01.sav"
[timestart] 0
[size] 1823 1173
[pos] 2056 0
*-24.698502 80100000 55877500 55843010 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[timestart] 8460000
[size] 1823 1180
[pos] 2059 -3
*-23.698502 45624323 55877500 55843010 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] x393_testbench01.
[treeopen] x393_testbench01.x393_i.