From 10a72d8e1f05cf13446bf5b3f73d74a4b720f44e Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Sun, 3 Mar 2024 20:43:37 -0800 Subject: [PATCH] Add sdram, don't think it works though --- hw/super6502_fpga/addr_map.mem | 4 +- .../ip/sdram_controller/ipm/component.pickle | Bin 0 -> 49111 bytes .../ip/sdram_controller/ipm/graph.pickle | Bin 0 -> 76832 bytes .../ip/sdram_controller/sdram_controller.v | 4347 +++++++++++++++++ .../sdram_controller_define.vh | 80 + .../sdram_controller/sdram_controller_tmpl.v | 127 + .../sdram_controller_tmpl.vhd | 220 + .../ip/sdram_controller/settings.json | 44 + hw/super6502_fpga/sources.list | 2 +- hw/super6502_fpga/src/rtl/super_6502_fpga.sv | 154 +- hw/super6502_fpga/src/sim/Makefile | 4 +- hw/super6502_fpga/src/sim/hvl/sim_top.sv | 56 +- .../sim/include/sdram_controller_define.vh | 80 + hw/super6502_fpga/src/sim/sources.list | 3 +- .../src/sim/sub/sim_sdram/generic_sdr.v | 1145 +++++ hw/super6502_fpga/super6502_fpga.xml | 14 +- sw/test_code/loop_test/main.s | 7 +- 17 files changed, 6256 insertions(+), 31 deletions(-) create mode 100644 hw/super6502_fpga/ip/sdram_controller/ipm/component.pickle create mode 100644 hw/super6502_fpga/ip/sdram_controller/ipm/graph.pickle create mode 100644 hw/super6502_fpga/ip/sdram_controller/sdram_controller.v create mode 100644 hw/super6502_fpga/ip/sdram_controller/sdram_controller_define.vh create mode 100644 hw/super6502_fpga/ip/sdram_controller/sdram_controller_tmpl.v create mode 100644 hw/super6502_fpga/ip/sdram_controller/sdram_controller_tmpl.vhd create mode 100644 hw/super6502_fpga/ip/sdram_controller/settings.json create mode 100644 hw/super6502_fpga/src/sim/include/sdram_controller_define.vh create mode 100644 hw/super6502_fpga/src/sim/sub/sim_sdram/generic_sdr.v diff --git a/hw/super6502_fpga/addr_map.mem b/hw/super6502_fpga/addr_map.mem index 3d631b3..7a02cdc 100644 --- a/hw/super6502_fpga/addr_map.mem +++ b/hw/super6502_fpga/addr_map.mem @@ -2,4 +2,6 @@ 00000000 000001ff 0000ff00 -0000ffff \ No newline at end of file +0000ffff +00000200 +0000efff \ No newline at end of file diff --git a/hw/super6502_fpga/ip/sdram_controller/ipm/component.pickle b/hw/super6502_fpga/ip/sdram_controller/ipm/component.pickle new file mode 100644 index 0000000000000000000000000000000000000000..1ef144d9d5587ce69f64befaf3456dd73d5498f1 GIT binary patch literal 49111 zcmeHQYiu0Xb>{me>TOxEtt4Yfc0^lTiqylZYt>nDm(p6KNH15SRWzM0cW1dX+TGdA z%!*VLHg=jgO*=u;WK#rr^pVs}fHnb&)M)c)>(nSxv@TjVY1$$PP$W%TAVJYI`BS7o zdd|J`yfd>iyX3BDMmAuRoclQUJKsI$%zd1Bw(mo){COAoM?Y3ofFV z%-tvnF;!5+Y)O1u79Z60{WEg8Dp!PxmJ!O;QdSe{AFPi(SKp|g(EBRcvQXFW5en

BL@%gKtsfhadcD9>d% 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 literal 0 HcmV?d00001 diff --git a/hw/super6502_fpga/ip/sdram_controller/ipm/graph.pickle b/hw/super6502_fpga/ip/sdram_controller/ipm/graph.pickle new file mode 100644 index 0000000000000000000000000000000000000000..6bb69b6b84f827a06bcc6c3ee8c6437daad16b69 GIT binary patch literal 76832 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 literal 0 HcmV?d00001 diff --git a/hw/super6502_fpga/ip/sdram_controller/sdram_controller.v b/hw/super6502_fpga/ip/sdram_controller/sdram_controller.v new file mode 100644 index 0000000..ad24e9d --- /dev/null +++ b/hw/super6502_fpga/ip/sdram_controller/sdram_controller.v @@ -0,0 +1,4347 @@ +// ============================================================================= +// Generated by efx_ipmgr +// Version: 2023.1.150 +// IP Version: 5.0 +// ============================================================================= + +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2013-2023 Efinix Inc. All rights reserved. +// +// This document contains proprietary information which is +// protected by copyright. All rights are reserved. This notice +// refers to original work by Efinix, Inc. which may be derivitive +// of other work distributed under license of the authors. In the +// case of derivative work, nothing in this notice overrides the +// original author's license agreement. Where applicable, the +// original license agreement is included in it's original +// unmodified form immediately below this header. +// +// WARRANTY DISCLAIMER. +// THE DESIGN, CODE, OR INFORMATION ARE PROVIDED “AS IS” AND +// EFINIX MAKES NO WARRANTIES, EXPRESS OR IMPLIED WITH +// RESPECT THERETO, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES, +// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR +// PURPOSE. SOME STATES DO NOT ALLOW EXCLUSIONS OF AN IMPLIED +// WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY TO LICENSEE. +// +// LIMITATION OF LIABILITY. +// NOTWITHSTANDING ANYTHING TO THE CONTRARY, EXCEPT FOR BODILY +// INJURY, EFINIX SHALL NOT BE LIABLE WITH RESPECT TO ANY SUBJECT +// MATTER OF THIS AGREEMENT UNDER TORT, CONTRACT, STRICT LIABILITY +// OR ANY OTHER LEGAL OR EQUITABLE THEORY (I) FOR ANY INDIRECT, +// SPECIAL, INCIDENTAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES OF ANY +// CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF +// GOODWILL, DATA OR PROFIT, WORK STOPPAGE, OR COMPUTER FAILURE OR +// MALFUNCTION, OR IN ANY EVENT (II) FOR ANY AMOUNT IN EXCESS, IN +// THE AGGREGATE, OF THE FEE PAID BY LICENSEE TO EFINIX HEREUNDER +// (OR, IF THE FEE HAS BEEN WAIVED, $100), EVEN IF EFINIX SHALL HAVE +// BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO +// NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR +// CONSEQUENTIAL DAMAGES, SO THIS LIMITATION AND EXCLUSION MAY NOT +// APPLY TO LICENSEE. +// +//////////////////////////////////////////////////////////////////////////////// + +`define IP_UUID _5c381f4179ce404bb3abce25f7e88ca9 +`define IP_NAME_CONCAT(a,b) a``b +`define IP_MODULE_NAME(name) `IP_NAME_CONCAT(name,`IP_UUID) +module sdram_controller ( +input i_aresetn, +input [23:0] i_AXI4_AWADDR, +input i_sysclk, +input i_sdrclk, +input i_tACclk, +input i_pll_locked, +output o_dbg_ref_req, +output o_dbg_wr_ack, +output o_dbg_rd_ack, +output [1:0] o_dbg_n_CS, +output [1:0] o_dbg_n_RAS, +output [1:0] o_dbg_n_CAS, +output [1:0] o_dbg_n_WE, +output [3:0] o_dbg_BA, +output [25:0] o_dbg_ADDR, +output [31:0] o_dbg_DATA_out, +output [31:0] o_dbg_DATA_in, +output o_pll_reset, +output o_AXI4_AWREADY, +input i_AXI4_AWVALID, +output o_AXI4_WREADY, +input [31:0] i_AXI4_WDATA, +input [3:0] i_AXI4_WSTRB, +input i_AXI4_WLAST, +input i_AXI4_WVALID, +output o_AXI4_BVALID, +input i_AXI4_BREADY, +output o_AXI4_ARREADY, +input [23:0] i_AXI4_ARADDR, +input i_AXI4_RREADY, +output [31:0] o_AXI4_RDATA, +output o_AXI4_RLAST, +output o_AXI4_RVALID, +input [3:0] i_AXI4_AWID, +input [2:0] i_AXI4_AWSIZE, +input i_AXI4_ARVALID, +input [3:0] i_AXI4_ARID, +input [7:0] i_AXI4_ARLEN, +input [2:0] i_AXI4_ARSIZE, +input [1:0] i_AXI4_ARBURST, +input [7:0] i_AXI4_AWLEN, +output [3:0] o_AXI4_RID, +output o_dbg_we, +output o_dbg_last, +output [23:0] o_dbg_addr, +output [31:0] o_dbg_din, +output [1:0] o_axi4_wrstate, +output o_fifo_wr, +output o_fifo_full, +output o_fifo_empty, +output [7:0] o_dbg_fifo_waddr, +output o_dbg_fifo_re, +output [7:0] o_dbg_fifo_raddr, +output o_dbg_fifo_we, +output o_dbg_axi4_wlast, +output [6:0] o_shift_cnt, +output o_re_lock, +output [1:0] o_axi4_rastate, +output o_axi4_nwr, +output [7:0] o_axi4_arlen, +output [1:0] o_axi4_rdstate, +output o_sdr_rd_valid, +output [36:0] o_sdr_dout, +output o_dbg_re, +output [3:0] o_AXI4_BID, +input [23:0] i_addr, +input [31:0] i_din, +input [3:0] i_dm, +output [31:0] o_dout, +output [3:0] o_sdr_state, +output o_sdr_init_done, +output o_wr_ack, +output o_rd_ack, +output o_ref_req, +output o_rd_valid, +output [1:0] o_sdr_CKE, +output [1:0] o_sdr_n_CS, +output [1:0] o_sdr_n_RAS, +output [1:0] o_sdr_n_CAS, +output [1:0] o_sdr_n_WE, +output [3:0] o_sdr_BA, +output [25:0] o_sdr_ADDR, +output [31:0] o_sdr_DATA, +output [31:0] o_sdr_DATA_oe, +input [31:0] i_sdr_DATA, +output [3:0] o_sdr_DQM +); +`IP_MODULE_NAME(efx_sdram_controller) #( +.fSYS_MHz (100), +.fCK_MHz (200), +.tIORT_u (2), +.CL (3), +.BL (1), +.DDIO_TYPE ("SOFT"), +.DQ_WIDTH (8), +.DQ_GROUP (2), +.BA_WIDTH (2), +.ROW_WIDTH (13), +.COL_WIDTH (9), +.tPWRUP (200000), +.tRAS (44), +.tRAS_MAX (120000), +.tRC (66), +.tRCD (20), +.tREF (64000000), +.tRFC (66), +.tRP (20), +.tWR (2), +.tMRD (2), +.SDRAM_MODE ("AXI4"), +.DATA_RATE (2), +.AXI_AWADDR_WIDTH (24), +.AXI_WDATA_WIDTH (32), +.AXI_ARADDR_WIDTH (24), +.AXI_RDATA_WIDTH (32), +.AXI_AWID_WIDTH (4), +.AXI_AWUSER_WIDTH (2), +.AXI_WUSER_WIDTH (2), +.AXI_BID_WIDTH (4), +.AXI_BUSER_WIDTH (2), +.AXI_ARID_WIDTH (4), +.AXI_ARUSER_WIDTH (3), +.AXI_RUSER_WIDTH (3) +) u_efx_sdram_controller( +.i_aresetn ( i_aresetn ), +.i_AXI4_AWADDR ( i_AXI4_AWADDR ), +.i_sysclk ( i_sysclk ), +.i_sdrclk ( i_sdrclk ), +.i_tACclk ( i_tACclk ), +.i_pll_locked ( i_pll_locked ), +.o_dbg_ref_req ( o_dbg_ref_req ), +.o_dbg_wr_ack ( o_dbg_wr_ack ), +.o_dbg_rd_ack ( o_dbg_rd_ack ), +.o_dbg_n_CS ( o_dbg_n_CS ), +.o_dbg_n_RAS ( o_dbg_n_RAS ), +.o_dbg_n_CAS ( o_dbg_n_CAS ), +.o_dbg_n_WE ( o_dbg_n_WE ), +.o_dbg_BA ( o_dbg_BA ), +.o_dbg_ADDR ( o_dbg_ADDR ), +.o_dbg_DATA_out ( o_dbg_DATA_out ), +.o_dbg_DATA_in ( o_dbg_DATA_in ), +.o_pll_reset ( o_pll_reset ), +.o_AXI4_AWREADY ( o_AXI4_AWREADY ), +.i_AXI4_AWVALID ( i_AXI4_AWVALID ), +.o_AXI4_WREADY ( o_AXI4_WREADY ), +.i_AXI4_WDATA ( i_AXI4_WDATA ), +.i_AXI4_WSTRB ( i_AXI4_WSTRB ), +.i_AXI4_WLAST ( i_AXI4_WLAST ), +.i_AXI4_WVALID ( i_AXI4_WVALID ), +.o_AXI4_BVALID ( o_AXI4_BVALID ), +.i_AXI4_BREADY ( i_AXI4_BREADY ), +.o_AXI4_ARREADY ( o_AXI4_ARREADY ), +.i_AXI4_ARADDR ( i_AXI4_ARADDR ), +.i_AXI4_RREADY ( i_AXI4_RREADY ), +.o_AXI4_RDATA ( o_AXI4_RDATA ), +.o_AXI4_RLAST ( o_AXI4_RLAST ), +.o_AXI4_RVALID ( o_AXI4_RVALID ), +.i_AXI4_AWID ( i_AXI4_AWID ), +.i_AXI4_AWSIZE ( i_AXI4_AWSIZE ), +.i_AXI4_ARVALID ( i_AXI4_ARVALID ), +.i_AXI4_ARID ( i_AXI4_ARID ), +.i_AXI4_ARLEN ( i_AXI4_ARLEN ), +.i_AXI4_ARSIZE ( i_AXI4_ARSIZE ), +.i_AXI4_ARBURST ( i_AXI4_ARBURST ), +.i_AXI4_AWLEN ( i_AXI4_AWLEN ), +.o_AXI4_RID ( o_AXI4_RID ), +.o_dbg_we ( o_dbg_we ), +.o_dbg_last ( o_dbg_last ), +.o_dbg_addr ( o_dbg_addr ), +.o_dbg_din ( o_dbg_din ), +.o_axi4_wrstate ( o_axi4_wrstate ), +.o_fifo_wr ( o_fifo_wr ), +.o_fifo_full ( o_fifo_full ), +.o_fifo_empty ( o_fifo_empty ), +.o_dbg_fifo_waddr ( o_dbg_fifo_waddr ), +.o_dbg_fifo_re ( o_dbg_fifo_re ), +.o_dbg_fifo_raddr ( o_dbg_fifo_raddr ), +.o_dbg_fifo_we ( o_dbg_fifo_we ), +.o_dbg_axi4_wlast ( o_dbg_axi4_wlast ), +.o_shift_cnt ( o_shift_cnt ), +.o_re_lock ( o_re_lock ), +.o_axi4_rastate ( o_axi4_rastate ), +.o_axi4_nwr ( o_axi4_nwr ), +.o_axi4_arlen ( o_axi4_arlen ), +.o_axi4_rdstate ( o_axi4_rdstate ), +.o_sdr_rd_valid ( o_sdr_rd_valid ), +.o_sdr_dout ( o_sdr_dout ), +.o_dbg_re ( o_dbg_re ), +.o_AXI4_BID ( o_AXI4_BID ), +.i_addr ( i_addr ), +.i_din ( i_din ), +.i_dm ( i_dm ), +.o_dout ( o_dout ), +.o_sdr_state ( o_sdr_state ), +.o_sdr_init_done ( o_sdr_init_done ), +.o_wr_ack ( o_wr_ack ), +.o_rd_ack ( o_rd_ack ), +.o_ref_req ( o_ref_req ), +.o_rd_valid ( o_rd_valid ), +.o_sdr_CKE ( o_sdr_CKE ), +.o_sdr_n_CS ( o_sdr_n_CS ), +.o_sdr_n_RAS ( o_sdr_n_RAS ), +.o_sdr_n_CAS ( o_sdr_n_CAS ), +.o_sdr_n_WE ( o_sdr_n_WE ), +.o_sdr_BA ( o_sdr_BA ), +.o_sdr_ADDR ( o_sdr_ADDR ), +.o_sdr_DATA ( o_sdr_DATA ), +.o_sdr_DATA_oe ( o_sdr_DATA_oe ), +.i_sdr_DATA ( i_sdr_DATA ), +.o_sdr_DQM ( o_sdr_DQM ) +); + +endmodule + +///////////////////////////////////////////////////////////////////////////// +// _____ +// / _______ Copyright (C) 2013-2020 Efinix Inc. All rights reserved. +// / / \ +// / / .. / `IP_MODULE_NAME(axi4_sdram_controller).v +// / / .' / +// __/ /.' / Description: +// __ \ / sdram contronller top with AXI4 interface +// /_/ /\ \_____/ / +// ____/ \_______/ +// +// ******************************* +// Revisions: +// 1.0 Initial rev +// Support ONLY AXI 32-bit data to SDRAM total DQ x16 half rate +// +// ******************************* +///////////////////////////////////////////////////////////////////////////// +// AxSIZE +`define BYTES_TX_1 3'b000 +`define BYTES_TX_2 3'b001 +`define BYTES_TX_4 3'b010 +`define BYTES_TX_8 3'b011 +`define BYTES_TX_16 3'b100 +`define BYTES_TX_32 3'b101 +`define BYTES_TX_64 3'b110 +`define BYTES_TX_128 3'b111 +`define OKAY 2'b00 + +module `IP_MODULE_NAME(axi4_sdram_controller) +#( + parameter AXI_AWADDR_WIDTH = 32, + parameter AXI_WDATA_WIDTH = 32, + parameter AXI_ARADDR_WIDTH = 32, + parameter AXI_RDATA_WIDTH = 32, + + parameter fSYS_MHz = 100, + parameter fCK_MHz = 100, + parameter DDIO_TYPE = "SOFT", + parameter tPWRUP = 100, // 100 us + parameter tRAS = 44, // 44 ns + parameter tRAS_MAX = 120, // 120 us + parameter tRC = 66, // 66 ns + parameter tRCD = 20, // 20 ns + parameter tREF = 64, // 64 ms + parameter tRFC = 66, // 66 ns + parameter tRP = 20, // 20 ns + parameter tWR = 2, // 1 CK+7.5 ns + parameter tMRD = 2, // 2 CK + parameter CL = 3, // 3 CK + parameter BL = 1, + parameter DATA_RATE = 1, + parameter tIORT_u = 2, + parameter BA_WIDTH = 2, + parameter ROW_WIDTH = 10, + parameter COL_WIDTH = 10, + parameter DQ_WIDTH = 8, // x4, x8 + parameter DQ_GROUP = 8, + // x4 x8 x16 x32 + // DQ_WIDTH 4 8 8 8 + // DQ_GROUP 1 1 2 4 + // AXI not support DQ_WIDTH = 4 DQ_GROUP = 1 + + //----- parameter not configurable by user---- + parameter AXI_AWID_WIDTH = 4, + parameter AXI_AWUSER_WIDTH = 2, + parameter AXI_WUSER_WIDTH = 2, + parameter AXI_BID_WIDTH = 4, + parameter AXI_BUSER_WIDTH = 2, + parameter AXI_ARID_WIDTH = 4, + parameter AXI_ARUSER_WIDTH = 2, + parameter AXI_RUSER_WIDTH = 2 +) +( + input i_aresetn, + input i_sysclk, + input i_sdrclk, + input i_tACclk, + input i_pll_locked, + output o_pll_reset, + + // Compulsory + output o_AXI4_AWREADY, + input [AXI_AWADDR_WIDTH-1:0]i_AXI4_AWADDR, + input [2:0]i_AXI4_AWPROT, // Dummy + input i_AXI4_AWVALID, + + output o_AXI4_WREADY, + input [AXI_WDATA_WIDTH/8-1:0]i_AXI4_WSTRB, + input [AXI_WDATA_WIDTH-1:0]i_AXI4_WDATA, + input i_AXI4_WLAST, + input i_AXI4_WVALID, + + output o_AXI4_BVALID, + input i_AXI4_BREADY, + + output o_AXI4_ARREADY, + input [AXI_ARADDR_WIDTH-1:0]i_AXI4_ARADDR, + input [2:0]i_AXI4_ARPROT, // Dummy + input i_AXI4_ARVALID, + + input i_AXI4_RREADY, + output [AXI_RDATA_WIDTH-1:0]o_AXI4_RDATA, + output o_AXI4_RLAST, + output o_AXI4_RVALID, + + // Optional + input [AXI_AWID_WIDTH-1:0]i_AXI4_AWID, + input [3:0]i_AXI4_AWREGION, // Dummy + input [7:0]i_AXI4_AWLEN, // Dummy + input [2:0]i_AXI4_AWSIZE, + input [1:0]i_AXI4_AWBURST, // Dummy + input i_AXI4_AWLOCK, // Dummy + input [3:0]i_AXI4_AWCACHE, // Dummy + input [3:0]i_AXI4_AWQOS, // Dummy + input [AXI_AWUSER_WIDTH-1:0]i_AXI4_AWUSER, // Dummy + + input [AXI_WUSER_WIDTH-1:0]i_AXI4_WUSER, // Dummy + + output [AXI_BID_WIDTH-1:0]o_AXI4_BID, + output [1:0]o_AXI4_BRESP, // Dummy + output [AXI_BUSER_WIDTH-1:0]o_AXI4_BUSER, // Dummy + + input [AXI_ARID_WIDTH-1:0]i_AXI4_ARID, + input [3:0]i_AXI4_ARREGION, // Dummy + input [7:0]i_AXI4_ARLEN, + input [2:0]i_AXI4_ARSIZE, + input [1:0]i_AXI4_ARBURST, // Dummy + input i_AXI4_ARLOCK, // Dummy + input [3:0]i_AXI4_ARCACHE, // Dummy + input [3:0]i_AXI4_ARQOS, // Dummy + input [AXI_ARUSER_WIDTH-1:0]i_AXI4_ARUSER, // Dummy + + output [AXI_ARID_WIDTH-1:0]o_AXI4_RID, + output [1:0]o_AXI4_RRESP, // Dummy + output [AXI_RUSER_WIDTH-1:0]o_AXI4_RUSER, // Dummy + + output [DATA_RATE -1:0] o_sdr_CKE, + output [DATA_RATE -1:0] o_sdr_n_CS, + output [DATA_RATE -1:0] o_sdr_n_RAS, + output [DATA_RATE -1:0] o_sdr_n_CAS, + output [DATA_RATE -1:0] o_sdr_n_WE, + output [DATA_RATE *BA_WIDTH -1:0] o_sdr_BA, + output [DATA_RATE *ROW_WIDTH -1:0] o_sdr_ADDR, + output [DATA_RATE *DQ_GROUP *DQ_WIDTH -1:0] o_sdr_DATA, + output [DATA_RATE *DQ_GROUP *DQ_WIDTH -1:0] o_sdr_DATA_oe, + input [DATA_RATE *DQ_GROUP *DQ_WIDTH -1:0] i_sdr_DATA, + output [DATA_RATE *DQ_GROUP -1:0] o_sdr_DQM, + + // Debug port + output [3:0]o_sdr_state, + output o_dbg_we, + output o_dbg_re, + output o_dbg_last, + output [BA_WIDTH+ROW_WIDTH+COL_WIDTH-1:0]o_dbg_addr, + output [AXI_WDATA_WIDTH-1:0]o_dbg_din, + output o_dbg_wr_ack, + output o_dbg_rd_ack, + output o_sdr_rd_valid, + output o_dbg_ref_req, + output [DATA_RATE*DQ_GROUP*DQ_WIDTH+AXI_ARID_WIDTH:0]o_sdr_dout, + output [1:0]o_axi4_wrstate, + output o_dbg_axi4_wlast, + output [1:0]o_axi4_rastate, + output [1:0]o_axi4_rdstate, + output o_axi4_nwr, + output o_re_lock, + output [6:0]o_shift_cnt, + output [7:0]o_axi4_arlen, + output o_fifo_wr, + output o_fifo_full, + output o_fifo_empty, + output o_dbg_fifo_we, + output [7:0]o_dbg_fifo_waddr, + output o_dbg_fifo_re, + output [7:0]o_dbg_fifo_raddr, + + output [DATA_RATE -1:0] o_dbg_n_CS, + output [DATA_RATE -1:0] o_dbg_n_RAS, + output [DATA_RATE -1:0] o_dbg_n_CAS, + output [DATA_RATE -1:0] o_dbg_n_WE, + output [DATA_RATE *BA_WIDTH -1:0] o_dbg_BA, + output [DATA_RATE *ROW_WIDTH -1:0] o_dbg_ADDR, + output [DATA_RATE *DQ_GROUP *DQ_WIDTH -1:0] o_dbg_DATA_out, + output [DATA_RATE *DQ_GROUP *DQ_WIDTH -1:0] o_dbg_DATA_in +); + +function integer log2; + input integer val; + integer i; + begin + log2 = 0; + for (i=0; 2**i= AXI_BID_WIDTH) + r_AXI4_BID_1P <= i_AXI4_AWID[AXI_BID_WIDTH-1:0]; + else + r_AXI4_BID_1P <= {{AXI_BID_WIDTH-AXI_AWID_WIDTH{1'b0}}, i_AXI4_AWID}; + + r_we_1P <= 1'b1; + // TODO AXI different width support + if (SDR_BWIDTH > AXI_WDATA_WIDTH) + begin + r_addr_1P[0+:BA_WIDTH+ROW_WIDTH+COL_WIDTH-(0-SDR_BWIDTH/AXI_WDATA_WIDTH+1)] <= i_AXI4_AWADDR[BA_WIDTH+ROW_WIDTH+COL_WIDTH-1:0-SDR_BWIDTH/AXI_WDATA_WIDTH+1]; + $display("foo_gt\n"); + end + else if (SDR_BWIDTH == AXI_WDATA_WIDTH) + begin + r_addr_1P <= {i_AXI4_AWADDR[BA_WIDTH+ROW_WIDTH+COL_WIDTH-1:COL_WIDTH], {(DATA_RATE-1){1'b0}}, i_AXI4_AWADDR[COL_WIDTH-1:DATA_RATE-1]}; + //r_addr_1P <= {{(DATA_RATE-1){1'b0}},i_AXI4_AWADDR[BA_WIDTH+ROW_WIDTH+COL_WIDTH-1:DATA_RATE-1]}; + $display("foo_eq\n"); + end + + if (SDR_BWIDTH > AXI_WDATA_WIDTH) + begin + //r_AXI4_WREADY_c <= 1'b1; + r_size_1P <= SDR_BWIDTH/AXI_WDATA_WIDTH-1'b1; + r_shift_cnt_1P <= SDR_BWIDTH/AXI_WDATA_WIDTH-1'b1; + $display("SDR_BWIDTH %d > AXI_WDATA_WIDTH %d\n", SDR_BWIDTH, AXI_WDATA_WIDTH); + end + else if (SDR_BWIDTH == AXI_WDATA_WIDTH) + begin + if (i_AXI4_WLAST) + begin + r_din_1P <= i_AXI4_WDATA; + r_dm_1P <= i_AXI4_WSTRB ^ {(AXI_WDATA_WIDTH/8){1'b1}}; //bitwise XOR to inver the bit + r_last_1P <= 1'b1; + end + r_size_1P <= SDR_BWIDTH/AXI_WDATA_WIDTH-1'b1; + r_shift_cnt_1P <= {7{1'b0}}; + $display("SDR_BWIDTH %d = AXI_WDATA_WIDTH %d\n", SDR_BWIDTH, AXI_WDATA_WIDTH); + end + else + begin + //r_AXI4_WREADY_c <= 1'b1; + r_size_1P <= AXI_WDATA_WIDTH/SDR_BWIDTH-1'b1; + r_shift_cnt_1P <= AXI_WDATA_WIDTH/SDR_BWIDTH-1'b1; + $display("SDR_BWIDTH %d < AXI_WDATA_WIDTH %d\n", SDR_BWIDTH, AXI_WDATA_WIDTH); + end + end + end + + s_WR_SHIFT: + begin + if (SDR_BWIDTH > AXI_WDATA_WIDTH) + begin + if (r_shift_cnt_1P != 7'd0) + begin + if (r_AXI4_WREADY_c) + r_shift_cnt_1P <= r_shift_cnt_1P-1'b1; + end + else + begin + r_shift_cnt_1P <= r_size_1P; + end + end + else if (SDR_BWIDTH == AXI_WDATA_WIDTH) + begin + if (r_AXI4_WREADY_2P) + r_addr_1P <= r_addr_1P+c_addr_increment; + + if (r_AXI4_WREADY_c) + begin + r_din_1P <= i_AXI4_WDATA; + r_dm_1P <= i_AXI4_WSTRB ^ {(AXI_WDATA_WIDTH/8){1'b1}}; //bitwise XOR to inver the bit; + end + + if (~r_AXI4_WREADY_c & r_AXI4_WREADY_2P & i_AXI4_WLAST) + begin + r_din_1P <= i_AXI4_WDATA; + r_dm_1P <= i_AXI4_WSTRB ^ {(AXI_WDATA_WIDTH/8){1'b1}}; //bitwise XOR to inver the bit; + end + end + + if (w_wr_ack) + begin + /*if (SDR_BWIDTH < AXI_WDATA_WIDTH) + begin + if (r_size_1P != `BYTES_TX_1) + r_addr_1P <= r_addr_1P+c_addr_increment; + else if (~r_wr_ack_1P) + r_addr_1P <= r_addr_1P+c_addr_increment; + else if (r_AXI4_WREADY_2P) + r_addr_1P <= r_addr_1P+c_addr_increment; + + r_shift_cnt_1P <= r_shift_cnt_1P-1'b1; + if (r_AXI4_WLAST_1P && r_shift_cnt_1P == 7'd1) + r_last_1P <= 1'b1; + end + else if (SDR_BWIDTH == AXI_WDATA_WIDTH) + begin + r_AXI4_WREADY_c <= 1'b1; + end + else + begin + r_AXI4_WREADY_c <= 1'b1; + + if (r_AXI4_WREADY_c) + r_addr_1P <= r_addr_1P+1'b1; + + if (r_shift_cnt_1P == 7'd1) + begin + if (i_AXI4_WLAST || r_AXI4_WLAST_1P) + begin + r_axi4_wrstate_1P <= s_WR_RESP; + r_AXI4_WREADY_c <= 1'b0; + r_AXI4_WLAST_1P <= 1'b0; + r_AXI4_BVALID_1P <= 1'b1; + + r_last_1P <= 1'b1; + end + end + end*/ + + if (r_shift_cnt_1P == 7'd0) + begin + //r_AXI4_WREADY_c <= 1'b1; + + r_AXI4_WLAST_1P <= i_AXI4_WLAST; + r_shift_cnt_1P <= r_size_1P; + + if (i_AXI4_WLAST && r_size_1P == {7{1'b0}} && r_AXI4_AWLEN_1P) + begin + r_axi4_wrstate_1P <= s_WR_RESP; + //r_AXI4_WREADY_c <= ~r_AXI4_WREADY_c; + r_AXI4_WLAST_1P <= 1'b0; + r_AXI4_BVALID_1P <= 1'b1; + + r_we_1P <= 1'b1; + r_last_1P <= 1'b1; + end + else if (r_AXI4_WLAST_1P) + begin + r_axi4_wrstate_1P <= s_WR_RESP; + //r_AXI4_WREADY_c <= ~r_AXI4_WREADY_c; + r_AXI4_WLAST_1P <= 1'b0; + r_AXI4_BVALID_1P <= 1'b1; + + r_we_1P <= 1'b0; + r_last_1P <= 1'b0; + end + end + end + end + + s_WR_RESP: + begin + r_we_1P <= 1'b0; + r_last_1P <= 1'b0; + + if (i_AXI4_BREADY) + begin + r_axi4_wrstate_1P <= s_IDLE; + r_AXI4_BVALID_1P <= 1'b0; + end + end + endcase + + case (r_axi4_rastate_1P) + s_INIT: + begin + if (w_sdr_init_done) + r_axi4_rastate_1P <= s_IDLE; + end + + s_IDLE: + begin + if (i_AXI4_ARVALID && r_axi4_nwr_1P + && ~r_we_1P && ~w_afull && ~r_AXI4_RVALID_1P) + begin + r_axi4_rastate_1P <= s_RD_ADDR; + r_AXI4_ARREADY_1P <= 1'b1; + r_AXI4_RID_1P <= i_AXI4_ARID; + + r_re_1P <= 1'b1; + r_re_lock_1P <= 1'b1; + if (i_AXI4_ARLEN == 8'd0 && (SDR_BWIDTH == AXI_RDATA_WIDTH)) + r_last_1P <= 1'b1; + + // TODO AXI different width support + if (SDR_BWIDTH > AXI_RDATA_WIDTH) + begin + r_addr_1P[0+:BA_WIDTH+ROW_WIDTH+COL_WIDTH-(0-SDR_BWIDTH/AXI_RDATA_WIDTH+1)] <= i_AXI4_ARADDR[BA_WIDTH+ROW_WIDTH+COL_WIDTH-1:0-SDR_BWIDTH/AXI_RDATA_WIDTH+1]; + end + else if (SDR_BWIDTH == AXI_RDATA_WIDTH) + begin + r_addr_1P <= {i_AXI4_ARADDR[BA_WIDTH+ROW_WIDTH+COL_WIDTH-1:COL_WIDTH], {(DATA_RATE-1){1'b0}}, i_AXI4_ARADDR[COL_WIDTH-1:DATA_RATE-1]}; + //r_addr_1P <= {{(DATA_RATE-1){1'b0}},i_AXI4_ARADDR[BA_WIDTH+ROW_WIDTH+COL_WIDTH-1:DATA_RATE-1]}; + end + + if (SDR_BWIDTH > AXI_WDATA_WIDTH) + begin + r_size_1P <= SDR_BWIDTH/AXI_RDATA_WIDTH-1'b1; + r_shift_cnt_1P <= SDR_BWIDTH/AXI_RDATA_WIDTH-1'b1; + r_addr_cnt_1P <= SDR_BWIDTH/AXI_RDATA_WIDTH-1'b1; + end + else if (SDR_BWIDTH == AXI_WDATA_WIDTH) + begin + r_AXI4_ARLEN_1P <= i_AXI4_ARLEN; + r_size_1P <= 7'd0; + r_shift_cnt_1P <= 7'd0; + r_addr_cnt_1P <= 7'd0; + r_arlen_cnt_1P <= i_AXI4_ARLEN; + end + else + begin + r_AXI4_ARLEN_1P <= i_AXI4_ARLEN; + r_size_1P <= AXI_RDATA_WIDTH/SDR_BWIDTH-1'b1; + r_shift_cnt_1P <= AXI_RDATA_WIDTH/SDR_BWIDTH-1'b1; + r_addr_cnt_1P <= AXI_RDATA_WIDTH/SDR_BWIDTH-1'b1; + r_arlen_cnt_1P <= i_AXI4_ARLEN; + end + end + end + + s_RD_ADDR: + begin + if (~w_afull) + r_re_1P <= 1'b1; + + if (w_rd_ack) + begin + if (w_afull) + r_re_1P <= 1'b0; + if (SDR_BWIDTH < AXI_WDATA_WIDTH) + r_addr_1P <= r_addr_1P+c_addr_increment; + else if (SDR_BWIDTH == AXI_WDATA_WIDTH) + r_addr_1P <= r_addr_1P+c_addr_increment; + else + r_addr_1P <= r_addr_1P+1'b1; + + r_addr_cnt_1P <= r_addr_cnt_1P-1'b1; + if (r_addr_cnt_1P == 7'd0) + begin + r_addr_cnt_1P <= r_size_1P; + r_arlen_cnt_1P <= r_arlen_cnt_1P-1'b1; + end + + if (r_arlen_cnt_1P == 8'd1 && (SDR_BWIDTH == AXI_RDATA_WIDTH)) + r_last_1P <= 1'b1; + + if (r_arlen_cnt_1P == 8'd0) + begin + if (r_addr_cnt_1P == 8'd1) + r_last_1P <= 1'b1; + + if (r_addr_cnt_1P == 8'd0) + begin + r_axi4_rastate_1P <= s_IDLE; + + r_re_1P <= 1'b0; + r_last_1P <= 1'b0; + r_re_lock_1P <= 1'b0; + end + end + end + end + endcase + + if (w_rd_valid) + begin + if (SDR_BWIDTH >= AXI_RDATA_WIDTH) + begin + r_dout_1P[DOUT_WIDTH-1:0] <= w_dout; + end + + r_dout_1P[DOUT_WIDTH+AXI_ARID_WIDTH-1:DOUT_WIDTH] <= r_AXI4_RID[CL+tIORT+1]; + + r_shift_cnt_1P <= r_shift_cnt_1P-1'b1; + + if (r_shift_cnt_1P == 7'd0) + begin + r_fifo_wr_1P <= 1'b1; + + if (arlen_cnt == r_AXI4_ARLEN_1P) begin + arlen_cnt <= {9{1'b0}}; + end + else begin + arlen_cnt <= arlen_cnt+1'b1; + end + + if (arlen_cnt == r_AXI4_ARLEN_1P) + r_dout_1P[DOUT_WIDTH+AXI_ARID_WIDTH] <= 1'b1; + else + r_dout_1P[DOUT_WIDTH+AXI_ARID_WIDTH] <= 1'b0; + r_shift_cnt_1P <= r_size_1P; + end + end + + case (r_axi4_rdstate_1P) + s_INIT: + begin + if (w_sdr_init_done) + r_axi4_rdstate_1P <= s_IDLE; + end + + s_IDLE: + begin + if (~w_empty & r_dout_1P[DOUT_WIDTH+AXI_ARID_WIDTH]) + begin + r_axi4_rdstate_1P <= s_RD_SHIFT; + r_fifo_rd_1P <= 1'b1; + r_dout_1P[DOUT_WIDTH+AXI_ARID_WIDTH] <= 1'b0; + end + end + + s_RD_SHIFT: + begin + r_AXI4_RVALID_1P <= 1'b1; + + if (i_AXI4_RREADY) + begin + if (w_empty) + begin + r_axi4_rdstate_1P <= s_IDLE; + r_AXI4_RVALID_1P <= 1'b0; + end + + if (rd_last) + begin + r_axi4_rdstate_1P <= s_IDLE; + r_AXI4_RVALID_1P <= 1'b0; + end + end + end + endcase + end +end + +genvar i; +generate + for (i=0; i 1) begin + `IP_MODULE_NAME(sdram_io_block) + #( + .DATA_RATE (DATA_RATE), + .BA_WIDTH (BA_WIDTH), + .ROW_WIDTH (ROW_WIDTH), + .COL_WIDTH (COL_WIDTH), + .DQ_WIDTH (DQ_WIDTH), + .DQ_GROUP (DQ_GROUP) + ) + inst_sdram_io_block + ( + .i_arst (i_arst), + .i_sysclk (i_sysclk), + .i_sdrclk (i_sdrclk), + .i_tACclk (i_tACclk), + .i_pll_locked (i_pll_locked), + + .i_sdr_CKE_core (w_sdr_CKE), + .i_sdr_n_CS_core (w_sdr_n_CS), + .i_sdr_n_RAS_core (w_sdr_n_RAS), + .i_sdr_n_CAS_core (w_sdr_n_CAS), + .i_sdr_n_WE_core (w_sdr_n_WE), + .i_sdr_BA_core (w_sdr_BA), + .i_sdr_ADDR_core (w_sdr_ADDR), + .i_sdr_DATA_core (w_sdr_DATA_out), + .i_sdr_DATA_oe_core (w_sdr_DATA_oe), + .o_sdr_DATA_core (w_sdr_DATA_in), + .i_sdr_DQM_core (w_sdr_DQM), + + .o_sdr_CKE_pad (o_sdr_CKE), + .o_sdr_n_CS_pad (o_sdr_n_CS), + .o_sdr_n_RAS_pad (o_sdr_n_RAS), + .o_sdr_n_CAS_pad (o_sdr_n_CAS), + .o_sdr_n_WE_pad (o_sdr_n_WE), + .o_sdr_BA_pad (o_sdr_BA), + .o_sdr_ADDR_pad (o_sdr_ADDR), + .o_sdr_DATA_pad (o_sdr_DATA), + .o_sdr_DATA_oe_pad (o_sdr_DATA_oe), + .i_sdr_DATA_pad (i_sdr_DATA), + .o_sdr_DQM_pad (o_sdr_DQM) + ); +end +else begin + reg [DATA_RATE *DQ_GROUP *DQ_WIDTH -1:0]r_sdr_DATA_in_tACclk_1P; + + always@(posedge i_arst or posedge i_tACclk) + begin + if (i_arst) + r_sdr_DATA_in_tACclk_1P <= {DATA_RATE*DQ_GROUP*DQ_WIDTH{1'b0}}; + else + r_sdr_DATA_in_tACclk_1P <= i_sdr_DATA; + end + + assign w_sdr_DATA_in = r_sdr_DATA_in_tACclk_1P; + assign o_sdr_CKE = w_sdr_CKE; + assign o_sdr_n_CS = w_sdr_n_CS; + assign o_sdr_n_RAS = w_sdr_n_RAS; + assign o_sdr_n_CAS = w_sdr_n_CAS; + assign o_sdr_n_WE = w_sdr_n_WE; + assign o_sdr_BA = w_sdr_BA; + assign o_sdr_ADDR = w_sdr_ADDR; + assign o_sdr_DATA = w_sdr_DATA_out; + assign o_sdr_DATA_oe = w_sdr_DATA_oe; + assign o_sdr_DQM = w_sdr_DQM; +end +endgenerate + +assign o_dbg_DATA_out = w_sdr_DATA_out; +assign o_dbg_DATA_in = w_sdr_DATA_in; + +endmodule + +////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2013-2019 Efinix Inc. All rights reserved. +// +// This document contains proprietary information which is +// protected by copyright. All rights are reserved. This notice +// refers to original work by Efinix, Inc. which may be derivitive +// of other work distributed under license of the authors. In the +// case of derivative work, nothing in this notice overrides the +// original author's license agreement. Where applicable, the +// original license agreement is included in it's original +// unmodified form immediately below this header. +// +// WARRANTY DISCLAIMER. +// THE DESIGN, CODE, OR INFORMATION ARE PROVIDED “AS IS” AND +// EFINIX MAKES NO WARRANTIES, EXPRESS OR IMPLIED WITH +// RESPECT THERETO, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES, +// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR +// PURPOSE. SOME STATES DO NOT ALLOW EXCLUSIONS OF AN IMPLIED +// WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY TO LICENSEE. +// +// LIMITATION OF LIABILITY. +// NOTWITHSTANDING ANYTHING TO THE CONTRARY, EXCEPT FOR BODILY +// INJURY, EFINIX SHALL NOT BE LIABLE WITH RESPECT TO ANY SUBJECT +// MATTER OF THIS AGREEMENT UNDER TORT, CONTRACT, STRICT LIABILITY +// OR ANY OTHER LEGAL OR EQUITABLE THEORY (I) FOR ANY INDIRECT, +// SPECIAL, INCIDENTAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES OF ANY +// CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF +// GOODWILL, DATA OR PROFIT, WORK STOPPAGE, OR COMPUTER FAILURE OR +// MALFUNCTION, OR IN ANY EVENT (II) FOR ANY AMOUNT IN EXCESS, IN +// THE AGGREGATE, OF THE FEE PAID BY LICENSEE TO EFINIX HEREUNDER +// (OR, IF THE FEE HAS BEEN WAIVED, $100), EVEN IF EFINIX SHALL HAVE +// BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO +// NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR +// CONSEQUENTIAL DAMAGES, SO THIS LIMITATION AND EXCLUSION MAY NOT +// APPLY TO LICENSEE. +// +///////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////// +// _____ +// / _______ Copyright (C) 2013-2020 Efinix Inc. All rights reserved. +// / / \ +// / / .. / `IP_MODULE_NAME(sdram_fsm).v +// / / .' / +// __/ /.' / Description: +// __ \ / sdram controller state machine +// /_/ /\ \_____/ / +// ____/ \_______/ +// +// ******************************* +// Revisions: +// 1.0 Initial rev +// +// ******************************* + +module `IP_MODULE_NAME(sdram_fsm) +#( + parameter fSYS_MHz = 100, + parameter fCK_MHz = 200, // MHz + parameter DLY_CNT_A_WIDTH = 6, + parameter DLY_CNT_B_WIDTH = 6, + parameter CHECK_ACT_BA = 4, + parameter REF_LATENCY = 2, // + + parameter tPWRUP = 200, // 100 us + parameter tRAS = 44, // 44 ns + parameter tRAS_MAX = 120000, // 120 us + parameter tRC = 66, // 66 ns + parameter tRCD = 20, // 20 ns + parameter tREF = 64, // 64 ms + parameter tRFC = 66, // 66 ns + parameter tRP = 20, // 20 ns + parameter tWR = 2, // 1 CK+7.5 ns + parameter tMRD = 2, // 2 CK + parameter CL = 3, // 3 CK + parameter BL = 1, + parameter tIORT = 2, + parameter DDIO_TYPE = "SOFT", + parameter DATA_RATE = 2, + parameter BA_WIDTH = 2, + parameter ROW_WIDTH = 13, + parameter COL_WIDTH = 10, + parameter DQ_WIDTH = 8, // x4, x8 + parameter DQ_GROUP = 4 + // x4 x8 x16 x32 + // DQ_WIDTH 4 8 8 8 + // DQ_GROUP 1 1 2 4 +) +( + input i_arst, + input i_sysclk, + input i_pll_locked, + + input i_we, + input i_re, + input i_last, + input [ (BA_WIDTH+ROW_WIDTH+COL_WIDTH) -1:0] i_addr, + input [DATA_RATE *DQ_GROUP *DQ_WIDTH -1:0] i_din, + input [(DATA_RATE *DQ_GROUP) -1:0] i_dm, + output [DATA_RATE *DQ_GROUP *DQ_WIDTH -1:0] o_dout, + output [3:0]o_sdr_state, + output o_sdr_init_done, + output o_wr_ack, + output o_rd_ack, + output o_ref_req, + output o_rd_valid, + + output [DATA_RATE -1:0] o_sdr_CKE, + output [DATA_RATE -1:0] o_sdr_n_CS, + output [DATA_RATE -1:0] o_sdr_n_RAS, + output [DATA_RATE -1:0] o_sdr_n_CAS, + output [DATA_RATE -1:0] o_sdr_n_WE, + output [DATA_RATE *BA_WIDTH -1:0] o_sdr_BA, + output [DATA_RATE *ROW_WIDTH -1:0] o_sdr_ADDR, + output [DATA_RATE *DQ_GROUP *DQ_WIDTH -1:0] o_sdr_DATA, + output [DATA_RATE *DQ_GROUP *DQ_WIDTH -1:0] o_sdr_DATA_oe, + input [DATA_RATE *DQ_GROUP *DQ_WIDTH -1:0] i_sdr_DATA, + output [DATA_RATE *DQ_GROUP -1:0] o_sdr_DQM, + + output [5:0]o_dbg_dly_cnt_b, + output o_dbg_tRCD_done, + output o_dbg_tRTW_done, + output o_dbg_ref_req, + output o_dbg_wr_ack, + output o_dbg_rd_ack, + output [DATA_RATE -1:0] o_dbg_n_CS, + output [DATA_RATE -1:0] o_dbg_n_RAS, + output [DATA_RATE -1:0] o_dbg_n_CAS, + output [DATA_RATE -1:0] o_dbg_n_WE, + output [DATA_RATE *BA_WIDTH -1:0] o_dbg_BA, + output [DATA_RATE *ROW_WIDTH -1:0] o_dbg_ADDR +); + +function integer log2; + input integer val; + integer i; + begin + log2 = 0; + for (i=0; 2**i> b; + end + end + end + + r_sdr_dq_1P <= i_din; + r_sdr_dm_1P <= i_dm; + r_sdr_dqoe_1P <= {DATA_RATE*DQ_GROUP*DQ_WIDTH{1'b1}}; + + r_dly_cnt_b_1P <= {DLY_CNT_B_WIDTH{1'b0}}; + r_tWR_done_1P <= 1'b0; + + r_wr_ack_1P <= ~r_ref_req_1P[0]; + + if (REF_LATENCY > 2) begin + if (r_ref_req_1P[1] || r_tRAS_MAX_done_1P[1] || (i_last & r_wr_ack_1P)) // + begin + r_sdr_cmd_1P <= {DATA_RATE{c_NOP}}; + r_sdr_dqoe_1P <= {DATA_RATE*DQ_GROUP*DQ_WIDTH{1'b0}}; + r_wr_ack_1P <= 1'b0; + end + end + else begin + if (r_ref_req_1P[REF_LATENCY-2] || r_tRAS_MAX_done_1P[REF_LATENCY-2] || (i_last & r_wr_ack_1P)) + begin + r_sdr_cmd_1P <= {DATA_RATE{c_NOP}}; + r_sdr_dqoe_1P <= {DATA_RATE*DQ_GROUP*DQ_WIDTH{1'b0}}; + r_wr_ack_1P <= 1'b0; + end + end + + end + else if (~i_we && i_re) + begin + if (DATA_RATE == 1) + begin + r_sdr_cmd_1P <= c_RD; + r_sdr_ba_2P <= i_addr[BA_MSB:BA_LSB]; + r_sdr_addr_2P <= i_addr[COL_MSB:COL_LSB]; + end + else + begin + for (c=0; c> b; + end + end + end + + r_dly_cnt_b_1P <= {DLY_CNT_B_WIDTH{1'b0}}; + r_tRTW_done_1P <= 1'b0; + r_tRC_done_1P <= 1'b0; + + r_rd_ack_P[0] <= ~r_ref_req_1P[0]; + + if (REF_LATENCY > 2) begin + if (r_ref_req_1P[1] || r_tRAS_MAX_done_1P[1] || (i_last & r_rd_ack_P[0])) + begin + if (r_rd_ack_P[0]) + begin + r_sdr_cmd_1P <= {DATA_RATE{c_NOP}}; + r_sdr_dqoe_1P <= {DATA_RATE*DQ_GROUP*DQ_WIDTH{1'b0}}; + r_rd_ack_P[0] <= 1'b0; + end + end + end + else begin + if (r_ref_req_1P[REF_LATENCY-2] || r_tRAS_MAX_done_1P[REF_LATENCY-2] || (i_last & r_rd_ack_P[0])) + begin + if (r_rd_ack_P[0]) + begin + r_sdr_cmd_1P <= {DATA_RATE{c_NOP}}; + r_sdr_dqoe_1P <= {DATA_RATE*DQ_GROUP*DQ_WIDTH{1'b0}}; + r_rd_ack_P[0] <= 1'b0; + end + end + end + end + end + end + end + + s_PRE: + begin + if (r_dly_cnt_a_1P == nRP-1'b1) + begin + if (r_ref_req_1P[REF_LATENCY-1]) + begin + if (r_pre_allbank) // check if the previous PRE is ALL_BANK or SINGLE_BANK + begin + r_sdr_state_1P <= s_REF; + r_sdr_cmd_1P[CYC_A+:4] <= c_REF; + r_pre_allbank <= 1'b0; + r_dly_cnt_a_1P <= {DLY_CNT_A_WIDTH{1'b0}}; + end + else + begin // if the previous PRE is SINGLE_BANK, issue PRE to ALL_BANK before trigger AUTO-refresh + r_sdr_state_1P <= s_PRE; + r_sdr_cmd_1P[CYC_A+:4] <= c_PRE; + r_sdr_addr_1P[CYC_A+10] <= PRE_ALL; + r_pre_allbank <= 1'b1; + if (CHECK_ACT_BA == 4) + begin + r_act_row_1P[0][ROW_WIDTH] <= 1'b0; + r_act_row_1P[1][ROW_WIDTH] <= 1'b0; + r_act_row_1P[2][ROW_WIDTH] <= 1'b0; + r_act_row_1P[3][ROW_WIDTH] <= 1'b0; + end + r_dly_cnt_a_1P <= {DLY_CNT_A_WIDTH{1'b0}}; + end + end + else + begin + r_sdr_state_1P <= s_IDLE; + end + end + end + + s_REF: + begin + if (r_dly_cnt_a_1P == nRFC) + begin + r_sdr_state_1P <= s_IDLE; + r_ref_req_1P[0] <= 1'b0; + r_dly_cnt_d_1P <= {DLY_CNT_D_WIDTH{1'b0}}; + end + end + endcase + end +end + +assign o_sdr_state = r_sdr_state_1P; +assign o_sdr_init_done = r_sdr_init_done_1P; +assign o_wr_ack = r_wr_ack_1P; +genvar i; +generate + for (i=1; i<=RD_PIPE; i=i+1) + begin: readback + always@(posedge i_arst or posedge i_sysclk) + begin + if (i_arst) + r_rd_ack_P[i] <= 1'b0; + else + r_rd_ack_P[i] <= r_rd_ack_P[i-1]; + end + end +endgenerate +assign o_rd_ack = r_rd_ack_P[0]; +assign o_ref_req = r_ref_req_1P[0]; +assign o_rd_valid = r_rd_ack_P[RD_PIPE]; +assign o_dout = r_sdr_dqin_1P; + +assign o_sdr_CKE = r_sdr_cke_1P; +genvar j; +generate + for (j=0; j i_aresetn, +i_AXI4_AWADDR => i_AXI4_AWADDR, +i_sysclk => i_sysclk, +i_sdrclk => i_sdrclk, +i_tACclk => i_tACclk, +i_pll_locked => i_pll_locked, +o_dbg_ref_req => o_dbg_ref_req, +o_dbg_wr_ack => o_dbg_wr_ack, +o_dbg_rd_ack => o_dbg_rd_ack, +o_dbg_n_CS => o_dbg_n_CS, +o_dbg_n_RAS => o_dbg_n_RAS, +o_dbg_n_CAS => o_dbg_n_CAS, +o_dbg_n_WE => o_dbg_n_WE, +o_dbg_BA => o_dbg_BA, +o_dbg_ADDR => o_dbg_ADDR, +o_dbg_DATA_out => o_dbg_DATA_out, +o_dbg_DATA_in => o_dbg_DATA_in, +o_pll_reset => o_pll_reset, +o_AXI4_AWREADY => o_AXI4_AWREADY, +i_AXI4_AWVALID => i_AXI4_AWVALID, +o_AXI4_WREADY => o_AXI4_WREADY, +i_AXI4_WDATA => i_AXI4_WDATA, +i_AXI4_WSTRB => i_AXI4_WSTRB, +i_AXI4_WLAST => i_AXI4_WLAST, +i_AXI4_WVALID => i_AXI4_WVALID, +o_AXI4_BVALID => o_AXI4_BVALID, +i_AXI4_BREADY => i_AXI4_BREADY, +o_AXI4_ARREADY => o_AXI4_ARREADY, +i_AXI4_ARADDR => i_AXI4_ARADDR, +i_AXI4_RREADY => i_AXI4_RREADY, +o_AXI4_RDATA => o_AXI4_RDATA, +o_AXI4_RLAST => o_AXI4_RLAST, +o_AXI4_RVALID => o_AXI4_RVALID, +i_AXI4_AWID => i_AXI4_AWID, +i_AXI4_AWSIZE => i_AXI4_AWSIZE, +i_AXI4_ARVALID => i_AXI4_ARVALID, +i_AXI4_ARID => i_AXI4_ARID, +i_AXI4_ARLEN => i_AXI4_ARLEN, +i_AXI4_ARSIZE => i_AXI4_ARSIZE, +i_AXI4_ARBURST => i_AXI4_ARBURST, +i_AXI4_AWLEN => i_AXI4_AWLEN, +o_AXI4_RID => o_AXI4_RID, +o_dbg_we => o_dbg_we, +o_dbg_last => o_dbg_last, +o_dbg_addr => o_dbg_addr, +o_dbg_din => o_dbg_din, +o_axi4_wrstate => o_axi4_wrstate, +o_fifo_wr => o_fifo_wr, +o_fifo_full => o_fifo_full, +o_fifo_empty => o_fifo_empty, +o_dbg_fifo_waddr => o_dbg_fifo_waddr, +o_dbg_fifo_re => o_dbg_fifo_re, +o_dbg_fifo_raddr => o_dbg_fifo_raddr, +o_dbg_fifo_we => o_dbg_fifo_we, +o_dbg_axi4_wlast => o_dbg_axi4_wlast, +o_shift_cnt => o_shift_cnt, +o_re_lock => o_re_lock, +o_axi4_rastate => o_axi4_rastate, +o_axi4_nwr => o_axi4_nwr, +o_axi4_arlen => o_axi4_arlen, +o_axi4_rdstate => o_axi4_rdstate, +o_sdr_rd_valid => o_sdr_rd_valid, +o_sdr_dout => o_sdr_dout, +o_dbg_re => o_dbg_re, +o_AXI4_BID => o_AXI4_BID, +i_addr => i_addr, +i_din => i_din, +i_dm => i_dm, +o_dout => o_dout, +o_sdr_state => o_sdr_state, +o_sdr_init_done => o_sdr_init_done, +o_wr_ack => o_wr_ack, +o_rd_ack => o_rd_ack, +o_ref_req => o_ref_req, +o_rd_valid => o_rd_valid, +o_sdr_CKE => o_sdr_CKE, +o_sdr_n_CS => o_sdr_n_CS, +o_sdr_n_RAS => o_sdr_n_RAS, +o_sdr_n_CAS => o_sdr_n_CAS, +o_sdr_n_WE => o_sdr_n_WE, +o_sdr_BA => o_sdr_BA, +o_sdr_ADDR => o_sdr_ADDR, +o_sdr_DATA => o_sdr_DATA, +o_sdr_DATA_oe => o_sdr_DATA_oe, +i_sdr_DATA => i_sdr_DATA, +o_sdr_DQM => o_sdr_DQM); +------------------------ End INSTANTIATION Template --------- diff --git a/hw/super6502_fpga/ip/sdram_controller/settings.json b/hw/super6502_fpga/ip/sdram_controller/settings.json new file mode 100644 index 0000000..a021290 --- /dev/null +++ b/hw/super6502_fpga/ip/sdram_controller/settings.json @@ -0,0 +1,44 @@ +{ + "args": [ + "-o", + "sdram_controller", + "--base_path", + "/home/byron/Projects/super6502/hw/super6502_fpga/ip", + "--vlnv", + { + "vendor": "efinixinc.com", + "library": "memory_controller", + "name": "efx_sdram_controller", + "version": "5.0" + } + ], + "conf": { + "fCK_MHz": "200", + "tIORT_u": "2", + "CL": "3", + "DDIO_TYPE": "\"SOFT\"", + "DQ_GROUP": "2", + "ROW_WIDTH": "13", + "COL_WIDTH": "9", + "tPWRUP": "200000", + "tRAS": "44", + "tRAS_MAX": "120000", + "tRC": "66", + "tRCD": "20", + "tREF": "64000000", + "tRFC": "66", + "tRP": "20", + "SDRAM_MODE": "\"AXI4\"", + "DATA_RATE": "2" + }, + "output": { + "external_source_source": [ + "/home/byron/Projects/super6502/hw/super6502_fpga/ip/sdram_controller/sdram_controller_tmpl.v", + "/home/byron/Projects/super6502/hw/super6502_fpga/ip/sdram_controller/sdram_controller.v", + "/home/byron/Projects/super6502/hw/super6502_fpga/ip/sdram_controller/sdram_controller_tmpl.vhd", + "/home/byron/Projects/super6502/hw/super6502_fpga/ip/sdram_controller/sdram_controller_define.vh" + ] + }, + "sw_version": "2023.1.150", + "generated_date": "2024-03-04T01:51:33.450281" +} \ No newline at end of file diff --git a/hw/super6502_fpga/sources.list b/hw/super6502_fpga/sources.list index e717faa..b9113d1 100644 --- a/hw/super6502_fpga/sources.list +++ b/hw/super6502_fpga/sources.list @@ -11,4 +11,4 @@ src/sub/rtl-common/src/rtl/axi4_lite_rom.sv src/sub/rtl-common/src/rtl/ff_cdc.sv src/sub/rtl-common/src/rtl/shallow_async_fifo.sv src/sub/rtl-common/src/rtl/sync_fifo.sv - +ip/sdram_controller/sdram_controller.v diff --git a/hw/super6502_fpga/src/rtl/super_6502_fpga.sv b/hw/super6502_fpga/src/rtl/super_6502_fpga.sv index 62429b3..84cdee6 100644 --- a/hw/super6502_fpga/src/rtl/super_6502_fpga.sv +++ b/hw/super6502_fpga/src/rtl/super_6502_fpga.sv @@ -12,6 +12,19 @@ module super6502_fpga( input i_pll_locked, output logic o_pll_reset, + output logic o_sdr_CKE, + output logic o_sdr_n_CS, + output logic o_sdr_n_WE, + output logic o_sdr_n_RAS, + output logic o_sdr_n_CAS, + output logic [1:0] o_sdr_BA, + output logic [12:0] o_sdr_ADDR, + input logic [15:0] i_sdr_DATA, + output logic [15:0] o_sdr_DATA, + output logic [15:0] o_sdr_DATA_oe, + output logic [1:0] o_sdr_DQM, + + input [7:0] i_cpu0_data_from_cpu, input i_cpu0_sync, input i_cpu0_rwb, @@ -38,10 +51,21 @@ assign o_clk_phi2 = clk_cpu; assign o_cpu0_data_oe = {8{i_cpu0_rwb}}; +logic vio0_reset; +assign vio0_reset = '1; logic master_reset; +logic sdram_ready; +logic [3:0] w_sdr_state; + +logic pre_reset; + +assign pre_reset = button_reset & vio0_reset; + +assign sdram_ready = |w_sdr_state; + +assign master_reset = pre_reset & sdram_ready; -assign master_reset = button_reset; logic cpu0_AWVALID; logic cpu0_AWREADY; @@ -98,6 +122,24 @@ logic rom_rready; logic [DATA_WIDTH-1:0] rom_rdata; logic [1:0] rom_rresp; +logic sdram_AWVALID; +logic sdram_AWREADY; +logic [ADDR_WIDTH-1:0] sdram_AWADDR; +logic sdram_WVALID; +logic sdram_WREADY; +logic [DATA_WIDTH-1:0] sdram_WDATA; +logic [DATA_WIDTH/8-1:0] sdram_WSTRB; +logic sdram_BVALID; +logic sdram_BREADY; +logic [1:0] sdram_BRESP; +logic sdram_ARVALID; +logic sdram_ARREADY; +logic [ADDR_WIDTH-1:0] sdram_ARADDR; +logic sdram_RVALID; +logic sdram_RREADY; +logic [DATA_WIDTH-1:0] sdram_RDATA; +logic [1:0] sdram_RRESP; + cpu_wrapper u_cpu_wrapper_0( .i_clk_cpu (clk_cpu), @@ -145,7 +187,7 @@ cpu_wrapper u_cpu_wrapper_0( axi_crossbar #( .N_INITIATORS(1), - .N_TARGETS(2) + .N_TARGETS(3) ) u_crossbar ( .clk(i_sysclk), .rst(~master_reset), @@ -168,23 +210,24 @@ axi_crossbar #( .ini_bvalid ({cpu0_BVALID }), .ini_bready ({cpu0_BREADY }), - .tgt_araddr ({ram_araddr, rom_araddr }), - .tgt_arvalid ({ram_arvalid, rom_arvalid }), - .tgt_arready ({ram_arready, rom_arready }), - .tgt_rdata ({ram_rdata, rom_rdata }), - .tgt_rresp ({ram_rresp, rom_rresp }), - .tgt_rvalid ({ram_rvalid, rom_rvalid }), - .tgt_rready ({ram_rready, rom_rready }), - .tgt_awaddr ({ram_awaddr, rom_awaddr }), - .tgt_awvalid ({ram_awvalid, rom_awvalid }), - .tgt_awready ({ram_awready, rom_awready }), - .tgt_wdata ({ram_wdata, rom_wdata }), - .tgt_wvalid ({ram_wvalid, rom_wvalid }), - .tgt_wready ({ram_wready, rom_wready }), - .tgt_wstrb ({ram_wstrb, rom_wstrb }), - .tgt_bresp ({ram_bresp, rom_bresp }), - .tgt_bvalid ({ram_bvalid, rom_bvalid }), - .tgt_bready ({ram_bready, rom_bready }) + .tgt_araddr ({ram_araddr, rom_araddr, sdram_ARADDR }), + .tgt_arvalid ({ram_arvalid, rom_arvalid, sdram_ARVALID }), + .tgt_arready ({ram_arready, rom_arready, sdram_ARREADY }), + .tgt_rdata ({ram_rdata, rom_rdata, sdram_RDATA }), + .tgt_rresp ({ram_rresp, rom_rresp, sdram_RRESP }), + .tgt_rvalid ({ram_rvalid, rom_rvalid, sdram_RVALID }), + .tgt_rready ({ram_rready, rom_rready, sdram_RREADY }), + .tgt_awaddr ({ram_awaddr, rom_awaddr, sdram_AWADDR }), + .tgt_awvalid ({ram_awvalid, rom_awvalid, sdram_AWVALID }), + .tgt_awready ({ram_awready, rom_awready, sdram_AWREADY }), + .tgt_wdata ({ram_wdata, rom_wdata, sdram_WDATA }), + .tgt_wvalid ({ram_wvalid, rom_wvalid, sdram_WVALID }), + .tgt_wready ({ram_wready, rom_wready, sdram_WREADY }), + .tgt_wstrb ({ram_wstrb, rom_wstrb, sdram_WSTRB }), + .tgt_bresp ({ram_bresp, rom_bresp, sdram_BRESP }), + .tgt_bvalid ({ram_bvalid, rom_bvalid, sdram_BVALID }), + .tgt_bready ({ram_bready, rom_bready, sdram_BREADY }) + ); axi4_lite_rom #( @@ -252,6 +295,79 @@ axi4_lite_ram #( .i_WSTRB(ram_wstrb) ); +logic [1:0] w_sdr_CKE; +logic [1:0] w_sdr_n_CS; +logic [1:0] w_sdr_n_RAS; +logic [1:0] w_sdr_n_CAS; +logic [1:0] w_sdr_n_WE; +logic [3:0] w_sdr_BA; +logic [25:0] w_sdr_ADDR; +logic [31:0] w_sdr_DATA; +logic [31:0] w_sdr_DATA_oe; +logic [3:0] w_sdr_DQM; + +assign o_sdr_CKE = w_sdr_CKE[0]; //Using SOFT ddio, ignore second cycle +assign o_sdr_n_CS = w_sdr_n_CS[0]; +assign o_sdr_n_RAS = w_sdr_n_RAS[0]; +assign o_sdr_n_CAS = w_sdr_n_CAS[0]; +assign o_sdr_n_WE = w_sdr_n_WE[0]; +assign o_sdr_BA = w_sdr_BA[0+:2]; +assign o_sdr_ADDR = w_sdr_ADDR[0+:13]; +assign o_sdr_DATA = w_sdr_DATA[0+:16]; +assign o_sdr_DATA_oe = w_sdr_DATA_oe[0+:16]; +assign o_sdr_DQM = w_sdr_DQM[0+:2]; + +sdram_controller u_sdram_controller( + .i_aresetn (pre_reset), + .i_sysclk (i_sysclk), + .i_sdrclk (i_sdrclk), + .i_tACclk (i_tACclk), + .o_pll_reset (), + .i_pll_locked ('1), + + .o_sdr_state (w_sdr_state), + + .i_AXI4_AWVALID (sdram_AWVALID), + .o_AXI4_AWREADY (sdram_AWREADY), + .i_AXI4_AWADDR (sdram_AWADDR[23:0]), + .i_AXI4_WVALID (sdram_WVALID), + .o_AXI4_WREADY (sdram_WREADY), + .i_AXI4_WDATA (sdram_WDATA), + .i_AXI4_WSTRB (sdram_WSTRB), + .o_AXI4_BVALID (sdram_BVALID), + .i_AXI4_BREADY (sdram_BREADY), + .i_AXI4_ARVALID (sdram_ARVALID), + .o_AXI4_ARREADY (sdram_ARREADY), + .i_AXI4_ARADDR (sdram_ARADDR[23:0]), + .o_AXI4_RVALID (sdram_RVALID), + .i_AXI4_RREADY (sdram_RREADY), + .o_AXI4_RDATA (sdram_RDATA), + + .i_AXI4_WLAST (sdram_WVALID), + .o_AXI4_RLAST (), + .i_AXI4_AWID ('0), + .i_AXI4_AWSIZE ('0), + .i_AXI4_ARID ('0), + .i_AXI4_ARLEN ('0), + .i_AXI4_ARSIZE ('0), + .i_AXI4_ARBURST ('0), + .i_AXI4_AWLEN ('0), + .o_AXI4_RID (), + .o_AXI4_BID (), + + .o_sdr_CKE (w_sdr_CKE), + .o_sdr_n_CS (w_sdr_n_CS), + .o_sdr_n_RAS (w_sdr_n_RAS), + .o_sdr_n_CAS (w_sdr_n_CAS), + .o_sdr_n_WE (w_sdr_n_WE), + .o_sdr_BA (w_sdr_BA), + .o_sdr_ADDR (w_sdr_ADDR), + .o_sdr_DATA (w_sdr_DATA), + .o_sdr_DATA_oe (w_sdr_DATA_oe), + .i_sdr_DATA ({{16'b0}, {i_sdr_DATA}}), + .o_sdr_DQM (w_sdr_DQM) +); + endmodule \ No newline at end of file diff --git a/hw/super6502_fpga/src/sim/Makefile b/hw/super6502_fpga/src/sim/Makefile index 1dccbe3..caf1014 100644 --- a/hw/super6502_fpga/src/sim/Makefile +++ b/hw/super6502_fpga/src/sim/Makefile @@ -4,6 +4,8 @@ SIM_SRCS_LIST=sources.list SUPER6502_FPGA_SOURCES=$(foreach file, $(shell cat $(FPGA_SRCS_LIST)), ../../$(file)) SIM_SOURCES=$(shell cat $(SIM_SRCS_LIST)) +INCLUDE=include/sdram_controller_define.vh + TB_NAME=sim_top COPY_FILES=addr_map.mem init_hex.mem @@ -14,7 +16,7 @@ waves: $(TB_NAME) ./$(TB_NAME) -fst $(TB_NAME): $(SUPER6502_FPGA_SOURCES) $(SIM_SOURCES) $(COPY_FILES) - iverilog -g2005-sv $(FLAGS) -s $@ -o $@ $(SUPER6502_FPGA_SOURCES) $(SIM_SOURCES) -I ../../ + iverilog -g2005-sv $(FLAGS) -s $@ -o $@ $(INCLUDE) $(SUPER6502_FPGA_SOURCES) $(SIM_SOURCES) -I ../../ $(COPY_FILES): ../../$@ cp ../../$@ . diff --git a/hw/super6502_fpga/src/sim/hvl/sim_top.sv b/hw/super6502_fpga/src/sim/hvl/sim_top.sv index 0afa07f..c4c29c8 100644 --- a/hw/super6502_fpga/src/sim/hvl/sim_top.sv +++ b/hw/super6502_fpga/src/sim/hvl/sim_top.sv @@ -2,6 +2,8 @@ module sim_top(); +`include "include/sdram_controller_define.vh" + localparam ADDR_WIDTH = 32; localparam DATA_WIDTH = 32; @@ -71,11 +73,48 @@ cpu_65c02 u_cpu0 ( .SYNC (w_cpu0_sync) ); +logic w_sdr_CKE; +logic w_sdr_n_CS; +logic w_sdr_n_WE; +logic w_sdr_n_RAS; +logic w_sdr_n_CAS; +logic [BA_WIDTH -1:0] w_sdr_BA; +logic [ROW_WIDTH -1:0] w_sdr_ADDR; +logic [DQ_GROUP *DQ_WIDTH -1:0] w_sdr_DATA; +logic [DQ_GROUP *DQ_WIDTH -1:0] w_sdr_DATA_oe; +logic [DQ_GROUP -1:0] w_sdr_DQM; +wire [DQ_GROUP *DQ_WIDTH -1:0] w_sdr_DQ; +// ^ Has to be wire because of tristate/inout stuff + +genvar i, j; +generate + for (i=0; i= tRAS) && // Case 1 + (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [0] >= 1) || // Case 2 + (Burst_length_2 == 1'b1 && Count_precharge [0] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge [0] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge [0] >= 8))) || + (RW_interrupt_write[0] == 1'b1 && RW_interrupt_counter[0] >= 1)) begin // Case 3 + Auto_precharge[0] = 1'b0; + Write_precharge[0] = 1'b0; + RW_interrupt_write[0] = 1'b0; + Pc_b0 = 1'b1; + Act_b0 = 1'b0; + RP_chk0 = $time + tWRa; + if (Debug) begin + $display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time); + end + end + end + if ((Auto_precharge[1] == 1'b1) && (Write_precharge[1] == 1'b1)) begin + if ((($time - RAS_chk1 >= tRAS) && // Case 1 + (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [1] >= 1) || // Case 2 + (Burst_length_2 == 1'b1 && Count_precharge [1] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge [1] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge [1] >= 8))) || + (RW_interrupt_write[1] == 1'b1 && RW_interrupt_counter[1] >= 1)) begin // Case 3 + Auto_precharge[1] = 1'b0; + Write_precharge[1] = 1'b0; + RW_interrupt_write[1] = 1'b0; + Pc_b1 = 1'b1; + Act_b1 = 1'b0; + RP_chk1 = $time + tWRa; + if (Debug) begin + $display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time); + end + end + end + if ((Auto_precharge[2] == 1'b1) && (Write_precharge[2] == 1'b1)) begin + if ((($time - RAS_chk2 >= tRAS) && // Case 1 + (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [2] >= 1) || // Case 2 + (Burst_length_2 == 1'b1 && Count_precharge [2] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge [2] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge [2] >= 8))) || + (RW_interrupt_write[2] == 1'b1 && RW_interrupt_counter[2] >= 1)) begin // Case 3 + Auto_precharge[2] = 1'b0; + Write_precharge[2] = 1'b0; + RW_interrupt_write[2] = 1'b0; + Pc_b2 = 1'b1; + Act_b2 = 1'b0; + RP_chk2 = $time + tWRa; + if (Debug) begin + $display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time); + end + end + end + if ((Auto_precharge[3] == 1'b1) && (Write_precharge[3] == 1'b1)) begin + if ((($time - RAS_chk3 >= tRAS) && // Case 1 + (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [3] >= 1) || // Case 2 + (Burst_length_2 == 1'b1 && Count_precharge [3] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge [3] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge [3] >= 8))) || + (RW_interrupt_write[3] == 1'b1 && RW_interrupt_counter[3] >= 1)) begin // Case 3 + Auto_precharge[3] = 1'b0; + Write_precharge[3] = 1'b0; + RW_interrupt_write[3] = 1'b0; + Pc_b3 = 1'b1; + Act_b3 = 1'b0; + RP_chk3 = $time + tWRa; + if (Debug) begin + $display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time); + end + end + end + + // Read with Auto Precharge Calculation + // The device start internal precharge: + // 1. Meet minimum tRAS requirement + // and 2. CAS Latency - 1 cycles before last burst + // or 3. Interrupt by a Read or Write (with or without AutoPrecharge) + if ((Auto_precharge[0] == 1'b1) && (Read_precharge[0] == 1'b1)) begin + if ((($time - RAS_chk0 >= tRAS) && // Case 1 + ((Burst_length_1 == 1'b1 && Count_precharge[0] >= 1) || // Case 2 + (Burst_length_2 == 1'b1 && Count_precharge[0] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge[0] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge[0] >= 8))) || + (RW_interrupt_read[0] == 1'b1)) begin // Case 3 + Pc_b0 = 1'b1; + Act_b0 = 1'b0; + RP_chk0 = $time; + Auto_precharge[0] = 1'b0; + Read_precharge[0] = 1'b0; + RW_interrupt_read[0] = 1'b0; + if (Debug) begin + $display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time); + end + end + end + if ((Auto_precharge[1] == 1'b1) && (Read_precharge[1] == 1'b1)) begin + if ((($time - RAS_chk1 >= tRAS) && + ((Burst_length_1 == 1'b1 && Count_precharge[1] >= 1) || + (Burst_length_2 == 1'b1 && Count_precharge[1] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge[1] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge[1] >= 8))) || + (RW_interrupt_read[1] == 1'b1)) begin + Pc_b1 = 1'b1; + Act_b1 = 1'b0; + RP_chk1 = $time; + Auto_precharge[1] = 1'b0; + Read_precharge[1] = 1'b0; + RW_interrupt_read[1] = 1'b0; + if (Debug) begin + $display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time); + end + end + end + if ((Auto_precharge[2] == 1'b1) && (Read_precharge[2] == 1'b1)) begin + if ((($time - RAS_chk2 >= tRAS) && + ((Burst_length_1 == 1'b1 && Count_precharge[2] >= 1) || + (Burst_length_2 == 1'b1 && Count_precharge[2] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge[2] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge[2] >= 8))) || + (RW_interrupt_read[2] == 1'b1)) begin + Pc_b2 = 1'b1; + Act_b2 = 1'b0; + RP_chk2 = $time; + Auto_precharge[2] = 1'b0; + Read_precharge[2] = 1'b0; + RW_interrupt_read[2] = 1'b0; + if (Debug) begin + $display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time); + end + end + end + if ((Auto_precharge[3] == 1'b1) && (Read_precharge[3] == 1'b1)) begin + if ((($time - RAS_chk3 >= tRAS) && + ((Burst_length_1 == 1'b1 && Count_precharge[3] >= 1) || + (Burst_length_2 == 1'b1 && Count_precharge[3] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge[3] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge[3] >= 8))) || + (RW_interrupt_read[3] == 1'b1)) begin + Pc_b3 = 1'b1; + Act_b3 = 1'b0; + RP_chk3 = $time; + Auto_precharge[3] = 1'b0; + Read_precharge[3] = 1'b0; + RW_interrupt_read[3] = 1'b0; + if (Debug) begin + $display("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time); + end + end + end + + // Internal Precharge or Bst + if (Command[0] == `PRECH) begin // Precharge terminate a read with same bank or all banks + if (Bank_precharge[0] == Bank || A10_precharge[0] == 1'b1) begin + if (Data_out_enable == 1'b1) begin + Data_out_enable = 1'b0; + end + end + end else if (Command[0] == `BST) begin // BST terminate a read to current bank + if (Data_out_enable == 1'b1) begin + Data_out_enable = 1'b0; + end + end + + if (Data_out_enable == 1'b0) begin + Dq_reg <= #tOH {DQ_BITS{1'bz}}; + end + + // Detect Read or Write command + if (Command[0] == `READ) begin + Bank = Bank_addr[0]; + Col = Col_addr[0]; + Col_brst = Col_addr[0]; + case (Bank_addr[0]) + 2'b00 : Row = B0_row_addr; + 2'b01 : Row = B1_row_addr; + 2'b10 : Row = B2_row_addr; + 2'b11 : Row = B3_row_addr; + endcase + Burst_counter = 0; + Data_in_enable = 1'b0; + Data_out_enable = 1'b1; + end else if (Command[0] == `WRITE) begin + Bank = Bank_addr[0]; + Col = Col_addr[0]; + Col_brst = Col_addr[0]; + case (Bank_addr[0]) + 2'b00 : Row = B0_row_addr; + 2'b01 : Row = B1_row_addr; + 2'b10 : Row = B2_row_addr; + 2'b11 : Row = B3_row_addr; + endcase + Burst_counter = 0; + Data_in_enable = 1'b1; + Data_out_enable = 1'b0; + end + + // DQ buffer (Driver/Receiver) + if (Data_in_enable == 1'b1) begin // Writing Data to Memory + // Array buffer + case (Bank) + 2'b00 : Dq_dqm = Bank0 [{Row, Col}]; + 2'b01 : Dq_dqm = Bank1 [{Row, Col}]; + 2'b10 : Dq_dqm = Bank2 [{Row, Col}]; + 2'b11 : Dq_dqm = Bank3 [{Row, Col}]; + endcase + + // Dqm operation +`ifdef x4 + if (Dqm[0] == 1'b0) begin + Dq_dqm [ 3 : 0] = Dq [ 3 : 0]; + end +`elsif x8 + if (Dqm[0] == 1'b0) begin + Dq_dqm [ 7 : 0] = Dq [ 7 : 0]; + end +`elsif x16 + if (Dqm[0] == 1'b0) begin + Dq_dqm [ 7 : 0] = Dq [ 7 : 0]; + end + if (Dqm[1] == 1'b0) begin + Dq_dqm [15 : 8] = Dq [15 : 8]; + end +`endif + + // Write to memory + case (Bank) + 2'b00 : Bank0 [{Row, Col}] = Dq_dqm; + 2'b01 : Bank1 [{Row, Col}] = Dq_dqm; + 2'b10 : Bank2 [{Row, Col}] = Dq_dqm; + 2'b11 : Bank3 [{Row, Col}] = Dq_dqm; + endcase + + // Display debug message + if (Dqm !== 2'b11) begin + // Record tWR for manual precharge + WR_chkm [Bank] = $time; + + if (Debug) begin + $display("%m : at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %h", $time, Bank, Row, Col, Dq_dqm); + end + end else begin + if (Debug) begin + $display("%m : at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col); + end + end + + // Advance burst counter subroutine + #tHZ Burst_decode; + + end else if (Data_out_enable == 1'b1) begin // Reading Data from Memory + // Array buffer + case (Bank) + 2'b00 : Dq_dqm = Bank0[{Row, Col}]; + 2'b01 : Dq_dqm = Bank1[{Row, Col}]; + 2'b10 : Dq_dqm = Bank2[{Row, Col}]; + 2'b11 : Dq_dqm = Bank3[{Row, Col}]; + endcase + + // Dqm operation +`ifdef x4 + if (Dqm_reg0 [0] == 1'b1) begin + Dq_dqm [ 3 : 0] = 4'bz; + end +`elsif x8 + if (Dqm_reg0 [0] == 1'b1) begin + Dq_dqm [ 7 : 0] = 8'bz; + end +`elsif x16 + if (Dqm_reg0 [0] == 1'b1) begin + Dq_dqm [ 7 : 0] = 8'bz; + end + if (Dqm_reg0 [1] == 1'b1) begin + Dq_dqm [15 : 8] = 8'bz; + end +`endif + + // Display debug message + Dq_reg = #tAC Dq_dqm; + if (Debug) begin + $display("%m : at time %t READ : Bank = %d Row = %d, Col = %d, Dqm = %b, Data = %h", $time, Bank, Row, Col, Dqm_reg0, Dq_reg); + end + + // Advance burst counter subroutine + Burst_decode; + end + end + + // Burst counter decode + task Burst_decode; + begin + // Advance Burst Counter + Burst_counter = Burst_counter + 1; + + // Burst Type + if (Mode_reg[3] == 1'b0) begin // Sequential Burst + Col_temp = Col + 1; + end else if (Mode_reg[3] == 1'b1) begin // Interleaved Burst + Col_temp[2] = Burst_counter[2] ^ Col_brst[2]; + Col_temp[1] = Burst_counter[1] ^ Col_brst[1]; + Col_temp[0] = Burst_counter[0] ^ Col_brst[0]; + end + + // Burst Length + if (Burst_length_2) begin // Burst Length = 2 + Col [0] = Col_temp [0]; + end else if (Burst_length_4) begin // Burst Length = 4 + Col [1 : 0] = Col_temp [1 : 0]; + end else if (Burst_length_8) begin // Burst Length = 8 + Col [2 : 0] = Col_temp [2 : 0]; + end else begin // Burst Length = FULL + Col = Col_temp; + end + + // Burst Read Single Write + if (Write_burst_mode == 1'b1) begin + Data_in_enable = 1'b0; + end + + // Data Counter + if (Burst_length_1 == 1'b1) begin + if (Burst_counter >= 1) begin + Data_in_enable = 1'b0; + Data_out_enable = 1'b0; + end + end else if (Burst_length_2 == 1'b1) begin + if (Burst_counter >= 2) begin + Data_in_enable = 1'b0; + Data_out_enable = 1'b0; + end + end else if (Burst_length_4 == 1'b1) begin + if (Burst_counter >= 4) begin + Data_in_enable = 1'b0; + Data_out_enable = 1'b0; + end + end else if (Burst_length_8 == 1'b1) begin + if (Burst_counter >= 8) begin + Data_in_enable = 1'b0; + Data_out_enable = 1'b0; + end + end + end + endtask + + // Timing Parameters for -75 (133 MHz @ CL3) + specify + specparam + tAH = 0.8, // Addr, Ba Hold Time + tAS = 1.5, // Addr, Ba Setup Time + `ifdef CLK_166 + tCK3 = 6, + `elsif CLK_133 + tCK3 = 7.5, + `elsif CLK_100 + tCK3 = 10, + `elsif CLK_200 + tCK3 = 5, + `endif + tCH = 2.5, // Clock High-Level Width + tCL = 2.5, // Clock Low-Level Width + tCKH = 0.8, // CKE Hold Time + tCKS = 1.5, // CKE Setup Time + tCMH = 0.8, // CS#, RAS#, CAS#, WE#, DQM# Hold Time + tCMS = 1.5, // CS#, RAS#, CAS#, WE#, DQM# Setup Time + tDH = 0.8, // Data-in Hold Time + tDS = 1.5; // Data-in Setup Time + $width (posedge Clk, tCH); + $width (negedge Clk, tCL); + $period (negedge Clk, tCK3); + $period (posedge Clk, tCK3); + $setuphold(posedge Clk, Cke, tCKS, tCKH); + $setuphold(posedge Clk, Cs_n, tCMS, tCMH); + $setuphold(posedge Clk, Cas_n, tCMS, tCMH); + $setuphold(posedge Clk, Ras_n, tCMS, tCMH); + $setuphold(posedge Clk, We_n, tCMS, tCMH); + $setuphold(posedge Clk, Addr, tAS, tAH); + $setuphold(posedge Clk, Ba, tAS, tAH); + $setuphold(posedge Clk, Dqm, tCMS, tCMH); + $setuphold(posedge Dq_chk, Dq, tDS, tDH); + endspecify + +endmodule diff --git a/hw/super6502_fpga/super6502_fpga.xml b/hw/super6502_fpga/super6502_fpga.xml index 7d569ac..71dd86e 100644 --- a/hw/super6502_fpga/super6502_fpga.xml +++ b/hw/super6502_fpga/super6502_fpga.xml @@ -1,4 +1,4 @@ - + @@ -24,7 +24,11 @@ - + + + + + @@ -51,6 +55,7 @@ + @@ -81,4 +86,9 @@ + + + + + \ No newline at end of file diff --git a/sw/test_code/loop_test/main.s b/sw/test_code/loop_test/main.s index 60aebb7..fbd3b02 100644 --- a/sw/test_code/loop_test/main.s +++ b/sw/test_code/loop_test/main.s @@ -6,8 +6,7 @@ .addr _init ; Reset vector .addr _irq_int ; IRQ/BRK vector -.zeropage -tmp: .res 1 +SDRAM= $200 .code @@ -17,8 +16,8 @@ _irq_int: _init: lda #$00 @start: - sta tmp - cmp tmp + sta SDRAM + cmp SDRAM bne @end ina bra @start